From 6ca8a8b1ce2e7befc90ea8128ea049134f5100a5 Mon Sep 17 00:00:00 2001 From: devops Date: Wed, 16 Aug 2023 11:07:02 +0000 Subject: [PATCH 01/16] deps/wasm-semantics: Set Version 51b9d18625ad764a784f6bca985ca57926d8e903 --- deps/wasm-semantics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/wasm-semantics b/deps/wasm-semantics index bf9b81b8..51b9d186 160000 --- a/deps/wasm-semantics +++ b/deps/wasm-semantics @@ -1 +1 @@ -Subproject commit bf9b81b83ca6d519c2432f62e44106a64179de3c +Subproject commit 51b9d18625ad764a784f6bca985ca57926d8e903 From 111b023c81b1304c98222c40dd9caebdfd5a8c0f Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Mon, 21 Aug 2023 23:01:43 +0300 Subject: [PATCH 02/16] init pykelrond --- pykelrond/.cruft.json | 18 + pykelrond/.flake8 | 7 + pykelrond/.gitignore | 3 + pykelrond/Makefile | 92 ++ pykelrond/README.md | 23 + pykelrond/flake.nix | 41 + pykelrond/poetry.lock | 1153 +++++++++++++++++ pykelrond/pyproject.toml | 51 + pykelrond/src/pykelrond/__init__.py | 0 pykelrond/src/pykelrond/hello.py | 2 + pykelrond/src/pykelrond/py.typed | 0 pykelrond/src/tests/__init__.py | 0 pykelrond/src/tests/integration/__init__.py | 0 .../src/tests/integration/test_integration.py | 5 + pykelrond/src/tests/unit/__init__.py | 0 pykelrond/src/tests/unit/test_unit.py | 5 + 16 files changed, 1400 insertions(+) create mode 100644 pykelrond/.cruft.json create mode 100644 pykelrond/.flake8 create mode 100644 pykelrond/.gitignore create mode 100644 pykelrond/Makefile create mode 100644 pykelrond/README.md create mode 100644 pykelrond/flake.nix create mode 100644 pykelrond/poetry.lock create mode 100644 pykelrond/pyproject.toml create mode 100644 pykelrond/src/pykelrond/__init__.py create mode 100644 pykelrond/src/pykelrond/hello.py create mode 100644 pykelrond/src/pykelrond/py.typed create mode 100644 pykelrond/src/tests/__init__.py create mode 100644 pykelrond/src/tests/integration/__init__.py create mode 100644 pykelrond/src/tests/integration/test_integration.py create mode 100644 pykelrond/src/tests/unit/__init__.py create mode 100644 pykelrond/src/tests/unit/test_unit.py diff --git a/pykelrond/.cruft.json b/pykelrond/.cruft.json new file mode 100644 index 00000000..3fea3ce1 --- /dev/null +++ b/pykelrond/.cruft.json @@ -0,0 +1,18 @@ +{ + "template": "https://github.com/runtimeverification/python-project-template", + "commit": "601d5e2a0e8a98c87dcb1ae694d22d76d0114e01", + "checkout": null, + "context": { + "cookiecutter": { + "project_name": "pykelrond", + "project_slug": "pykelrond", + "package_name": "pykelrond", + "version": "0.1.0", + "description": "Python tools for Elrond semantics", + "author_name": "Runtime Verification, Inc.", + "author_email": "contact@runtimeverification.com", + "_template": "https://github.com/runtimeverification/python-project-template" + } + }, + "directory": null +} diff --git a/pykelrond/.flake8 b/pykelrond/.flake8 new file mode 100644 index 00000000..a518873c --- /dev/null +++ b/pykelrond/.flake8 @@ -0,0 +1,7 @@ +[flake8] +max-line-length = 120 +extend-select = B9, TC1 +extend-ignore = B950,E,W1,W2,W3,W4,W5 +per-file-ignores = + */__init__.py: F401 +type-checking-strict = true diff --git a/pykelrond/.gitignore b/pykelrond/.gitignore new file mode 100644 index 00000000..98fe5a7f --- /dev/null +++ b/pykelrond/.gitignore @@ -0,0 +1,3 @@ +/dist/ +__pycache__/ +.coverage diff --git a/pykelrond/Makefile b/pykelrond/Makefile new file mode 100644 index 00000000..d627d381 --- /dev/null +++ b/pykelrond/Makefile @@ -0,0 +1,92 @@ +POETRY := poetry +POETRY_RUN := $(POETRY) run + + +default: check test-unit + +all: check cov + +.PHONY: clean +clean: + rm -rf dist .coverage cov-* .mypy_cache .pytest_cache + find -type d -name __pycache__ -prune -exec rm -rf {} \; + +.PHONY: build +build: + $(POETRY) build + +.PHONY: poetry-install +poetry-install: + $(POETRY) install + + +# Tests + +TEST_ARGS := + +test: test-all + +test-all: poetry-install + $(POETRY_RUN) pytest src/tests --maxfail=1 --verbose --durations=0 --numprocesses=4 --dist=worksteal $(TEST_ARGS) + +test-unit: poetry-install + $(POETRY_RUN) pytest src/tests/unit --maxfail=1 --verbose $(TEST_ARGS) + +test-integration: poetry-install + $(POETRY_RUN) pytest src/tests/integration --maxfail=1 --verbose --durations=0 --numprocesses=4 --dist=worksteal $(TEST_ARGS) + + +# Coverage + +COV_ARGS := + +cov: cov-all + +cov-%: TEST_ARGS += --cov=pykelrond --no-cov-on-fail --cov-branch --cov-report=term + +cov-all: TEST_ARGS += --cov-report=html:cov-all-html $(COV_ARGS) +cov-all: test-all + +cov-unit: TEST_ARGS += --cov-report=html:cov-unit-html $(COV_ARGS) +cov-unit: test-unit + +cov-integration: TEST_ARGS += --cov-report=html:cov-integration-html $(COV_ARGS) +cov-integration: test-integration + + +# Checks and formatting + +format: autoflake isort black +check: check-flake8 check-mypy check-autoflake check-isort check-black + +check-flake8: poetry-install + $(POETRY_RUN) flake8 src + +check-mypy: poetry-install + $(POETRY_RUN) mypy src + +autoflake: poetry-install + $(POETRY_RUN) autoflake --quiet --in-place src + +check-autoflake: poetry-install + $(POETRY_RUN) autoflake --quiet --check src + +isort: poetry-install + $(POETRY_RUN) isort src + +check-isort: poetry-install + $(POETRY_RUN) isort --check src + +black: poetry-install + $(POETRY_RUN) black src + +check-black: poetry-install + $(POETRY_RUN) black --check src + + +# Optional tools + +SRC_FILES := $(shell find src -type f -name '*.py') + +pyupgrade: poetry-install + $(POETRY_RUN) pyupgrade --py310-plus $(SRC_FILES) diff --git a/pykelrond/README.md b/pykelrond/README.md new file mode 100644 index 00000000..3b1575ed --- /dev/null +++ b/pykelrond/README.md @@ -0,0 +1,23 @@ +# pykelrond + + +## Installation + +Prerequsites: `python >= 3.10`, `pip >= 20.0.2`, `poetry >= 1.3.2`. + +```bash +make build +pip install dist/*.whl +``` + + +## For Developers + +Use `make` to run common tasks (see the [Makefile](Makefile) for a complete list of available targets). + +* `make build`: Build wheel +* `make check`: Check code style +* `make format`: Format code +* `make test-unit`: Run unit tests + +For interactive use, spawn a shell with `poetry shell` (after `poetry install`), then run an interpreter. diff --git a/pykelrond/flake.nix b/pykelrond/flake.nix new file mode 100644 index 00000000..db6b0786 --- /dev/null +++ b/pykelrond/flake.nix @@ -0,0 +1,41 @@ +{ + description = "pykelrond - Python tools for Elrond semantics"; + inputs = { + nixpkgs.url = "nixpkgs/nixos-22.05"; + flake-utils.url = "github:numtide/flake-utils"; + poetry2nix.url = "github:nix-community/poetry2nix"; + }; + outputs = { self, nixpkgs, flake-utils, poetry2nix }: + let + allOverlays = [ + poetry2nix.overlay + (final: prev: { + pykelrond = prev.poetry2nix.mkPoetryApplication { + python = prev.python310; + projectDir = ./.; + groups = []; + # We remove `dev` from `checkGroups`, so that poetry2nix does not try to resolve dev dependencies. + checkGroups = []; + }; + }) + ]; + in flake-utils.lib.eachSystem [ + "x86_64-linux" + "x86_64-darwin" + "aarch64-linux" + "aarch64-darwin" + ] (system: + let + pkgs = import nixpkgs { + inherit system; + overlays = allOverlays; + }; + in { + packages = rec { + inherit (pkgs) pykelrond; + default = pykelrond; + }; + }) // { + overlay = nixpkgs.lib.composeManyExtensions allOverlays; + }; +} diff --git a/pykelrond/poetry.lock b/pykelrond/poetry.lock new file mode 100644 index 00000000..58cb5065 --- /dev/null +++ b/pykelrond/poetry.lock @@ -0,0 +1,1153 @@ +# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand. + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "autoflake" +version = "2.2.0" +description = "Removes unused imports and unused variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "autoflake-2.2.0-py3-none-any.whl", hash = "sha256:de409b009a34c1c2a7cc2aae84c4c05047f9773594317c6a6968bd497600d4a0"}, + {file = "autoflake-2.2.0.tar.gz", hash = "sha256:62e1f74a0fdad898a96fee6f99fe8241af90ad99c7110c884b35855778412251"}, +] + +[package.dependencies] +pyflakes = ">=3.0.0" +tomli = {version = ">=2.0.1", markers = "python_version < \"3.11\""} + +[[package]] +name = "black" +version = "23.7.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, + {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, + {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, + {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, + {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, + {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, + {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, + {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, + {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, + {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, + {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, +] + +[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_version < \"3.11\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "classify-imports" +version = "4.2.0" +description = "Utilities for refactoring imports in python-like syntax." +optional = false +python-versions = ">=3.7" +files = [ + {file = "classify_imports-4.2.0-py2.py3-none-any.whl", hash = "sha256:dbbc264b70a470ed8c6c95976a11dfb8b7f63df44ed1af87328bbed2663f5161"}, + {file = "classify_imports-4.2.0.tar.gz", hash = "sha256:7abfb7ea92149b29d046bd34573d247ba6e68cc28100c801eba4af17964fc40e"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "cmd2" +version = "2.4.3" +description = "cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "cmd2-2.4.3-py3-none-any.whl", hash = "sha256:f1988ff2fff0ed812a2d25218a081b0fa0108d45b48ba2a9272bb98091b654e6"}, + {file = "cmd2-2.4.3.tar.gz", hash = "sha256:71873c11f72bd19e2b1db578214716f0d4f7c8fa250093c601265a9a717dee52"}, +] + +[package.dependencies] +attrs = ">=16.3.0" +pyperclip = ">=1.6" +pyreadline3 = {version = "*", markers = "sys_platform == \"win32\""} +wcwidth = ">=0.1.7" + +[package.extras] +dev = ["codecov", "doc8", "flake8", "invoke", "mypy", "nox", "pytest (>=4.6)", "pytest-cov", "pytest-mock", "sphinx", "sphinx-autobuild", "sphinx-rtd-theme", "twine (>=1.11)"] +test = ["codecov", "coverage", "gnureadline", "pytest (>=4.6)", "pytest-cov", "pytest-mock"] +validate = ["flake8", "mypy", "types-pkg-resources"] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "coloredlogs" +version = "15.0.1" +description = "Colored terminal output for Python's logging module" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "coloredlogs-15.0.1-py2.py3-none-any.whl", hash = "sha256:612ee75c546f53e92e70049c9dbfcc18c935a2b9a53b66085ce9ef6a6e5c0934"}, + {file = "coloredlogs-15.0.1.tar.gz", hash = "sha256:7c991aa71a4577af2f82600d8f8f3a89f936baeaf9b50a9c197da014e5bf16b0"}, +] + +[package.dependencies] +humanfriendly = ">=9.1" + +[package.extras] +cron = ["capturer (>=2.4)"] + +[[package]] +name = "coverage" +version = "7.3.0" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "coverage-7.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db76a1bcb51f02b2007adacbed4c88b6dee75342c37b05d1822815eed19edee5"}, + {file = "coverage-7.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c02cfa6c36144ab334d556989406837336c1d05215a9bdf44c0bc1d1ac1cb637"}, + {file = "coverage-7.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:477c9430ad5d1b80b07f3c12f7120eef40bfbf849e9e7859e53b9c93b922d2af"}, + {file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce2ee86ca75f9f96072295c5ebb4ef2a43cecf2870b0ca5e7a1cbdd929cf67e1"}, + {file = "coverage-7.3.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68d8a0426b49c053013e631c0cdc09b952d857efa8f68121746b339912d27a12"}, + {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b3eb0c93e2ea6445b2173da48cb548364f8f65bf68f3d090404080d338e3a689"}, + {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:90b6e2f0f66750c5a1178ffa9370dec6c508a8ca5265c42fbad3ccac210a7977"}, + {file = "coverage-7.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:96d7d761aea65b291a98c84e1250cd57b5b51726821a6f2f8df65db89363be51"}, + {file = "coverage-7.3.0-cp310-cp310-win32.whl", hash = "sha256:63c5b8ecbc3b3d5eb3a9d873dec60afc0cd5ff9d9f1c75981d8c31cfe4df8527"}, + {file = "coverage-7.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:97c44f4ee13bce914272589b6b41165bbb650e48fdb7bd5493a38bde8de730a1"}, + {file = "coverage-7.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:74c160285f2dfe0acf0f72d425f3e970b21b6de04157fc65adc9fd07ee44177f"}, + {file = "coverage-7.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b543302a3707245d454fc49b8ecd2c2d5982b50eb63f3535244fd79a4be0c99d"}, + {file = "coverage-7.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad0f87826c4ebd3ef484502e79b39614e9c03a5d1510cfb623f4a4a051edc6fd"}, + {file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:13c6cbbd5f31211d8fdb477f0f7b03438591bdd077054076eec362cf2207b4a7"}, + {file = "coverage-7.3.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fac440c43e9b479d1241fe9d768645e7ccec3fb65dc3a5f6e90675e75c3f3e3a"}, + {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3c9834d5e3df9d2aba0275c9f67989c590e05732439b3318fa37a725dff51e74"}, + {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4c8e31cf29b60859876474034a83f59a14381af50cbe8a9dbaadbf70adc4b214"}, + {file = "coverage-7.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7a9baf8e230f9621f8e1d00c580394a0aa328fdac0df2b3f8384387c44083c0f"}, + {file = "coverage-7.3.0-cp311-cp311-win32.whl", hash = "sha256:ccc51713b5581e12f93ccb9c5e39e8b5d4b16776d584c0f5e9e4e63381356482"}, + {file = "coverage-7.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:887665f00ea4e488501ba755a0e3c2cfd6278e846ada3185f42d391ef95e7e70"}, + {file = "coverage-7.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d000a739f9feed900381605a12a61f7aaced6beae832719ae0d15058a1e81c1b"}, + {file = "coverage-7.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:59777652e245bb1e300e620ce2bef0d341945842e4eb888c23a7f1d9e143c446"}, + {file = "coverage-7.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9737bc49a9255d78da085fa04f628a310c2332b187cd49b958b0e494c125071"}, + {file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5247bab12f84a1d608213b96b8af0cbb30d090d705b6663ad794c2f2a5e5b9fe"}, + {file = "coverage-7.3.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2ac9a1de294773b9fa77447ab7e529cf4fe3910f6a0832816e5f3d538cfea9a"}, + {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:85b7335c22455ec12444cec0d600533a238d6439d8d709d545158c1208483873"}, + {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:36ce5d43a072a036f287029a55b5c6a0e9bd73db58961a273b6dc11a2c6eb9c2"}, + {file = "coverage-7.3.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:211a4576e984f96d9fce61766ffaed0115d5dab1419e4f63d6992b480c2bd60b"}, + {file = "coverage-7.3.0-cp312-cp312-win32.whl", hash = "sha256:56afbf41fa4a7b27f6635bc4289050ac3ab7951b8a821bca46f5b024500e6321"}, + {file = "coverage-7.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:7f297e0c1ae55300ff688568b04ff26b01c13dfbf4c9d2b7d0cb688ac60df479"}, + {file = "coverage-7.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ac0dec90e7de0087d3d95fa0533e1d2d722dcc008bc7b60e1143402a04c117c1"}, + {file = "coverage-7.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:438856d3f8f1e27f8e79b5410ae56650732a0dcfa94e756df88c7e2d24851fcd"}, + {file = "coverage-7.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1084393c6bda8875c05e04fce5cfe1301a425f758eb012f010eab586f1f3905e"}, + {file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49ab200acf891e3dde19e5aa4b0f35d12d8b4bd805dc0be8792270c71bd56c54"}, + {file = "coverage-7.3.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a67e6bbe756ed458646e1ef2b0778591ed4d1fcd4b146fc3ba2feb1a7afd4254"}, + {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f39c49faf5344af36042b293ce05c0d9004270d811c7080610b3e713251c9b0"}, + {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7df91fb24c2edaabec4e0eee512ff3bc6ec20eb8dccac2e77001c1fe516c0c84"}, + {file = "coverage-7.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:34f9f0763d5fa3035a315b69b428fe9c34d4fc2f615262d6be3d3bf3882fb985"}, + {file = "coverage-7.3.0-cp38-cp38-win32.whl", hash = "sha256:bac329371d4c0d456e8d5f38a9b0816b446581b5f278474e416ea0c68c47dcd9"}, + {file = "coverage-7.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:b859128a093f135b556b4765658d5d2e758e1fae3e7cc2f8c10f26fe7005e543"}, + {file = "coverage-7.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fc0ed8d310afe013db1eedd37176d0839dc66c96bcfcce8f6607a73ffea2d6ba"}, + {file = "coverage-7.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61260ec93f99f2c2d93d264b564ba912bec502f679793c56f678ba5251f0393"}, + {file = "coverage-7.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97af9554a799bd7c58c0179cc8dbf14aa7ab50e1fd5fa73f90b9b7215874ba28"}, + {file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3558e5b574d62f9c46b76120a5c7c16c4612dc2644c3d48a9f4064a705eaee95"}, + {file = "coverage-7.3.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37d5576d35fcb765fca05654f66aa71e2808d4237d026e64ac8b397ffa66a56a"}, + {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:07ea61bcb179f8f05ffd804d2732b09d23a1238642bf7e51dad62082b5019b34"}, + {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:80501d1b2270d7e8daf1b64b895745c3e234289e00d5f0e30923e706f110334e"}, + {file = "coverage-7.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4eddd3153d02204f22aef0825409091a91bf2a20bce06fe0f638f5c19a85de54"}, + {file = "coverage-7.3.0-cp39-cp39-win32.whl", hash = "sha256:2d22172f938455c156e9af2612650f26cceea47dc86ca048fa4e0b2d21646ad3"}, + {file = "coverage-7.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:60f64e2007c9144375dd0f480a54d6070f00bb1a28f65c408370544091c9bc9e"}, + {file = "coverage-7.3.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:5492a6ce3bdb15c6ad66cb68a0244854d9917478877a25671d70378bdc8562d0"}, + {file = "coverage-7.3.0.tar.gz", hash = "sha256:49dbb19cdcafc130f597d9e04a29d0a032ceedf729e41b181f51cd170e6ee865"}, +] + +[package.dependencies] +tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""} + +[package.extras] +toml = ["tomli"] + +[[package]] +name = "cytoolz" +version = "0.12.2" +description = "Cython implementation of Toolz: High performance functional utilities" +optional = false +python-versions = ">=3.6" +files = [ + {file = "cytoolz-0.12.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4bff49986c9bae127928a2f9fd6313146a342bfae8292f63e562f872bd01b871"}, + {file = "cytoolz-0.12.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:908c13f305d34322e11b796de358edaeea47dd2d115c33ca22909c5e8fb036fd"}, + {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:735147aa41b8eeb104da186864b55e2a6623c758000081d19c93d759cd9523e3"}, + {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7d352d4de060604e605abdc5c8a5d0429d5f156cb9866609065d3003454d4cea"}, + {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:89247ac220031a4f9f689688bcee42b38fd770d4cce294e5d914afc53b630abe"}, + {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9070ae35c410d644e6df98a8f69f3ed2807e657d0df2a26b2643127cbf6944a5"}, + {file = "cytoolz-0.12.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:843500cd3e4884b92fd4037912bc42d5f047108d2c986d36352e880196d465b0"}, + {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6a93644d7996fd696ab7f1f466cd75d718d0a00d5c8118b9fe8c64231dc1f85e"}, + {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:96796594c770bc6587376e74ddc7d9c982d68f47116bb69d90873db5e0ea88b6"}, + {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:48425107fbb1af3f0f2410c004f16be10ffc9374358e5600b57fa543f46f8def"}, + {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:cde6dbb788a4cbc4a80a72aa96386ba4c2b17bdfff3ace0709799adbe16d6476"}, + {file = "cytoolz-0.12.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:68ae7091cc73a752f0b938f15bb193de80ca5edf5ae2ea6360d93d3e9228357b"}, + {file = "cytoolz-0.12.2-cp310-cp310-win32.whl", hash = "sha256:997b7e0960072f6bb445402da162f964ea67387b9f18bda2361edcc026e13597"}, + {file = "cytoolz-0.12.2-cp310-cp310-win_amd64.whl", hash = "sha256:663911786dcde3e4a5d88215c722c531c7548903dc07d418418c0d1c768072c0"}, + {file = "cytoolz-0.12.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4a7d8b869ded171f6cdf584fc2fc6ae03b30a0e1e37a9daf213a59857a62ed90"}, + {file = "cytoolz-0.12.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9b28787eaf2174e68f0acb3c66f9c6b98bdfeb0930c0d0b08e1941c7aedc8d27"}, + {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00547da587f124b32b072ce52dd5e4b37cf199fedcea902e33c67548523e4678"}, + {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:275d53fd769df2102d6c9fc98e553bd8a9a38926f54d6b20cf29f0dd00bf3b75"}, + {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5556acde785a61d4cf8b8534ae109b023cbd2f9df65ee2afbe070be47c410f8c"}, + {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b41a85b9b9a2530b72b0d3d10e383fc3c2647ae88169d557d5e216f881860318"}, + {file = "cytoolz-0.12.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673d6e9e3aa86949343b46ac2b7be266c36e07ce77fa1d40f349e6987a814d6e"}, + {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:81e6a9a8fda78a2f4901d2915b25bf620f372997ca1f20a14f7cefef5ad6f6f4"}, + {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fa44215bc31675a6380cd896dadb7f2054a7b94cfb87e53e52af844c65406a54"}, + {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:a08b4346350660799d81d4016e748bcb134a9083301d41f9618f64a6077f89f2"}, + {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2fb740482794a72e2e5fec58e4d9b00dcd5a60a8cef68431ff12f2ba0e0d9a7e"}, + {file = "cytoolz-0.12.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9007bb1290c79402be6b84bcf9e7a622a073859d61fcee146dc7bc47afe328f3"}, + {file = "cytoolz-0.12.2-cp311-cp311-win32.whl", hash = "sha256:a973f5286758f76824ecf19ae1999f6697371a9121c8f163295d181d19a819d7"}, + {file = "cytoolz-0.12.2-cp311-cp311-win_amd64.whl", hash = "sha256:1ce324d1b413636ea5ee929f79637821f13c9e55e9588f38228947294944d2ed"}, + {file = "cytoolz-0.12.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c08094b9e5d1b6dfb0845a0253cc2655ca64ce70d15162dfdb102e28c8993493"}, + {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baf020f4b708f800b353259cd7575e335a79f1ac912d9dda55b2aa0bf3616e42"}, + {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4416ee86a87180b6a28e7483102c92debc077bec59c67eda8cc63fc52a218ac0"}, + {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6ee222671eed5c5b16a5ad2aea07f0a715b8b199ee534834bc1dd2798f1ade7"}, + {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad92e37be0b106fdbc575a3a669b43b364a5ef334495c9764de4c2d7541f7a99"}, + {file = "cytoolz-0.12.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:460c05238fbfe6d848141669d17a751a46c923f9f0c9fd8a3a462ab737623a44"}, + {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9e5075e30be626ef0f9bedf7a15f55ed4d7209e832bc314fdc232dbd61dcbf44"}, + {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:03b58f843f09e73414e82e57f7e8d88f087eaabf8f276b866a40661161da6c51"}, + {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:5e4e612b7ecc9596e7c859cd9e0cd085e6d0c576b4f0d917299595eb56bf9c05"}, + {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:08a0e03f287e45eb694998bb55ac1643372199c659affa8319dfbbdec7f7fb3c"}, + {file = "cytoolz-0.12.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b029bdd5a8b6c9a7c0e8fdbe4fc25ffaa2e09b77f6f3462314696e3a20511829"}, + {file = "cytoolz-0.12.2-cp36-cp36m-win32.whl", hash = "sha256:18580d060fa637ff01541640ecde6de832a248df02b8fb57e6dd578f189d62c7"}, + {file = "cytoolz-0.12.2-cp36-cp36m-win_amd64.whl", hash = "sha256:97cf514a9f3426228d8daf880f56488330e4b2948a6d183a106921217850d9eb"}, + {file = "cytoolz-0.12.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:18a0f838677f9510aef0330c0096778dd6406d21d4ff9504bf79d85235a18460"}, + {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb081b2b02bf4405c804de1ece6f904916838ab0e057f1446e4ac12fac827960"}, + {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:57233e1600560ceb719bed759dc78393edd541b9a3e7fefc3079abd83c26a6ea"}, + {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0295289c4510efa41174850e75bc9188f82b72b1b54d0ea57d1781729c2924d5"}, + {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a92aab8dd1d427ac9bc7480cfd3481dbab0ef024558f2f5a47de672d8a5ffaa"}, + {file = "cytoolz-0.12.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:51d3495235af09f21aa92a7cdd51504bda640b108b6be834448b774f52852c09"}, + {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f9c690b359f503f18bf1c46a6456370e4f6f3fc4320b8774ae69c4f85ecc6c94"}, + {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:481e3129a76ea01adcc0e7097ccb8dbddab1cfc40b6f0e32c670153512957c0f"}, + {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:55e94124af9c8fbb1df54195cc092688fdad0765641b738970b6f1d5ea72e776"}, + {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5616d386dfbfba7c39e9418ba668c734f6ceaacc0130877e8a100cad11e6838b"}, + {file = "cytoolz-0.12.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:732d08228fa8d366fec284f7032cc868d28a99fa81fc71e3adf7ecedbcf33a0f"}, + {file = "cytoolz-0.12.2-cp37-cp37m-win32.whl", hash = "sha256:f039c5373f7b314b151432c73219216857b19ab9cb834f0eb5d880f74fc7851c"}, + {file = "cytoolz-0.12.2-cp37-cp37m-win_amd64.whl", hash = "sha256:246368e983eaee9851b15d7755f82030eab4aa82098d2a34f6bef9c689d33fcc"}, + {file = "cytoolz-0.12.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:81074edf3c74bc9bd250d223408a5df0ff745d1f7a462597536cd26b9390e2d6"}, + {file = "cytoolz-0.12.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:960d85ebaa974ecea4e71fa56d098378fa51fd670ee744614cbb95bf95e28fc7"}, + {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c8d0dff4865da54ae825d43e1721925721b19f3b9aca8e730c2ce73dee2c630"}, + {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0a9d12436fd64937bd2c9609605f527af7f1a8db6e6637639b44121c0fe715d6"}, + {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd461e402e24929d866f05061d2f8337e3a8456e75e21b72c125abff2477c7f7"}, + {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0568d4da0a9ee9f9f5ab318f6501557f1cfe26d18c96c8e0dac7332ae04c6717"}, + {file = "cytoolz-0.12.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:101b5bd32badfc8b1f9c7be04ba3ae04fb47f9c8736590666ce9449bff76e0b1"}, + {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8bb624dbaef4661f5e3625c1e39ad98ecceef281d1380e2774d8084ad0810275"}, + {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:3e993804e6b04113d61fdb9541b6df2f096ec265a506dad7437517470919c90f"}, + {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ab911033e5937fc221a2c165acce7f66ae5ac9d3e54bec56f3c9c197a96be574"}, + {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6de6a4bdfaee382c2de2a3580b3ae76fce6105da202bbd835e5efbeae6a9c6e"}, + {file = "cytoolz-0.12.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9480b4b327be83c4d29cb88bcace761b11f5e30198ffe2287889455c6819e934"}, + {file = "cytoolz-0.12.2-cp38-cp38-win32.whl", hash = "sha256:4180b2785d1278e6abb36a72ac97c92432db53fa2df00ee943d2c15a33627d31"}, + {file = "cytoolz-0.12.2-cp38-cp38-win_amd64.whl", hash = "sha256:d0086ba8d41d73647b13087a3ca9c020f6bfec338335037e8f5172b4c7c8dce5"}, + {file = "cytoolz-0.12.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d29988bde28a90a00367edcf92afa1a2f7ecf43ea3ae383291b7da6d380ccc25"}, + {file = "cytoolz-0.12.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:24c0d71e9ac91f4466b1bd280f7de43aa4d94682daaf34d85d867a9b479b87cc"}, + {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa436abd4ac9ca71859baf5794614e6ec8fa27362f0162baedcc059048da55f7"}, + {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45c7b4eac7571707269ebc2893facdf87e359cd5c7cfbfa9e6bd8b33fb1079c5"}, + {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:294d24edc747ef4e1b28e54365f713becb844e7898113fafbe3e9165dc44aeea"}, + {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:478051e5ef8278b2429864c8d148efcebdc2be948a61c9a44757cd8c816c98f5"}, + {file = "cytoolz-0.12.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14108cafb140dd68fdda610c2bbc6a37bf052cd48cfebf487ed44145f7a2b67f"}, + {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5fef7b602ccf8a3c77ab483479ccd7a952a8c5bb1c263156671ba7aaa24d1035"}, + {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9bf51354e15520715f068853e6ab8190e77139940e8b8b633bdb587956a08fb0"}, + {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:388f840fd911d61a96e9e595eaf003f9dc39e847c9060b8e623ab29e556f009b"}, + {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:a67f75cc51a2dc7229a8ac84291e4d61dc5abfc8940befcf37a2836d95873340"}, + {file = "cytoolz-0.12.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:63b31345e20afda2ae30dba246955517a4264464d75e071fc2fa641e88c763ec"}, + {file = "cytoolz-0.12.2-cp39-cp39-win32.whl", hash = "sha256:f6e86ac2b45a95f75c6f744147483e0fc9697ce7dfe1726083324c236f873f8b"}, + {file = "cytoolz-0.12.2-cp39-cp39-win_amd64.whl", hash = "sha256:5998f81bf6a2b28a802521efe14d9fc119f74b64e87b62ad1b0e7c3d8366d0c7"}, + {file = "cytoolz-0.12.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:593e89e2518eaf81e96edcc9ef2c5fca666e8fc922b03d5cb7a7b8964dbee336"}, + {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ff451d614ca1d4227db0ffa627fb51df71968cf0d9baf0210528dad10fdbc3ab"}, + {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad9ea4a50d2948738351790047d45f2b1a023facc01bf0361988109b177e8b2f"}, + {file = "cytoolz-0.12.2-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbe038bb78d599b5a29d09c438905defaa615a522bc7e12f8016823179439497"}, + {file = "cytoolz-0.12.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:d494befe648c13c98c0f3d56d05489c839c9228a32f58e9777305deb6c2c1cee"}, + {file = "cytoolz-0.12.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:c26805b6c8dc8565ed91045c44040bf6c0fe5cb5b390c78cd1d9400d08a6cd39"}, + {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df4e32badb2ccf1773e1e74020b7e3b8caf9e92f842c6be7d14888ecdefc2c6c"}, + {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce7889dc3701826d519ede93cdff11940fb5567dbdc165dce0e78047eece02b7"}, + {file = "cytoolz-0.12.2-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c820608e7077416f766b148d75e158e454881961881b657cff808529d261dd24"}, + {file = "cytoolz-0.12.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:698da4fa1f7baeea0607738cb1f9877ed1ba50342b29891b0223221679d6f729"}, + {file = "cytoolz-0.12.2.tar.gz", hash = "sha256:31d4b0455d72d914645f803d917daf4f314d115c70de0578d3820deb8b101f66"}, +] + +[package.dependencies] +toolz = ">=0.8.0" + +[package.extras] +cython = ["cython"] + +[[package]] +name = "exceptiongroup" +version = "1.1.3" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "execnet" +version = "2.0.2" +description = "execnet: rapid multi-Python deployment" +optional = false +python-versions = ">=3.7" +files = [ + {file = "execnet-2.0.2-py3-none-any.whl", hash = "sha256:88256416ae766bc9e8895c76a87928c0012183da3cc4fc18016e6f050e025f41"}, + {file = "execnet-2.0.2.tar.gz", hash = "sha256:cc59bc4423742fd71ad227122eb0dd44db51efb3dc4095b45ac9a08c770096af"}, +] + +[package.extras] +testing = ["hatch", "pre-commit", "pytest", "tox"] + +[[package]] +name = "filelock" +version = "3.12.2" +description = "A platform independent file lock." +optional = false +python-versions = ">=3.7" +files = [ + {file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"}, + {file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"}, +] + +[package.extras] +docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"] + +[[package]] +name = "flake8" +version = "6.1.0" +description = "the modular source code checker: pep8 pyflakes and co" +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "flake8-6.1.0-py2.py3-none-any.whl", hash = "sha256:ffdfce58ea94c6580c77888a86506937f9a1a227dfcd15f245d694ae20a6b6e5"}, + {file = "flake8-6.1.0.tar.gz", hash = "sha256:d5b3857f07c030bdb5bf41c7f53799571d75c4491748a3adcd47de929e34cd23"}, +] + +[package.dependencies] +mccabe = ">=0.7.0,<0.8.0" +pycodestyle = ">=2.11.0,<2.12.0" +pyflakes = ">=3.1.0,<3.2.0" + +[[package]] +name = "flake8-bugbear" +version = "23.7.10" +description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "flake8-bugbear-23.7.10.tar.gz", hash = "sha256:0ebdc7d8ec1ca8bd49347694562381f099f4de2f8ec6bda7a7dca65555d9e0d4"}, + {file = "flake8_bugbear-23.7.10-py3-none-any.whl", hash = "sha256:d99d005114020fbef47ed5e4aebafd22f167f9a0fbd0d8bf3c9e90612cb25c34"}, +] + +[package.dependencies] +attrs = ">=19.2.0" +flake8 = ">=6.0.0" + +[package.extras] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "pytest", "tox"] + +[[package]] +name = "flake8-comprehensions" +version = "3.14.0" +description = "A flake8 plugin to help you write better list/set/dict comprehensions." +optional = false +python-versions = ">=3.8" +files = [ + {file = "flake8_comprehensions-3.14.0-py3-none-any.whl", hash = "sha256:7b9d07d94aa88e62099a6d1931ddf16c344d4157deedf90fe0d8ee2846f30e97"}, + {file = "flake8_comprehensions-3.14.0.tar.gz", hash = "sha256:81768c61bfc064e1a06222df08a2580d97de10cb388694becaf987c331c6c0cf"}, +] + +[package.dependencies] +flake8 = ">=3.0,<3.2.0 || >3.2.0" + +[[package]] +name = "flake8-quotes" +version = "3.3.2" +description = "Flake8 lint for quotes." +optional = false +python-versions = "*" +files = [ + {file = "flake8-quotes-3.3.2.tar.gz", hash = "sha256:6e26892b632dacba517bf27219c459a8396dcfac0f5e8204904c5a4ba9b480e1"}, +] + +[package.dependencies] +flake8 = "*" + +[[package]] +name = "flake8-type-checking" +version = "2.4.1" +description = "A flake8 plugin for managing type-checking imports & forward references" +optional = false +python-versions = ">=3.8" +files = [ + {file = "flake8_type_checking-2.4.1-py3-none-any.whl", hash = "sha256:fe75cfe668e3bf6914dd2ba36579bbe6c82f3795127774e7584ecc8c9f7379e5"}, + {file = "flake8_type_checking-2.4.1.tar.gz", hash = "sha256:f3c7023114dee2ec2e8282a9080206ffd8fdd61205626593aa5c801bc2f8035d"}, +] + +[package.dependencies] +classify-imports = "*" +flake8 = "*" + +[[package]] +name = "graphviz" +version = "0.20.1" +description = "Simple Python interface for Graphviz" +optional = false +python-versions = ">=3.7" +files = [ + {file = "graphviz-0.20.1-py3-none-any.whl", hash = "sha256:587c58a223b51611c0cf461132da386edd896a029524ca61a1462b880bf97977"}, + {file = "graphviz-0.20.1.zip", hash = "sha256:8c58f14adaa3b947daf26c19bc1e98c4e0702cdc31cf99153e6f06904d492bf8"}, +] + +[package.extras] +dev = ["flake8", "pep8-naming", "tox (>=3)", "twine", "wheel"] +docs = ["sphinx (>=5)", "sphinx-autodoc-typehints", "sphinx-rtd-theme"] +test = ["coverage", "mock (>=4)", "pytest (>=7)", "pytest-cov", "pytest-mock (>=3)"] + +[[package]] +name = "humanfriendly" +version = "10.0" +description = "Human friendly output for text interfaces using Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "humanfriendly-10.0-py2.py3-none-any.whl", hash = "sha256:1697e1a8a8f550fd43c2865cd84542fc175a61dcb779b6fee18cf6b6ccba1477"}, + {file = "humanfriendly-10.0.tar.gz", hash = "sha256:6b0b831ce8f15f7300721aa49829fc4e83921a9a301cc7f606be6686a2288ddc"}, +] + +[package.dependencies] +pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "isort" +version = "5.12.0" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"}, + {file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"}, +] + +[package.extras] +colors = ["colorama (>=0.4.3)"] +pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"] +plugins = ["setuptools"] +requirements-deprecated-finder = ["pip-api", "pipreqs"] + +[[package]] +name = "linkify-it-py" +version = "2.0.2" +description = "Links recognition library with FULL unicode support." +optional = false +python-versions = ">=3.7" +files = [ + {file = "linkify-it-py-2.0.2.tar.gz", hash = "sha256:19f3060727842c254c808e99d465c80c49d2c7306788140987a1a7a29b0d6ad2"}, + {file = "linkify_it_py-2.0.2-py3-none-any.whl", hash = "sha256:a3a24428f6c96f27370d7fe61d2ac0be09017be5190d68d8658233171f1b6541"}, +] + +[package.dependencies] +uc-micro-py = "*" + +[package.extras] +benchmark = ["pytest", "pytest-benchmark"] +dev = ["black", "flake8", "isort", "pre-commit", "pyproject-flake8"] +doc = ["myst-parser", "sphinx", "sphinx-book-theme"] +test = ["coverage", "pytest", "pytest-cov"] + +[[package]] +name = "markdown-it-py" +version = "2.2.0" +description = "Python port of markdown-it. Markdown parsing, done right!" +optional = false +python-versions = ">=3.7" +files = [ + {file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"}, + {file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"}, +] + +[package.dependencies] +linkify-it-py = {version = ">=1,<3", optional = true, markers = "extra == \"linkify\""} +mdit-py-plugins = {version = "*", optional = true, markers = "extra == \"plugins\""} +mdurl = ">=0.1,<1.0" + +[package.extras] +benchmarking = ["psutil", "pytest", "pytest-benchmark"] +code-style = ["pre-commit (>=3.0,<4.0)"] +compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"] +linkify = ["linkify-it-py (>=1,<3)"] +plugins = ["mdit-py-plugins"] +profiling = ["gprof2dot"] +rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mdit-py-plugins" +version = "0.4.0" +description = "Collection of plugins for markdown-it-py" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mdit_py_plugins-0.4.0-py3-none-any.whl", hash = "sha256:b51b3bb70691f57f974e257e367107857a93b36f322a9e6d44ca5bf28ec2def9"}, + {file = "mdit_py_plugins-0.4.0.tar.gz", hash = "sha256:d8ab27e9aed6c38aa716819fedfde15ca275715955f8a185a8e1cf90fb1d2c1b"}, +] + +[package.dependencies] +markdown-it-py = ">=1.0.0,<4.0.0" + +[package.extras] +code-style = ["pre-commit"] +rtd = ["myst-parser", "sphinx-book-theme"] +testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"] + +[[package]] +name = "mdurl" +version = "0.1.2" +description = "Markdown URL utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"}, + {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, +] + +[[package]] +name = "mypy" +version = "1.0.1" +description = "Optional static typing for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "mypy-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:71a808334d3f41ef011faa5a5cd8153606df5fc0b56de5b2e89566c8093a0c9a"}, + {file = "mypy-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:920169f0184215eef19294fa86ea49ffd4635dedfdea2b57e45cb4ee85d5ccaf"}, + {file = "mypy-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27a0f74a298769d9fdc8498fcb4f2beb86f0564bcdb1a37b58cbbe78e55cf8c0"}, + {file = "mypy-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:65b122a993d9c81ea0bfde7689b3365318a88bde952e4dfa1b3a8b4ac05d168b"}, + {file = "mypy-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:5deb252fd42a77add936b463033a59b8e48eb2eaec2976d76b6878d031933fe4"}, + {file = "mypy-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2013226d17f20468f34feddd6aae4635a55f79626549099354ce641bc7d40262"}, + {file = "mypy-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:48525aec92b47baed9b3380371ab8ab6e63a5aab317347dfe9e55e02aaad22e8"}, + {file = "mypy-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c96b8a0c019fe29040d520d9257d8c8f122a7343a8307bf8d6d4a43f5c5bfcc8"}, + {file = "mypy-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:448de661536d270ce04f2d7dddaa49b2fdba6e3bd8a83212164d4174ff43aa65"}, + {file = "mypy-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:d42a98e76070a365a1d1c220fcac8aa4ada12ae0db679cb4d910fabefc88b994"}, + {file = "mypy-1.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e64f48c6176e243ad015e995de05af7f22bbe370dbb5b32bd6988438ec873919"}, + {file = "mypy-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fdd63e4f50e3538617887e9aee91855368d9fc1dea30da743837b0df7373bc4"}, + {file = "mypy-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dbeb24514c4acbc78d205f85dd0e800f34062efcc1f4a4857c57e4b4b8712bff"}, + {file = "mypy-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:a2948c40a7dd46c1c33765718936669dc1f628f134013b02ff5ac6c7ef6942bf"}, + {file = "mypy-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bc8d6bd3b274dd3846597855d96d38d947aedba18776aa998a8d46fabdaed76"}, + {file = "mypy-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:17455cda53eeee0a4adb6371a21dd3dbf465897de82843751cf822605d152c8c"}, + {file = "mypy-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e831662208055b006eef68392a768ff83596035ffd6d846786578ba1714ba8f6"}, + {file = "mypy-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e60d0b09f62ae97a94605c3f73fd952395286cf3e3b9e7b97f60b01ddfbbda88"}, + {file = "mypy-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:0af4f0e20706aadf4e6f8f8dc5ab739089146b83fd53cb4a7e0e850ef3de0bb6"}, + {file = "mypy-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:24189f23dc66f83b839bd1cce2dfc356020dfc9a8bae03978477b15be61b062e"}, + {file = "mypy-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:93a85495fb13dc484251b4c1fd7a5ac370cd0d812bbfc3b39c1bafefe95275d5"}, + {file = "mypy-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5f546ac34093c6ce33f6278f7c88f0f147a4849386d3bf3ae193702f4fe31407"}, + {file = "mypy-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c6c2ccb7af7154673c591189c3687b013122c5a891bb5651eca3db8e6c6c55bd"}, + {file = "mypy-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:15b5a824b58c7c822c51bc66308e759243c32631896743f030daf449fe3677f3"}, + {file = "mypy-1.0.1-py3-none-any.whl", hash = "sha256:eda5c8b9949ed411ff752b9a01adda31afe7eae1e53e946dbdf9db23865e66c4"}, + {file = "mypy-1.0.1.tar.gz", hash = "sha256:28cea5a6392bb43d266782983b5a4216c25544cd7d80be681a155ddcdafd152d"}, +] + +[package.dependencies] +mypy-extensions = ">=0.4.3" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = ">=3.10" + +[package.extras] +dmypy = ["psutil (>=4.0)"] +install-types = ["pip"] +python2 = ["typed-ast (>=1.4.0,<2)"] +reports = ["lxml"] + +[[package]] +name = "mypy-extensions" +version = "0.4.4" +description = "Experimental type system extensions for programs checked with the mypy typechecker." +optional = false +python-versions = ">=2.7" +files = [ + {file = "mypy_extensions-0.4.4.tar.gz", hash = "sha256:c8b707883a96efe9b4bb3aaf0dcc07e7e217d7d8368eec4db4049ee9e142f4fd"}, +] + +[[package]] +name = "numpy" +version = "1.25.2" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"}, + {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"}, + {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"}, + {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"}, + {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"}, + {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"}, + {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"}, + {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"}, + {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"}, + {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"}, + {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, +] + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "pep8-naming" +version = "0.13.3" +description = "Check PEP-8 naming conventions, plugin for flake8" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pep8-naming-0.13.3.tar.gz", hash = "sha256:1705f046dfcd851378aac3be1cd1551c7c1e5ff363bacad707d43007877fa971"}, + {file = "pep8_naming-0.13.3-py3-none-any.whl", hash = "sha256:1a86b8c71a03337c97181917e2b472f0f5e4ccb06844a0d6f0a33522549e7a80"}, +] + +[package.dependencies] +flake8 = ">=5.0.0" + +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "pluggy" +version = "1.2.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pluggy-1.2.0-py3-none-any.whl", hash = "sha256:c2fd55a7d7a3863cba1a013e4e2414658b1d07b6bc57b3919e0c63c9abb99849"}, + {file = "pluggy-1.2.0.tar.gz", hash = "sha256:d12f0c4b579b15f5e054301bb226ee85eeeba08ffec228092f8defbaa3a4c4b3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "psutil" +version = "5.9.5" +description = "Cross-platform lib for process and system monitoring in Python." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"}, + {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"}, + {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"}, + {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"}, + {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"}, + {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"}, + {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"}, + {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"}, + {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"}, + {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"}, + {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"}, +] + +[package.extras] +test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] + +[[package]] +name = "py-wasm" +version = "0.1.0-alpha.0" +description = "" +optional = false +python-versions = ">=3.5, <4" +files = [ + {file = "0.1.0-alpha.0.tar.gz", hash = "sha256:758fb1ab880365bc4d0fcca9290ed7ca5226de8bc6df194d434e9a6a43a9a75a"}, +] + +[package.dependencies] +cytoolz = {version = ">=0.9.0,<1.0.0", markers = "implementation_name == \"cpython\""} +mypy_extensions = ">=0.4.1,<1.0.0" +numpy = ">=1.16.0,<2" +toolz = {version = ">0.9.0,<1", markers = "implementation_name == \"pypy\""} + +[package.extras] +dev = ["bumpversion (>=0.5.3,<1)", "ipython", "pytest-watch (>=4.1.0,<5)", "twine", "wheel"] +doc = ["Sphinx (>=1.6.5,<2)", "sphinx_rtd_theme (>=0.1.9)"] +lint = ["flake8 (==3.6.0)", "isort (>=4.3.9,<5)", "mypy (==0.660)"] +test = ["hypothesis (>=3.88.3,<4)", "pytest (==4.1.0)", "pytest-watch (==4.2.0)", "pytest-xdist", "tox (>=2.9.1,<3)"] + +[package.source] +type = "url" +url = "https://github.com/runtimeverification/py-wasm/archive/refs/tags/0.1.0-alpha.0.tar.gz" + +[[package]] +name = "pybind11" +version = "2.11.1" +description = "Seamless operability between C++11 and Python" +optional = false +python-versions = ">=3.6" +files = [ + {file = "pybind11-2.11.1-py3-none-any.whl", hash = "sha256:33cdd02a6453380dd71cc70357ce388ad1ee8d32bd0e38fc22b273d050aa29b3"}, + {file = "pybind11-2.11.1.tar.gz", hash = "sha256:00cd59116a6e8155aecd9174f37ba299d1d397ed4a6b86ac1dfe01b3e40f2cc4"}, +] + +[package.extras] +global = ["pybind11-global (==2.11.1)"] + +[[package]] +name = "pycodestyle" +version = "2.11.0" +description = "Python style guide checker" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pycodestyle-2.11.0-py2.py3-none-any.whl", hash = "sha256:5d1013ba8dc7895b548be5afb05740ca82454fd899971563d2ef625d090326f8"}, + {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, +] + +[[package]] +name = "pyflakes" +version = "3.1.0" +description = "passive checker of Python programs" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pyflakes-3.1.0-py2.py3-none-any.whl", hash = "sha256:4132f6d49cb4dae6819e5379898f2b8cce3c5f23994194c24b77d5da2e36f774"}, + {file = "pyflakes-3.1.0.tar.gz", hash = "sha256:a0aae034c444db0071aa077972ba4768d40c830d9539fd45bf4cd3f8f6992efc"}, +] + +[[package]] +name = "pygments" +version = "2.16.1" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Pygments-2.16.1-py3-none-any.whl", hash = "sha256:13fc09fa63bc8d8671a6d247e1eb303c4b343eaee81d861f3404db2935653692"}, + {file = "Pygments-2.16.1.tar.gz", hash = "sha256:1daff0494820c69bc8941e407aa20f577374ee88364ee10a98fdbe0aece96e29"}, +] + +[package.extras] +plugins = ["importlib-metadata"] + +[[package]] +name = "pyk" +version = "0.1.398" +description = "" +optional = false +python-versions = "^3.10" +files = [] +develop = false + +[package.dependencies] +cmd2 = "^2.4.2" +coloredlogs = "^15.0.1" +filelock = "^3.9.0" +graphviz = "^0.20.1" +psutil = "^5.9.4" +pybind11 = "^2.10.3" +textual = "^0.27.0" +tomli = "^2.0.1" + +[package.source] +type = "git" +url = "https://github.com/runtimeverification/pyk.git" +reference = "v0.1.398" +resolved_reference = "ce44c2336bfe1ca1d3b94b0f8c003bf16c8d4699" + +[[package]] +name = "pykwasm" +version = "0.1.0" +description = "" +optional = false +python-versions = "^3.10" +files = [] +develop = false + +[package.dependencies] +cytoolz = "^0.12.1" +numpy = "^1.24.2" +py-wasm = {url = "https://github.com/runtimeverification/py-wasm/archive/refs/tags/0.1.0-alpha.0.tar.gz"} +pyk = {git = "https://github.com/runtimeverification/pyk.git", tag = "v0.1.398"} + +[package.source] +type = "directory" +url = "../deps/wasm-semantics/pykwasm" + +[[package]] +name = "pyperclip" +version = "1.8.2" +description = "A cross-platform clipboard module for Python. (Only handles plain text for now.)" +optional = false +python-versions = "*" +files = [ + {file = "pyperclip-1.8.2.tar.gz", hash = "sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57"}, +] + +[[package]] +name = "pyreadline3" +version = "3.4.1" +description = "A python implementation of GNU readline." +optional = false +python-versions = "*" +files = [ + {file = "pyreadline3-3.4.1-py3-none-any.whl", hash = "sha256:b0efb6516fd4fb07b45949053826a62fa4cb353db5be2bbb4a7aa1fdd1e345fb"}, + {file = "pyreadline3-3.4.1.tar.gz", hash = "sha256:6f3d1f7b8a31ba32b73917cefc1f28cc660562f39aea8646d30bd6eff21f7bae"}, +] + +[[package]] +name = "pytest" +version = "7.4.0" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-7.4.0-py3-none-any.whl", hash = "sha256:78bf16451a2eb8c7a2ea98e32dc119fd2aa758f1d5d66dbf0a59d69a3969df32"}, + {file = "pytest-7.4.0.tar.gz", hash = "sha256:b4bf8c45bd59934ed84001ad51e11b4ee40d40a1229d2c79f9c592b0a3f6bd8a"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=0.12,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "4.1.0" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"}, + {file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"}, +] + +[package.dependencies] +coverage = {version = ">=5.2.1", extras = ["toml"]} +pytest = ">=4.6" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] + +[[package]] +name = "pytest-mock" +version = "3.11.1" +description = "Thin-wrapper around the mock package for easier use with pytest" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-mock-3.11.1.tar.gz", hash = "sha256:7f6b125602ac6d743e523ae0bfa71e1a697a2f5534064528c6ff84c2f7c2fc7f"}, + {file = "pytest_mock-3.11.1-py3-none-any.whl", hash = "sha256:21c279fff83d70763b05f8874cc9cfb3fcacd6d354247a976f9529d19f9acf39"}, +] + +[package.dependencies] +pytest = ">=5.0" + +[package.extras] +dev = ["pre-commit", "pytest-asyncio", "tox"] + +[[package]] +name = "pytest-xdist" +version = "3.3.1" +description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pytest-xdist-3.3.1.tar.gz", hash = "sha256:d5ee0520eb1b7bcca50a60a518ab7a7707992812c578198f8b44fdfac78e8c93"}, + {file = "pytest_xdist-3.3.1-py3-none-any.whl", hash = "sha256:ff9daa7793569e6a68544850fd3927cd257cc03a7ef76c95e86915355e82b5f2"}, +] + +[package.dependencies] +execnet = ">=1.1" +pytest = ">=6.2.0" + +[package.extras] +psutil = ["psutil (>=3.0)"] +setproctitle = ["setproctitle"] +testing = ["filelock"] + +[[package]] +name = "pyupgrade" +version = "3.10.1" +description = "A tool to automatically upgrade syntax for newer versions." +optional = false +python-versions = ">=3.8.1" +files = [ + {file = "pyupgrade-3.10.1-py2.py3-none-any.whl", hash = "sha256:f565b4d26daa46ed522e98746834e77e444269103f8bc04413d77dad95169a24"}, + {file = "pyupgrade-3.10.1.tar.gz", hash = "sha256:1d8d138c2ccdd3c42b1419230ae036d5607dc69465a26feacc069642fc8d1b90"}, +] + +[package.dependencies] +tokenize-rt = ">=5.2.0" + +[[package]] +name = "rich" +version = "13.5.2" +description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal" +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "rich-13.5.2-py3-none-any.whl", hash = "sha256:146a90b3b6b47cac4a73c12866a499e9817426423f57c5a66949c086191a8808"}, + {file = "rich-13.5.2.tar.gz", hash = "sha256:fb9d6c0a0f643c99eed3875b5377a184132ba9be4d61516a55273d3554d75a39"}, +] + +[package.dependencies] +markdown-it-py = ">=2.2.0" +pygments = ">=2.13.0,<3.0.0" + +[package.extras] +jupyter = ["ipywidgets (>=7.5.1,<9)"] + +[[package]] +name = "textual" +version = "0.27.0" +description = "Modern Text User Interface framework" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "textual-0.27.0-py3-none-any.whl", hash = "sha256:dc45eaf7da330686c56d6f76f59d05fd216ce6aad90fa44ee269881efc622151"}, + {file = "textual-0.27.0.tar.gz", hash = "sha256:8bdcb09dc35a706ef939b1276ccfdec10eaaee6147b41cb7587cf33298a8dd33"}, +] + +[package.dependencies] +importlib-metadata = ">=4.11.3" +markdown-it-py = {version = ">=2.1.0,<3.0.0", extras = ["linkify", "plugins"]} +rich = ">=13.3.3" +typing-extensions = ">=4.4.0,<5.0.0" + +[package.extras] +dev = ["aiohttp (>=3.8.1)", "click (>=8.1.2)", "msgpack (>=1.0.3)"] + +[[package]] +name = "tokenize-rt" +version = "5.2.0" +description = "A wrapper around the stdlib `tokenize` which roundtrips." +optional = false +python-versions = ">=3.8" +files = [ + {file = "tokenize_rt-5.2.0-py2.py3-none-any.whl", hash = "sha256:b79d41a65cfec71285433511b50271b05da3584a1da144a0752e9c621a285289"}, + {file = "tokenize_rt-5.2.0.tar.gz", hash = "sha256:9fe80f8a5c1edad2d3ede0f37481cc0cc1538a2f442c9c2f9e4feacd2792d054"}, +] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "toolz" +version = "0.12.0" +description = "List processing tools and functional utilities" +optional = false +python-versions = ">=3.5" +files = [ + {file = "toolz-0.12.0-py3-none-any.whl", hash = "sha256:2059bd4148deb1884bb0eb770a3cde70e7f954cfbbdc2285f1f2de01fd21eb6f"}, + {file = "toolz-0.12.0.tar.gz", hash = "sha256:88c570861c440ee3f2f6037c4654613228ff40c93a6c25e0eba70d17282c6194"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "uc-micro-py" +version = "1.0.2" +description = "Micro subset of unicode data files for linkify-it-py projects." +optional = false +python-versions = ">=3.7" +files = [ + {file = "uc-micro-py-1.0.2.tar.gz", hash = "sha256:30ae2ac9c49f39ac6dce743bd187fcd2b574b16ca095fa74cd9396795c954c54"}, + {file = "uc_micro_py-1.0.2-py3-none-any.whl", hash = "sha256:8c9110c309db9d9e87302e2f4ad2c3152770930d88ab385cd544e7a7e75f3de0"}, +] + +[package.extras] +test = ["coverage", "pytest", "pytest-cov"] + +[[package]] +name = "wcwidth" +version = "0.2.6" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +files = [ + {file = "wcwidth-0.2.6-py2.py3-none-any.whl", hash = "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e"}, + {file = "wcwidth-0.2.6.tar.gz", hash = "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0"}, +] + +[[package]] +name = "zipp" +version = "3.16.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "5c5761506ddd7c3f9d75fd65f5ea5c6366a00fe4ef743a025202ad0bd389f721" diff --git a/pykelrond/pyproject.toml b/pykelrond/pyproject.toml new file mode 100644 index 00000000..01799aea --- /dev/null +++ b/pykelrond/pyproject.toml @@ -0,0 +1,51 @@ +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry] +name = "pykelrond" +version = "0.1.0" +description = "Python tools for Elrond semantics" +authors = [ + "Runtime Verification, Inc. ", +] + +[tool.poetry.dependencies] +python = "^3.10" +pykwasm = {path = "../deps/wasm-semantics/pykwasm"} + +[tool.poetry.group.dev.dependencies] +autoflake = "*" +black = "*" +flake8 = "*" +flake8-bugbear = "*" +flake8-comprehensions = "*" +flake8-quotes = "*" +flake8-type-checking = "*" +isort = "*" +mypy = "*" +pep8-naming = "*" +pytest = "*" +pytest-cov = "*" +pytest-mock = "*" +pytest-xdist = "*" +pyupgrade = "*" + +[tool.isort] +profile = "black" +line_length = 120 + +[tool.autoflake] +recursive = true +expand-star-imports = true +remove-all-unused-imports = true +ignore-init-module-imports = true +remove-duplicate-keys = true +remove-unused-variables = true + +[tool.black] +line-length = 120 +skip-string-normalization = true + +[tool.mypy] +disallow_untyped_defs = true diff --git a/pykelrond/src/pykelrond/__init__.py b/pykelrond/src/pykelrond/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pykelrond/src/pykelrond/hello.py b/pykelrond/src/pykelrond/hello.py new file mode 100644 index 00000000..6cab2ee4 --- /dev/null +++ b/pykelrond/src/pykelrond/hello.py @@ -0,0 +1,2 @@ +def hello(name: str) -> str: + return f'Hello, {name}!' diff --git a/pykelrond/src/pykelrond/py.typed b/pykelrond/src/pykelrond/py.typed new file mode 100644 index 00000000..e69de29b diff --git a/pykelrond/src/tests/__init__.py b/pykelrond/src/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pykelrond/src/tests/integration/__init__.py b/pykelrond/src/tests/integration/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pykelrond/src/tests/integration/test_integration.py b/pykelrond/src/tests/integration/test_integration.py new file mode 100644 index 00000000..a46ab9cc --- /dev/null +++ b/pykelrond/src/tests/integration/test_integration.py @@ -0,0 +1,5 @@ +from pykelrond.hello import hello + + +def test_hello() -> None: + assert hello('World') == 'Hello, World!' diff --git a/pykelrond/src/tests/unit/__init__.py b/pykelrond/src/tests/unit/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pykelrond/src/tests/unit/test_unit.py b/pykelrond/src/tests/unit/test_unit.py new file mode 100644 index 00000000..a46ab9cc --- /dev/null +++ b/pykelrond/src/tests/unit/test_unit.py @@ -0,0 +1,5 @@ +from pykelrond.hello import hello + + +def test_hello() -> None: + assert hello('World') == 'Hello, World!' From f00a5d93ecf1591c0c8a1bbfd87eba1807da2a8f Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 23 Aug 2023 02:09:06 +0300 Subject: [PATCH 03/16] move python files to pykelrond --- pykelrond/poetry.lock | 86 +++- pykelrond/pyproject.toml | 6 + .../src/pykelrond/foundry.py | 128 +++-- pykelrond/src/pykelrond/hello.py | 2 - .../src/pykelrond/scenario.py | 480 ++++++++++-------- .../src/tests/integration/test_integration.py | 5 - pykelrond/src/tests/unit/test_unit.py | 5 - 7 files changed, 430 insertions(+), 282 deletions(-) rename run_foundry.py => pykelrond/src/pykelrond/foundry.py (83%) delete mode 100644 pykelrond/src/pykelrond/hello.py rename run_elrond_tests.py => pykelrond/src/pykelrond/scenario.py (66%) delete mode 100644 pykelrond/src/tests/integration/test_integration.py delete mode 100644 pykelrond/src/tests/unit/test_unit.py diff --git a/pykelrond/poetry.lock b/pykelrond/poetry.lock index 58cb5065..23be2cb9 100644 --- a/pykelrond/poetry.lock +++ b/pykelrond/poetry.lock @@ -477,6 +477,38 @@ files = [ [package.dependencies] pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_version >= \"3.8\""} +[[package]] +name = "hypothesis" +version = "6.82.6" +description = "A library for property-based testing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "hypothesis-6.82.6-py3-none-any.whl", hash = "sha256:e99c445140e43f1cceda07b569f2f2d920d95435c6b0e6b507b35b01bb025e9d"}, + {file = "hypothesis-6.82.6.tar.gz", hash = "sha256:f52ac4180a16208224e3d648fbf0fef8b9ca24863ba4b41bfef30a78c42646bd"}, +] + +[package.dependencies] +attrs = ">=19.2.0" +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)", "lark (>=0.10.1)", "libcst (>=0.3.16)", "numpy (>=1.17.3)", "pandas (>=1.1)", "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)"] +django = ["django (>=3.2)"] +dpcontracts = ["dpcontracts (>=0.4)"] +ghostwriter = ["black (>=19.10b0)"] +lark = ["lark (>=0.10.1)"] +numpy = ["numpy (>=1.17.3)"] +pandas = ["pandas (>=1.1)"] +pytest = ["pytest (>=4.6)"] +pytz = ["pytz (>=2014.1)"] +redis = ["redis (>=3.0.0)"] +zoneinfo = ["backports.zoneinfo (>=0.2.1)", "tzdata (>=2023.3)"] + [[package]] name = "importlib-metadata" version = "6.8.0" @@ -844,6 +876,47 @@ files = [ {file = "pycodestyle-2.11.0.tar.gz", hash = "sha256:259bcc17857d8a8b3b4a2327324b79e5f020a13c16074670f9c8c8f872ea76d0"}, ] +[[package]] +name = "pycryptodomex" +version = "3.18.0" +description = "Cryptographic library for Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "pycryptodomex-3.18.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:160a39a708c36fa0b168ab79386dede588e62aec06eb505add870739329aecc6"}, + {file = "pycryptodomex-3.18.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:c2953afebf282a444c51bf4effe751706b4d0d63d7ca2cc51db21f902aa5b84e"}, + {file = "pycryptodomex-3.18.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:ba95abd563b0d1b88401658665a260852a8e6c647026ee6a0a65589287681df8"}, + {file = "pycryptodomex-3.18.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:192306cf881fe3467dda0e174a4f47bb3a8bb24b90c9cdfbdc248eec5fc0578c"}, + {file = "pycryptodomex-3.18.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:f9ab5ef0718f6a8716695dea16d83b671b22c45e9c0c78fd807c32c0192e54b5"}, + {file = "pycryptodomex-3.18.0-cp27-cp27m-win32.whl", hash = "sha256:50308fcdbf8345e5ec224a5502b4215178bdb5e95456ead8ab1a69ffd94779cb"}, + {file = "pycryptodomex-3.18.0-cp27-cp27m-win_amd64.whl", hash = "sha256:4d9379c684efea80fdab02a3eb0169372bca7db13f9332cb67483b8dc8b67c37"}, + {file = "pycryptodomex-3.18.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:5594a125dae30d60e94f37797fc67ce3c744522de7992c7c360d02fdb34918f8"}, + {file = "pycryptodomex-3.18.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:8ff129a5a0eb5ff16e45ca4fa70a6051da7f3de303c33b259063c19be0c43d35"}, + {file = "pycryptodomex-3.18.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:3d9314ac785a5b75d5aaf924c5f21d6ca7e8df442e5cf4f0fefad4f6e284d422"}, + {file = "pycryptodomex-3.18.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:f237278836dda412a325e9340ba2e6a84cb0f56b9244781e5b61f10b3905de88"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-macosx_10_9_universal2.whl", hash = "sha256:ac614363a86cc53d8ba44b6c469831d1555947e69ab3276ae8d6edc219f570f7"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:302a8f37c224e7b5d72017d462a2be058e28f7be627bdd854066e16722d0fc0c"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:6421d23d6a648e83ba2670a352bcd978542dad86829209f59d17a3f087f4afef"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84e105787f5e5d36ec6a581ff37a1048d12e638688074b2a00bcf402f9aa1c2"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6875eb8666f68ddbd39097867325bd22771f595b4e2b0149739b5623c8bf899b"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:27072a494ce621cc7a9096bbf60ed66826bb94db24b49b7359509e7951033e74"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-musllinux_1_1_i686.whl", hash = "sha256:1949e09ea49b09c36d11a951b16ff2a05a0ffe969dda1846e4686ee342fe8646"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6ed3606832987018615f68e8ed716a7065c09a0fe94afd7c9ca1b6777f0ac6eb"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-win32.whl", hash = "sha256:d56c9ec41258fd3734db9f5e4d2faeabe48644ba9ca23b18e1839b3bdf093222"}, + {file = "pycryptodomex-3.18.0-cp35-abi3-win_amd64.whl", hash = "sha256:e00a4bacb83a2627e8210cb353a2e31f04befc1155db2976e5e239dd66482278"}, + {file = "pycryptodomex-3.18.0-pp27-pypy_73-manylinux2010_x86_64.whl", hash = "sha256:2dc4eab20f4f04a2d00220fdc9258717b82d31913552e766d5f00282c031b70a"}, + {file = "pycryptodomex-3.18.0-pp27-pypy_73-win32.whl", hash = "sha256:75672205148bdea34669173366df005dbd52be05115e919551ee97171083423d"}, + {file = "pycryptodomex-3.18.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bec6c80994d4e7a38312072f89458903b65ec99bed2d65aa4de96d997a53ea7a"}, + {file = "pycryptodomex-3.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d35a8ffdc8b05e4b353ba281217c8437f02c57d7233363824e9d794cf753c419"}, + {file = "pycryptodomex-3.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76f0a46bee539dae4b3dfe37216f678769349576b0080fdbe431d19a02da42ff"}, + {file = "pycryptodomex-3.18.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:71687eed47df7e965f6e0bf3cadef98f368d5221f0fb89d2132effe1a3e6a194"}, + {file = "pycryptodomex-3.18.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:73d64b32d84cf48d9ec62106aa277dbe99ab5fbfd38c5100bc7bddd3beb569f7"}, + {file = "pycryptodomex-3.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbdcce0a226d9205560a5936b05208c709b01d493ed8307792075dedfaaffa5f"}, + {file = "pycryptodomex-3.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58fc0aceb9c961b9897facec9da24c6a94c5db04597ec832060f53d4d6a07196"}, + {file = "pycryptodomex-3.18.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:215be2980a6b70704c10796dd7003eb4390e7be138ac6fb8344bf47e71a8d470"}, + {file = "pycryptodomex-3.18.0.tar.gz", hash = "sha256:3e3ecb5fe979e7c1bb0027e518340acf7ee60415d79295e5251d13c68dde576e"}, +] + [[package]] name = "pyflakes" version = "3.1.0" @@ -1043,6 +1116,17 @@ pygments = ">=2.13.0,<3.0.0" [package.extras] jupyter = ["ipywidgets (>=7.5.1,<9)"] +[[package]] +name = "sortedcontainers" +version = "2.4.0" +description = "Sorted Containers -- Sorted List, Sorted Dict, Sorted Set" +optional = false +python-versions = "*" +files = [ + {file = "sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"}, + {file = "sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88"}, +] + [[package]] name = "textual" version = "0.27.0" @@ -1150,4 +1234,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "5c5761506ddd7c3f9d75fd65f5ea5c6366a00fe4ef743a025202ad0bd389f721" +content-hash = "6c0e5af7322663a42ee17a19fc09989375d2177e743c67852a2a75e17fb2755c" diff --git a/pykelrond/pyproject.toml b/pykelrond/pyproject.toml index 01799aea..ed2bedaf 100644 --- a/pykelrond/pyproject.toml +++ b/pykelrond/pyproject.toml @@ -13,6 +13,8 @@ authors = [ [tool.poetry.dependencies] python = "^3.10" pykwasm = {path = "../deps/wasm-semantics/pykwasm"} +pycryptodomex = "^3.18.0" +hypothesis = "^6.82.6" [tool.poetry.group.dev.dependencies] autoflake = "*" @@ -49,3 +51,7 @@ skip-string-normalization = true [tool.mypy] disallow_untyped_defs = true + +[tool.poetry.scripts] +mandos = "pykelrond.scenario:run_tests" +foundry = "pykelrond.foundry:main" diff --git a/run_foundry.py b/pykelrond/src/pykelrond/foundry.py similarity index 83% rename from run_foundry.py rename to pykelrond/src/pykelrond/foundry.py index 561b8409..a19d8094 100644 --- a/run_foundry.py +++ b/pykelrond/src/pykelrond/foundry.py @@ -1,19 +1,42 @@ +from __future__ import annotations + import argparse import glob +import json +import sys from os.path import join -from typing import Iterable, Mapping - -from hypothesis import given, settings, Verbosity -from hypothesis.strategies import SearchStrategy, integers, tuples -from pyk.prelude.utils import token -from pyk.prelude.collections import list_of, map_of -from pyk.kast.inner import KSort, KVariable -from pyk.cterm import CTerm, build_claim, KClaim -from pyk.utils import ensure_dir_path +from pathlib import Path +from typing import TYPE_CHECKING, Iterable, Mapping, cast + +from hypothesis import Verbosity, given, settings +from hypothesis.strategies import integers, tuples +from pyk.cli.utils import dir_path +from pyk.cterm import CTerm, build_claim +from pyk.kast.inner import KApply, KSequence, KSort, KToken, KVariable, Subst +from pyk.ktool.krun import KRun +from pyk.prelude.collections import list_of, map_of, set_of from pyk.prelude.kint import leInt from pyk.prelude.ml import mlEqualsTrue - -from run_elrond_tests import * +from pyk.prelude.utils import token +from pyk.utils import ensure_dir_path +from pykwasm import wasm2kast +from pykwasm.kwasm_ast import KInt + +from pykelrond.scenario import ( + KList, + KMapBytesToBytes, + KWasmString, + ListBytes, + get_steps_sc_call, + mandos_argument_to_kbytes, + split_config_from, + wrapBytes, +) + +if TYPE_CHECKING: + from hypothesis.strategies import SearchStrategy + from pyk.cterm import KClaim + from pyk.kast.inner import KInner INPUT_FILE_NAME = 'foundry.json' TEST_PREFIX = 'test_' @@ -22,14 +45,14 @@ TEST_SC_ADDR = 'sc:k-test' REC_LIMIT = 4000 -sys.setrecursionlimit(REC_LIMIT) + def load_input_json(test_dir: str) -> dict: try: with open(join(test_dir, INPUT_FILE_NAME), 'r') as f: return json.load(f) - except FileNotFoundError as e: - raise FileNotFoundError('"{INPUT_FILE_NAME}" not found in "{test_dir}"') + except FileNotFoundError: + raise FileNotFoundError('"{INPUT_FILE_NAME}" not found in "{test_dir}"') from None def load_wasm(filename: str) -> KInner: @@ -47,9 +70,7 @@ def find_test_wasm_path(test_dir: str) -> str: def load_contract_wasms(contract_wasm_paths: Iterable[str]) -> dict[bytes, KInner]: - contract_wasm_modules = { - bytes(f, 'ascii'): load_wasm(f) for f in contract_wasm_paths - } + contract_wasm_modules = {bytes(f, 'ascii'): load_wasm(f) for f in contract_wasm_paths} return contract_wasm_modules @@ -58,9 +79,7 @@ def set_exit_code(i: int) -> KInner: return KApply('setExitCode', [KInt(i)]) -def deploy_test( - krun: KRun, test_wasm: KInner, contract_wasms: dict[bytes, KInner] -) -> tuple[KInner, dict[str, KInner]]: +def deploy_test(krun: KRun, test_wasm: KInner, contract_wasms: dict[bytes, KInner]) -> tuple[KInner, dict[str, KInner]]: """ 1. create a main account: 'k' 2. reserve a new address for the test contract: owner = 'k', contract address = 'k-test' @@ -87,23 +106,17 @@ def deploy_test( # deploy the test contract arguments = ListBytes(wrapBytes(token(k)) for k in contract_wasms) gas = token(5000000000000) - deploy_cmd = KApply( - 'deployTx', [k_addr, token(0), test_wasm, arguments, gas, token(0)] - ) + deploy_cmd = KApply('deployTx', [k_addr, token(0), test_wasm, arguments, gas, token(0)]) # initialization steps - init_steps = KSequence( - [set_exit_code(1), init_main_acct, new_address, deploy_cmd, set_exit_code(0)] - ) + init_steps = KSequence([set_exit_code(1), init_main_acct, new_address, deploy_cmd, set_exit_code(0)]) # create an empty config and embed init steps empty_conf = krun.definition.init_config(KSort('GeneratedTopCell')) conf, subst = split_config_from(empty_conf) subst['K_CELL'] = init_steps - subst['WASMSTORE_CELL'] = map_of( - {token(path): mod for path, mod in contract_wasms.items()} - ) + subst['WASMSTORE_CELL'] = map_of({cast('KInner', token(path)): mod for path, mod in contract_wasms.items()}) conf_with_steps = Subst(subst)(conf) _, sym_conf, subst = run_config_and_check_empty(krun, conf_with_steps) @@ -114,15 +127,12 @@ def deploy_test( def run_config(krun: KRun, conf: KInner) -> KInner: - conf_kore = krun.kast_to_kore(conf, sort=KSort('GeneratedTopCell')) + conf_kore = krun.kast_to_kore(conf, sort=KSort('GeneratedTopCell')) res_conf_kore = krun.run_kore_term(conf_kore, expect_rc=0) return krun.kore_to_kast(res_conf_kore) -def run_config_and_check_empty( - krun: KRun, conf: KInner -) -> tuple[KInner, KInner, dict[str, KInner]]: - +def run_config_and_check_empty(krun: KRun, conf: KInner) -> tuple[KInner, KInner, dict[str, KInner]]: final_conf = run_config(krun, conf) sym_conf, subst = split_config_from(final_conf) k_cell = subst['K_CELL'] @@ -134,9 +144,7 @@ def run_config_and_check_empty( return final_conf, sym_conf, subst -def run_test( - krun: KRun, sym_conf: KInner, init_subst: dict[str, KInner], endpoint: str, args: tuple[str, ...] -): +def run_test(krun: KRun, sym_conf: KInner, init_subst: dict[str, KInner], endpoint: str, args: tuple[str, ...]) -> None: step = { 'tx': { 'from': ROOT_ACCT_ADDR, @@ -149,9 +157,7 @@ def run_test( }, 'expect': {'status': '0'}, } - tx_steps = KSequence( - [set_exit_code(1)] + get_steps_sc_call(step) + [set_exit_code(0)] - ) + tx_steps = KSequence([set_exit_code(1)] + get_steps_sc_call(step) + [set_exit_code(0)]) subst = init_subst.copy() subst['K_CELL'] = tx_steps @@ -164,6 +170,7 @@ def run_test( raise RuntimeError(f'Test failed for input input: {args}') from None raise rte + # Test metadata @@ -211,14 +218,9 @@ def arg_types_to_strategy(types: Iterable[str]) -> SearchStrategy[tuple[str, ... def test_with_hypothesis( - krun: KRun, - sym_conf: KInner, - init_subst: dict[str, KInner], - endpoint: str, - arg_types: Iterable[str] + krun: KRun, sym_conf: KInner, init_subst: dict[str, KInner], endpoint: str, arg_types: Iterable[str] ) -> None: - - def test(args: tuple[str,...]): + def test(args: tuple[str, ...]) -> None: # set the recursion limit every time because hypothesis changes it if sys.getrecursionlimit() < REC_LIMIT: sys.setrecursionlimit(REC_LIMIT) @@ -243,9 +245,8 @@ def run_concrete( sym_conf: KInner, init_subst: dict[str, KInner], ) -> None: - for endpoint, arg_types in test_endpoints.items(): - print(f'Testing "{endpoint}"') + print(f'Testing {endpoint !r}') test_with_hypothesis(krun, sym_conf, init_subst, endpoint, arg_types) @@ -278,7 +279,6 @@ def generate_claim( sym_conf: KInner, init_subst: dict[str, KInner], ) -> KClaim: - root_acc = mandos_argument_to_kbytes(ROOT_ACCT_ADDR) test_sc = mandos_argument_to_kbytes(TEST_SC_ADDR) vars, ctrs = make_vars_and_constraints(arg_types) @@ -320,7 +320,6 @@ def generate_claim( def lhs_subst(init_subst: dict[str, KInner], steps: KInner) -> dict[str, KInner]: - subst = { 'K_CELL': steps, 'CHECKEDACCOUNTS_CELL': set_of(()), @@ -354,7 +353,6 @@ def lhs_subst(init_subst: dict[str, KInner], steps: KInner) -> dict[str, KInner] def rhs_subst(init_subst: dict[str, KInner]) -> dict[str, KInner]: - subst = { 'K_CELL': KSequence(), 'CHECKEDACCOUNTS_CELL': set_of(()), @@ -389,10 +387,7 @@ def var_to_bytes(var: KVariable) -> KInner: raise TypeError(f'Cannot convert sort {sort} to Bytes') -def make_vars_and_constraints( - types: tuple[str, ...] -) -> tuple[tuple[KVariable, ...], tuple[KInner, ...]]: - +def make_vars_and_constraints(types: tuple[str, ...]) -> tuple[tuple[KVariable, ...], tuple[KInner, ...]]: vars: tuple[KVariable, ...] = () ctrs: tuple[KInner, ...] = () for i, typ in enumerate(types): @@ -404,9 +399,9 @@ def make_vars_and_constraints( def make_var_and_constraints(id: str, typ: str) -> tuple[KVariable, tuple[KInner, ...]]: - ''' + """ Create a K variable and constraints from a type - ''' + """ sort = type_to_sort(typ) var = KVariable(id, sort) @@ -434,13 +429,18 @@ def type_to_constraint(typ: str, var: KVariable) -> tuple[KInner, ...]: # Main Script -def main(): +def main() -> None: sys.setrecursionlimit(REC_LIMIT) - + parser = argparse.ArgumentParser(description='Symbolic testing for MultiversX contracts') parser.add_argument( - '-d', '--directory', required=True, help='path to the test contract' + '--definition-dir', + default=None, + dest='definition_dir', + type=dir_path, + help='Path to Foundry LLVM definition to use.', ) + parser.add_argument('-d', '--directory', required=True, help='path to the test contract') parser.add_argument( '--gen-claims', dest='gen_claims', @@ -468,7 +468,7 @@ def main(): wasm_paths = (join(test_dir, p) for p in input_json['contract_paths']) contract_wasms = load_contract_wasms(wasm_paths) - krun = KRun(Path('.build/defn/llvm/foundry-kompiled')) + krun = KRun(args.definition_dir) print('Initializing the test...') sym_conf, init_subst = deploy_test(krun, test_wasm, contract_wasms) @@ -487,7 +487,3 @@ def main(): generate_claims(krun, test_endpoints, sym_conf, init_subst, output_dir) else: run_concrete(krun, test_endpoints, sym_conf, init_subst) - - -if __name__ == '__main__': - main() diff --git a/pykelrond/src/pykelrond/hello.py b/pykelrond/src/pykelrond/hello.py deleted file mode 100644 index 6cab2ee4..00000000 --- a/pykelrond/src/pykelrond/hello.py +++ /dev/null @@ -1,2 +0,0 @@ -def hello(name: str) -> str: - return f'Hello, {name}!' diff --git a/run_elrond_tests.py b/pykelrond/src/pykelrond/scenario.py similarity index 66% rename from run_elrond_tests.py rename to pykelrond/src/pykelrond/scenario.py index 9a233a88..cb72d2fa 100755 --- a/run_elrond_tests.py +++ b/pykelrond/src/pykelrond/scenario.py @@ -2,80 +2,94 @@ import argparse import json -from pathlib import Path -from pyk.kast.inner import KSequence, KInner, KToken, KApply, Subst, KSort -from pyk.ktool.krun import KRun -from pyk.kast.manip import split_config_from -from pyk.prelude.collections import set_of +import os import resource import subprocess import sys -from Cryptodome.Hash import keccak import tempfile -import os -import wasm2kast -from kwasm_ast import KString, KInt, KBytes +from typing import Iterable, Optional, TypeVar + +from Cryptodome.Hash import keccak +from pyk.cli.utils import dir_path +from pyk.kast.inner import KApply, KInner, KSequence, KSort, KToken, Subst +from pyk.kast.manip import split_config_from +from pyk.ktool.krun import KRun +from pyk.prelude.collections import set_of +from pykwasm import wasm2kast +from pykwasm.kwasm_ast import KBytes, KInt, KString -def flatten(l): +T = TypeVar('T') + + +def flatten(l: list[list[T]]) -> list[T]: return [item for sublist in l for item in sublist] -def wrapBytes(bs: KInner): + +def wrapBytes(bs: KToken) -> KInner: # noqa: N802 assert bs.sort == KSort('Bytes') return KApply('wrapBytes', [bs]) -def KWasmString(value): + +def KWasmString(value: str) -> KToken: # noqa: N802 return KToken('"%s"' % value, 'WasmStringToken') -def KMap(kitem_pairs, empty_map:str=".Map", map_item:str="_|->_", map_concat:str="_Map_"): + +def KMap( # noqa: N802 + kitem_pairs: list[tuple[KInner, KInner]], + empty_map: str = '.Map', + map_item: str = '_|->_', + map_concat: str = '_Map_', +) -> KInner: """Takes a list of pairs of KItems and produces a Map with them as keys and values.""" if len(kitem_pairs) == 0: return KApply(empty_map, []) ((k, v), tail) = (kitem_pairs[0], kitem_pairs[1:]) res = KApply(map_item, [k, v]) - for (k, v) in tail: + for k, v in tail: new_item = KApply(map_item, [k, v]) res = KApply(map_concat, [res, new_item]) return res -def KMapBytesToBytes(kitem_pairs): - return KMap( - kitem_pairs, - empty_map=".MapBytesToBytes", - map_item="_Bytes2Bytes|->_", - map_concat="_MapBytesToBytes_") -def KList(items, list_item:str="ListItem", empty:str=".List", concat:str="_List_"): - list_items = list(map(lambda x: KApply(list_item, [x]), items)) - def KList_aux(lis): +def KMapBytesToBytes(kitem_pairs: list[tuple[KInner, KInner]]) -> KInner: # noqa: N802 + return KMap(kitem_pairs, empty_map='.MapBytesToBytes', map_item='_Bytes2Bytes|->_', map_concat='_MapBytesToBytes_') + + +def KList( # noqa: N802 + items: Iterable[KInner], list_item: str = 'ListItem', empty: str = '.List', concat: str = '_List_' +) -> KInner: + list_items = [KApply(list_item, [x]) for x in items] + + def KList_aux(lis: list[KApply]) -> KInner: # noqa: N802 if lis == []: return KApply(empty, []) head = lis[0] tail = KList_aux(lis[1:]) return KApply(concat, [head, tail]) + return KList_aux(list_items) -def ListBytes(items): - return KList(items, empty=".ListBytes", list_item="ListBytesItem", concat="_ListBytes_") -def config_to_kast_term(config): - return { 'format' : 'KAST', 'version': 2, 'term': config.to_dict() } +def ListBytes(items: Iterable[KInner]) -> KInner: # noqa: N802 + return KList(items, empty='.ListBytes', list_item='ListBytesItem', concat='_ListBytes_') -############################### -WASM_definition_main_file = 'mandos' -WASM_definition_llvm_dir = Path('.build/defn/llvm') -WASM_definition_llvm_kompiled_dir = WASM_definition_llvm_dir / (WASM_definition_main_file + '-kompiled') +def config_to_kast_term(config: KInner) -> dict: + return {'format': 'KAST', 'version': 2, 'term': config.to_dict()} -addr_prefix = "address:" -sc_prefix = "sc:" -keccak_prefix = "keccak256:" -u64_prefix = "u64:" -u32_prefix = "u32:" -u16_prefix = "u16:" -u8_prefix = "u8:" -biguint_prefix = "biguint:" -nested_prefix = "nested:" +############################### + +addr_prefix = 'address:' +sc_prefix = 'sc:' +keccak_prefix = 'keccak256:' +u64_prefix = 'u64:' +u32_prefix = 'u32:' +u16_prefix = 'u16:' +u8_prefix = 'u8:' + +biguint_prefix = 'biguint:' +nested_prefix = 'nested:' # number of zero bytes every smart contract address begins with. sc_addr_num_leading_zeros = 8 @@ -88,14 +102,16 @@ def config_to_kast_term(config): sys.setrecursionlimit(1500000000) resource.setrlimit(resource.RLIMIT_STACK, (resource.RLIM_INFINITY, resource.RLIM_INFINITY)) -def mandos_int_to_kint(mandos_int: str): + +def mandos_int_to_kint(mandos_int: str) -> KToken: if mandos_int[0:2] == '0x': return KInt(int(mandos_int, 16)) unseparated_int = mandos_int.replace(',', '') parsed_int = int(unseparated_int) return KInt(parsed_int) -def mandos_argument_to_bytes(arg): + +def mandos_argument_to_bytes(arg: str | list | dict) -> bytes: if isinstance(arg, str): return mandos_string_to_bytes(arg) @@ -113,8 +129,9 @@ def mandos_argument_to_bytes(arg): raise ValueError(f'Argument type not yet supported: {arg}') -def mandos_string_to_bytes(raw_str: str): - if raw_str == "": + +def mandos_string_to_bytes(raw_str: str) -> bytes: + if raw_str == '': return bytes() if '|' in raw_str: @@ -124,9 +141,9 @@ def mandos_string_to_bytes(raw_str: str): bs += bytearray(mandos_argument_to_bytes(s)) return bytes(bs) - if raw_str == "false": + if raw_str == 'false': return bytes() - if raw_str == "true": + if raw_str == 'true': return bytes([1]) # string prefix @@ -137,17 +154,17 @@ def mandos_string_to_bytes(raw_str: str): # address if raw_str.startswith(addr_prefix): - addr_arg = raw_str[len(addr_prefix):] + addr_arg = raw_str[len(addr_prefix) :] return address_expression(addr_arg) # smart contract address if raw_str.startswith(sc_prefix): - addr_arg = raw_str[len(sc_prefix):] + addr_arg = raw_str[len(sc_prefix) :] return sc_expression(addr_arg) # keccak256 if raw_str.startswith(keccak_prefix): - input_bytes = mandos_string_to_bytes(raw_str[len(keccak_prefix):]) + input_bytes = mandos_string_to_bytes(raw_str[len(keccak_prefix) :]) k = keccak.new(digest_bits=256) k.update(input_bytes) return bytes.fromhex(k.hexdigest()) @@ -155,20 +172,20 @@ def mandos_string_to_bytes(raw_str: str): # biguint if raw_str.startswith(biguint_prefix): bs = bytearray() - num_int, num_len = convert_string_to_uint(raw_str[len(biguint_prefix):]) + num_int, num_len = convert_string_to_uint(raw_str[len(biguint_prefix) :]) bs += bytearray(num_len.to_bytes(4, 'big')) bs += bytearray(num_int.to_bytes(num_len, 'big')) return bytes(bs) # fixed width number if raw_str.startswith(u64_prefix): - return mandos_interpret_as_uint_fixedwidth(raw_str[len(u64_prefix):], 8) + return mandos_interpret_as_uint_fixedwidth(raw_str[len(u64_prefix) :], 8) if raw_str.startswith(u32_prefix): - return mandos_interpret_as_uint_fixedwidth(raw_str[len(u32_prefix):], 4) + return mandos_interpret_as_uint_fixedwidth(raw_str[len(u32_prefix) :], 4) if raw_str.startswith(u16_prefix): - return mandos_interpret_as_uint_fixedwidth(raw_str[len(u16_prefix):], 2) + return mandos_interpret_as_uint_fixedwidth(raw_str[len(u16_prefix) :], 2) if raw_str.startswith(u8_prefix): - return mandos_interpret_as_uint_fixedwidth(raw_str[len(u8_prefix):], 1) + return mandos_interpret_as_uint_fixedwidth(raw_str[len(u8_prefix) :], 1) # signed integer if raw_str.startswith('+') or raw_str.startswith('-'): @@ -179,7 +196,7 @@ def mandos_string_to_bytes(raw_str: str): pass if raw_str.startswith(nested_prefix): - return interpret_nested_bytes(raw_str[len(nested_prefix):]) + return interpret_nested_bytes(raw_str[len(nested_prefix) :]) # unsigned integer try: @@ -188,33 +205,39 @@ def mandos_string_to_bytes(raw_str: str): except ValueError: pass - raise ValueError("Argument type not yet supported: %s" % raw_str) + raise ValueError(f'Argument type not yet supported: {raw_str}') -def interpret_nested_bytes(raw_str): + +def interpret_nested_bytes(raw_str: str) -> bytes: nested_bytes = mandos_string_to_bytes(raw_str) length_bytes = len(nested_bytes).to_bytes(4, 'big') return length_bytes + nested_bytes + def address_expression(addr_arg: str) -> bytes: return create_address_optional_shard_id(addr_arg, 0) + def create_address_optional_shard_id(input: str, num_leading_zeros: int) -> bytes: # TODO implement addresses with optional shard ID: https://github.com/multiversx/mx-chain-scenario-go/blob/3d0b8aea51a94fe640bf1c62a78dd5b4abbad459/expression/interpreter/functions.go#L52 - zero_padded = "\0" * num_leading_zeros + input + zero_padded = '\0' * num_leading_zeros + input padded_addr = zero_padded.ljust(32, '_') padded_addr_bytes = bytes(padded_addr[:32], 'ascii') return padded_addr_bytes + def sc_expression(input: str) -> bytes: addr = create_address_optional_shard_id(input, sc_addr_reserved_prefix_len) # TODO insert VM type: https://github.com/multiversx/mx-chain-scenario-go/blob/3d0b8aea51a94fe640bf1c62a78dd5b4abbad459/expression/interpreter/functions.go#L78 return addr -def mandos_interpret_as_uint_fixedwidth(raw_str: str, width: int): + +def mandos_interpret_as_uint_fixedwidth(raw_str: str, width: int) -> bytes: num_int, _ = convert_string_to_uint(raw_str) return num_int.to_bytes(width, byteorder='big') -def convert_string_to_uint(raw_str: str): + +def convert_string_to_uint(raw_str: str) -> tuple[int, int]: num_str = raw_str.replace('_', '') num_str = num_str.replace(',', '') @@ -239,44 +262,52 @@ def convert_string_to_uint(raw_str: str): return (num_int, num_len) num_int = int(num_str) - if (num_int < 0): - raise ValueError("Negative number not allowed in this context: %s" % raw_str) + if num_int < 0: + raise ValueError(f'Negative number not allowed in this context: {raw_str}') num_len = (num_int.bit_length() + 7) // 8 return (num_int, num_len) -def convert_string_to_sint(raw_str: str): + +def convert_string_to_sint(raw_str: str) -> tuple[int, int]: num_int, _ = convert_string_to_uint(raw_str[1:]) if raw_str.startswith('-'): num_int = -num_int num_len = (8 + (num_int + (num_int < 0)).bit_length()) // 8 return (num_int, num_len) -def mandos_argument_to_kbytes(argument: str): + +def mandos_argument_to_kbytes(argument: str) -> KToken: bs = mandos_argument_to_bytes(argument) return KBytes(bs) -def mandos_arguments_to_klist(arguments: list): - tokenized = list(map(lambda x: mandos_argument_to_kbytes(x), arguments)) + +def mandos_arguments_to_klist(arguments: list[str]) -> KInner: + tokenized = [mandos_argument_to_kbytes(x) for x in arguments] wrapped = list(map(wrapBytes, tokenized)) return ListBytes(wrapped) -def mandos_to_set_account(address, sections, filename, output_dir): - """Creates a K account cell from a Mandos account description. """ + +def mandos_to_set_account(address: str, sections: dict, filename: str, output_dir: str) -> list[KApply]: + """Creates a K account cell from a Mandos account description.""" address_value = mandos_argument_to_kbytes(address) - nonce_value = mandos_int_to_kint(sections.get('nonce', '0')) + nonce_value = mandos_int_to_kint(sections.get('nonce', '0')) balance_value = mandos_int_to_kint(sections.get('balance', '0')) - owner_value = mandos_argument_to_kbytes(sections.get('owner', '')) - code_value = KApply(".Code", []) + owner_value = mandos_argument_to_kbytes(sections.get('owner', '')) + code_value: KInner = KApply('.Code', []) if 'code' in sections: code_path = get_contract_code(sections['code'], filename) if code_path is not None: code_value = file_to_module_decl(code_path, output_dir) - storage_pairs = [ (mandos_argument_to_kbytes(k), mandos_argument_to_kbytes(v)) for (k, v) in sections.get('storage', {}).items() ] - storage_pairs = [ (wrapBytes(k), wrapBytes(v)) for (k, v) in storage_pairs ] - storage_value = KMapBytesToBytes(storage_pairs) + storage_pairs = [ + (mandos_argument_to_kbytes(k), mandos_argument_to_kbytes(v)) for (k, v) in sections.get('storage', {}).items() + ] + wrapped_pairs = [(wrapBytes(k), wrapBytes(v)) for (k, v) in storage_pairs] + storage_value = KMapBytesToBytes(wrapped_pairs) - set_account_steps = [KApply('setAccount', [address_value, nonce_value, balance_value, code_value, owner_value, storage_value])] + set_account_steps = [ + KApply('setAccount', [address_value, nonce_value, balance_value, code_value, owner_value, storage_value]) + ] if 'esdt' in sections: for k, v in sections['esdt'].items(): @@ -287,16 +318,17 @@ def mandos_to_set_account(address, sections, filename, output_dir): return set_account_steps -# ESDT value is either an integer (compact) or a dictionary (full) -def mandos_to_esdt_value(v): - try: + +# ESDT value is either an integer (compact) or a dictionary (full) +def mandos_to_esdt_value(v: str | dict) -> KToken: + if isinstance(v, str): return mandos_int_to_kint(v) - except TypeError: - # TODO properly parse 'instances' - return mandos_int_to_kint(v['instances'][0]['balance']) + # TODO properly parse 'instances' + return mandos_int_to_kint(v['instances'][0]['balance']) -def mandos_to_check_account(address, sections, filename): - k_steps = [] + +def mandos_to_check_account(address: str, sections: dict, filename: str) -> list: + k_steps: list[KInner] = [] address_value = mandos_argument_to_kbytes(address) if ('nonce' in sections) and (sections['nonce'] != '*'): nonce_value = mandos_int_to_kint(sections['nonce']) @@ -305,52 +337,55 @@ def mandos_to_check_account(address, sections, filename): balance_value = mandos_int_to_kint(sections['balance']) k_steps.append(KApply('checkAccountBalance', [address_value, balance_value])) if ('storage' in sections) and (sections['storage'] != '*'): + # TODO move storage map creation to a function and reuse in mandos_to_set_account storage_pairs = [] - for (k, v) in sections['storage'].items(): + for k, v in sections['storage'].items(): k_bytes = mandos_argument_to_kbytes(k) v_bytes = mandos_argument_to_kbytes(v) storage_pairs.append((k_bytes, v_bytes)) - storage_pairs = [ (wrapBytes(k), wrapBytes(v)) for (k, v) in storage_pairs ] - storage_value = KMapBytesToBytes(storage_pairs) + wrapped_pairs = [(wrapBytes(k), wrapBytes(v)) for (k, v) in storage_pairs] + storage_value = KMapBytesToBytes(wrapped_pairs) k_steps.append(KApply('checkAccountStorage', [address_value, storage_value])) if ('code' in sections) and (sections['code'] != '*'): code_path = get_contract_code(sections['code'], filename) if code_path is None: - code_path = "" - code_path = KString(code_path) - k_steps.append(KApply('checkAccountCode', [address_value, code_path])) + code_path = '' + k_code_path = KString(code_path) + k_steps.append(KApply('checkAccountCode', [address_value, k_code_path])) k_steps.append(KApply('checkedAccount', [address_value])) return k_steps -def mandos_to_deploy_tx(tx, filename, output_dir): + +def mandos_to_deploy_tx(tx: dict, filename: str, output_dir: str) -> KInner: sender = mandos_argument_to_kbytes(tx['from']) - value = mandos_int_to_kint(getEgldValue(tx)) + value = mandos_int_to_kint(get_egld_value(tx)) arguments = mandos_arguments_to_klist(tx['arguments']) - gasLimit = mandos_int_to_kint(tx['gasLimit']) - gasPrice = mandos_int_to_kint(tx['gasPrice']) + gas_limit = mandos_int_to_kint(tx['gasLimit']) + gas_price = mandos_int_to_kint(tx['gasPrice']) code = get_contract_code(tx['contractCode'], filename) + assert isinstance(code, str) module = file_to_module_decl(code, output_dir) - deployTx = KApply('deployTx', [sender, value, module, arguments, gasLimit, gasPrice]) - return deployTx + return KApply('deployTx', [sender, value, module, arguments, gas_limit, gas_price]) -def mandos_to_call_tx(tx): + +def mandos_to_call_tx(tx: dict) -> KInner: sender = mandos_argument_to_kbytes(tx['from']) to = mandos_argument_to_kbytes(tx['to']) - value = mandos_int_to_kint(getEgldValue(tx)) + value = mandos_int_to_kint(get_egld_value(tx)) esdt_value = mandos_esdt_to_klist(tx.get('esdtValue', [])) function = KWasmString(tx['function']) arguments = mandos_arguments_to_klist(tx['arguments']) - gasLimit = mandos_int_to_kint(tx['gasLimit']) - gasPrice = mandos_int_to_kint(tx['gasPrice']) + gas_limit = mandos_int_to_kint(tx['gasLimit']) + gas_price = mandos_int_to_kint(tx['gasPrice']) + + return KApply('callTx', [sender, to, value, esdt_value, function, arguments, gas_limit, gas_price]) - callTx = KApply('callTx', [sender, to, value, esdt_value, function, arguments, gasLimit, gasPrice]) - return callTx -def mandos_esdt_to_klist(esdt_values): - def esdt(esdt_value): +def mandos_esdt_to_klist(esdt_values: list[dict]) -> KInner: + def esdt(esdt_value: dict) -> KApply: tok_id = mandos_argument_to_kbytes(esdt_value['tokenIdentifier']) value = mandos_int_to_kint(esdt_value['value']) nonce = mandos_int_to_kint(esdt_value.get('nonce', '0')) @@ -359,54 +394,57 @@ def esdt(esdt_value): return KList(esdt(i) for i in esdt_values) -def mandos_to_transfer_tx(tx): +def mandos_to_transfer_tx(tx: dict) -> KInner: sender = mandos_argument_to_kbytes(tx['from']) to = mandos_argument_to_kbytes(tx['to']) - value = mandos_int_to_kint(getEgldValue(tx)) - - transferTx = KApply('transferTx', [sender, to, value]) - return transferTx + value = mandos_int_to_kint(get_egld_value(tx)) + + return KApply('transferTx', [sender, to, value]) -def mandos_to_validator_reward_tx(tx): + +def mandos_to_validator_reward_tx(tx: dict) -> KApply: to = mandos_argument_to_kbytes(tx['to']) - value = mandos_int_to_kint(getEgldValue(tx)) - rewardTx = KApply('validatorRewardTx', [to, value]) - return rewardTx + value = mandos_int_to_kint(get_egld_value(tx)) + + return KApply('validatorRewardTx', [to, value]) + -def getEgldValue(tx): +def get_egld_value(tx: dict) -> str: # backwards compatibility if 'value' in tx: return tx['value'] - return tx.get('egldValue', "0") + return tx.get('egldValue', '0') + # TODO: implement checkExpect gas, refund -def mandos_to_expect(expect): +STATUS_CODES = { + 0: 'OK', + 1: 'FunctionNotFound', + 2: 'FunctionWrongSignature', + 3: 'ContractNotFound', + 4: 'UserError', + 5: 'OutOfGas', + 6: 'AccountCollision', + 7: 'OutOfFunds', + 8: 'CallStackOverFlow', + 9: 'ContractInvalid', + 10: 'ExecutionFailed', + 11: 'UpgradeFailed', + 12: 'SimulateFailed', +} + + +def mandos_to_expect(expect: dict) -> list: k_steps = [] - def int_to_kreturncode(status: str): - if status == "": + def int_to_kreturncode(status: str) -> KApply: + if status == '': return KApply('OK', []) status_int, _ = convert_string_to_uint(status) - STATUS_CODES = { - 0: 'OK', - 1: 'FunctionNotFound', - 2: 'FunctionWrongSignature', - 3: 'ContractNotFound', - 4: 'UserError', - 5: 'OutOfGas', - 6: 'AccountCollision', - 7: 'OutOfFunds', - 8: 'CallStackOverFlow', - 9: 'ContractInvalid', - 10: 'ExecutionFailed', - 11: 'UpgradeFailed', - 12: 'SimulateFailed', - } - if status_int in STATUS_CODES: return KApply(STATUS_CODES[status_int], []) - raise ValueError("Status code %s not supported" % status) + raise ValueError(f'Status code {status} not supported') if ('out' in expect) and (expect['out'] != '*'): expect_out = mandos_arguments_to_klist(expect['out']) @@ -422,12 +460,13 @@ def int_to_kreturncode(status: str): identifier = mandos_argument_to_kbytes(log['endpoint']) topics = mandos_arguments_to_klist(log['topics']) data = mandos_argument_to_kbytes(log['data']) - logEntry = KApply('logEntry', [address, identifier, topics, data]) - logs.append(logEntry) + log_entry = KApply('logEntry', [address, identifier, topics, data]) + logs.append(log_entry) k_steps.append(KApply('checkExpectLogs', [KList(logs)])) return k_steps -def mandos_to_block_info(block_info): + +def mandos_to_block_info(block_info: dict) -> list: block_infos = [] if 'blockTimestamp' in block_info: block_infos += [KApply('blockTimestamp', [mandos_int_to_kint(block_info['blockTimestamp'])])] @@ -441,52 +480,59 @@ def mandos_to_block_info(block_info): block_infos += [KApply('blockRandomSeed', [mandos_argument_to_kbytes(block_info['blockRandomSeed'])])] return block_infos -def register(with_name: str): + +def register(with_name: str) -> KInner: return KApply('register', [KString(with_name)]) -def file_to_module_decl(filename: str, output_dir): + +def file_to_module_decl(filename: str, output_dir: str) -> KInner: if filename[-5:] == '.wasm': return wasm_file_to_module_decl(filename) if filename[-5:] == '.wast' or filename[-4:] == '.wat': return wat_file_to_module_decl(filename, output_dir) - raise ValueError('Filetype not yet supported: %s' % filename) + raise ValueError(f'Filetype not yet supported: {filename}') -def wasm_file_to_module_decl(filename: str): + +def wasm_file_to_module_decl(filename: str) -> KInner: # Check that file exists. with open(filename, 'rb') as f: module = wasm2kast.wasm2kast(f, filename) return module -def wat_file_to_module_decl(filename: str, output_dir): + +def wat_file_to_module_decl(filename: str, output_dir: str) -> KInner: if not os.path.exists(filename): - raise Exception("file %s does not exist" % filename) - + raise Exception(f'file {filename} does not exist') + new_wasm_filename = os.path.join(output_dir, os.path.basename(filename) + '.wasm') try: - wat = subprocess.check_output("wat2wasm %s --output=%s" % (filename, new_wasm_filename), shell=True) + subprocess.check_output(f'wat2wasm {filename} --output={new_wasm_filename}', shell=True) except subprocess.CalledProcessError as e: - print("Failed: %s" % e.cmd) - print("return code: %d" % e.returncode) - print("stdout:") + print('Failed: %s' % e.cmd) + print('return code: %d' % e.returncode) + print('stdout:') print(e.output) - print("stderr:") + print('stderr:') print(e.stderr) raise e return wasm_file_to_module_decl(new_wasm_filename) -def get_external_file_path(test_file, rel_path_to_new_file): + +def get_external_file_path(test_file: str, rel_path_to_new_file: str) -> str: test_file_path = os.path.dirname(test_file) ext_file = os.path.normpath(os.path.join(test_file_path, rel_path_to_new_file)) return ext_file -def get_contract_code(code, filename): + +def get_contract_code(code: str, filename: str) -> Optional[str]: if code[0:5] == 'file:': return get_external_file_path(filename, code[5:]) if code == '': return None raise Exception('Currently only support getting code from file, or empty code.') -def get_steps_sc_deploy(step, filename, output_dir): + +def get_steps_sc_deploy(step: dict, filename: str, output_dir: str) -> list: k_steps = [] tx = mandos_to_deploy_tx(step['tx'], filename, output_dir) k_steps.append(tx) @@ -495,7 +541,8 @@ def get_steps_sc_deploy(step, filename, output_dir): k_steps += expect return k_steps -def get_steps_sc_call(step): + +def get_steps_sc_call(step: dict) -> list: k_steps = [] tx = mandos_to_call_tx(step['tx']) k_steps.append(tx) @@ -504,15 +551,16 @@ def get_steps_sc_call(step): k_steps += expect return k_steps -def mandos_to_query_tx(tx): + +def mandos_to_query_tx(tx: dict) -> KInner: to = mandos_argument_to_kbytes(tx['to']) function = KWasmString(tx['function']) arguments = mandos_arguments_to_klist(tx.get('arguments', [])) - queryTx = KApply('queryTx', [to, function, arguments]) - return queryTx + return KApply('queryTx', [to, function, arguments]) -def get_steps_sc_query(step): + +def get_steps_sc_query(step: dict) -> list: k_steps = [] tx = mandos_to_query_tx(step['tx']) @@ -521,52 +569,60 @@ def get_steps_sc_query(step): if 'expect' in step: expect = mandos_to_expect(step['expect']) k_steps += expect - + return k_steps -def get_steps_transfer(step): + +def get_steps_transfer(step: dict) -> list: tx = mandos_to_transfer_tx(step['tx']) return [KApply('transfer', [tx])] -def get_steps_validator_reward(step): + +def get_steps_validator_reward(step: dict) -> list[KApply]: tx = mandos_to_validator_reward_tx(step['tx']) return [KApply('validatorReward', [tx])] -def get_steps_new_addresses(new_addresses): + +def get_steps_new_addresses(new_addresses: Optional[dict]) -> list[KApply]: if new_addresses is None: return [] - ret = [] + ret: list[KApply] = [] for new_address in new_addresses: creator = mandos_argument_to_kbytes(new_address['creatorAddress']) - nonce = mandos_int_to_kint(new_address['creatorNonce']) - new = mandos_argument_to_kbytes(new_address['newAddress']) + nonce = mandos_int_to_kint(new_address['creatorNonce']) + new = mandos_argument_to_kbytes(new_address['newAddress']) ret.append(KApply('newAddress', [creator, nonce, new])) return ret -def get_steps_set_state(step, filename, output_dir): - k_steps = [] + +def get_steps_set_state(step: dict, filename: str, output_dir: str) -> list[KApply]: + k_steps: list[KApply] = [] if 'accounts' in step: - set_accounts = [ mandos_to_set_account(address, sections, filename, output_dir) for (address, sections) in step['accounts'].items() ] + set_accounts = [ + mandos_to_set_account(address, sections, filename, output_dir) + for (address, sections) in step['accounts'].items() + ] k_steps = k_steps + flatten(set_accounts) if 'newAddresses' in step: new_addresses = get_steps_new_addresses(step['newAddresses']) k_steps = k_steps + new_addresses if 'currentBlockInfo' in step: block_infos = mandos_to_block_info(step['currentBlockInfo']) - set_current_blockInfos = list(map(lambda x: KApply('setCurBlockInfo', [x]), block_infos)) - k_steps = k_steps + set_current_blockInfos + set_current_block_infos = [KApply('setCurBlockInfo', [x]) for x in block_infos] + k_steps = k_steps + set_current_block_infos if 'previousBlockInfo' in step: block_infos = mandos_to_block_info(step['previousBlockInfo']) - set_previous_blockInfos = list(map(lambda x: KApply('setPrevBlockInfo', [x]), block_infos)) - k_steps = k_steps + set_previous_blockInfos + set_previous_block_infos = [KApply('setPrevBlockInfo', [x]) for x in block_infos] + k_steps = k_steps + set_previous_block_infos if k_steps == []: raise Exception('Step not implemented: %s' % step) return k_steps -def get_steps_check_state(step, filename): + +def get_steps_check_state(step: dict, filename: str) -> list: k_steps = [] if 'accounts' in step: - for (address, sections) in step['accounts'].items(): + for address, sections in step['accounts'].items(): if address != '+': k_steps += mandos_to_check_account(address, sections, filename) if not '+' in step['accounts'].keys(): @@ -576,8 +632,8 @@ def get_steps_check_state(step, filename): k_steps.append(KApply('clearCheckedAccounts', [])) return k_steps -def get_steps_as_kseq(filename, output_dir): - global args + +def get_steps_as_kseq(filename: str, output_dir: str, args: argparse.Namespace) -> list: with open(filename, 'r') as f: mandos_test = json.loads(f.read()) if 'name' in mandos_test: @@ -585,7 +641,7 @@ def get_steps_as_kseq(filename, output_dir): print('Reading "%s"' % mandos_test['name']) if 'comment' in mandos_test: if args.verbose: - print('Comment:\n"%s"' % mandos_test['comment']) + print('Comment:"%s"' % mandos_test['comment']) k_steps = [] for step in mandos_test['steps']: @@ -602,7 +658,7 @@ def get_steps_as_kseq(filename, output_dir): elif step['step'] == 'externalSteps': steps_file = get_external_file_path(filename, step['path']) print('Load external: %s' % steps_file) - k_steps = k_steps + get_steps_as_kseq(steps_file, output_dir) + k_steps = k_steps + get_steps_as_kseq(steps_file, output_dir, args) elif step['step'] == 'transfer': k_steps.append((step['step'], get_steps_transfer(step))) elif step['step'] == 'validatorReward': @@ -611,21 +667,27 @@ def get_steps_as_kseq(filename, output_dir): raise Exception('Step %s not implemented yet' % step['step']) return k_steps -def run_test_file(krun: KRun, template_wasm_config, test_file_path, output_dir, cmd_args): - global args + +def run_test_file( + krun: KRun, + template_wasm_config: KInner, + test_file_path: str, + output_dir: str, + cmd_args: argparse.Namespace, +) -> KInner: test_name = os.path.basename(test_file_path) - k_steps = get_steps_as_kseq(test_file_path, output_dir) - final_config = None + k_steps = get_steps_as_kseq(test_file_path, output_dir, cmd_args) + final_config = template_wasm_config if cmd_args.log_level == 'none' or cmd_args.log_level == 'per-file': # Flatten the list of k_steps, just run them all in one go. - k_steps = [ ('full', [ y for (_, x) in k_steps for y in x ]) ] + k_steps = [('full', [y for (_, x) in k_steps for y in x])] (symbolic_config, init_subst) = split_config_from(template_wasm_config) for i in range(len(k_steps)): step_name, curr_step = k_steps[i] - if args.verbose: + if cmd_args.verbose: print('Executing step %s' % step_name) init_subst['K_CELL'] = KSequence(curr_step) @@ -633,66 +695,81 @@ def run_test_file(krun: KRun, template_wasm_config, test_file_path, output_dir, # Run: generate a new JSON as a temporary file, then read that as the new wasm state. if cmd_args.log_level != 'none': - log_intermediate_state(krun, "%s_%d_%s.pre" % (test_name, i, step_name), init_config, output_dir) + log_intermediate_state(krun, '%s_%d_%s.pre' % (test_name, i, step_name), init_config, output_dir) new_config = krun_config(krun, init_config=init_config) final_config = new_config if cmd_args.log_level != 'none': - log_intermediate_state(krun, "%s_%d_%s" % (test_name, i, step_name), final_config, output_dir) + log_intermediate_state(krun, '%s_%d_%s' % (test_name, i, step_name), final_config, output_dir) # Check if the k cell is empty symbolic_config, init_subst = split_config_from(new_config) k_cell = init_subst['K_CELL'] - if not isinstance(k_cell, KSequence) or k_cell.arity != 0: + assert isinstance(k_cell, KSequence) + + if k_cell.arity != 0: raise ValueError(f'k cell not empty, contains a sequence of {k_cell.arity} items.\nSee {output_dir}') return final_config + def krun_config(krun: KRun, init_config: KInner) -> KInner: kore_config = krun.kast_to_kore(init_config, sort=KSort('GeneratedTopCell')) kore_config = krun.run_kore_term(kore_config) return krun.kore_to_kast(kore_config) + # ... Setup Elrond Wasm -def log_intermediate_state(krun: KRun, name, config, output_dir): + +def log_intermediate_state(krun: KRun, name: str, config: KInner, output_dir: str) -> None: with open('%s/%s' % (output_dir, name), 'w') as f: f.write(json.dumps(config_to_kast_term(config))) with open('%s/%s.pretty.k' % (output_dir, name), 'w') as f: pretty = krun.pretty_print(config) f.write(pretty) + # Main Script args = None -def run_tests(): + +def run_tests() -> None: global args - testArgs = argparse.ArgumentParser(description='') - testArgs.add_argument('files', metavar='N', type=str, nargs='+', help='') - testArgs.add_argument('--log-level', choices=['none', 'per-file', 'per-step'], default='per-file') - testArgs.add_argument('--verbose', action='store_true', help='') - args = testArgs.parse_args() + test_args = argparse.ArgumentParser(description='') + test_args.add_argument('files', metavar='N', type=str, nargs='+', help='') + test_args.add_argument('--log-level', choices=['none', 'per-file', 'per-step'], default='per-file') + test_args.add_argument('--verbose', action='store_true', help='') + test_args.add_argument( + '--definition-dir', + default=None, + dest='definition_dir', + type=dir_path, + help='Path to Mandos LLVM definition to use.', + ) + args = test_args.parse_args() tests = args.files - krun = KRun(WASM_definition_llvm_kompiled_dir) - + krun = KRun(args.definition_dir) + with open('src/elrond-runtime.loaded.json', 'r') as f: runtime_json = json.load(f) template_wasm_config = KInner.from_dict(runtime_json['term']) - + _, cells = split_config_from(template_wasm_config) + assert isinstance(cells['K_CELL'], KSequence) assert cells['K_CELL'].arity == 0 for test in tests: if args.verbose: - print("Running test %s" % test) - tmpdir = tempfile.mkdtemp(prefix="mandos_") + print('Running test %s' % test) + tmpdir = tempfile.mkdtemp(prefix='mandos_') if args.verbose: - print("Intermediate test outputs stored in:\n%s" % tmpdir) + print('Intermediate test outputs stored in:\n%s' % tmpdir) - initial_name = "0000_initial_config" + initial_name = '0000_initial_config' with open('%s/%s' % (tmpdir, initial_name), 'w') as f: f.write(json.dumps(config_to_kast_term(template_wasm_config))) @@ -701,6 +778,3 @@ def run_tests(): if args.verbose: print('See %s' % tmpdir) print() - -if __name__ == "__main__": - run_tests() diff --git a/pykelrond/src/tests/integration/test_integration.py b/pykelrond/src/tests/integration/test_integration.py deleted file mode 100644 index a46ab9cc..00000000 --- a/pykelrond/src/tests/integration/test_integration.py +++ /dev/null @@ -1,5 +0,0 @@ -from pykelrond.hello import hello - - -def test_hello() -> None: - assert hello('World') == 'Hello, World!' diff --git a/pykelrond/src/tests/unit/test_unit.py b/pykelrond/src/tests/unit/test_unit.py deleted file mode 100644 index a46ab9cc..00000000 --- a/pykelrond/src/tests/unit/test_unit.py +++ /dev/null @@ -1,5 +0,0 @@ -from pykelrond.hello import hello - - -def test_hello() -> None: - assert hello('World') == 'Hello, World!' From f8f2f1eb45c778dc97deb9e3c8f6e7916550c606 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 23 Aug 2023 02:09:35 +0300 Subject: [PATCH 04/16] update makefile --- Makefile | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index e21d7051..4f309803 100644 --- a/Makefile +++ b/Makefile @@ -262,15 +262,21 @@ $(ELROND_LOADED_JSON): $(ELROND_RUNTIME) # Elrond Tests # ------------ +POETRY := poetry -C pykelrond +POETRY_RUN := $(POETRY) run -TEST_MANDOS := python3 run_elrond_tests.py +.PHONY: poetry-install +poetry-install: + $(POETRY) install + +TEST_MANDOS := $(POETRY_RUN) mandos --definition-dir $(llvm_dir)/mandos-kompiled ## Mandos Test MANDOS_TESTS_DIR := tests/mandos mandos_tests=$(sort $(wildcard $(MANDOS_TESTS_DIR)/*.scen.json)) -mandos-test: $(llvm_kompiled) +mandos-test: $(llvm_kompiled) poetry-install $(TEST_MANDOS) $(mandos_tests) ## Adder Test @@ -278,7 +284,7 @@ mandos-test: $(llvm_kompiled) ELROND_ADDER_DIR := $(ELROND_CONTRACT_EXAMPLES)/adder elrond_adder_tests=$(shell find $(ELROND_ADDER_DIR) -name "*.scen.json") -test-elrond-adder: $(llvm_kompiled) +test-elrond-adder: $(llvm_kompiled) poetry-install mxpy contract build "$(ELROND_ADDER_DIR)" --wasm-symbols $(TEST_MANDOS) $(elrond_adder_tests) @@ -288,7 +294,7 @@ test-elrond-adder: $(llvm_kompiled) ELROND_CROWDFUNDING_DIR := $(ELROND_CONTRACT_EXAMPLES)/crowdfunding-esdt elrond_crowdfunding_tests=$(shell find $(ELROND_CROWDFUNDING_DIR) -name "*.scen.json") -test-elrond-crowdfunding-esdt: $(llvm_kompiled) +test-elrond-crowdfunding-esdt: $(llvm_kompiled) poetry-install mxpy contract build "$(ELROND_CROWDFUNDING_DIR)" --wasm-symbols $(TEST_MANDOS) $(elrond_crowdfunding_tests) @@ -297,7 +303,7 @@ test-elrond-crowdfunding-esdt: $(llvm_kompiled) ELROND_MULTISIG_DIR=$(ELROND_CONTRACT_EXAMPLES)/multisig elrond_multisig_tests=$(shell cat tests/multisig.test) -test-elrond-multisig: $(llvm_kompiled) +test-elrond-multisig: $(llvm_kompiled) poetry-install mxpy contract build "$(ELROND_MULTISIG_DIR)" --wasm-symbols $(TEST_MANDOS) $(elrond_multisig_tests) @@ -313,7 +319,7 @@ $(ELROND_BASIC_FEATURES_WASM): # TODO optimize test runner and enable logging test-elrond-basic-features: $(elrond_basic_features_tests:=.mandos) -$(ELROND_BASIC_FEATURES_DIR)/scenarios/%.scen.json.mandos: $(llvm_kompiled) $(ELROND_BASIC_FEATURES_WASM) +$(ELROND_BASIC_FEATURES_DIR)/scenarios/%.scen.json.mandos: $(llvm_kompiled) $(ELROND_BASIC_FEATURES_WASM) poetry-install $(TEST_MANDOS) $(ELROND_BASIC_FEATURES_DIR)/scenarios/$*.scen.json --log-level none ## Alloc Features Test @@ -328,7 +334,7 @@ $(ELROND_ALLOC_FEATURES_WASM): # TODO optimize test runner and enable logging test-elrond-alloc-features: $(elrond_alloc_features_tests:=.mandos) -$(ELROND_ALLOC_FEATURES_DIR)/scenarios/%.scen.json.mandos: $(llvm_kompiled) $(ELROND_ALLOC_FEATURES_WASM) +$(ELROND_ALLOC_FEATURES_DIR)/scenarios/%.scen.json.mandos: $(llvm_kompiled) $(ELROND_ALLOC_FEATURES_WASM) poetry-install $(TEST_MANDOS) $(ELROND_ALLOC_FEATURES_DIR)/scenarios/$*.scen.json --log-level none # Custom contract tests @@ -343,7 +349,7 @@ ELROND_ADDERCALLER_DIR := tests/contracts/addercaller elrond_addercaller_tests=$(shell find $(ELROND_ADDERCALLER_DIR) -name "*.scen.json") ELROND_MYADDER_DIR := tests/contracts/myadder -test-elrond-addercaller: $(llvm_kompiled) +test-elrond-addercaller: $(llvm_kompiled) poetry-install mxpy contract build "$(ELROND_MYADDER_DIR)" --wasm-symbols mxpy contract build "$(ELROND_ADDERCALLER_DIR)" --wasm-symbols $(TEST_MANDOS) $(elrond_addercaller_tests) @@ -354,7 +360,7 @@ ELROND_CALLER_DIR := tests/contracts/caller ELROND_CALLEE_DIR := tests/contracts/callee elrond_callercallee_tests=$(shell find $(ELROND_CALLER_DIR) -name "*.scen.json") -test-elrond-callercallee: $(llvm_kompiled) +test-elrond-callercallee: $(llvm_kompiled) poetry-install mxpy contract build "$(ELROND_CALLER_DIR)" --wasm-symbols mxpy contract build "$(ELROND_CALLEE_DIR)" --wasm-symbols $(TEST_MANDOS) $(elrond_callercallee_tests) From 001222afab4e64c918f3836ba6102b354f3ab47d Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 23 Aug 2023 02:20:05 +0300 Subject: [PATCH 05/16] Dockerfile: remove pip installs, add poetry --- Dockerfile | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Dockerfile b/Dockerfile index a21aa1a8..2b5f7ef0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,6 +18,9 @@ RUN apt-get update \ python3-pip \ python3-venv +RUN curl -sSL https://install.python-poetry.org | POETRY_HOME=/usr python3 - \ + && poetry --version + ARG USER=github-user ARG GROUP=$USER ARG USER_ID=1000 @@ -31,13 +34,7 @@ WORKDIR /home/$USER RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain nightly-2023-03-01 --target wasm32-unknown-unknown ENV PATH=/home/$USER/.cargo/bin:$PATH -ARG PYK_VERSION RUN python3 -m pip install --upgrade pip -RUN pip3 install --user --upgrade \ - cytoolz \ - numpy \ - pycryptodomex \ - git+https://github.com/runtimeverification/pyk.git@${PYK_VERSION} RUN git clone 'https://github.com/WebAssembly/wabt' --branch 1.0.13 --recurse-submodules wabt \ && cd wabt \ From c6d369033e07e682506cc9b121e9c5adfae19bd0 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 23 Aug 2023 02:20:32 +0300 Subject: [PATCH 06/16] remove PYK_VERSION build arg --- .github/actions/with-docker/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/with-docker/action.yml b/.github/actions/with-docker/action.yml index 209d7e85..0c84f267 100644 --- a/.github/actions/with-docker/action.yml +++ b/.github/actions/with-docker/action.yml @@ -21,7 +21,7 @@ runs: GROUP=$(id -gn) GROUP_ID=$(id -g) - docker build . --tag ${TAG} --build-arg K_COMMIT="$(cat deps/wasm-semantics/deps/k_release)" --build-arg PYK_VERSION="$(cat deps/wasm-semantics/deps/pyk_release)" --build-arg USER_ID=${USER_ID} --build-arg GROUP_ID=${GROUP_ID} --build-arg USER=${USER} --build-arg GROUP=${GROUP} + docker build . --tag ${TAG} --build-arg K_COMMIT="$(cat deps/wasm-semantics/deps/k_release)" --build-arg USER_ID=${USER_ID} --build-arg GROUP_ID=${GROUP_ID} --build-arg USER=${USER} --build-arg GROUP=${GROUP} docker run \ --name ${CONTAINER_NAME} \ From cf7afd6492afe832c90aa028c106abfa7d6b7b6e Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 23 Aug 2023 02:20:43 +0300 Subject: [PATCH 07/16] update README.md --- README.md | 60 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 98730b2d..c19c06f1 100644 --- a/README.md +++ b/README.md @@ -1,25 +1,23 @@ Semantics of Elrond and Mandos ============================== -This repository is work-in-progress, and currently a fork of [KWasm](https://github.com/kframework/wasm-semantics). +This repository the semantics of the [MultiversX](https://multiversx.com/) (formerly Elrond) blockchain in K on top of WebAssembly semantics ([KWasm](https://github.com/kframework/wasm-semantics)). -Elrond-specific code is in `elrond.md` and `run_elrond_tests.py`. ## Installation ### Dependencies * Python3 -* WABT +* [WABT v1.0.13](https://github.com/WebAssembly/wabt/tree/1.0.13) * K framework ([version](./deps/wasm-semantics/deps/k_release)) -* `pyk` ([version](./deps/wasm-semantics/deps/pyk_release)) -* Crypto++ +* [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) * Rustup * [mxpy](https://docs.multiversx.com/sdk-and-tools/sdk-py/installing-mxpy/) -See [Dockerfile](./Dockerfile) for installation. +See [Dockerfile](./Dockerfile) for installation details. -### Build +### Building the semantics Compile the semantics with: @@ -42,6 +40,39 @@ $ make elrond-clean-sources $ make elrond-loaded ``` +### Installing `pykelrond` + +`pykelrond` is a Python package providing libraries and CLI tools to interact with the semantics. +To install `pykelrond` and its dependencies into a virtual environment, run + +``` +# from the project's root directory +poetry -C pykelrond install +``` + +After the installation, the Python package `pykelrond` and CLI tools `mandos` and `foundry` will be available via the `poetry run` command + +``` +poetry -C run mandos --help +poetry -C run foundry --help +``` + +Or you can activate the virtual environment managed by `poetry` and use the commands directly + +``` +poetry -C pykelrond shell +mandos --help +``` + +Alternatively, you can install `pykelrond` globally + +``` +make -C pykelrond build +pip install pykelrond/dist/*.whl +mandos --help +foundry --help +``` + ## Run To run Mandos tests, first build the contract: @@ -53,13 +84,13 @@ $ mxpy contract build "" --wasm-symbols Then run Mandos scenarios with: ```shell -$ python3 run_elrond_tests.py +poetry -C pykelrond run mandos --definition .build/defn/llvm/mandos-kompiled ``` -__Important__: `run_elrond_tests.py` makes use of Python modules implemented in the `wasm-semantics` submodule. For the time being, it requires setting the `PYTHONPATH` environment variable. +Or with a globally installed instance ```shell -$ export PYTHONPATH=$(pwd)/deps/wasm-semantics/binary-parser:$PYTHONPATH +mandos --definition .build/defn/llvm/mandos-kompiled ``` Example: @@ -69,7 +100,7 @@ $ mxpy contract build "deps/mx-sdk-rs/contracts/examples/multisig" --wasm-symbol ... INFO:projects.core:Build ran. INFO:projects.core:WASM file generated: /path/to/multisig/output/multisig.wasm -$ python3 run_elrond_tests.py deps/mx-sdk-rs/contracts/examples/multisig/scenarios/changeBoard.scen.json +$ mandos deps/mx-sdk-rs/contracts/examples/multisig/scenarios/changeBoard.scen.json ``` ## Rule Coverage @@ -214,12 +245,13 @@ Build the test contract by executing mxpy contract build ``` -Run the `run_foundry.py` script with the test contract's path as the argument: + +Run the `foundry` tool with the test contract's path as the argument: ```shell -python3 run_foundry.py --directory +foundry --definition-dir .build/defn/llvm/foundry-kompiled --directory ``` -The `run_foundry.py` script will deploy the test contract using the arguments specified in the `foundry.json` file located in the test directory. It will extract the names and argument types of the test endpoints. Subsequently, the script will test these endpoints using random inputs generated with the `hypothesis` library, enabling fuzz testing. If it encounters an input that falsifies the assertions made in the test cases, it attempts to shrink the input and identify a minimal failing example. +The `foundry` tool will deploy the test contract using the arguments specified in the `foundry.json` file located in the test directory. It will extract the names and argument types of the test endpoints. Subsequently, the script will test these endpoints using random inputs generated with the `hypothesis` library, enabling fuzz testing. If it encounters an input that falsifies the assertions made in the test cases, it attempts to shrink the input and identify a minimal failing example. By following these steps, you can efficiently and comprehensively evaluate your Smart Contracts, ensuring their correctness and reliability in various scenarios and inputs. From 3f6cea2bdd43fa8e397d308f2ebd0cc5dd8e0fe4 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Thu, 24 Aug 2023 00:41:36 +0300 Subject: [PATCH 08/16] checkout with submodules recursive --- .github/workflows/test-pr.yml | 56 ++++++++--------------------------- 1 file changed, 12 insertions(+), 44 deletions(-) diff --git a/.github/workflows/test-pr.yml b/.github/workflows/test-pr.yml index d031e2db..00038af7 100644 --- a/.github/workflows/test-pr.yml +++ b/.github/workflows/test-pr.yml @@ -12,18 +12,10 @@ jobs: name: 'Simple Tests' timeout-minutes: 30 steps: - - name: Checkout + - name: 'Check out code' uses: actions/checkout@v3 - with: - token: ${{ secrets.JENKINS_GITHUB_PAT }} - - name: Checkout submodules - env: - GITHUB_TOKEN: ${{ secrets.JENKINS_GITHUB_PAT }} - run: | - # https://gist.github.com/taoyuan/bfa3ff87e4b5611b5cbe ; for a repository we don't control the submodules over. - git config --global url."https://github.com/".insteadOf git@github.com: - git config --global url."https://".insteadOf git:// - git submodule update --init --recursive + with: + submodules: recursive - name: 'Set up Docker' uses: ./.github/actions/with-docker with: @@ -47,18 +39,10 @@ jobs: needs: [simple-tests] timeout-minutes: 120 steps: - - name: Checkout + - name: 'Check out code' uses: actions/checkout@v3 - with: - token: ${{ secrets.JENKINS_GITHUB_PAT }} - - name: Checkout submodules - env: - GITHUB_TOKEN: ${{ secrets.JENKINS_GITHUB_PAT }} - run: | - # https://gist.github.com/taoyuan/bfa3ff87e4b5611b5cbe ; for a repository we don't control the submodules over. - git config --global url."https://github.com/".insteadOf git@github.com: - git config --global url."https://".insteadOf git:// - git submodule update --init --recursive + with: + submodules: recursive - name: 'Set up Docker' uses: ./.github/actions/with-docker with: @@ -80,18 +64,10 @@ jobs: needs: [feature-tests] timeout-minutes: 60 steps: - - name: Checkout + - name: 'Check out code' uses: actions/checkout@v3 - with: - token: ${{ secrets.JENKINS_GITHUB_PAT }} - - name: Checkout submodules - env: - GITHUB_TOKEN: ${{ secrets.JENKINS_GITHUB_PAT }} - run: | - # https://gist.github.com/taoyuan/bfa3ff87e4b5611b5cbe ; for a repository we don't control the submodules over. - git config --global url."https://github.com/".insteadOf git@github.com: - git config --global url."https://".insteadOf git:// - git submodule update --init --recursive + with: + submodules: recursive - name: 'Set up Docker' uses: ./.github/actions/with-docker with: @@ -115,18 +91,10 @@ jobs: needs: [feature-tests] timeout-minutes: 30 steps: - - name: Checkout + - name: 'Check out code' uses: actions/checkout@v3 - with: - token: ${{ secrets.JENKINS_GITHUB_PAT }} - - name: Checkout submodules - env: - GITHUB_TOKEN: ${{ secrets.JENKINS_GITHUB_PAT }} - run: | - # https://gist.github.com/taoyuan/bfa3ff87e4b5611b5cbe ; for a repository we don't control the submodules over. - git config --global url."https://github.com/".insteadOf git@github.com: - git config --global url."https://".insteadOf git:// - git submodule update --init --recursive + with: + submodules: recursive - name: 'Set up Docker' uses: ./.github/actions/with-docker with: From 5cfb6c9c2ea5bd43a27a6c65eb56fb2daa9e7345 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Thu, 24 Aug 2023 17:51:09 +0300 Subject: [PATCH 09/16] make poetry-install a separate step --- .github/workflows/test-pr.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/test-pr.yml b/.github/workflows/test-pr.yml index 00038af7..9324dbcb 100644 --- a/.github/workflows/test-pr.yml +++ b/.github/workflows/test-pr.yml @@ -22,6 +22,8 @@ jobs: container-name: elrond-semantics-ci-${{ github.sha }} - name: 'Build' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make build RELEASE=true -j4' + - name: 'Install Pykelrond' + run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make poetry-install' - name: 'Run Python Unit Tests' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make TEST_CONCRETE_BACKEND=llvm unittest-python' - name: 'Run Simple Test' @@ -49,6 +51,8 @@ jobs: container-name: elrond-semantics-ci-${{ github.sha }} - name: 'Build' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make build RELEASE=true -j4' + - name: 'Install Pykelrond' + run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make poetry-install' - name: 'Run Basic Feature Test' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make TEST_CONCRETE_BACKEND=llvm test-elrond-basic-features -j6' - name: 'Run Alloc Feature Test' @@ -74,6 +78,8 @@ jobs: container-name: elrond-semantics-ci-${{ github.sha }} - name: 'Build' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make build RELEASE=true -j4' + - name: 'Install Pykelrond' + run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make poetry-install' - name: 'Run Adder Contract Test' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make TEST_CONCRETE_BACKEND=llvm test-elrond-adder' - name: 'Run Crowdfunding ESDT Contract Test' @@ -101,6 +107,8 @@ jobs: container-name: elrond-semantics-ci-${{ github.sha }} - name: 'Build' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make build RELEASE=true -j4' + - name: 'Install Pykelrond' + run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make poetry-install' - name: 'Run Custom Contract Tests' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make TEST_CONCRETE_BACKEND=llvm test-custom-contracts' - name: 'Tear down Docker' From 151965488dd0438f410ef9dcf53f51d85d1e4253 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Fri, 25 Aug 2023 12:25:45 +0300 Subject: [PATCH 10/16] poetry install no ansi output --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4f309803..704cab5f 100644 --- a/Makefile +++ b/Makefile @@ -267,7 +267,7 @@ POETRY_RUN := $(POETRY) run .PHONY: poetry-install poetry-install: - $(POETRY) install + $(POETRY) install --no-ansi TEST_MANDOS := $(POETRY_RUN) mandos --definition-dir $(llvm_dir)/mandos-kompiled From e8f32a1626eb926b967fdc759f8101d2a4f0ffc9 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Tue, 29 Aug 2023 12:56:47 +0300 Subject: [PATCH 11/16] generate Cargo.lock if it doesn't exist --- Makefile | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 704cab5f..1a4d5789 100644 --- a/Makefile +++ b/Makefile @@ -271,6 +271,12 @@ poetry-install: TEST_MANDOS := $(POETRY_RUN) mandos --definition-dir $(llvm_dir)/mandos-kompiled +mxpy-build/%: + if [ ! -f "$*/Cargo.lock" ]; then \ + cargo generate-lockfile --manifest-path $*/Cargo.toml -Z minimal-versions ; \ + fi + + mxpy contract build "$*" --wasm-symbols --no-wasm-opt ## Mandos Test @@ -284,8 +290,7 @@ mandos-test: $(llvm_kompiled) poetry-install ELROND_ADDER_DIR := $(ELROND_CONTRACT_EXAMPLES)/adder elrond_adder_tests=$(shell find $(ELROND_ADDER_DIR) -name "*.scen.json") -test-elrond-adder: $(llvm_kompiled) poetry-install - mxpy contract build "$(ELROND_ADDER_DIR)" --wasm-symbols +test-elrond-adder: $(llvm_kompiled) poetry-install mxpy-build/$(ELROND_ADDER_DIR) $(TEST_MANDOS) $(elrond_adder_tests) @@ -294,8 +299,7 @@ test-elrond-adder: $(llvm_kompiled) poetry-install ELROND_CROWDFUNDING_DIR := $(ELROND_CONTRACT_EXAMPLES)/crowdfunding-esdt elrond_crowdfunding_tests=$(shell find $(ELROND_CROWDFUNDING_DIR) -name "*.scen.json") -test-elrond-crowdfunding-esdt: $(llvm_kompiled) poetry-install - mxpy contract build "$(ELROND_CROWDFUNDING_DIR)" --wasm-symbols +test-elrond-crowdfunding-esdt: $(llvm_kompiled) poetry-install mxpy-build/$(ELROND_CROWDFUNDING_DIR) $(TEST_MANDOS) $(elrond_crowdfunding_tests) ## Multisg Test @@ -303,8 +307,7 @@ test-elrond-crowdfunding-esdt: $(llvm_kompiled) poetry-install ELROND_MULTISIG_DIR=$(ELROND_CONTRACT_EXAMPLES)/multisig elrond_multisig_tests=$(shell cat tests/multisig.test) -test-elrond-multisig: $(llvm_kompiled) poetry-install - mxpy contract build "$(ELROND_MULTISIG_DIR)" --wasm-symbols +test-elrond-multisig: $(llvm_kompiled) poetry-install mxpy-build/$(ELROND_MULTISIG_DIR) $(TEST_MANDOS) $(elrond_multisig_tests) ## Basic Feature Test @@ -313,8 +316,7 @@ ELROND_BASIC_FEATURES_DIR=$(ELROND_CONTRACT)/feature-tests/basic-features ELROND_BASIC_FEATURES_WASM=$(ELROND_BASIC_FEATURES_DIR)/output/basic-features.wasm elrond_basic_features_tests=$(shell cat tests/basic_features.test) -$(ELROND_BASIC_FEATURES_WASM): - mxpy contract build "$(ELROND_BASIC_FEATURES_DIR)" --wasm-symbols +$(ELROND_BASIC_FEATURES_WASM): mxpy-build/$(ELROND_BASIC_FEATURES_DIR) # TODO optimize test runner and enable logging test-elrond-basic-features: $(elrond_basic_features_tests:=.mandos) @@ -328,8 +330,7 @@ ELROND_ALLOC_FEATURES_DIR=$(ELROND_CONTRACT)/feature-tests/alloc-features ELROND_ALLOC_FEATURES_WASM=$(ELROND_ALLOC_FEATURES_DIR)/output/alloc-features.wasm elrond_alloc_features_tests=$(shell cat tests/alloc_features.test) -$(ELROND_ALLOC_FEATURES_WASM): - mxpy contract build "$(ELROND_ALLOC_FEATURES_DIR)" --wasm-symbols +$(ELROND_ALLOC_FEATURES_WASM): mxpy-build/$(ELROND_ALLOC_FEATURES_DIR) # TODO optimize test runner and enable logging test-elrond-alloc-features: $(elrond_alloc_features_tests:=.mandos) @@ -349,9 +350,10 @@ ELROND_ADDERCALLER_DIR := tests/contracts/addercaller elrond_addercaller_tests=$(shell find $(ELROND_ADDERCALLER_DIR) -name "*.scen.json") ELROND_MYADDER_DIR := tests/contracts/myadder -test-elrond-addercaller: $(llvm_kompiled) poetry-install - mxpy contract build "$(ELROND_MYADDER_DIR)" --wasm-symbols - mxpy contract build "$(ELROND_ADDERCALLER_DIR)" --wasm-symbols +test-elrond-addercaller: $(llvm_kompiled) \ + poetry-install \ + mxpy-build/$(ELROND_MYADDER_DIR) \ + mxpy-build/$(ELROND_ADDERCALLER_DIR) $(TEST_MANDOS) $(elrond_addercaller_tests) ## Caller Callee Test @@ -360,9 +362,10 @@ ELROND_CALLER_DIR := tests/contracts/caller ELROND_CALLEE_DIR := tests/contracts/callee elrond_callercallee_tests=$(shell find $(ELROND_CALLER_DIR) -name "*.scen.json") -test-elrond-callercallee: $(llvm_kompiled) poetry-install - mxpy contract build "$(ELROND_CALLER_DIR)" --wasm-symbols - mxpy contract build "$(ELROND_CALLEE_DIR)" --wasm-symbols +test-elrond-callercallee: $(llvm_kompiled) \ + poetry-install \ + mxpy-build/$(ELROND_CALLER_DIR) \ + mxpy-build/$(ELROND_CALLEE_DIR) $(TEST_MANDOS) $(elrond_callercallee_tests) # Unit Tests From 18dd0558373b6c02bc6f495d5a987f869e828925 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Tue, 29 Aug 2023 22:31:59 +0300 Subject: [PATCH 12/16] add comment to mxpy-build --- Makefile | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Makefile b/Makefile index 1a4d5789..ca47a42d 100644 --- a/Makefile +++ b/Makefile @@ -271,6 +271,13 @@ poetry-install: TEST_MANDOS := $(POETRY_RUN) mandos --definition-dir $(llvm_dir)/mandos-kompiled +# Cargo resolves dependencies to the latest version that satisfy requirements without taking +# the rustc version into account, which leads to the following error: +# +# > error: package `clap_derive v4.4.0` cannot be built because it requires rustc 1.70.0 or newer, +# > while the currently active rustc version is 1.69.0-nightly +# +# To avoid this, we enforce minimal version resolution before building the contract mxpy-build/%: if [ ! -f "$*/Cargo.lock" ]; then \ cargo generate-lockfile --manifest-path $*/Cargo.toml -Z minimal-versions ; \ From 0ac887d6773833668f85fe7b5827b76a087966e6 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Tue, 29 Aug 2023 22:46:17 +0300 Subject: [PATCH 13/16] pykelrond => kmultiversx --- .github/workflows/test-pr.yml | 8 ++++---- Makefile | 2 +- README.md | 20 +++++++++---------- {pykelrond => kmultiversx}/.cruft.json | 6 +++--- {pykelrond => kmultiversx}/.flake8 | 0 {pykelrond => kmultiversx}/.gitignore | 0 {pykelrond => kmultiversx}/Makefile | 2 +- {pykelrond => kmultiversx}/README.md | 2 +- {pykelrond => kmultiversx}/flake.nix | 8 ++++---- {pykelrond => kmultiversx}/poetry.lock | 0 {pykelrond => kmultiversx}/pyproject.toml | 6 +++--- .../src/kmultiversx}/__init__.py | 0 .../src/kmultiversx}/foundry.py | 2 +- .../src/kmultiversx}/py.typed | 0 .../src/kmultiversx}/scenario.py | 0 .../src/tests/__init__.py | 0 .../src/tests/integration/__init__.py | 0 .../src/tests/unit/__init__.py | 0 18 files changed, 28 insertions(+), 28 deletions(-) rename {pykelrond => kmultiversx}/.cruft.json (81%) rename {pykelrond => kmultiversx}/.flake8 (100%) rename {pykelrond => kmultiversx}/.gitignore (100%) rename {pykelrond => kmultiversx}/Makefile (95%) rename {pykelrond => kmultiversx}/README.md (97%) rename {pykelrond => kmultiversx}/flake.nix (82%) rename {pykelrond => kmultiversx}/poetry.lock (100%) rename {pykelrond => kmultiversx}/pyproject.toml (91%) rename {pykelrond/src/pykelrond => kmultiversx/src/kmultiversx}/__init__.py (100%) rename {pykelrond/src/pykelrond => kmultiversx/src/kmultiversx}/foundry.py (99%) rename {pykelrond/src/pykelrond => kmultiversx/src/kmultiversx}/py.typed (100%) rename {pykelrond/src/pykelrond => kmultiversx/src/kmultiversx}/scenario.py (100%) rename {pykelrond => kmultiversx}/src/tests/__init__.py (100%) rename {pykelrond => kmultiversx}/src/tests/integration/__init__.py (100%) rename {pykelrond => kmultiversx}/src/tests/unit/__init__.py (100%) diff --git a/.github/workflows/test-pr.yml b/.github/workflows/test-pr.yml index 9324dbcb..f62c5bfa 100644 --- a/.github/workflows/test-pr.yml +++ b/.github/workflows/test-pr.yml @@ -22,7 +22,7 @@ jobs: container-name: elrond-semantics-ci-${{ github.sha }} - name: 'Build' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make build RELEASE=true -j4' - - name: 'Install Pykelrond' + - name: 'Install Kmultiversx' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make poetry-install' - name: 'Run Python Unit Tests' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make TEST_CONCRETE_BACKEND=llvm unittest-python' @@ -51,7 +51,7 @@ jobs: container-name: elrond-semantics-ci-${{ github.sha }} - name: 'Build' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make build RELEASE=true -j4' - - name: 'Install Pykelrond' + - name: 'Install Kmultiversx' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make poetry-install' - name: 'Run Basic Feature Test' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make TEST_CONCRETE_BACKEND=llvm test-elrond-basic-features -j6' @@ -78,7 +78,7 @@ jobs: container-name: elrond-semantics-ci-${{ github.sha }} - name: 'Build' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make build RELEASE=true -j4' - - name: 'Install Pykelrond' + - name: 'Install Kmultiversx' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make poetry-install' - name: 'Run Adder Contract Test' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make TEST_CONCRETE_BACKEND=llvm test-elrond-adder' @@ -107,7 +107,7 @@ jobs: container-name: elrond-semantics-ci-${{ github.sha }} - name: 'Build' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make build RELEASE=true -j4' - - name: 'Install Pykelrond' + - name: 'Install Kmultiversx' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make poetry-install' - name: 'Run Custom Contract Tests' run: docker exec -t elrond-semantics-ci-${GITHUB_SHA} /bin/bash -c 'make TEST_CONCRETE_BACKEND=llvm test-custom-contracts' diff --git a/Makefile b/Makefile index ca47a42d..95115add 100644 --- a/Makefile +++ b/Makefile @@ -262,7 +262,7 @@ $(ELROND_LOADED_JSON): $(ELROND_RUNTIME) # Elrond Tests # ------------ -POETRY := poetry -C pykelrond +POETRY := poetry -C kmultiversx POETRY_RUN := $(POETRY) run .PHONY: poetry-install diff --git a/README.md b/README.md index c19c06f1..b6622f88 100644 --- a/README.md +++ b/README.md @@ -40,17 +40,17 @@ $ make elrond-clean-sources $ make elrond-loaded ``` -### Installing `pykelrond` +### Installing `kmultiversx` -`pykelrond` is a Python package providing libraries and CLI tools to interact with the semantics. -To install `pykelrond` and its dependencies into a virtual environment, run +`kmultiversx` is a Python package providing libraries and CLI tools to interact with the semantics. +To install `kmultiversx` and its dependencies into a virtual environment, run ``` # from the project's root directory -poetry -C pykelrond install +poetry -C kmultiversx install ``` -After the installation, the Python package `pykelrond` and CLI tools `mandos` and `foundry` will be available via the `poetry run` command +After the installation, the Python package `kmultiversx` and CLI tools `mandos` and `foundry` will be available via the `poetry run` command ``` poetry -C run mandos --help @@ -60,15 +60,15 @@ poetry -C run foundry --help Or you can activate the virtual environment managed by `poetry` and use the commands directly ``` -poetry -C pykelrond shell +poetry -C kmultiversx shell mandos --help ``` -Alternatively, you can install `pykelrond` globally +Alternatively, you can install `kmultiversx` globally ``` -make -C pykelrond build -pip install pykelrond/dist/*.whl +make -C kmultiversx build +pip install kmultiversx/dist/*.whl mandos --help foundry --help ``` @@ -84,7 +84,7 @@ $ mxpy contract build "" --wasm-symbols Then run Mandos scenarios with: ```shell -poetry -C pykelrond run mandos --definition .build/defn/llvm/mandos-kompiled +poetry -C kmultiversx run mandos --definition .build/defn/llvm/mandos-kompiled ``` Or with a globally installed instance diff --git a/pykelrond/.cruft.json b/kmultiversx/.cruft.json similarity index 81% rename from pykelrond/.cruft.json rename to kmultiversx/.cruft.json index 3fea3ce1..66838433 100644 --- a/pykelrond/.cruft.json +++ b/kmultiversx/.cruft.json @@ -4,9 +4,9 @@ "checkout": null, "context": { "cookiecutter": { - "project_name": "pykelrond", - "project_slug": "pykelrond", - "package_name": "pykelrond", + "project_name": "kmultiversx", + "project_slug": "kmultiversx", + "package_name": "kmultiversx", "version": "0.1.0", "description": "Python tools for Elrond semantics", "author_name": "Runtime Verification, Inc.", diff --git a/pykelrond/.flake8 b/kmultiversx/.flake8 similarity index 100% rename from pykelrond/.flake8 rename to kmultiversx/.flake8 diff --git a/pykelrond/.gitignore b/kmultiversx/.gitignore similarity index 100% rename from pykelrond/.gitignore rename to kmultiversx/.gitignore diff --git a/pykelrond/Makefile b/kmultiversx/Makefile similarity index 95% rename from pykelrond/Makefile rename to kmultiversx/Makefile index d627d381..c7b97436 100644 --- a/pykelrond/Makefile +++ b/kmultiversx/Makefile @@ -42,7 +42,7 @@ COV_ARGS := cov: cov-all -cov-%: TEST_ARGS += --cov=pykelrond --no-cov-on-fail --cov-branch --cov-report=term +cov-%: TEST_ARGS += --cov=kmultiversx --no-cov-on-fail --cov-branch --cov-report=term cov-all: TEST_ARGS += --cov-report=html:cov-all-html $(COV_ARGS) cov-all: test-all diff --git a/pykelrond/README.md b/kmultiversx/README.md similarity index 97% rename from pykelrond/README.md rename to kmultiversx/README.md index 3b1575ed..367ea801 100644 --- a/pykelrond/README.md +++ b/kmultiversx/README.md @@ -1,4 +1,4 @@ -# pykelrond +# kmultiversx ## Installation diff --git a/pykelrond/flake.nix b/kmultiversx/flake.nix similarity index 82% rename from pykelrond/flake.nix rename to kmultiversx/flake.nix index db6b0786..928ab406 100644 --- a/pykelrond/flake.nix +++ b/kmultiversx/flake.nix @@ -1,5 +1,5 @@ { - description = "pykelrond - Python tools for Elrond semantics"; + description = "kmultiversx - Python tools for Elrond semantics"; inputs = { nixpkgs.url = "nixpkgs/nixos-22.05"; flake-utils.url = "github:numtide/flake-utils"; @@ -10,7 +10,7 @@ allOverlays = [ poetry2nix.overlay (final: prev: { - pykelrond = prev.poetry2nix.mkPoetryApplication { + kmultiversx = prev.poetry2nix.mkPoetryApplication { python = prev.python310; projectDir = ./.; groups = []; @@ -32,8 +32,8 @@ }; in { packages = rec { - inherit (pkgs) pykelrond; - default = pykelrond; + inherit (pkgs) kmultiversx; + default = kmultiversx; }; }) // { overlay = nixpkgs.lib.composeManyExtensions allOverlays; diff --git a/pykelrond/poetry.lock b/kmultiversx/poetry.lock similarity index 100% rename from pykelrond/poetry.lock rename to kmultiversx/poetry.lock diff --git a/pykelrond/pyproject.toml b/kmultiversx/pyproject.toml similarity index 91% rename from pykelrond/pyproject.toml rename to kmultiversx/pyproject.toml index ed2bedaf..d013b6d5 100644 --- a/pykelrond/pyproject.toml +++ b/kmultiversx/pyproject.toml @@ -3,7 +3,7 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.poetry] -name = "pykelrond" +name = "kmultiversx" version = "0.1.0" description = "Python tools for Elrond semantics" authors = [ @@ -53,5 +53,5 @@ skip-string-normalization = true disallow_untyped_defs = true [tool.poetry.scripts] -mandos = "pykelrond.scenario:run_tests" -foundry = "pykelrond.foundry:main" +mandos = "kmultiversx.scenario:run_tests" +foundry = "kmultiversx.foundry:main" diff --git a/pykelrond/src/pykelrond/__init__.py b/kmultiversx/src/kmultiversx/__init__.py similarity index 100% rename from pykelrond/src/pykelrond/__init__.py rename to kmultiversx/src/kmultiversx/__init__.py diff --git a/pykelrond/src/pykelrond/foundry.py b/kmultiversx/src/kmultiversx/foundry.py similarity index 99% rename from pykelrond/src/pykelrond/foundry.py rename to kmultiversx/src/kmultiversx/foundry.py index a19d8094..153ff9ad 100644 --- a/pykelrond/src/pykelrond/foundry.py +++ b/kmultiversx/src/kmultiversx/foundry.py @@ -22,7 +22,7 @@ from pykwasm import wasm2kast from pykwasm.kwasm_ast import KInt -from pykelrond.scenario import ( +from kmultiversx.scenario import ( KList, KMapBytesToBytes, KWasmString, diff --git a/pykelrond/src/pykelrond/py.typed b/kmultiversx/src/kmultiversx/py.typed similarity index 100% rename from pykelrond/src/pykelrond/py.typed rename to kmultiversx/src/kmultiversx/py.typed diff --git a/pykelrond/src/pykelrond/scenario.py b/kmultiversx/src/kmultiversx/scenario.py similarity index 100% rename from pykelrond/src/pykelrond/scenario.py rename to kmultiversx/src/kmultiversx/scenario.py diff --git a/pykelrond/src/tests/__init__.py b/kmultiversx/src/tests/__init__.py similarity index 100% rename from pykelrond/src/tests/__init__.py rename to kmultiversx/src/tests/__init__.py diff --git a/pykelrond/src/tests/integration/__init__.py b/kmultiversx/src/tests/integration/__init__.py similarity index 100% rename from pykelrond/src/tests/integration/__init__.py rename to kmultiversx/src/tests/integration/__init__.py diff --git a/pykelrond/src/tests/unit/__init__.py b/kmultiversx/src/tests/unit/__init__.py similarity index 100% rename from pykelrond/src/tests/unit/__init__.py rename to kmultiversx/src/tests/unit/__init__.py From fb047c144927db66e281c87bf2cf55ef1dc4c4cf Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 30 Aug 2023 15:28:05 +0300 Subject: [PATCH 14/16] minor corrections --- README.md | 6 +++--- kmultiversx/src/kmultiversx/foundry.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b6622f88..2a8eb863 100644 --- a/README.md +++ b/README.md @@ -46,15 +46,15 @@ $ make elrond-loaded To install `kmultiversx` and its dependencies into a virtual environment, run ``` -# from the project's root directory +# from the 'elrond-semantics' directory poetry -C kmultiversx install ``` After the installation, the Python package `kmultiversx` and CLI tools `mandos` and `foundry` will be available via the `poetry run` command ``` -poetry -C run mandos --help -poetry -C run foundry --help +poetry -C kmultiversx run mandos --help +poetry -C kmultiversx run foundry --help ``` Or you can activate the virtual environment managed by `poetry` and use the commands directly diff --git a/kmultiversx/src/kmultiversx/foundry.py b/kmultiversx/src/kmultiversx/foundry.py index 153ff9ad..36948755 100644 --- a/kmultiversx/src/kmultiversx/foundry.py +++ b/kmultiversx/src/kmultiversx/foundry.py @@ -52,7 +52,7 @@ def load_input_json(test_dir: str) -> dict: with open(join(test_dir, INPUT_FILE_NAME), 'r') as f: return json.load(f) except FileNotFoundError: - raise FileNotFoundError('"{INPUT_FILE_NAME}" not found in "{test_dir}"') from None + raise FileNotFoundError(f'"{INPUT_FILE_NAME}" not found in "{test_dir}"') from None def load_wasm(filename: str) -> KInner: From b3245110f49b83c7a81695860ff0ae814b835c88 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 30 Aug 2023 15:28:47 +0300 Subject: [PATCH 15/16] add python code quality checks --- .github/workflows/test-pr.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/test-pr.yml b/.github/workflows/test-pr.yml index f62c5bfa..db1a28c1 100644 --- a/.github/workflows/test-pr.yml +++ b/.github/workflows/test-pr.yml @@ -7,9 +7,22 @@ concurrency: cancel-in-progress: true jobs: + python-code-quality-checks: + name: 'Code Quality Checks' + runs-on: ubuntu-latest + steps: + - name: 'Check out code' + uses: actions/checkout@v3 + with: + submodules: recursive + - name: 'Install Poetry' + uses: Gr1N/setup-poetry@v8 + - name: 'Build and run code quality checks' + run: make -C kmultiversx check simple-tests: runs-on: [self-hosted, linux, normal] name: 'Simple Tests' + needs: [python-code-quality-checks] timeout-minutes: 30 steps: - name: 'Check out code' From 5e29e87aa021785a9fd0494012f8cd17ae288b72 Mon Sep 17 00:00:00 2001 From: Burak Bilge Yalcinkaya Date: Wed, 30 Aug 2023 15:35:28 +0300 Subject: [PATCH 16/16] add conversion flags --- kmultiversx/src/kmultiversx/foundry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kmultiversx/src/kmultiversx/foundry.py b/kmultiversx/src/kmultiversx/foundry.py index 36948755..216c21f4 100644 --- a/kmultiversx/src/kmultiversx/foundry.py +++ b/kmultiversx/src/kmultiversx/foundry.py @@ -52,7 +52,7 @@ def load_input_json(test_dir: str) -> dict: with open(join(test_dir, INPUT_FILE_NAME), 'r') as f: return json.load(f) except FileNotFoundError: - raise FileNotFoundError(f'"{INPUT_FILE_NAME}" not found in "{test_dir}"') from None + raise FileNotFoundError(f'{INPUT_FILE_NAME!r} not found in "{test_dir!r}"') from None def load_wasm(filename: str) -> KInner: