From d006babfd7f41c39840ab6c3bb124e6d04664a71 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:50:36 +0000 Subject: [PATCH 1/8] chore(deps): Bump markdown from 3.6 to 3.7 Bumps [markdown](https://github.com/Python-Markdown/markdown) from 3.6 to 3.7. - [Release notes](https://github.com/Python-Markdown/markdown/releases) - [Changelog](https://github.com/Python-Markdown/markdown/blob/master/docs/changelog.md) - [Commits](https://github.com/Python-Markdown/markdown/compare/3.6...3.7) --- updated-dependencies: - dependency-name: markdown dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- poetry.lock | 8 ++++---- pyproject.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poetry.lock b/poetry.lock index d78d79bea0..8b725b5f0a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1340,13 +1340,13 @@ source = ["Cython (>=3.0.10)"] [[package]] name = "markdown" -version = "3.6" +version = "3.7" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.8" files = [ - {file = "Markdown-3.6-py3-none-any.whl", hash = "sha256:48f276f4d8cfb8ce6527c8f79e2ee29708508bf4d40aa410fbc3b4ee832c850f"}, - {file = "Markdown-3.6.tar.gz", hash = "sha256:ed4f41f6daecbeeb96e576ce414c41d2d876daa9a16cb35fa8ed8c2ddfad0224"}, + {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, + {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, ] [package.extras] @@ -2838,4 +2838,4 @@ didcommv2 = ["didcomm-messaging"] [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "7e88483ab9712512407e9aebe7643e00a01cb1adcc2b7b034b4e25896b458550" +content-hash = "8a2afe7d38e2e6e4a2e31303a2e6527a1259ead9410e8c96554b5e031d77f4bd" diff --git a/pyproject.toml b/pyproject.toml index 0954e29d40..00c0175e76 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,7 +26,7 @@ ConfigArgParse="~1.7" deepmerge="~0.3.0" ecdsa="~0.19.0" jsonpath-ng="1.6.1" -Markdown="~3.6" +Markdown="~3.7" markupsafe="2.1.5" marshmallow="~3.21.3" nest_asyncio="~1.6.0" From 063156569ba74c139796e0271c57a697a940a7ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 08:31:43 -0700 Subject: [PATCH 2/8] chore(deps): Bump mike from 2.1.2 to 2.1.3 (#3179) Bumps [mike](https://github.com/jimporter/mike) from 2.1.2 to 2.1.3. - [Release notes](https://github.com/jimporter/mike/releases) - [Changelog](https://github.com/jimporter/mike/blob/master/CHANGES.md) - [Commits](https://github.com/jimporter/mike/compare/v2.1.2...v2.1.3) --- updated-dependencies: - dependency-name: mike dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- mkdocs-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs-requirements.txt b/mkdocs-requirements.txt index a61c96e5e6..fa7911c6b2 100644 --- a/mkdocs-requirements.txt +++ b/mkdocs-requirements.txt @@ -1,3 +1,3 @@ mkdocs-material==9.5.31 -mike==2.1.2 +mike==2.1.3 From 4460981106844e884a58fa894558b2091a3de310 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Aug 2024 08:54:35 -0700 Subject: [PATCH 3/8] chore(deps): Bump mkdocs-material from 9.5.31 to 9.5.32 (#3178) Bumps [mkdocs-material](https://github.com/squidfunk/mkdocs-material) from 9.5.31 to 9.5.32. - [Release notes](https://github.com/squidfunk/mkdocs-material/releases) - [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG) - [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.5.31...9.5.32) --- updated-dependencies: - dependency-name: mkdocs-material dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- mkdocs-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs-requirements.txt b/mkdocs-requirements.txt index fa7911c6b2..6d8cc0a50d 100644 --- a/mkdocs-requirements.txt +++ b/mkdocs-requirements.txt @@ -1,3 +1,3 @@ -mkdocs-material==9.5.31 +mkdocs-material==9.5.32 mike==2.1.3 From f29e67e452cb0168b2d2199a5010b4115fa89bf0 Mon Sep 17 00:00:00 2001 From: Ricky Ng-Adam Date: Tue, 20 Aug 2024 14:12:18 -0400 Subject: [PATCH 4/8] fixes #3186: check that the section handler_timed_file_handler exists before trying to modify it (#3187) Signed-off-by: Ricky Ng-Adam Co-authored-by: Stephen Curran --- aries_cloudagent/config/logging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aries_cloudagent/config/logging.py b/aries_cloudagent/config/logging.py index 9d74b0b0a7..695b680dd2 100644 --- a/aries_cloudagent/config/logging.py +++ b/aries_cloudagent/config/logging.py @@ -118,7 +118,7 @@ def fileConfig( except configparser.ParsingError as e: raise RuntimeError(f"{fname} is invalid: {e}") - if new_file_path: + if new_file_path and cp.has_section("handler_timed_file_handler"): cp.set( "handler_timed_file_handler", "args", From 96e831539a84bac7bff12cf8ab7ee65a073d760b Mon Sep 17 00:00:00 2001 From: jamshale <31809382+jamshale@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:17:08 -0700 Subject: [PATCH 5/8] Adjust message queue error handling (#3170) Signed-off-by: jamshale --- .../transport/outbound/manager.py | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/aries_cloudagent/transport/outbound/manager.py b/aries_cloudagent/transport/outbound/manager.py index 55be0bd8d4..0ee1258b74 100644 --- a/aries_cloudagent/transport/outbound/manager.py +++ b/aries_cloudagent/transport/outbound/manager.py @@ -470,40 +470,43 @@ def deliver_queued_message(self, queued: QueuedOutboundMessage) -> asyncio.Task: ) return queued.task + def _finished_deliver_error_handler(self, queued: QueuedOutboundMessage, retry: bool): + if retry: + LOGGER.debug( + ( + ">>> Error when posting to: %s; " + "Error: %s; " + "Payload: %s; Re-queue failed message ..." + ), + queued.endpoint, + queued.error, + queued.payload, + ) + else: + err_msg = ">>> Outbound message failed to deliver, NOT Re-queued." + if "/webhook/topic" in queued.endpoint: + LOGGER.warning( + err_msg, + exc_info=queued.error, + ) + else: + LOGGER.exception( + err_msg, + exc_info=queued.error, + ) + def finished_deliver(self, queued: QueuedOutboundMessage, completed: CompletedTask): """Handle completion of queued message delivery.""" if completed.exc_info: queued.error = completed.exc_info if queued.retries: - if LOGGER.isEnabledFor(logging.DEBUG): - LOGGER.error( - ( - ">>> Error when posting to: %s; " - "Error: %s; " - "Payload: %s; Re-queue failed message ..." - ), - queued.endpoint, - queued.error, - queued.payload, - ) - else: - LOGGER.error( - ( - ">>> Error when posting to: %s; " - "Error: %s; Re-queue failed message ..." - ), - queued.endpoint, - queued.error, - ) + self._finished_deliver_error_handler(queued, retry=True) queued.retries -= 1 queued.state = QueuedOutboundMessage.STATE_RETRY queued.retry_at = time.perf_counter() + 10 else: - LOGGER.exception( - ">>> Outbound message failed to deliver, NOT Re-queued.", - exc_info=queued.error, - ) + self._finished_deliver_error_handler(queued, retry=False) queued.state = QueuedOutboundMessage.STATE_DONE else: queued.error = None From 3c7919764348e831886edcf79cb36e1bcd27295b Mon Sep 17 00:00:00 2001 From: Ricky Ng-Adam Date: Thu, 22 Aug 2024 11:45:12 -0400 Subject: [PATCH 6/8] issue #3182: replace deprecated ptvsd debugger by debugpy (#3183) * fixes #3182: migrate from ptvsd to debugpy Signed-off-by: Ricky Ng-Adam * issue #3182: replace underlying debugger with debugpy Signed-off-by: Ricky Ng-Adam * issue #3182: allow to debug provision and upgrade Signed-off-by: Ricky Ng-Adam * issue #3182: introduce DAP_HOST and DAP_PORT Signed-off-by: Ricky Ng-Adam * issue #3182: fix up conftest.py to use debugpy Signed-off-by: Ricky Ng-Adam * issue #3182: update command-line help for --debug Signed-off-by: Ricky Ng-Adam --------- Signed-off-by: Ricky Ng-Adam --- aries_cloudagent/__main__.py | 14 +- aries_cloudagent/config/argparse.py | 32 +- aries_cloudagent/tests/test_main.py | 6 +- conftest.py | 25 +- docs/features/DevReadMe.md | 13 +- poetry.lock | 673 +++++++++++++++------------- pyproject.toml | 2 +- 7 files changed, 421 insertions(+), 344 deletions(-) diff --git a/aries_cloudagent/__main__.py b/aries_cloudagent/__main__.py index 9c62fb9d8e..6b4ebc76f7 100644 --- a/aries_cloudagent/__main__.py +++ b/aries_cloudagent/__main__.py @@ -20,16 +20,16 @@ def init_debug(args): # --debug to use microsoft's visual studio remote debugger if ENABLE_PTVSD or "--debug" in args: + DAP_HOST = os.getenv("PTVSD_HOST", None) or os.getenv("DAP_HOST", "localhost") + DAP_PORT = os.getenv("PTVSD_PORT", None) or os.getenv("DAP_PORT", 5678) try: - import ptvsd + import debugpy - ptvsd.enable_attach() - print("ptvsd is running") - print("=== Waiting for debugger to attach ===") - # To pause execution until the debugger is attached: - ptvsd.wait_for_attach() + debugpy.listen((DAP_HOST, DAP_PORT)) + print(f"=== Waiting for debugger to attach to {DAP_HOST}:{DAP_PORT} ===") + debugpy.wait_for_client() except ImportError: - print("ptvsd library was not found") + print("debugpy library was not found") if ENABLE_PYDEVD_PYCHARM or "--debug-pycharm" in args: try: diff --git a/aries_cloudagent/config/argparse.py b/aries_cloudagent/config/argparse.py index 34427e9431..717169e5d0 100644 --- a/aries_cloudagent/config/argparse.py +++ b/aries_cloudagent/config/argparse.py @@ -214,11 +214,11 @@ def get_settings(self, args: Namespace): return settings -@group(CAT_START) -class DebugGroup(ArgumentGroup): - """Debug settings.""" +@group(CAT_PROVISION, CAT_START, CAT_UPGRADE) +class DebuggerGroup(ArgumentGroup): + """Debugger settings.""" - GROUP_NAME = "Debug" + GROUP_NAME = "Debugger" def add_arguments(self, parser: ArgumentParser): """Add debug command line arguments to the parser.""" @@ -228,10 +228,28 @@ def add_arguments(self, parser: ArgumentParser): env_var="ACAPY_DEBUG", help=( "Enables a remote debugging service that can be accessed " - "using ptvsd for Visual Studio Code. The framework will wait " - "for the debugger to connect at start-up. Default: false." + "using the Debug Adapter Protocol (supported by Visual Studio Code). " + "The framework will wait for the debugger to connect at start-up. " + "Default: false." ), ) + + def get_settings(self, args: Namespace) -> dict: + """Extract debug settings.""" + settings = {} + if args.debug: + settings["debug.enabled"] = True + return settings + + +@group(CAT_START) +class DebugGroup(ArgumentGroup): + """Debug settings.""" + + GROUP_NAME = "Debug" + + def add_arguments(self, parser: ArgumentParser): + """Add debug command line arguments to the parser.""" parser.add_argument( "--debug-seed", dest="debug_seed", @@ -415,8 +433,6 @@ def add_arguments(self, parser: ArgumentParser): def get_settings(self, args: Namespace) -> dict: """Extract debug settings.""" settings = {} - if args.debug: - settings["debug.enabled"] = True if args.debug_connections: settings["debug.connections"] = True if args.debug_credentials: diff --git a/aries_cloudagent/tests/test_main.py b/aries_cloudagent/tests/test_main.py index 897d1b21db..c7093b80b0 100644 --- a/aries_cloudagent/tests/test_main.py +++ b/aries_cloudagent/tests/test_main.py @@ -34,9 +34,9 @@ def test_ptvsd(self): test_module.init_debug(["aca-py", "--debug"]) mock_import.assert_called_once() - self.assertEqual(mock_import.call_args[0][0], "ptvsd") - mock_import.return_value.enable_attach.assert_called_once() - mock_import.return_value.wait_for_attach.assert_called_once() + self.assertEqual(mock_import.call_args[0][0], "debugpy") + mock_import.return_value.listen.assert_called_once() + mock_import.return_value.wait_for_client.assert_called_once() def test_ptvsd_import_x(self): with mock.patch("builtins.__import__") as mock_import: diff --git a/conftest.py b/conftest.py index d92c54c430..16262bba93 100644 --- a/conftest.py +++ b/conftest.py @@ -146,19 +146,24 @@ def stub_ursa_bbs_signatures() -> Stub: def pytest_sessionstart(session): global STUBS, POSTGRES_URL, ENABLE_PTVSD - ENABLE_PTVSD = os.getenv("ENABLE_PTVSD", False) - # --debug-vs to use microsoft's visual studio remote debugger - if ENABLE_PTVSD or "--debug" in sys.argv: + args = sys.argv + + # copied from __main__.py:init_debug + ENABLE_PTVSD = os.getenv("ENABLE_PTVSD", "").lower() + ENABLE_PTVSD = ENABLE_PTVSD and ENABLE_PTVSD not in ("false", "0") + + # --debug to use microsoft's visual studio remote debugger + if ENABLE_PTVSD or "--debug" in args: + DAP_HOST = os.getenv("PTVSD_HOST", None) or os.getenv("DAP_HOST", "localhost") + DAP_PORT = os.getenv("PTVSD_PORT", None) or os.getenv("DAP_PORT", 5678) try: - import ptvsd + import debugpy - ptvsd.enable_attach(address=("0.0.0.0", 5678)) - print("ptvsd is running") - print("=== Waiting for debugger to attach ===") - # To pause execution until the debugger is attached: - ptvsd.wait_for_attach() + debugpy.listen((DAP_HOST, DAP_PORT)) + print(f"=== Waiting for debugger to attach to {DAP_HOST}:{DAP_PORT} ===") + debugpy.wait_for_client() except ImportError: - print("ptvsd library was not found") + print("debugpy library was not found") POSTGRES_URL = os.getenv("POSTGRES_URL") diff --git a/docs/features/DevReadMe.md b/docs/features/DevReadMe.md index d11553c302..debd55e5b3 100644 --- a/docs/features/DevReadMe.md +++ b/docs/features/DevReadMe.md @@ -182,7 +182,18 @@ For example: ./scripts/run_docker start --inbound-transport http 0.0.0.0 10000 --outbound-transport http --debug --log-level DEBUG ``` -To enable the [ptvsd](https://github.com/Microsoft/ptvsd) Python debugger for Visual Studio/VSCode use the `--debug` command line parameter. +To enable the [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/) using the [debugpy implementation for Python 3](https://github.com/microsoft/debugpy/) Python debugger for Visual Studio/VSCode use the `--debug` command line parameter. + +When debugging an agent running within a docker container, you will need to set the DAP_HOST environment variable (defaults to ```localhost```) to ```0.0.0.0``` to allow forwarding from within your docker container. + +Note that you may still find references to [PTVSD](https://github.com/microsoft/ptvsd), the deprecated implementation of DAP. PTVSD_HOST and PTVSD_PORT are interchangeable with DAP_HOST and DAP_PORT. + +Example: + +```bash +ENV_VARS="DAP_HOST=0.0.0.0" scripts/run_docker provision --log-level debug --wallet-type askar --wallet-name $(whoami) --wallet-key mysecretkey --endpoint http://localhost:8080 --no-ledger --debug +``` + Any ports you will be using from the docker container should be published using the `PORTS` environment variable. For example: diff --git a/poetry.lock b/poetry.lock index 8b725b5f0a..6f631dabe0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,13 +2,13 @@ [[package]] name = "aiohappyeyeballs" -version = "2.3.4" +version = "2.4.0" description = "Happy Eyeballs for asyncio" optional = false -python-versions = "<4.0,>=3.8" +python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.3.4-py3-none-any.whl", hash = "sha256:40a16ceffcf1fc9e142fd488123b2e218abc4188cf12ac20c67200e1579baa42"}, - {file = "aiohappyeyeballs-2.3.4.tar.gz", hash = "sha256:7e1ae8399c320a8adec76f6c919ed5ceae6edd4c3672f4d9eae2b27e37c80ff6"}, + {file = "aiohappyeyeballs-2.4.0-py3-none-any.whl", hash = "sha256:7ce92076e249169a13c2f49320d1967425eaf1f407522d707d59cac7628d62bd"}, + {file = "aiohappyeyeballs-2.4.0.tar.gz", hash = "sha256:55a1714f084e63d49639800f95716da97a1f173d46a16dfcfda0016abb93b6b2"}, ] [[package]] @@ -237,32 +237,32 @@ files = [ [[package]] name = "attrs" -version = "23.2.0" +version = "24.2.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.7" files = [ - {file = "attrs-23.2.0-py3-none-any.whl", hash = "sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"}, - {file = "attrs-23.2.0.tar.gz", hash = "sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30"}, + {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, + {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, ] [package.extras] -cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] -dev = ["attrs[tests]", "pre-commit"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] -tests = ["attrs[tests-no-zope]", "zope-interface"] -tests-mypy = ["mypy (>=1.6)", "pytest-mypy-plugins"] -tests-no-zope = ["attrs[tests-mypy]", "cloudpickle", "hypothesis", "pympler", "pytest (>=4.3.0)", "pytest-xdist[psutil]"] +benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "babel" -version = "2.15.0" +version = "2.16.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" files = [ - {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, - {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, + {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, + {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, ] [package.extras] @@ -295,13 +295,13 @@ files = [ [[package]] name = "cachetools" -version = "5.4.0" +version = "5.5.0" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" files = [ - {file = "cachetools-5.4.0-py3-none-any.whl", hash = "sha256:3ae3b49a3d5e28a77a0be2b37dbcb89005058959cb2323858c2657c4a8cab474"}, - {file = "cachetools-5.4.0.tar.gz", hash = "sha256:b8adc2e7c07f105ced7bc56dbb6dfbe7c4a00acce20e2227b3f355be89bc6827"}, + {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, + {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, ] [[package]] @@ -317,63 +317,78 @@ files = [ [[package]] name = "cffi" -version = "1.16.0" +version = "1.17.0" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" files = [ - {file = "cffi-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088"}, - {file = "cffi-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7"}, - {file = "cffi-1.16.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743"}, - {file = "cffi-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d"}, - {file = "cffi-1.16.0-cp310-cp310-win32.whl", hash = "sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a"}, - {file = "cffi-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404"}, - {file = "cffi-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56"}, - {file = "cffi-1.16.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc"}, - {file = "cffi-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb"}, - {file = "cffi-1.16.0-cp311-cp311-win32.whl", hash = "sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab"}, - {file = "cffi-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956"}, - {file = "cffi-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6"}, - {file = "cffi-1.16.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969"}, - {file = "cffi-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520"}, - {file = "cffi-1.16.0-cp312-cp312-win32.whl", hash = "sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b"}, - {file = "cffi-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235"}, - {file = "cffi-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b"}, - {file = "cffi-1.16.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324"}, - {file = "cffi-1.16.0-cp38-cp38-win32.whl", hash = "sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a"}, - {file = "cffi-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed"}, - {file = "cffi-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4"}, - {file = "cffi-1.16.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000"}, - {file = "cffi-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe"}, - {file = "cffi-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4"}, - {file = "cffi-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8"}, - {file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"}, + {file = "cffi-1.17.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f9338cc05451f1942d0d8203ec2c346c830f8e86469903d5126c1f0a13a2bcbb"}, + {file = "cffi-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0ce71725cacc9ebf839630772b07eeec220cbb5f03be1399e0457a1464f8e1a"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c815270206f983309915a6844fe994b2fa47e5d05c4c4cef267c3b30e34dbe42"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6bdcd415ba87846fd317bee0774e412e8792832e7805938987e4ede1d13046d"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a98748ed1a1df4ee1d6f927e151ed6c1a09d5ec21684de879c7ea6aa96f58f2"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0a048d4f6630113e54bb4b77e315e1ba32a5a31512c31a273807d0027a7e69ab"}, + {file = "cffi-1.17.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24aa705a5f5bd3a8bcfa4d123f03413de5d86e497435693b638cbffb7d5d8a1b"}, + {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:856bf0924d24e7f93b8aee12a3a1095c34085600aa805693fb7f5d1962393206"}, + {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:4304d4416ff032ed50ad6bb87416d802e67139e31c0bde4628f36a47a3164bfa"}, + {file = "cffi-1.17.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:331ad15c39c9fe9186ceaf87203a9ecf5ae0ba2538c9e898e3a6967e8ad3db6f"}, + {file = "cffi-1.17.0-cp310-cp310-win32.whl", hash = "sha256:669b29a9eca6146465cc574659058ed949748f0809a2582d1f1a324eb91054dc"}, + {file = "cffi-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:48b389b1fd5144603d61d752afd7167dfd205973a43151ae5045b35793232aa2"}, + {file = "cffi-1.17.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5d97162c196ce54af6700949ddf9409e9833ef1003b4741c2b39ef46f1d9720"}, + {file = "cffi-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5ba5c243f4004c750836f81606a9fcb7841f8874ad8f3bf204ff5e56332b72b9"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb9333f58fc3a2296fb1d54576138d4cf5d496a2cc118422bd77835e6ae0b9cb"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:435a22d00ec7d7ea533db494da8581b05977f9c37338c80bc86314bec2619424"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1df34588123fcc88c872f5acb6f74ae59e9d182a2707097f9e28275ec26a12d"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:df8bb0010fdd0a743b7542589223a2816bdde4d94bb5ad67884348fa2c1c67e8"}, + {file = "cffi-1.17.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8b5b9712783415695663bd463990e2f00c6750562e6ad1d28e072a611c5f2a6"}, + {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ffef8fd58a36fb5f1196919638f73dd3ae0db1a878982b27a9a5a176ede4ba91"}, + {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e67d26532bfd8b7f7c05d5a766d6f437b362c1bf203a3a5ce3593a645e870b8"}, + {file = "cffi-1.17.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:45f7cd36186db767d803b1473b3c659d57a23b5fa491ad83c6d40f2af58e4dbb"}, + {file = "cffi-1.17.0-cp311-cp311-win32.whl", hash = "sha256:a9015f5b8af1bb6837a3fcb0cdf3b874fe3385ff6274e8b7925d81ccaec3c5c9"}, + {file = "cffi-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:b50aaac7d05c2c26dfd50c3321199f019ba76bb650e346a6ef3616306eed67b0"}, + {file = "cffi-1.17.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aec510255ce690d240f7cb23d7114f6b351c733a74c279a84def763660a2c3bc"}, + {file = "cffi-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2770bb0d5e3cc0e31e7318db06efcbcdb7b31bcb1a70086d3177692a02256f59"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:db9a30ec064129d605d0f1aedc93e00894b9334ec74ba9c6bdd08147434b33eb"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a47eef975d2b8b721775a0fa286f50eab535b9d56c70a6e62842134cf7841195"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3e0992f23bbb0be00a921eae5363329253c3b86287db27092461c887b791e5e"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6107e445faf057c118d5050560695e46d272e5301feffda3c41849641222a828"}, + {file = "cffi-1.17.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb862356ee9391dc5a0b3cbc00f416b48c1b9a52d252d898e5b7696a5f9fe150"}, + {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c1c13185b90bbd3f8b5963cd8ce7ad4ff441924c31e23c975cb150e27c2bf67a"}, + {file = "cffi-1.17.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:17c6d6d3260c7f2d94f657e6872591fe8733872a86ed1345bda872cfc8c74885"}, + {file = "cffi-1.17.0-cp312-cp312-win32.whl", hash = "sha256:c3b8bd3133cd50f6b637bb4322822c94c5ce4bf0d724ed5ae70afce62187c492"}, + {file = "cffi-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:dca802c8db0720ce1c49cce1149ff7b06e91ba15fa84b1d59144fef1a1bc7ac2"}, + {file = "cffi-1.17.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6ce01337d23884b21c03869d2f68c5523d43174d4fc405490eb0091057943118"}, + {file = "cffi-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cab2eba3830bf4f6d91e2d6718e0e1c14a2f5ad1af68a89d24ace0c6b17cced7"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14b9cbc8f7ac98a739558eb86fabc283d4d564dafed50216e7f7ee62d0d25377"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b00e7bcd71caa0282cbe3c90966f738e2db91e64092a877c3ff7f19a1628fdcb"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:41f4915e09218744d8bae14759f983e466ab69b178de38066f7579892ff2a555"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4760a68cab57bfaa628938e9c2971137e05ce48e762a9cb53b76c9b569f1204"}, + {file = "cffi-1.17.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:011aff3524d578a9412c8b3cfaa50f2c0bd78e03eb7af7aa5e0df59b158efb2f"}, + {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:a003ac9edc22d99ae1286b0875c460351f4e101f8c9d9d2576e78d7e048f64e0"}, + {file = "cffi-1.17.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ef9528915df81b8f4c7612b19b8628214c65c9b7f74db2e34a646a0a2a0da2d4"}, + {file = "cffi-1.17.0-cp313-cp313-win32.whl", hash = "sha256:70d2aa9fb00cf52034feac4b913181a6e10356019b18ef89bc7c12a283bf5f5a"}, + {file = "cffi-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:b7b6ea9e36d32582cda3465f54c4b454f62f23cb083ebc7a94e2ca6ef011c3a7"}, + {file = "cffi-1.17.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:964823b2fc77b55355999ade496c54dde161c621cb1f6eac61dc30ed1b63cd4c"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:516a405f174fd3b88829eabfe4bb296ac602d6a0f68e0d64d5ac9456194a5b7e"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dec6b307ce928e8e112a6bb9921a1cb00a0e14979bf28b98e084a4b8a742bd9b"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e4094c7b464cf0a858e75cd14b03509e84789abf7b79f8537e6a72152109c76e"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2404f3de742f47cb62d023f0ba7c5a916c9c653d5b368cc966382ae4e57da401"}, + {file = "cffi-1.17.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa9d43b02a0c681f0bfbc12d476d47b2b2b6a3f9287f11ee42989a268a1833c"}, + {file = "cffi-1.17.0-cp38-cp38-win32.whl", hash = "sha256:0bb15e7acf8ab35ca8b24b90af52c8b391690ef5c4aec3d31f38f0d37d2cc499"}, + {file = "cffi-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:93a7350f6706b31f457c1457d3a3259ff9071a66f312ae64dc024f049055f72c"}, + {file = "cffi-1.17.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ddbac59dc3716bc79f27906c010406155031a1c801410f1bafff17ea304d2"}, + {file = "cffi-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6327b572f5770293fc062a7ec04160e89741e8552bf1c358d1a23eba68166759"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbc183e7bef690c9abe5ea67b7b60fdbca81aa8da43468287dae7b5c046107d4"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5bdc0f1f610d067c70aa3737ed06e2726fd9d6f7bfee4a351f4c40b6831f4e82"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6d872186c1617d143969defeadac5a904e6e374183e07977eedef9c07c8953bf"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d46ee4764b88b91f16661a8befc6bfb24806d885e27436fdc292ed7e6f6d058"}, + {file = "cffi-1.17.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f76a90c345796c01d85e6332e81cab6d70de83b829cf1d9762d0a3da59c7932"}, + {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0e60821d312f99d3e1569202518dddf10ae547e799d75aef3bca3a2d9e8ee693"}, + {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:eb09b82377233b902d4c3fbeeb7ad731cdab579c6c6fda1f763cd779139e47c3"}, + {file = "cffi-1.17.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:24658baf6224d8f280e827f0a50c46ad819ec8ba380a42448e24459daf809cf4"}, + {file = "cffi-1.17.0-cp39-cp39-win32.whl", hash = "sha256:0fdacad9e0d9fc23e519efd5ea24a70348305e8d7d85ecbb1a5fa66dc834e7fb"}, + {file = "cffi-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cbc78dc018596315d4e7841c8c3a7ae31cc4d638c9b627f87d52e8abaaf2d29"}, + {file = "cffi-1.17.0.tar.gz", hash = "sha256:f3157624b7558b914cb039fd1af735e5e8049a87c817cc215109ad1c8779df76"}, ] [package.dependencies] @@ -517,63 +532,83 @@ yaml = ["PyYAML"] [[package]] name = "coverage" -version = "7.6.0" +version = "7.6.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, - {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, - {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, - {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, - {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, - {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, - {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, - {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, - {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, - {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, - {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, - {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, - {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, - {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, - {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, - {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, - {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, - {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, - {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, - {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, - {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, - {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, - {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, - {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, - {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, - {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, - {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, - {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"}, + {file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"}, + {file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"}, + {file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"}, + {file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"}, + {file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"}, + {file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"}, + {file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"}, + {file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"}, + {file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"}, + {file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"}, + {file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"}, + {file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"}, + {file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"}, + {file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"}, + {file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"}, + {file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"}, + {file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"}, + {file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"}, + {file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"}, + {file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"}, + {file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"}, + {file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"}, + {file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"}, + {file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"}, + {file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"}, + {file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"}, + {file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"}, + {file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"}, + {file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"}, + {file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"}, + {file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"}, + {file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"}, + {file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"}, + {file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"}, + {file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"}, + {file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"}, + {file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"}, ] [package.extras] @@ -747,6 +782,37 @@ toolz = ">=0.8.0" [package.extras] cython = ["cython"] +[[package]] +name = "debugpy" +version = "1.8.5" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "debugpy-1.8.5-cp310-cp310-macosx_12_0_x86_64.whl", hash = "sha256:7e4d594367d6407a120b76bdaa03886e9eb652c05ba7f87e37418426ad2079f7"}, + {file = "debugpy-1.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4413b7a3ede757dc33a273a17d685ea2b0c09dbd312cc03f5534a0fd4d40750a"}, + {file = "debugpy-1.8.5-cp310-cp310-win32.whl", hash = "sha256:dd3811bd63632bb25eda6bd73bea8e0521794cda02be41fa3160eb26fc29e7ed"}, + {file = "debugpy-1.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:b78c1250441ce893cb5035dd6f5fc12db968cc07f91cc06996b2087f7cefdd8e"}, + {file = "debugpy-1.8.5-cp311-cp311-macosx_12_0_universal2.whl", hash = "sha256:606bccba19f7188b6ea9579c8a4f5a5364ecd0bf5a0659c8a5d0e10dcee3032a"}, + {file = "debugpy-1.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db9fb642938a7a609a6c865c32ecd0d795d56c1aaa7a7a5722d77855d5e77f2b"}, + {file = "debugpy-1.8.5-cp311-cp311-win32.whl", hash = "sha256:4fbb3b39ae1aa3e5ad578f37a48a7a303dad9a3d018d369bc9ec629c1cfa7408"}, + {file = "debugpy-1.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:345d6a0206e81eb68b1493ce2fbffd57c3088e2ce4b46592077a943d2b968ca3"}, + {file = "debugpy-1.8.5-cp312-cp312-macosx_12_0_universal2.whl", hash = "sha256:5b5c770977c8ec6c40c60d6f58cacc7f7fe5a45960363d6974ddb9b62dbee156"}, + {file = "debugpy-1.8.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0a65b00b7cdd2ee0c2cf4c7335fef31e15f1b7056c7fdbce9e90193e1a8c8cb"}, + {file = "debugpy-1.8.5-cp312-cp312-win32.whl", hash = "sha256:c9f7c15ea1da18d2fcc2709e9f3d6de98b69a5b0fff1807fb80bc55f906691f7"}, + {file = "debugpy-1.8.5-cp312-cp312-win_amd64.whl", hash = "sha256:28ced650c974aaf179231668a293ecd5c63c0a671ae6d56b8795ecc5d2f48d3c"}, + {file = "debugpy-1.8.5-cp38-cp38-macosx_12_0_x86_64.whl", hash = "sha256:3df6692351172a42af7558daa5019651f898fc67450bf091335aa8a18fbf6f3a"}, + {file = "debugpy-1.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cd04a73eb2769eb0bfe43f5bfde1215c5923d6924b9b90f94d15f207a402226"}, + {file = "debugpy-1.8.5-cp38-cp38-win32.whl", hash = "sha256:8f913ee8e9fcf9d38a751f56e6de12a297ae7832749d35de26d960f14280750a"}, + {file = "debugpy-1.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:a697beca97dad3780b89a7fb525d5e79f33821a8bc0c06faf1f1289e549743cf"}, + {file = "debugpy-1.8.5-cp39-cp39-macosx_12_0_x86_64.whl", hash = "sha256:0a1029a2869d01cb777216af8c53cda0476875ef02a2b6ff8b2f2c9a4b04176c"}, + {file = "debugpy-1.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e84c276489e141ed0b93b0af648eef891546143d6a48f610945416453a8ad406"}, + {file = "debugpy-1.8.5-cp39-cp39-win32.whl", hash = "sha256:ad84b7cde7fd96cf6eea34ff6c4a1b7887e0fe2ea46e099e53234856f9d99a34"}, + {file = "debugpy-1.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:7b0fe36ed9d26cb6836b0a51453653f8f2e347ba7348f2bbfe76bfeb670bfb1c"}, + {file = "debugpy-1.8.5-py2.py3-none-any.whl", hash = "sha256:55919dce65b471eff25901acf82d328bbd5b833526b6c1364bd5133754777a44"}, + {file = "debugpy-1.8.5.zip", hash = "sha256:b2112cfeb34b4507399d298fe7023a16656fc553ed5246536060ca7bd0e668d0"}, +] + [[package]] name = "deepmerge" version = "0.3.0" @@ -867,44 +933,45 @@ test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-typing" -version = "4.4.0" +version = "5.0.0" description = "eth-typing: Common type annotations for ethereum python packages" optional = false python-versions = "<4,>=3.8" files = [ - {file = "eth_typing-4.4.0-py3-none-any.whl", hash = "sha256:a5e30a6e69edda7b1d1e96e9d71bab48b9bb988a77909d8d1666242c5562f841"}, - {file = "eth_typing-4.4.0.tar.gz", hash = "sha256:93848083ac6bb4c20cc209ea9153a08b0a528be23337c889f89e1e5ffbe9807d"}, + {file = "eth_typing-5.0.0-py3-none-any.whl", hash = "sha256:c7ebc8595e7b65175bb4b4176c2b548ab21b13329f2058e84d4f8c289ba9f577"}, + {file = "eth_typing-5.0.0.tar.gz", hash = "sha256:87ce7cee75665c09d2dcff8de1b496609d5e32fcd2e2b1d8fc0370c29eedcdc0"}, ] [package.dependencies] typing-extensions = ">=4.5.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-utils" -version = "4.1.1" +version = "5.0.0" description = "eth-utils: Common utility functions for python code that interacts with Ethereum" optional = false python-versions = "<4,>=3.8" files = [ - {file = "eth_utils-4.1.1-py3-none-any.whl", hash = "sha256:ccbbac68a6d65cb6e294c5bcb6c6a5cec79a241c56dc5d9c345ed788c30f8534"}, - {file = "eth_utils-4.1.1.tar.gz", hash = "sha256:71c8d10dec7494aeed20fa7a4d52ec2ce4a2e52fdce80aab4f5c3c19f3648b25"}, + {file = "eth_utils-5.0.0-py3-none-any.whl", hash = "sha256:99c44eca11db74dbb881a1d70b24cd80436fc62fe527d2f5c3e3cf7932aba7b2"}, + {file = "eth_utils-5.0.0.tar.gz", hash = "sha256:a5eb9555f43f4579eb83cb84f9dda9f3d6663bbd4a5a6b693f8d35045f305a1f"}, ] [package.dependencies] cytoolz = {version = ">=0.10.1", markers = "implementation_name == \"cpython\""} eth-hash = ">=0.3.1" -eth-typing = ">=3.0.0" +eth-typing = ">=5.0.0" +hexbytes = ">=1.0.0" toolz = {version = ">0.8.2", markers = "implementation_name == \"pypy\""} [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "eth-hash[pycryptodome]", "hypothesis (>=4.43.0)", "ipython", "mypy (==1.5.1)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +dev = ["build (>=0.9.0)", "bump-my-version (>=0.19.0)", "eth-hash[pycryptodome]", "hypothesis (>=4.43.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] -test = ["hypothesis (>=4.43.0)", "mypy (==1.5.1)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] +test = ["hypothesis (>=4.43.0)", "mypy (==1.10.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "filelock" @@ -1050,6 +1117,22 @@ files = [ {file = "frozenlist-1.4.1.tar.gz", hash = "sha256:c037a86e8513059a2613aaba4d817bb90b9d9b6b69aace3ce9c877e8c8ed402b"}, ] +[[package]] +name = "hexbytes" +version = "1.2.1" +description = "hexbytes: Python `bytes` subclass that decodes hex, with a readable console output" +optional = false +python-versions = "<4,>=3.8" +files = [ + {file = "hexbytes-1.2.1-py3-none-any.whl", hash = "sha256:e64890b203a31f4a23ef11470ecfcca565beaee9198df623047df322b757471a"}, + {file = "hexbytes-1.2.1.tar.gz", hash = "sha256:515f00dddf31053db4d0d7636dd16061c1d896c3109b8e751005db4ca46bcca7"}, +] + +[package.extras] +dev = ["build (>=0.9.0)", "bump-my-version (>=0.19.0)", "eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] +test = ["eth-utils (>=2.0.0)", "hypothesis (>=3.44.24,<=6.31.6)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] + [[package]] name = "identify" version = "2.6.0" @@ -1182,153 +1265,149 @@ typing-extensions = ">=4.5.0" [[package]] name = "lxml" -version = "5.2.2" +version = "5.3.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false python-versions = ">=3.6" files = [ - {file = "lxml-5.2.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:364d03207f3e603922d0d3932ef363d55bbf48e3647395765f9bfcbdf6d23632"}, - {file = "lxml-5.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50127c186f191b8917ea2fb8b206fbebe87fd414a6084d15568c27d0a21d60db"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74e4f025ef3db1c6da4460dd27c118d8cd136d0391da4e387a15e48e5c975147"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:981a06a3076997adf7c743dcd0d7a0415582661e2517c7d961493572e909aa1d"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aef5474d913d3b05e613906ba4090433c515e13ea49c837aca18bde190853dff"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e275ea572389e41e8b039ac076a46cb87ee6b8542df3fff26f5baab43713bca"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5b65529bb2f21ac7861a0e94fdbf5dc0daab41497d18223b46ee8515e5ad297"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bcc98f911f10278d1daf14b87d65325851a1d29153caaf146877ec37031d5f36"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:b47633251727c8fe279f34025844b3b3a3e40cd1b198356d003aa146258d13a2"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:fbc9d316552f9ef7bba39f4edfad4a734d3d6f93341232a9dddadec4f15d425f"}, - {file = "lxml-5.2.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:13e69be35391ce72712184f69000cda04fc89689429179bc4c0ae5f0b7a8c21b"}, - {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3b6a30a9ab040b3f545b697cb3adbf3696c05a3a68aad172e3fd7ca73ab3c835"}, - {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a233bb68625a85126ac9f1fc66d24337d6e8a0f9207b688eec2e7c880f012ec0"}, - {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:dfa7c241073d8f2b8e8dbc7803c434f57dbb83ae2a3d7892dd068d99e96efe2c"}, - {file = "lxml-5.2.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1a7aca7964ac4bb07680d5c9d63b9d7028cace3e2d43175cb50bba8c5ad33316"}, - {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae4073a60ab98529ab8a72ebf429f2a8cc612619a8c04e08bed27450d52103c0"}, - {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:ffb2be176fed4457e445fe540617f0252a72a8bc56208fd65a690fdb1f57660b"}, - {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:e290d79a4107d7d794634ce3e985b9ae4f920380a813717adf61804904dc4393"}, - {file = "lxml-5.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:96e85aa09274955bb6bd483eaf5b12abadade01010478154b0ec70284c1b1526"}, - {file = "lxml-5.2.2-cp310-cp310-win32.whl", hash = "sha256:f956196ef61369f1685d14dad80611488d8dc1ef00be57c0c5a03064005b0f30"}, - {file = "lxml-5.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:875a3f90d7eb5c5d77e529080d95140eacb3c6d13ad5b616ee8095447b1d22e7"}, - {file = "lxml-5.2.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:45f9494613160d0405682f9eee781c7e6d1bf45f819654eb249f8f46a2c22545"}, - {file = "lxml-5.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0b3f2df149efb242cee2ffdeb6674b7f30d23c9a7af26595099afaf46ef4e88"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d28cb356f119a437cc58a13f8135ab8a4c8ece18159eb9194b0d269ec4e28083"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:657a972f46bbefdbba2d4f14413c0d079f9ae243bd68193cb5061b9732fa54c1"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b74b9ea10063efb77a965a8d5f4182806fbf59ed068b3c3fd6f30d2ac7bee734"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:07542787f86112d46d07d4f3c4e7c760282011b354d012dc4141cc12a68cef5f"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:303f540ad2dddd35b92415b74b900c749ec2010e703ab3bfd6660979d01fd4ed"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:2eb2227ce1ff998faf0cd7fe85bbf086aa41dfc5af3b1d80867ecfe75fb68df3"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:1d8a701774dfc42a2f0b8ccdfe7dbc140500d1049e0632a611985d943fcf12df"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:56793b7a1a091a7c286b5f4aa1fe4ae5d1446fe742d00cdf2ffb1077865db10d"}, - {file = "lxml-5.2.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eb00b549b13bd6d884c863554566095bf6fa9c3cecb2e7b399c4bc7904cb33b5"}, - {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a2569a1f15ae6c8c64108a2cd2b4a858fc1e13d25846be0666fc144715e32ab"}, - {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:8cf85a6e40ff1f37fe0f25719aadf443686b1ac7652593dc53c7ef9b8492b115"}, - {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:d237ba6664b8e60fd90b8549a149a74fcc675272e0e95539a00522e4ca688b04"}, - {file = "lxml-5.2.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0b3f5016e00ae7630a4b83d0868fca1e3d494c78a75b1c7252606a3a1c5fc2ad"}, - {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:23441e2b5339bc54dc949e9e675fa35efe858108404ef9aa92f0456929ef6fe8"}, - {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:2fb0ba3e8566548d6c8e7dd82a8229ff47bd8fb8c2da237607ac8e5a1b8312e5"}, - {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:79d1fb9252e7e2cfe4de6e9a6610c7cbb99b9708e2c3e29057f487de5a9eaefa"}, - {file = "lxml-5.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6dcc3d17eac1df7859ae01202e9bb11ffa8c98949dcbeb1069c8b9a75917e01b"}, - {file = "lxml-5.2.2-cp311-cp311-win32.whl", hash = "sha256:4c30a2f83677876465f44c018830f608fa3c6a8a466eb223535035fbc16f3438"}, - {file = "lxml-5.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:49095a38eb333aaf44c06052fd2ec3b8f23e19747ca7ec6f6c954ffea6dbf7be"}, - {file = "lxml-5.2.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7429e7faa1a60cad26ae4227f4dd0459efde239e494c7312624ce228e04f6391"}, - {file = "lxml-5.2.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:50ccb5d355961c0f12f6cf24b7187dbabd5433f29e15147a67995474f27d1776"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dc911208b18842a3a57266d8e51fc3cfaccee90a5351b92079beed912a7914c2"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33ce9e786753743159799fdf8e92a5da351158c4bfb6f2db0bf31e7892a1feb5"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec87c44f619380878bd49ca109669c9f221d9ae6883a5bcb3616785fa8f94c97"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08ea0f606808354eb8f2dfaac095963cb25d9d28e27edcc375d7b30ab01abbf6"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75a9632f1d4f698b2e6e2e1ada40e71f369b15d69baddb8968dcc8e683839b18"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:74da9f97daec6928567b48c90ea2c82a106b2d500f397eeb8941e47d30b1ca85"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:0969e92af09c5687d769731e3f39ed62427cc72176cebb54b7a9d52cc4fa3b73"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:9164361769b6ca7769079f4d426a41df6164879f7f3568be9086e15baca61466"}, - {file = "lxml-5.2.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d26a618ae1766279f2660aca0081b2220aca6bd1aa06b2cf73f07383faf48927"}, - {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab67ed772c584b7ef2379797bf14b82df9aa5f7438c5b9a09624dd834c1c1aaf"}, - {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:3d1e35572a56941b32c239774d7e9ad724074d37f90c7a7d499ab98761bd80cf"}, - {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:8268cbcd48c5375f46e000adb1390572c98879eb4f77910c6053d25cc3ac2c67"}, - {file = "lxml-5.2.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e282aedd63c639c07c3857097fc0e236f984ceb4089a8b284da1c526491e3f3d"}, - {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfdc2bfe69e9adf0df4915949c22a25b39d175d599bf98e7ddf620a13678585"}, - {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4aefd911793b5d2d7a921233a54c90329bf3d4a6817dc465f12ffdfe4fc7b8fe"}, - {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8b8df03a9e995b6211dafa63b32f9d405881518ff1ddd775db4e7b98fb545e1c"}, - {file = "lxml-5.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f11ae142f3a322d44513de1018b50f474f8f736bc3cd91d969f464b5bfef8836"}, - {file = "lxml-5.2.2-cp312-cp312-win32.whl", hash = "sha256:16a8326e51fcdffc886294c1e70b11ddccec836516a343f9ed0f82aac043c24a"}, - {file = "lxml-5.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:bbc4b80af581e18568ff07f6395c02114d05f4865c2812a1f02f2eaecf0bfd48"}, - {file = "lxml-5.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e3d9d13603410b72787579769469af730c38f2f25505573a5888a94b62b920f8"}, - {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38b67afb0a06b8575948641c1d6d68e41b83a3abeae2ca9eed2ac59892b36706"}, - {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c689d0d5381f56de7bd6966a4541bff6e08bf8d3871bbd89a0c6ab18aa699573"}, - {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:cf2a978c795b54c539f47964ec05e35c05bd045db5ca1e8366988c7f2fe6b3ce"}, - {file = "lxml-5.2.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:739e36ef7412b2bd940f75b278749106e6d025e40027c0b94a17ef7968d55d56"}, - {file = "lxml-5.2.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d8bbcd21769594dbba9c37d3c819e2d5847656ca99c747ddb31ac1701d0c0ed9"}, - {file = "lxml-5.2.2-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:2304d3c93f2258ccf2cf7a6ba8c761d76ef84948d87bf9664e14d203da2cd264"}, - {file = "lxml-5.2.2-cp36-cp36m-win32.whl", hash = "sha256:02437fb7308386867c8b7b0e5bc4cd4b04548b1c5d089ffb8e7b31009b961dc3"}, - {file = "lxml-5.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:edcfa83e03370032a489430215c1e7783128808fd3e2e0a3225deee278585196"}, - {file = "lxml-5.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:28bf95177400066596cdbcfc933312493799382879da504633d16cf60bba735b"}, - {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a745cc98d504d5bd2c19b10c79c61c7c3df9222629f1b6210c0368177589fb8"}, - {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b590b39ef90c6b22ec0be925b211298e810b4856909c8ca60d27ffbca6c12e6"}, - {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b336b0416828022bfd5a2e3083e7f5ba54b96242159f83c7e3eebaec752f1716"}, - {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:c2faf60c583af0d135e853c86ac2735ce178f0e338a3c7f9ae8f622fd2eb788c"}, - {file = "lxml-5.2.2-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:4bc6cb140a7a0ad1f7bc37e018d0ed690b7b6520ade518285dc3171f7a117905"}, - {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7ff762670cada8e05b32bf1e4dc50b140790909caa8303cfddc4d702b71ea184"}, - {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:57f0a0bbc9868e10ebe874e9f129d2917750adf008fe7b9c1598c0fbbfdde6a6"}, - {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:a6d2092797b388342c1bc932077ad232f914351932353e2e8706851c870bca1f"}, - {file = "lxml-5.2.2-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:60499fe961b21264e17a471ec296dcbf4365fbea611bf9e303ab69db7159ce61"}, - {file = "lxml-5.2.2-cp37-cp37m-win32.whl", hash = "sha256:d9b342c76003c6b9336a80efcc766748a333573abf9350f4094ee46b006ec18f"}, - {file = "lxml-5.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:b16db2770517b8799c79aa80f4053cd6f8b716f21f8aca962725a9565ce3ee40"}, - {file = "lxml-5.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7ed07b3062b055d7a7f9d6557a251cc655eed0b3152b76de619516621c56f5d3"}, - {file = "lxml-5.2.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f60fdd125d85bf9c279ffb8e94c78c51b3b6a37711464e1f5f31078b45002421"}, - {file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8a7e24cb69ee5f32e003f50e016d5fde438010c1022c96738b04fc2423e61706"}, - {file = "lxml-5.2.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23cfafd56887eaed93d07bc4547abd5e09d837a002b791e9767765492a75883f"}, - {file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:19b4e485cd07b7d83e3fe3b72132e7df70bfac22b14fe4bf7a23822c3a35bff5"}, - {file = "lxml-5.2.2-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:7ce7ad8abebe737ad6143d9d3bf94b88b93365ea30a5b81f6877ec9c0dee0a48"}, - {file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e49b052b768bb74f58c7dda4e0bdf7b79d43a9204ca584ffe1fb48a6f3c84c66"}, - {file = "lxml-5.2.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d14a0d029a4e176795cef99c056d58067c06195e0c7e2dbb293bf95c08f772a3"}, - {file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:be49ad33819d7dcc28a309b86d4ed98e1a65f3075c6acd3cd4fe32103235222b"}, - {file = "lxml-5.2.2-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a6d17e0370d2516d5bb9062c7b4cb731cff921fc875644c3d751ad857ba9c5b1"}, - {file = "lxml-5.2.2-cp38-cp38-win32.whl", hash = "sha256:5b8c041b6265e08eac8a724b74b655404070b636a8dd6d7a13c3adc07882ef30"}, - {file = "lxml-5.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:f61efaf4bed1cc0860e567d2ecb2363974d414f7f1f124b1df368bbf183453a6"}, - {file = "lxml-5.2.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:fb91819461b1b56d06fa4bcf86617fac795f6a99d12239fb0c68dbeba41a0a30"}, - {file = "lxml-5.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d4ed0c7cbecde7194cd3228c044e86bf73e30a23505af852857c09c24e77ec5d"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54401c77a63cc7d6dc4b4e173bb484f28a5607f3df71484709fe037c92d4f0ed"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:625e3ef310e7fa3a761d48ca7ea1f9d8718a32b1542e727d584d82f4453d5eeb"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:519895c99c815a1a24a926d5b60627ce5ea48e9f639a5cd328bda0515ea0f10c"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c7079d5eb1c1315a858bbf180000757db8ad904a89476653232db835c3114001"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:343ab62e9ca78094f2306aefed67dcfad61c4683f87eee48ff2fd74902447726"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:cd9e78285da6c9ba2d5c769628f43ef66d96ac3085e59b10ad4f3707980710d3"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:546cf886f6242dff9ec206331209db9c8e1643ae642dea5fdbecae2453cb50fd"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:02f6a8eb6512fdc2fd4ca10a49c341c4e109aa6e9448cc4859af5b949622715a"}, - {file = "lxml-5.2.2-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:339ee4a4704bc724757cd5dd9dc8cf4d00980f5d3e6e06d5847c1b594ace68ab"}, - {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0a028b61a2e357ace98b1615fc03f76eb517cc028993964fe08ad514b1e8892d"}, - {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:f90e552ecbad426eab352e7b2933091f2be77115bb16f09f78404861c8322981"}, - {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:d83e2d94b69bf31ead2fa45f0acdef0757fa0458a129734f59f67f3d2eb7ef32"}, - {file = "lxml-5.2.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a02d3c48f9bb1e10c7788d92c0c7db6f2002d024ab6e74d6f45ae33e3d0288a3"}, - {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6d68ce8e7b2075390e8ac1e1d3a99e8b6372c694bbe612632606d1d546794207"}, - {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:453d037e09a5176d92ec0fd282e934ed26d806331a8b70ab431a81e2fbabf56d"}, - {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:3b019d4ee84b683342af793b56bb35034bd749e4cbdd3d33f7d1107790f8c472"}, - {file = "lxml-5.2.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cb3942960f0beb9f46e2a71a3aca220d1ca32feb5a398656be934320804c0df9"}, - {file = "lxml-5.2.2-cp39-cp39-win32.whl", hash = "sha256:ac6540c9fff6e3813d29d0403ee7a81897f1d8ecc09a8ff84d2eea70ede1cdbf"}, - {file = "lxml-5.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:610b5c77428a50269f38a534057444c249976433f40f53e3b47e68349cca1425"}, - {file = "lxml-5.2.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:b537bd04d7ccd7c6350cdaaaad911f6312cbd61e6e6045542f781c7f8b2e99d2"}, - {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4820c02195d6dfb7b8508ff276752f6b2ff8b64ae5d13ebe02e7667e035000b9"}, - {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2a09f6184f17a80897172863a655467da2b11151ec98ba8d7af89f17bf63dae"}, - {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:76acba4c66c47d27c8365e7c10b3d8016a7da83d3191d053a58382311a8bf4e1"}, - {file = "lxml-5.2.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b128092c927eaf485928cec0c28f6b8bead277e28acf56800e972aa2c2abd7a2"}, - {file = "lxml-5.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ae791f6bd43305aade8c0e22f816b34f3b72b6c820477aab4d18473a37e8090b"}, - {file = "lxml-5.2.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a2f6a1bc2460e643785a2cde17293bd7a8f990884b822f7bca47bee0a82fc66b"}, - {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e8d351ff44c1638cb6e980623d517abd9f580d2e53bfcd18d8941c052a5a009"}, - {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bec4bd9133420c5c52d562469c754f27c5c9e36ee06abc169612c959bd7dbb07"}, - {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:55ce6b6d803890bd3cc89975fca9de1dff39729b43b73cb15ddd933b8bc20484"}, - {file = "lxml-5.2.2-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:8ab6a358d1286498d80fe67bd3d69fcbc7d1359b45b41e74c4a26964ca99c3f8"}, - {file = "lxml-5.2.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:06668e39e1f3c065349c51ac27ae430719d7806c026fec462e5693b08b95696b"}, - {file = "lxml-5.2.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:9cd5323344d8ebb9fb5e96da5de5ad4ebab993bbf51674259dbe9d7a18049525"}, - {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89feb82ca055af0fe797a2323ec9043b26bc371365847dbe83c7fd2e2f181c34"}, - {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e481bba1e11ba585fb06db666bfc23dbe181dbafc7b25776156120bf12e0d5a6"}, - {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:9d6c6ea6a11ca0ff9cd0390b885984ed31157c168565702959c25e2191674a14"}, - {file = "lxml-5.2.2-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3d98de734abee23e61f6b8c2e08a88453ada7d6486dc7cdc82922a03968928db"}, - {file = "lxml-5.2.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:69ab77a1373f1e7563e0fb5a29a8440367dec051da6c7405333699d07444f511"}, - {file = "lxml-5.2.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:34e17913c431f5ae01d8658dbf792fdc457073dcdfbb31dc0cc6ab256e664a8d"}, - {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05f8757b03208c3f50097761be2dea0aba02e94f0dc7023ed73a7bb14ff11eb0"}, - {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a520b4f9974b0a0a6ed73c2154de57cdfd0c8800f4f15ab2b73238ffed0b36e"}, - {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5e097646944b66207023bc3c634827de858aebc226d5d4d6d16f0b77566ea182"}, - {file = "lxml-5.2.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b5e4ef22ff25bfd4ede5f8fb30f7b24446345f3e79d9b7455aef2836437bc38a"}, - {file = "lxml-5.2.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff69a9a0b4b17d78170c73abe2ab12084bdf1691550c5629ad1fe7849433f324"}, - {file = "lxml-5.2.2.tar.gz", hash = "sha256:bb2dc4898180bea79863d5487e5f9c7c34297414bad54bcd0f0852aee9cfdb87"}, + {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656"}, + {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:501d0d7e26b4d261fca8132854d845e4988097611ba2531408ec91cf3fd9d20a"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb66442c2546446944437df74379e9cf9e9db353e61301d1a0e26482f43f0dd8"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e41506fec7a7f9405b14aa2d5c8abbb4dbbd09d88f9496958b6d00cb4d45330"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f7d4a670107d75dfe5ad080bed6c341d18c4442f9378c9f58e5851e86eb79965"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41ce1f1e2c7755abfc7e759dc34d7d05fd221723ff822947132dc934d122fe22"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:44264ecae91b30e5633013fb66f6ddd05c006d3e0e884f75ce0b4755b3e3847b"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_ppc64le.whl", hash = "sha256:3c174dc350d3ec52deb77f2faf05c439331d6ed5e702fc247ccb4e6b62d884b7"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_s390x.whl", hash = "sha256:2dfab5fa6a28a0b60a20638dc48e6343c02ea9933e3279ccb132f555a62323d8"}, + {file = "lxml-5.3.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:b1c8c20847b9f34e98080da785bb2336ea982e7f913eed5809e5a3c872900f32"}, + {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2c86bf781b12ba417f64f3422cfc302523ac9cd1d8ae8c0f92a1c66e56ef2e86"}, + {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:c162b216070f280fa7da844531169be0baf9ccb17263cf5a8bf876fcd3117fa5"}, + {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:36aef61a1678cb778097b4a6eeae96a69875d51d1e8f4d4b491ab3cfb54b5a03"}, + {file = "lxml-5.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f65e5120863c2b266dbcc927b306c5b78e502c71edf3295dfcb9501ec96e5fc7"}, + {file = "lxml-5.3.0-cp310-cp310-win32.whl", hash = "sha256:ef0c1fe22171dd7c7c27147f2e9c3e86f8bdf473fed75f16b0c2e84a5030ce80"}, + {file = "lxml-5.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:052d99051e77a4f3e8482c65014cf6372e61b0a6f4fe9edb98503bb5364cfee3"}, + {file = "lxml-5.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:74bcb423462233bc5d6066e4e98b0264e7c1bed7541fff2f4e34fe6b21563c8b"}, + {file = "lxml-5.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a3d819eb6f9b8677f57f9664265d0a10dd6551d227afb4af2b9cd7bdc2ccbf18"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b8f5db71b28b8c404956ddf79575ea77aa8b1538e8b2ef9ec877945b3f46442"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3406b63232fc7e9b8783ab0b765d7c59e7c59ff96759d8ef9632fca27c7ee4"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2ecdd78ab768f844c7a1d4a03595038c166b609f6395e25af9b0f3f26ae1230f"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:168f2dfcfdedf611eb285efac1516c8454c8c99caf271dccda8943576b67552e"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa617107a410245b8660028a7483b68e7914304a6d4882b5ff3d2d3eb5948d8c"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:69959bd3167b993e6e710b99051265654133a98f20cec1d9b493b931942e9c16"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_ppc64le.whl", hash = "sha256:bd96517ef76c8654446fc3db9242d019a1bb5fe8b751ba414765d59f99210b79"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_s390x.whl", hash = "sha256:ab6dd83b970dc97c2d10bc71aa925b84788c7c05de30241b9e96f9b6d9ea3080"}, + {file = "lxml-5.3.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:eec1bb8cdbba2925bedc887bc0609a80e599c75b12d87ae42ac23fd199445654"}, + {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a7095eeec6f89111d03dabfe5883a1fd54da319c94e0fb104ee8f23616b572d"}, + {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6f651ebd0b21ec65dfca93aa629610a0dbc13dbc13554f19b0113da2e61a4763"}, + {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:f422a209d2455c56849442ae42f25dbaaba1c6c3f501d58761c619c7836642ec"}, + {file = "lxml-5.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:62f7fdb0d1ed2065451f086519865b4c90aa19aed51081979ecd05a21eb4d1be"}, + {file = "lxml-5.3.0-cp311-cp311-win32.whl", hash = "sha256:c6379f35350b655fd817cd0d6cbeef7f265f3ae5fedb1caae2eb442bbeae9ab9"}, + {file = "lxml-5.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c52100e2c2dbb0649b90467935c4b0de5528833c76a35ea1a2691ec9f1ee7a1"}, + {file = "lxml-5.3.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e99f5507401436fdcc85036a2e7dc2e28d962550afe1cbfc07c40e454256a859"}, + {file = "lxml-5.3.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:384aacddf2e5813a36495233b64cb96b1949da72bef933918ba5c84e06af8f0e"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:874a216bf6afaf97c263b56371434e47e2c652d215788396f60477540298218f"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:65ab5685d56914b9a2a34d67dd5488b83213d680b0c5d10b47f81da5a16b0b0e"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aac0bbd3e8dd2d9c45ceb82249e8bdd3ac99131a32b4d35c8af3cc9db1657179"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b369d3db3c22ed14c75ccd5af429086f166a19627e84a8fdade3f8f31426e52a"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c24037349665434f375645fa9d1f5304800cec574d0310f618490c871fd902b3"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:62d172f358f33a26d6b41b28c170c63886742f5b6772a42b59b4f0fa10526cb1"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_ppc64le.whl", hash = "sha256:c1f794c02903c2824fccce5b20c339a1a14b114e83b306ff11b597c5f71a1c8d"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_s390x.whl", hash = "sha256:5d6a6972b93c426ace71e0be9a6f4b2cfae9b1baed2eed2006076a746692288c"}, + {file = "lxml-5.3.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:3879cc6ce938ff4eb4900d901ed63555c778731a96365e53fadb36437a131a99"}, + {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:74068c601baff6ff021c70f0935b0c7bc528baa8ea210c202e03757c68c5a4ff"}, + {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ecd4ad8453ac17bc7ba3868371bffb46f628161ad0eefbd0a855d2c8c32dd81a"}, + {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:7e2f58095acc211eb9d8b5771bf04df9ff37d6b87618d1cbf85f92399c98dae8"}, + {file = "lxml-5.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e63601ad5cd8f860aa99d109889b5ac34de571c7ee902d6812d5d9ddcc77fa7d"}, + {file = "lxml-5.3.0-cp312-cp312-win32.whl", hash = "sha256:17e8d968d04a37c50ad9c456a286b525d78c4a1c15dd53aa46c1d8e06bf6fa30"}, + {file = "lxml-5.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:c1a69e58a6bb2de65902051d57fde951febad631a20a64572677a1052690482f"}, + {file = "lxml-5.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c72e9563347c7395910de6a3100a4840a75a6f60e05af5e58566868d5eb2d6a"}, + {file = "lxml-5.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e92ce66cd919d18d14b3856906a61d3f6b6a8500e0794142338da644260595cd"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d04f064bebdfef9240478f7a779e8c5dc32b8b7b0b2fc6a62e39b928d428e51"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c2fb570d7823c2bbaf8b419ba6e5662137f8166e364a8b2b91051a1fb40ab8b"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c120f43553ec759f8de1fee2f4794452b0946773299d44c36bfe18e83caf002"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:562e7494778a69086f0312ec9689f6b6ac1c6b65670ed7d0267e49f57ffa08c4"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:423b121f7e6fa514ba0c7918e56955a1d4470ed35faa03e3d9f0e3baa4c7e492"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:c00f323cc00576df6165cc9d21a4c21285fa6b9989c5c39830c3903dc4303ef3"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_ppc64le.whl", hash = "sha256:1fdc9fae8dd4c763e8a31e7630afef517eab9f5d5d31a278df087f307bf601f4"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_s390x.whl", hash = "sha256:658f2aa69d31e09699705949b5fc4719cbecbd4a97f9656a232e7d6c7be1a367"}, + {file = "lxml-5.3.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:1473427aff3d66a3fa2199004c3e601e6c4500ab86696edffdbc84954c72d832"}, + {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a87de7dd873bf9a792bf1e58b1c3887b9264036629a5bf2d2e6579fe8e73edff"}, + {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:0d7b36afa46c97875303a94e8f3ad932bf78bace9e18e603f2085b652422edcd"}, + {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:cf120cce539453ae086eacc0130a324e7026113510efa83ab42ef3fcfccac7fb"}, + {file = "lxml-5.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:df5c7333167b9674aa8ae1d4008fa4bc17a313cc490b2cca27838bbdcc6bb15b"}, + {file = "lxml-5.3.0-cp313-cp313-win32.whl", hash = "sha256:c802e1c2ed9f0c06a65bc4ed0189d000ada8049312cfeab6ca635e39c9608957"}, + {file = "lxml-5.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:406246b96d552e0503e17a1006fd27edac678b3fcc9f1be71a2f94b4ff61528d"}, + {file = "lxml-5.3.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:8f0de2d390af441fe8b2c12626d103540b5d850d585b18fcada58d972b74a74e"}, + {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1afe0a8c353746e610bd9031a630a95bcfb1a720684c3f2b36c4710a0a96528f"}, + {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:56b9861a71575f5795bde89256e7467ece3d339c9b43141dbdd54544566b3b94"}, + {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_28_x86_64.whl", hash = "sha256:9fb81d2824dff4f2e297a276297e9031f46d2682cafc484f49de182aa5e5df99"}, + {file = "lxml-5.3.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:2c226a06ecb8cdef28845ae976da407917542c5e6e75dcac7cc33eb04aaeb237"}, + {file = "lxml-5.3.0-cp36-cp36m-musllinux_1_2_x86_64.whl", hash = "sha256:7d3d1ca42870cdb6d0d29939630dbe48fa511c203724820fc0fd507b2fb46577"}, + {file = "lxml-5.3.0-cp36-cp36m-win32.whl", hash = "sha256:094cb601ba9f55296774c2d57ad68730daa0b13dc260e1f941b4d13678239e70"}, + {file = "lxml-5.3.0-cp36-cp36m-win_amd64.whl", hash = "sha256:eafa2c8658f4e560b098fe9fc54539f86528651f61849b22111a9b107d18910c"}, + {file = "lxml-5.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cb83f8a875b3d9b458cada4f880fa498646874ba4011dc974e071a0a84a1b033"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25f1b69d41656b05885aa185f5fdf822cb01a586d1b32739633679699f220391"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23e0553b8055600b3bf4a00b255ec5c92e1e4aebf8c2c09334f8368e8bd174d6"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ada35dd21dc6c039259596b358caab6b13f4db4d4a7f8665764d616daf9cc1d"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_28_aarch64.whl", hash = "sha256:81b4e48da4c69313192d8c8d4311e5d818b8be1afe68ee20f6385d0e96fc9512"}, + {file = "lxml-5.3.0-cp37-cp37m-manylinux_2_28_x86_64.whl", hash = "sha256:2bc9fd5ca4729af796f9f59cd8ff160fe06a474da40aca03fcc79655ddee1a8b"}, + {file = "lxml-5.3.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:07da23d7ee08577760f0a71d67a861019103e4812c87e2fab26b039054594cc5"}, + {file = "lxml-5.3.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:ea2e2f6f801696ad7de8aec061044d6c8c0dd4037608c7cab38a9a4d316bfb11"}, + {file = "lxml-5.3.0-cp37-cp37m-win32.whl", hash = "sha256:5c54afdcbb0182d06836cc3d1be921e540be3ebdf8b8a51ee3ef987537455f84"}, + {file = "lxml-5.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:f2901429da1e645ce548bf9171784c0f74f0718c3f6150ce166be39e4dd66c3e"}, + {file = "lxml-5.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c56a1d43b2f9ee4786e4658c7903f05da35b923fb53c11025712562d5cc02753"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ee8c39582d2652dcd516d1b879451500f8db3fe3607ce45d7c5957ab2596040"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fdf3a3059611f7585a78ee10399a15566356116a4288380921a4b598d807a22"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:146173654d79eb1fc97498b4280c1d3e1e5d58c398fa530905c9ea50ea849b22"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_28_aarch64.whl", hash = "sha256:0a7056921edbdd7560746f4221dca89bb7a3fe457d3d74267995253f46343f15"}, + {file = "lxml-5.3.0-cp38-cp38-manylinux_2_28_x86_64.whl", hash = "sha256:9e4b47ac0f5e749cfc618efdf4726269441014ae1d5583e047b452a32e221920"}, + {file = "lxml-5.3.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f914c03e6a31deb632e2daa881fe198461f4d06e57ac3d0e05bbcab8eae01945"}, + {file = "lxml-5.3.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:213261f168c5e1d9b7535a67e68b1f59f92398dd17a56d934550837143f79c42"}, + {file = "lxml-5.3.0-cp38-cp38-win32.whl", hash = "sha256:218c1b2e17a710e363855594230f44060e2025b05c80d1f0661258142b2add2e"}, + {file = "lxml-5.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:315f9542011b2c4e1d280e4a20ddcca1761993dda3afc7a73b01235f8641e903"}, + {file = "lxml-5.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:1ffc23010330c2ab67fac02781df60998ca8fe759e8efde6f8b756a20599c5de"}, + {file = "lxml-5.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2b3778cb38212f52fac9fe913017deea2fdf4eb1a4f8e4cfc6b009a13a6d3fcc"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4b0c7a688944891086ba192e21c5229dea54382f4836a209ff8d0a660fac06be"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:747a3d3e98e24597981ca0be0fd922aebd471fa99d0043a3842d00cdcad7ad6a"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86a6b24b19eaebc448dc56b87c4865527855145d851f9fc3891673ff97950540"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b11a5d918a6216e521c715b02749240fb07ae5a1fefd4b7bf12f833bc8b4fe70"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68b87753c784d6acb8a25b05cb526c3406913c9d988d51f80adecc2b0775d6aa"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:109fa6fede314cc50eed29e6e56c540075e63d922455346f11e4d7a036d2b8cf"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_ppc64le.whl", hash = "sha256:02ced472497b8362c8e902ade23e3300479f4f43e45f4105c85ef43b8db85229"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_s390x.whl", hash = "sha256:6b038cc86b285e4f9fea2ba5ee76e89f21ed1ea898e287dc277a25884f3a7dfe"}, + {file = "lxml-5.3.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:7437237c6a66b7ca341e868cda48be24b8701862757426852c9b3186de1da8a2"}, + {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7f41026c1d64043a36fda21d64c5026762d53a77043e73e94b71f0521939cc71"}, + {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:482c2f67761868f0108b1743098640fbb2a28a8e15bf3f47ada9fa59d9fe08c3"}, + {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:1483fd3358963cc5c1c9b122c80606a3a79ee0875bcac0204149fa09d6ff2727"}, + {file = "lxml-5.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dec2d1130a9cda5b904696cec33b2cfb451304ba9081eeda7f90f724097300a"}, + {file = "lxml-5.3.0-cp39-cp39-win32.whl", hash = "sha256:a0eabd0a81625049c5df745209dc7fcef6e2aea7793e5f003ba363610aa0a3ff"}, + {file = "lxml-5.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:89e043f1d9d341c52bf2af6d02e6adde62e0a46e6755d5eb60dc6e4f0b8aeca2"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7b1cd427cb0d5f7393c31b7496419da594fe600e6fdc4b105a54f82405e6626c"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:51806cfe0279e06ed8500ce19479d757db42a30fd509940b1701be9c86a5ff9a"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee70d08fd60c9565ba8190f41a46a54096afa0eeb8f76bd66f2c25d3b1b83005"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:8dc2c0395bea8254d8daebc76dcf8eb3a95ec2a46fa6fae5eaccee366bfe02ce"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:6ba0d3dcac281aad8a0e5b14c7ed6f9fa89c8612b47939fc94f80b16e2e9bc83"}, + {file = "lxml-5.3.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6e91cf736959057f7aac7adfc83481e03615a8e8dd5758aa1d95ea69e8931dba"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:94d6c3782907b5e40e21cadf94b13b0842ac421192f26b84c45f13f3c9d5dc27"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c300306673aa0f3ed5ed9372b21867690a17dba38c68c44b287437c362ce486b"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d9b952e07aed35fe2e1a7ad26e929595412db48535921c5013edc8aa4a35ce"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:01220dca0d066d1349bd6a1726856a78f7929f3878f7e2ee83c296c69495309e"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:2d9b8d9177afaef80c53c0a9e30fa252ff3036fb1c6494d427c066a4ce6a282f"}, + {file = "lxml-5.3.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:20094fc3f21ea0a8669dc4c61ed7fa8263bd37d97d93b90f28fc613371e7a875"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ace2c2326a319a0bb8a8b0e5b570c764962e95818de9f259ce814ee666603f19"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92e67a0be1639c251d21e35fe74df6bcc40cba445c2cda7c4a967656733249e2"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd5350b55f9fecddc51385463a4f67a5da829bc741e38cf689f38ec9023f54ab"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:4c1fefd7e3d00921c44dc9ca80a775af49698bbfd92ea84498e56acffd4c5469"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:71a8dd38fbd2f2319136d4ae855a7078c69c9a38ae06e0c17c73fd70fc6caad8"}, + {file = "lxml-5.3.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:97acf1e1fd66ab53dacd2c35b319d7e548380c2e9e8c54525c6e76d21b1ae3b1"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:68934b242c51eb02907c5b81d138cb977b2129a0a75a8f8b60b01cb8586c7b21"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b710bc2b8292966b23a6a0121f7a6c51d45d2347edcc75f016ac123b8054d3f2"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18feb4b93302091b1541221196a2155aa296c363fd233814fa11e181adebc52f"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:3eb44520c4724c2e1a57c0af33a379eee41792595023f367ba3952a2d96c2aab"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:609251a0ca4770e5a8768ff902aa02bf636339c5a93f9349b48eb1f606f7f3e9"}, + {file = "lxml-5.3.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:516f491c834eb320d6c843156440fe7fc0d50b33e44387fcec5b02f0bc118a4c"}, + {file = "lxml-5.3.0.tar.gz", hash = "sha256:4e109ca30d1edec1ac60cdbe341905dc3b8f55b16855e03a54aaf59e51ec8c6f"}, ] [package.extras] @@ -1336,7 +1415,7 @@ cssselect = ["cssselect (>=0.7)"] html-clean = ["lxml-html-clean"] html5 = ["html5lib"] htmlsoup = ["BeautifulSoup4"] -source = ["Cython (>=3.0.10)"] +source = ["Cython (>=3.0.11)"] [[package]] name = "markdown" @@ -1765,40 +1844,6 @@ files = [ six = ">=1.9.0" wcwidth = "*" -[[package]] -name = "ptvsd" -version = "4.3.2" -description = "Remote debugging server for Python support in Visual Studio and Visual Studio Code" -optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*" -files = [ - {file = "ptvsd-4.3.2-cp27-cp27m-macosx_10_13_x86_64.whl", hash = "sha256:22b699369a18ff28d4d1aa6a452739e50c7b7790cb16c6312d766e023c12fe27"}, - {file = "ptvsd-4.3.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:3f839fe91d9ddca0d6a3a0afd6a1c824be1768498a737ab9333d084c5c3f3591"}, - {file = "ptvsd-4.3.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:70260b4591c07bff95566d49b6a5dc3051d8558035c43c847bad9a954def46bb"}, - {file = "ptvsd-4.3.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:d2662ec37ee049c0f8f2f9a378abeb7e570d9215c19eaf0a6d7189464195009f"}, - {file = "ptvsd-4.3.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:d9337ebba4d099698982e090b203e85670086c4b29cf1185b2e45cd353a8053e"}, - {file = "ptvsd-4.3.2-cp34-cp34m-macosx_10_13_x86_64.whl", hash = "sha256:cf09fd4d90c4c42ddd9bf853290f1a80bc2128993a3923bd3b96b68cc1acd03f"}, - {file = "ptvsd-4.3.2-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:ccc5c533135305709461f545feed5061c608714db38fa0f58e3f848a127b7fde"}, - {file = "ptvsd-4.3.2-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:de5234bec74c47da668e1a1a21bcc9821af0cbb28b5153df78cd5abc744b29a2"}, - {file = "ptvsd-4.3.2-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:c893fb9d1c2ef8f980cc00ced3fd90356f86d9f59b58ee97e0e7e622b8860f76"}, - {file = "ptvsd-4.3.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:2bbc121bce3608501998afbe742f02b80e7d26b8fecd38f78b903f22f52a81d9"}, - {file = "ptvsd-4.3.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:fad06de012a78f277318d0c308dd3d7cc1f67167f3b2e1e2f7c6caf04c03440c"}, - {file = "ptvsd-4.3.2-cp35-cp35m-win32.whl", hash = "sha256:92d26aa7c8f7ffe41cb4b50a00846027027fa17acdf2d9dd8c24de77b25166c6"}, - {file = "ptvsd-4.3.2-cp35-cp35m-win_amd64.whl", hash = "sha256:eda10ecd43daacc180a6fbe524992be76a877c3559e2b78016b4ada8fec10273"}, - {file = "ptvsd-4.3.2-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:c01204e3f025c3f7252c79c1a8a028246d29e3ef339e1a01ddf652999f47bdea"}, - {file = "ptvsd-4.3.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:c97c71835dde7e67fc7b06398bee1c012559a0784ebda9cf8acaf176c7ae766c"}, - {file = "ptvsd-4.3.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:612948a045fcf9c8931cd306972902440278f34de7ca684b49d4caeec9f1ec62"}, - {file = "ptvsd-4.3.2-cp36-cp36m-win32.whl", hash = "sha256:72d114baa5737baf29c8068d1ccdd93cbb332d2030601c888eed0e3761b588d7"}, - {file = "ptvsd-4.3.2-cp36-cp36m-win_amd64.whl", hash = "sha256:58508485a1609a495dd45829bd6d219303cf9edef5ca1f01a9ed8ffaa87f390c"}, - {file = "ptvsd-4.3.2-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:20f48ffed42a6beb879c250d82662e175ad59cc46a29c95c6a4472ae413199c5"}, - {file = "ptvsd-4.3.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b9970e3dc987eb2a6001af6c9d2f726dd6455cfc6d47e0f51925cbdee7ea2157"}, - {file = "ptvsd-4.3.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:1d3d82ecc82186d099992a748556e6e54037f5c5e4d3fc9bba3e2302354be0d4"}, - {file = "ptvsd-4.3.2-cp37-cp37m-win32.whl", hash = "sha256:10745fbb788001959b4de405198d8bd5243611a88fb5a2e2c6800245bc0ddd74"}, - {file = "ptvsd-4.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:90cbd082e7a9089664888d0d94aca760202f080133fca8f3fe65c48ed6b9e39d"}, - {file = "ptvsd-4.3.2-py2.py3-none-any.whl", hash = "sha256:459137736068bb02515040b2ed2738169cb30d69a38e0fd5dffcba255f41e68d"}, - {file = "ptvsd-4.3.2.zip", hash = "sha256:3b05c06018fdbce5943c50fb0baac695b5c11326f9e21a5266c854306bda28ab"}, -] - [[package]] name = "pycparser" version = "2.22" @@ -2838,4 +2883,4 @@ didcommv2 = ["didcomm-messaging"] [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "8a2afe7d38e2e6e4a2e31303a2e6527a1259ead9410e8c96554b5e031d77f4bd" +content-hash = "d44b9e66fa51dd6f349af68df58bbf0603bafcc98854f6890f9cdf600d1b64d8" diff --git a/pyproject.toml b/pyproject.toml index 00c0175e76..170373ad39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,7 +69,6 @@ ruff = "0.6.1" sphinx="^5.3.0" sphinx-rtd-theme=">=0.4.3" -ptvsd="4.3.2" pydevd="1.5.1" pydevd-pycharm="~193.7288.30" @@ -79,6 +78,7 @@ pytest = "^8.3.2" pytest-asyncio = "^0.23.6" pytest-cov = "^5.0.0" pytest-ruff = "^0.4.1" +debugpy = "^1.8.5" [tool.poetry.extras] askar = [ From 81b4d4af93e5f0190a55777be40f53d75353386c Mon Sep 17 00:00:00 2001 From: Ian Costanzo Date: Thu, 22 Aug 2024 08:53:09 -0700 Subject: [PATCH 7/8] Fix logic to send verbose webhooks Signed-off-by: Ian Costanzo --- .../protocols/issue_credential/v2_0/models/cred_ex_record.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aries_cloudagent/protocols/issue_credential/v2_0/models/cred_ex_record.py b/aries_cloudagent/protocols/issue_credential/v2_0/models/cred_ex_record.py index 15ab3cce7b..7e853f36d4 100644 --- a/aries_cloudagent/protocols/issue_credential/v2_0/models/cred_ex_record.py +++ b/aries_cloudagent/protocols/issue_credential/v2_0/models/cred_ex_record.py @@ -201,7 +201,7 @@ async def emit_event(self, session: ProfileSession, payload: Any = None): # serialize payload before checking for webhook contents if not payload: payload = self.serialize() - else: + if not session.profile.settings.get("debug.webhooks"): payload = V20CredExRecordWebhook(**payload) payload = payload.__dict__ From 197db4fe7b4c12a3ddbd1548369bf90a11b43c92 Mon Sep 17 00:00:00 2001 From: jamshale Date: Mon, 19 Aug 2024 21:31:33 +0000 Subject: [PATCH 8/8] Change Integration Testing Signed-off-by: jamshale --- ...iontests.yml => bdd-integration-tests.yml} | 4 +- .github/workflows/bdd-interop-tests.yml | 47 +++ .github/workflows/integration-tests.yml | 39 +++ demo/features/0160-connection.feature | 6 +- demo/features/0453-issue-credential.feature | 48 +-- demo/features/0454-present-proof.feature | 46 +-- demo/features/revocation-api.feature | 8 +- docs/deploying/BBSSignatures.md | 2 +- .../ContainerImagesAndGithubActions.md | 2 +- .../{INTEGRATION-TESTS.md => BDDTests.md} | 2 +- docs/testing/IntegrationTests.md | 24 ++ integration-tests/Dockerfile | 17 + integration-tests/README.md | 3 + integration-tests/conftest.py | 126 +++++++ integration-tests/docker-compose.yml | 91 +++++ .../connectionless/docker-compose.yml | 91 +++++ .../examples/connectionless/example.py | 241 +++++++++++++ .../examples/json_ld/docker-compose.yml | 65 ++++ integration-tests/examples/json_ld/example.py | 319 ++++++++++++++++++ .../examples/mediation/docker-compose.yml | 105 ++++++ .../examples/mediation/example.py | 44 +++ .../examples/multitenancy/docker-compose.yml | 61 ++++ .../examples/multitenancy/example.py | 81 +++++ .../docker-compose.yml | 103 ++++++ .../presenting_revoked_credential/example.py | 178 ++++++++++ .../examples/self_attested/docker-compose.yml | 102 ++++++ .../examples/self_attested/example.py | 152 +++++++++ .../examples/simple/docker-compose.yml | 91 +++++ integration-tests/examples/simple/example.py | 26 ++ integration-tests/examples/tunnels/__skip__ | 0 .../examples/tunnels/docker-compose.yml | 126 +++++++ integration-tests/examples/tunnels/example.py | 178 ++++++++++ integration-tests/examples/tunnels/ngrok.yml | 8 + .../examples/tunnels/tunnel_endpoint.sh | 36 ++ integration-tests/pyproject.toml | 20 ++ mkdocs.yml | 2 +- 36 files changed, 2434 insertions(+), 60 deletions(-) rename .github/workflows/{integrationtests.yml => bdd-integration-tests.yml} (93%) create mode 100644 .github/workflows/bdd-interop-tests.yml create mode 100644 .github/workflows/integration-tests.yml rename docs/testing/{INTEGRATION-TESTS.md => BDDTests.md} (99%) create mode 100644 docs/testing/IntegrationTests.md create mode 100644 integration-tests/Dockerfile create mode 100644 integration-tests/README.md create mode 100644 integration-tests/conftest.py create mode 100644 integration-tests/docker-compose.yml create mode 100644 integration-tests/examples/connectionless/docker-compose.yml create mode 100644 integration-tests/examples/connectionless/example.py create mode 100644 integration-tests/examples/json_ld/docker-compose.yml create mode 100644 integration-tests/examples/json_ld/example.py create mode 100644 integration-tests/examples/mediation/docker-compose.yml create mode 100644 integration-tests/examples/mediation/example.py create mode 100644 integration-tests/examples/multitenancy/docker-compose.yml create mode 100644 integration-tests/examples/multitenancy/example.py create mode 100644 integration-tests/examples/presenting_revoked_credential/docker-compose.yml create mode 100644 integration-tests/examples/presenting_revoked_credential/example.py create mode 100644 integration-tests/examples/self_attested/docker-compose.yml create mode 100644 integration-tests/examples/self_attested/example.py create mode 100644 integration-tests/examples/simple/docker-compose.yml create mode 100644 integration-tests/examples/simple/example.py create mode 100644 integration-tests/examples/tunnels/__skip__ create mode 100644 integration-tests/examples/tunnels/docker-compose.yml create mode 100644 integration-tests/examples/tunnels/example.py create mode 100644 integration-tests/examples/tunnels/ngrok.yml create mode 100755 integration-tests/examples/tunnels/tunnel_endpoint.sh create mode 100644 integration-tests/pyproject.toml diff --git a/.github/workflows/integrationtests.yml b/.github/workflows/bdd-integration-tests.yml similarity index 93% rename from .github/workflows/integrationtests.yml rename to .github/workflows/bdd-integration-tests.yml index 0fc4159460..ed466ba5ff 100644 --- a/.github/workflows/integrationtests.yml +++ b/.github/workflows/bdd-integration-tests.yml @@ -1,4 +1,4 @@ -name: acapy-integration-tests +name: acapy-bdd-integration-tests on: schedule: @@ -20,7 +20,7 @@ defaults: jobs: test: runs-on: ubuntu-latest - if: (github.event_name == 'pull_request' && github.event.pull_request.draft == false && github.repository == 'hyperledger/aries-cloudagent-python') || (github.event_name != 'pull_request') + if: (github.event_name == 'pull_request' && github.event.pull_request.draft == false && github.repository == 'jamshale/aries-cloudagent-python') || (github.event_name != 'pull_request') outputs: is_release: ${{ steps.check_if_release.outputs.is_release }} steps: diff --git a/.github/workflows/bdd-interop-tests.yml b/.github/workflows/bdd-interop-tests.yml new file mode 100644 index 0000000000..ce86eb257a --- /dev/null +++ b/.github/workflows/bdd-interop-tests.yml @@ -0,0 +1,47 @@ +name: acapy-bdd-interop-tests + +on: + pull_request: + branches: + - main + types: [opened, synchronize, reopened, ready_for_review] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +jobs: + test: + runs-on: ubuntu-latest + if: (github.event_name == 'pull_request' && github.event.pull_request.draft == false && github.repository == 'jamshale/aries-cloudagent-python') || (github.event_name != 'pull_request') + outputs: + is_release: ${{ steps.check_if_release.outputs.is_release }} + steps: + - name: checkout-acapy + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Request GitHub API for PR data + uses: octokit/request-action@v2.x + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + id: get_pr_data + with: + route: GET /repos/${{ github.event.repository.full_name }}/pulls/${{ github.event.number }} + - name: Run BDD Interop Tests + run: | + # Get AATH + git clone https://github.com/hyperledger/aries-agent-test-harness.git + echo ${{ fromJson(steps.get_pr_data.outputs.data).head.repo.html_url }} + echo ${{ fromJson(steps.get_pr_data.outputs.data).head.ref }} + ls -a + sed -i 's|@git+https://github.com/hyperledger/aries-cloudagent-python@main|@git+${{ fromJson(steps.get_pr_data.outputs.data).head.repo.html_url }}@${{ fromJson(steps.get_pr_data.outputs.data).head.ref }}|g' ./aries-agent-test-harness/aries-backchannels/acapy/requirements-main.txt + cat aries-agent-test-harness/aries-backchannels/acapy/requirements-main.txt + cd aries-agent-test-harness + ./manage build -a acapy-main + NO_TTY=1 LEDGER_URL_CONFIG=http://test.bcovrin.vonx.io TAILS_SERVER_URL_CONFIG=https://tails.vonx.io ./manage run -d acapy-main -t @AcceptanceTest -t ~@wip -t ~@T004-RFC0211 -t ~@DidMethod_orb -t ~@Transport_NoHttpOutbound + diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml new file mode 100644 index 0000000000..0d6cacc54f --- /dev/null +++ b/.github/workflows/integration-tests.yml @@ -0,0 +1,39 @@ +name: acapy-integration-tests + +on: + pull_request: + branches: + - main + types: [opened, synchronize, reopened, ready_for_review] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +defaults: + run: + shell: bash + +jobs: + test: + runs-on: ubuntu-latest + if: (github.event_name == 'pull_request' && github.event.pull_request.draft == false && github.repository == 'jamshale/aries-cloudagent-python') || (github.event_name != 'pull_request') + steps: + - name: checkout-acapy + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Install poetry + run: pipx install poetry + id: setup-poetry + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + cache: "poetry" + - name: Run Integration tests + run: | + # Build the docker image for testing + docker build -t acapy-test -f docker/Dockerfile.run . + cd integration-tests + poetry install --no-root + poetry run pytest -m examples diff --git a/demo/features/0160-connection.feature b/demo/features/0160-connection.feature index a68e651711..7d2df7c2d2 100644 --- a/demo/features/0160-connection.feature +++ b/demo/features/0160-connection.feature @@ -12,7 +12,7 @@ Feature: RFC 0160 Aries agent connection functions Then "Acme" has an active connection And "Bob" has an active connection - @PR @Release @UnqualifiedDids + @UnqualifiedDids Examples: | Acme_capabilities | Acme_extra | Bob_capabilities | Bob_extra | | --public-did --did-exchange --emit-did-peer-2 | | --did-exchange --emit-did-peer-2 | | @@ -40,7 +40,7 @@ Feature: RFC 0160 Aries agent connection functions | --did-exchange --emit-did-peer-4 | | --emit-did-peer-4 | | | --did-exchange --reuse-connections --emit-did-peer-4 | | --reuse-connections --emit-did-peer-4 | | - @PR @Release @MultiUseConnectionReuse + @MultiUseConnectionReuse Examples: | Acme_capabilities | Acme_extra | Bob_capabilities | Bob_extra | | --did-exchange --multi-use-invitations --emit-did-peer-2 | | --emit-did-peer-2 | | @@ -56,7 +56,7 @@ Feature: RFC 0160 Aries agent connection functions | --public-did --did-exchange --multi-use-invitations --emit-did-peer-4 | | --did-exchange --emit-did-peer-2 | | | --public-did --did-exchange --multi-use-invitations --reuse-connections --emit-did-peer-2 | | --did-exchange --reuse-connections --emit-did-peer-4 | | - @PR @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | Acme_capabilities | Acme_extra | Bob_capabilities | Bob_extra | | --public-did --did-exchange --wallet-type askar-anoncreds --emit-did-peer-2 | | --did-exchange --wallet-type askar-anoncreds --emit-did-peer-2 | | diff --git a/demo/features/0453-issue-credential.feature b/demo/features/0453-issue-credential.feature index 9a6aae587b..9a19ca025a 100644 --- a/demo/features/0453-issue-credential.feature +++ b/demo/features/0453-issue-credential.feature @@ -12,37 +12,37 @@ Feature: RFC 0453 Aries agent issue credential When "Acme" offers a credential with data Then "Bob" has the credential issued - @Release @WalletType_Askar @BasicTest + @WalletType_Askar @BasicTest Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Acme_extra | Bob_extra | | --public-did --did-exchange | --did-exchange | driverslicense | Data_DL_NormalizedValues | | | - @Release @WalletType_Askar @AltTests + @WalletType_Askar @AltTests Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Acme_extra | Bob_extra | | --public-did | | driverslicense | Data_DL_NormalizedValues | | | | --public-did --mediation | --mediation | driverslicense | Data_DL_NormalizedValues | | | | --public-did --multitenant | --multitenant --log-file | driverslicense | Data_DL_NormalizedValues | | | - @Release @WalletType_Askar_AnonCreds @BasicTest @cred_type_vc_di + @WalletType_Askar_AnonCreds @BasicTest @cred_type_vc_di Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Acme_extra | Bob_extra | | --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | | | | --public-did --wallet-type askar-anoncreds --cred-type vc_di | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | | | - @Release @WalletType_Askar_AnonCreds @AltTests + @WalletType_Askar_AnonCreds @AltTests Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Acme_extra | Bob_extra | | --public-did --wallet-type askar-anoncreds | | driverslicense | Data_DL_NormalizedValues | | | | --public-did | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | | | - @PR @Release @WalletType_Askar @ConnectionTests + @WalletType_Askar @ConnectionTests Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Acme_extra | Bob_extra | | --did-exchange --emit-did-peer-4 | --did-exchange --emit-did-peer-4 | driverslicense | Data_DL_NormalizedValues | | | | --did-exchange --reuse-connections --emit-did-peer-4 | --did-exchange --reuse-connections --emit-did-peer-4 | driverslicense | Data_DL_NormalizedValues | | | - @PR @Release @WalletType_Askar_AnonCreds @ConnectionTests + @WalletType_Askar_AnonCreds @ConnectionTests Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Acme_extra | Bob_extra | | --did-exchange --wallet-type askar-anoncreds --emit-did-peer-4 | --did-exchange --wallet-type askar-anoncreds --emit-did-peer-4 | driverslicense | Data_DL_NormalizedValues | | | @@ -82,7 +82,7 @@ Feature: RFC 0453 Aries agent issue credential And "Acme" offers and deletes a credential with data Then "Bob" has the exchange abandoned - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | | --public-did | | driverslicense | Data_DL_NormalizedValues | @@ -110,7 +110,7 @@ Feature: RFC 0453 Aries agent issue credential And "Acme" is ready to issue a credential for When "Bob" requests a credential with data from "Acme" it fails - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | | --public-did | | driverslicense | Data_DL_NormalizedValues | @@ -141,13 +141,13 @@ Feature: RFC 0453 Aries agent issue credential Then "Bob" has the json-ld credential issued And "Acme" has the exchange completed - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2018 | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | - @PR @Release @WalletType_Askar @BBS + @WalletType_Askar @BBS Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | @@ -193,18 +193,18 @@ Feature: RFC 0453 Aries agent issue credential When "Acme" offers "Bob" a json-ld credential with data and Then "Bob" has the json-ld credential issued - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2018 | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | - @PR @Release @WalletType_Askar @BBS + @WalletType_Askar @BBS Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | - @Release @WalletType_Askar + @WalletType_Askar Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld --did-exchange | --did-exchange | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2018 | @@ -214,14 +214,14 @@ Feature: RFC 0453 Aries agent issue credential | --public-did --cred-type json-ld --mediation | --mediation | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | | --public-did --cred-type json-ld --multitenant --log-file | --multitenant | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | - @Release @WalletType_Askar @BBS + @WalletType_Askar @BBS Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld --did-exchange | --did-exchange | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | | --public-did --cred-type json-ld --mediation | --mediation | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | | --public-did --cred-type json-ld --multitenant --log-file | --multitenant | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | - @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2018 | @@ -229,7 +229,7 @@ Feature: RFC 0453 Aries agent issue credential | --public-did --cred-type json-ld --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | | --public-did --cred-type json-ld --did-exchange --wallet-type askar-anoncreds | --did-exchange --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | - @Release @WalletType_Askar_AnonCreds @BBS + @WalletType_Askar_AnonCreds @BBS Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | @@ -262,18 +262,18 @@ Feature: RFC 0453 Aries agent issue credential When "Bob" requests a json-ld credential with data from "Acme" with Then "Bob" has the json-ld credential issued - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2018 | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | - @PR @Release @WalletType_Askar @BBS + @WalletType_Askar @BBS Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld | | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | - @Release @WalletType_Askar + @WalletType_Askar Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld --did-exchange | --did-exchange | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2018 | @@ -283,20 +283,20 @@ Feature: RFC 0453 Aries agent issue credential | --public-did --cred-type json-ld --mediation | --mediation | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | | --public-did --cred-type json-ld --multitenant | --multitenant | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | - @Release @WalletType_Askar @BBS + @WalletType_Askar @BBS Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld --did-exchange | --did-exchange | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | | --public-did --cred-type json-ld --mediation | --mediation | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | | --public-did --cred-type json-ld --multitenant | --multitenant | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | - @PR @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2018 | | --public-did --cred-type json-ld --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | ed25519 | Ed25519Signature2020 | - @PR @Release @WalletType_Askar_AnonCreds @BBS + @WalletType_Askar_AnonCreds @BBS Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Key_type | Sig_type | | --public-did --cred-type json-ld --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | bls12381g2 | BbsBlsSignature2020 | @@ -313,14 +313,14 @@ Feature: RFC 0453 Aries agent issue credential Then "Acme" revokes the credential And "Bob" has the credential issued - @Release @WalletType_Askar + @WalletType_Askar Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | | --revocation --public-did | | driverslicense | Data_DL_NormalizedValues | | --revocation --public-did --did-exchange | --did-exchange | driverslicense | Data_DL_NormalizedValues | | --revocation --public-did --multitenant | --multitenant | driverslicense | Data_DL_NormalizedValues | - @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | | --revocation --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense | Data_DL_NormalizedValues | diff --git a/demo/features/0454-present-proof.feature b/demo/features/0454-present-proof.feature index 36973d828f..dffc1f598c 100644 --- a/demo/features/0454-present-proof.feature +++ b/demo/features/0454-present-proof.feature @@ -12,27 +12,27 @@ Feature: RFC 0454 Aries agent present proof When "Faber" sends a request for proof presentation to "Bob" Then "Faber" has the proof verified - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --public-did | | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --public-did --did-exchange | --did-exchange | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @PR @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @Release @WalletType_Askar_AnonCreds @cred_type_vc_di + @WalletType_Askar_AnonCreds @cred_type_vc_di Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --public-did --wallet-type askar-anoncreds --cred-type vc_di | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --public-did --wallet-type askar-anoncreds | | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | @@ -51,12 +51,12 @@ Feature: RFC 0454 Aries agent present proof When "Faber" sends a request for proof presentation to "Bob" Then "Faber" has the proof verified - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer | Acme_capabilities | Acme_extra | Bob_capabilities | Bob_extra | Schema_name | Credential_data | Proof_request | | Faber | --public-did --did-exchange --emit-did-peer-2 | | --did-exchange --emit-did-peer-2 | | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @PR @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | issuer | Acme_capabilities | Acme_extra | Bob_capabilities | Bob_extra | Schema_name | Credential_data | Proof_request | | Faber | --public-did --wallet-type askar-anoncreds --emit-did-peer-2 | | --wallet-type askar-anoncreds --emit-did-peer-2 | | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | @@ -103,17 +103,17 @@ Feature: RFC 0454 Aries agent present proof When "Faber" sends a request for json-ld proof presentation to "Bob" with Then "Faber" has the proof verified - @PR @Release @WalletType_Askar @BBS + @WalletType_Askar @BBS Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | Key_type | Sig_type | | Acme | --public-did --cred-type json-ld | | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | bls12381g2 | BbsBlsSignature2020 | - @Release @WalletType_Askar @BBS + @WalletType_Askar @BBS Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | Key_type | Sig_type | | Faber | --public-did --cred-type json-ld --did-exchange | --did-exchange | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | bls12381g2 | BbsBlsSignature2020 | - @PR @Release @WalletType_Askar_AnonCreds @BBS + @WalletType_Askar_AnonCreds @BBS Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | Key_type | Sig_type | | Faber | --public-did --cred-type json-ld --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | bls12381g2 | BbsBlsSignature2020 | @@ -132,22 +132,22 @@ Feature: RFC 0454 Aries agent present proof When "Faber" sends a request for proof presentation to "Bob" Then "Faber" has the proof verification fail - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --revocation --public-did | | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --revocation --public-did --did-exchange | --did-exchange | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @PR @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --revocation --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @Release @WalletType_Askar_AnonCreds @cred_type_vc_di + @WalletType_Askar_AnonCreds @cred_type_vc_di Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | | Faber | --revocation --public-did --wallet-type askar-anoncreds --cred-type vc_di | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | @@ -198,17 +198,17 @@ Feature: RFC 0454 Aries agent present proof When "Faber" sends a request for proof presentation to "Bob" Then "Faber" has the proof verified - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did | Acme2 | --public-did | | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id | - @PR @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did --wallet-type askar-anoncreds | Acme2 | --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id | - @Release @WalletType_Askar_AnonCreds @cred_type_vc_di + @WalletType_Askar_AnonCreds @cred_type_vc_di Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did --wallet-type askar-anoncreds --cred-type vc_di | Acme2 | --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id | @@ -229,7 +229,7 @@ Feature: RFC 0454 Aries agent present proof When "Faber" sends a request for proof presentation to "Bob" Then "Faber" has the proof verification fail - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did | Acme2 | --public-did | | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id_r2 | @@ -256,13 +256,13 @@ Feature: RFC 0454 Aries agent present proof When "Faber" sends a request for proof presentation to "Bob" Then "Faber" has the proof verification fail - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did | Acme2 | --public-did | | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id | | Acme1 | --revocation --public-did | Acme2 | --public-did | | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id_r2 | - @PR @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did --wallet-type askar-anoncreds | Acme2 | --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id | @@ -284,17 +284,17 @@ Feature: RFC 0454 Aries agent present proof When "Faber" sends a request with explicit revocation status for proof presentation to "Bob" Then "Faber" has the proof verified - @PR @Release @WalletType_Askar + @WalletType_Askar Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did | Acme2 | --public-did | | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id_no_revoc | - @PR @Release @WalletType_Askar_AnonCreds + @WalletType_Askar_AnonCreds Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did --wallet-type askar-anoncreds | Acme2 | --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id_no_revoc | - @PR @Release @WalletType_Askar_AnonCreds @cred_type_vc_di + @WalletType_Askar_AnonCreds @cred_type_vc_di Examples: | issuer1 | Acme1_capabilities | issuer2 | Acme2_capabilities | Bob_cap | Schema_name_1 | Credential_data_1 | Schema_name_2 | Credential_data_2 | Proof_request | | Acme1 | --revocation --public-did --wallet-type askar-anoncreds --cred-type vc_di | Acme2 | --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | health_id | Data_DL_MaxValues | DL_age_over_19_v2_with_health_id_no_revoc | diff --git a/demo/features/revocation-api.feature b/demo/features/revocation-api.feature index ebfdb120de..a1c7fa2f81 100644 --- a/demo/features/revocation-api.feature +++ b/demo/features/revocation-api.feature @@ -1,6 +1,6 @@ Feature: ACA-Py Revocation API - @Revoc-api @PR @Release + @Revoc-api Scenario Outline: Using revocation api, issue and revoke credentials Given we have "3" agents | name | role | capabilities | @@ -19,7 +19,7 @@ Feature: ACA-Py Revocation API #| Acme | --revocation --public-did | | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | | Acme | --revocation --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @Revoc-api @PR @Release + @Revoc-api Scenario Outline: Using revocation api, issue, revoke credentials and publish Given we have "3" agents | name | role | capabilities | @@ -76,7 +76,7 @@ Feature: ACA-Py Revocation API | Acme | --revocation --public-did --did-exchange --multitenant --wallet-type askar | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | | Acme | --revocation --public-did --did-exchange --multitenant --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @Revoc-api @PR @Release + @Revoc-api Scenario Outline: Using revocation api, rotate revocation Given we have "3" agents | name | role | capabilities | @@ -93,7 +93,7 @@ Feature: ACA-Py Revocation API #| Acme | --revocation --public-did | | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | | Acme | --revocation --public-did --wallet-type askar-anoncreds | --wallet-type askar-anoncreds | driverslicense_v2 | Data_DL_MaxValues | DL_age_over_19_v2 | - @Revoc-api @PR @Release + @Revoc-api Scenario Outline: Using revocation api, fill registry (need to run with "TAILS_FILE_COUNT": "4" env var) Given we have "2" agents | name | role | capabilities | diff --git a/docs/deploying/BBSSignatures.md b/docs/deploying/BBSSignatures.md index b03be5e2a2..76579b76fb 100644 --- a/docs/deploying/BBSSignatures.md +++ b/docs/deploying/BBSSignatures.md @@ -24,4 +24,4 @@ WARNNG: if you do NOT have `bbs` installed you should exclude the BBS specific i ./run_bdd -t ~@BBS ``` -See the [Unit](../testing/UnitTests.md) and [Integration](../testing/INTEGRATION-TESTS.md) testing docs for more information on how to run tests. +See the [Unit](../testing/UnitTests.md) and [Integration](../testing/BDDTests.md) testing docs for more information on how to run tests. diff --git a/docs/deploying/ContainerImagesAndGithubActions.md b/docs/deploying/ContainerImagesAndGithubActions.md index 6e891fcddb..91e96c8d37 100644 --- a/docs/deploying/ContainerImagesAndGithubActions.md +++ b/docs/deploying/ContainerImagesAndGithubActions.md @@ -90,7 +90,7 @@ variants and between the BC Gov ACA-Py images. - Publish (`.github/workflows/publish.yml`) - Run on new release published or when manually triggered; builds and pushes the Standard ACA-Py variant to the Github Container Registry. -- Integration Tests (`.github/workflows/integrationtests.yml`) - Run on pull +- BDD Integration Tests (`.github/workflows/BDDTests.yml`) - Run on pull requests (to the hyperledger fork only); runs BDD integration tests. - Format (`.github/workflows/format.yml`) - Run on pull requests; checks formatting of files modified by the PR. diff --git a/docs/testing/INTEGRATION-TESTS.md b/docs/testing/BDDTests.md similarity index 99% rename from docs/testing/INTEGRATION-TESTS.md rename to docs/testing/BDDTests.md index dad1955b6c..8ed9b76472 100644 --- a/docs/testing/INTEGRATION-TESTS.md +++ b/docs/testing/BDDTests.md @@ -28,7 +28,7 @@ cd aries-cloudagent-python/demo Note that an Indy ledger and tails server are both required (these can also be specified using environment variables). -Note also that some tests require a ledger with TAA enabled, how to run these tests will be described later. +Note also that some tests require a ledger with TAA enabled, how to run tEhese tests will be described later. By default the test suite runs using a default (SQLite) wallet, to run the tests using postgres run the following: diff --git a/docs/testing/IntegrationTests.md b/docs/testing/IntegrationTests.md new file mode 100644 index 0000000000..5356e5eac1 --- /dev/null +++ b/docs/testing/IntegrationTests.md @@ -0,0 +1,24 @@ +# Integration Test Plan + +Integration testing in ACA-Py consists of 3 different levels or types. +1. Interop profile (AATH) BDD tests. +2. ACA-Py specific BDD tests. +3. End to End tests. + +## Interop profile (AATH) BDD tests + +Interoperability is extremely important in the aries community. When implementing or changing features that are included in the [aries interop profile](https://github.com/hyperledger/aries-rfcs/blob/main/concepts/0302-aries-interop-profile/README.md) the developer should try to add tests to this test suite. The tests will then be ran for PR's and scheduled workflows for acapy <--> acapy agents. + +These tests are contained in a separate repo [AATH](https://github.com/hyperledger/aries-agent-test-harness). They use the gherkin syntax and a http back channel. + + +## ACA-Py specific BDD tests + +These tests leverage the demo agent and also use behave syntax and a back channel. See [README](./BDDTests.md) + +These tests are another tool for leveraging the demo agent and the gherkin syntax. They should not be used to test features that involve the interop profile, as they can not be used to test against other frameworks. None of the tests that are covered by the AATH tests will be ran automatically. They are here because some developers may prefer the testing strategy and can be useful for explicit testing steps and protocols not included in the interop profile. + +## Scenario testing + +These tests utilize the minimal example [agent](https://github.com/Indicio-tech/acapy-minimal-example) produced by Indicio. They exist in the `integration-tests` directory. They are very useful for running specific test plans and checking webhooks. + diff --git a/integration-tests/Dockerfile b/integration-tests/Dockerfile new file mode 100644 index 0000000000..e08aee4d2b --- /dev/null +++ b/integration-tests/Dockerfile @@ -0,0 +1,17 @@ +FROM python:3.10 +WORKDIR /usr/src/app/ + +ENV POETRY_VERSION=1.8.3 +ENV POETRY_HOME=/opt/poetry +RUN curl -sSL https://install.python-poetry.org | python - + +ENV PATH="/opt/poetry/bin:$PATH" +RUN poetry config virtualenvs.in-project true + +# Setup project +COPY pyproject.toml poetry.lock README.md ./ +RUN poetry install + +COPY examples/ examples/ + +ENTRYPOINT ["poetry", "run"] \ No newline at end of file diff --git a/integration-tests/README.md b/integration-tests/README.md new file mode 100644 index 0000000000..85819a0d65 --- /dev/null +++ b/integration-tests/README.md @@ -0,0 +1,3 @@ +This project is used to write integration tests leveraging the [acapy-minimal-example](https://github.com/Indicio-tech/acapy-minimal-example) library provided by the contributors from Indicio + +Every test example will have a docker-compose.yml file for all the agents and services used in the test scenario. \ No newline at end of file diff --git a/integration-tests/conftest.py b/integration-tests/conftest.py new file mode 100644 index 0000000000..fcfe03ec86 --- /dev/null +++ b/integration-tests/conftest.py @@ -0,0 +1,126 @@ +"""Pytest fixtures and configuration.""" + +import subprocess +from pathlib import Path + +import pytest +from pytest import Session + +EXAMPLES_DIR = Path(__file__).parent / "examples" + + +class ExampleFailedException(Exception): + """Raised when an example fails.""" + + def __init__(self, message: str, exit_status: int): + """Initialize ExampleFailedException.""" + + super().__init__(message) + self.exit_status = exit_status + + +class ExampleRunner: + """Run the docker compose of a given example.""" + + def __init__(self, compose_file: str): + """Initialize ExampleRunner.""" + + self.compose_file = compose_file + + def compose(self, *command: str) -> int: + """Runs docker compose using subprocess with the given command. + + Returns exit status and output. + """ + try: + subprocess.run( + ["docker", "compose", "-f", self.compose_file, *command], + check=True, + ) + return 0 + except subprocess.CalledProcessError as e: + return e.returncode + + def cleanup(self): + """Runs docker compose down -v for cleanup.""" + exit_status = self.compose("down", "-v") + if exit_status != 0: + raise ExampleFailedException( + f"Cleanup failed with exit status {exit_status}", exit_status + ) + + def handle_run(self, *command: str): + """Handles the run of docker compose/. + + raises exception if exit status is non-zero. + """ + try: + exit_status = self.compose(*command) + if exit_status != 0: + raise ExampleFailedException( + f"Command failed with exit status: {exit_status}", + exit_status=exit_status, + ) + finally: + self.cleanup() + + +def pytest_collect_file(parent: Session, file_path: Path): + """Pytest collection hook. + + This will collect the docker compose.yml files from the examples and create + pytest items to run them. + """ + file = Path(str(file_path)) + + # Skip certain examples + if (file.parent / "__skip__").exists(): + return + + if file.suffix == ".yml" and file.parent.parent == EXAMPLES_DIR: + return ExampleFile.from_parent(parent, path=file.parent) + + +class ExampleFile(pytest.File): + """Pytest file for example.""" + + def collect(self): + """Collect tests from example file.""" + path = Path(self.fspath) + item = ExampleItem.from_parent( + self, name=path.name, compose_file=str(path / "docker-compose.yml") + ) + item.add_marker(pytest.mark.examples) + yield item + + +class ExampleItem(pytest.Item): + """Example item. + + Runs the docker-compose.yml file of the example and reports failure if the + exit status is non-zero. + """ + + def __init__(self, name: str, parent: pytest.File, compose_file: str): + """Initialize ExampleItem.""" + super().__init__(name, parent) + self.compose_file = compose_file + + def runtest(self) -> None: + """Run the test.""" + ExampleRunner(self.compose_file).handle_run("run", "example") + + def repr_failure(self, excinfo): + """Called when self.runtest() raises an exception.""" + if isinstance(excinfo.value, ExampleFailedException): + return "\n".join( + [ + "Example failed!", + f" {excinfo.value}", + ] + ) + return f"Some other exception happened: {excinfo.value}" + + def reportinfo(self): + """Report info about the example.""" + return self.fspath, 0, f"example: {self.name}" diff --git a/integration-tests/docker-compose.yml b/integration-tests/docker-compose.yml new file mode 100644 index 0000000000..5573cff1c2 --- /dev/null +++ b/integration-tests/docker-compose.yml @@ -0,0 +1,91 @@ +# This docker-compose file is used for tests only + +services: + alice: + image: acapy-test + ports: + - "3001:3001" + command: > + start + --label Alice + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://alice:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + + bob: + image: acapy-test + ports: + - "3002:3001" + command: > + start + --label Bob + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name bob + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + + tails: + image: ghcr.io/bcgov/tails-server:latest + ports: + - 6543:6543 + environment: + - GENESIS_URL=https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + command: > + tails-server + --host 0.0.0.0 + --port 6543 + --storage-path /tmp/tails-files + --log-level INFO + + tests: + container_name: juggernaut + build: + context: . + args: + install_flags: "" + environment: + - ALICE=http://alice:3001 + - BOB=http://bob:3001 + volumes: + - ./tests:/usr/src/app/tests:z + entrypoint: "poetry run pytest" + depends_on: + alice: + condition: service_healthy + bob: + condition: service_healthy \ No newline at end of file diff --git a/integration-tests/examples/connectionless/docker-compose.yml b/integration-tests/examples/connectionless/docker-compose.yml new file mode 100644 index 0000000000..95702ed09c --- /dev/null +++ b/integration-tests/examples/connectionless/docker-compose.yml @@ -0,0 +1,91 @@ + services: + alice: + image: acapy-test + ports: + - "3001:3001" + environment: + RUST_LOG: 'aries-askar::log::target=error' + command: > + start + --label Alice + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://alice:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + + bob: + image: acapy-test + ports: + - "3002:3001" + environment: + RUST_LOG: 'aries-askar::log::target=error' + command: > + start + --label Bob + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name bob + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + + tails: + image: ghcr.io/bcgov/tails-server:latest + ports: + - 6543:6543 + environment: + - GENESIS_URL=https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + command: > + tails-server + --host 0.0.0.0 + --port 6543 + --storage-path /tmp/tails-files + --log-level INFO + + example: + container_name: controller + build: + context: ../.. + environment: + - ALICE=http://alice:3001 + - BOB=http://bob:3001 + volumes: + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + alice: + condition: service_healthy + bob: + condition: service_healthy diff --git a/integration-tests/examples/connectionless/example.py b/integration-tests/examples/connectionless/example.py new file mode 100644 index 0000000000..a0dcc78895 --- /dev/null +++ b/integration-tests/examples/connectionless/example.py @@ -0,0 +1,241 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +from dataclasses import dataclass +from os import getenv + +from acapy_controller import Controller +from acapy_controller.controller import Minimal +from acapy_controller.logging import logging_to_stdout +from acapy_controller.protocols import ( + InvitationRecord, + V20CredExRecordDetail, + V20CredExRecordIndy, + indy_anoncred_onboard, + indy_anoncred_credential_artifacts, +) + +ALICE = getenv("ALICE", "http://alice:3001") +BOB = getenv("BOB", "http://bob:3001") + + +@dataclass +class ConnectionlessV20CredExRecord(Minimal): + """Minimal record for connectionless v2 cred ex record.""" + + cred_ex_id: str + + +async def icv2(): + """Test Controller protocols.""" + async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + await indy_anoncred_onboard(alice) + _, cred_def = await indy_anoncred_credential_artifacts( + alice, ["firstname", "lastname"] + ) + + attributes = {"firstname": "Bob", "lastname": "Builder"} + offer = await alice.post( + "/issue-credential-2.0/create-offer", + json={ + "auto_issue": False, + "auto_remove": False, + "comment": "Credential from minimal example", + "trace": False, + "filter": {"indy": {"cred_def_id": cred_def.credential_definition_id}}, + "credential_preview": { + "type": "issue-credential-2.0/2.0/credential-preview", # pyright: ignore + "attributes": [ + { + "mime_type": None, + "name": name, + "value": value, + } + for name, value in attributes.items() + ], + }, + }, + response=ConnectionlessV20CredExRecord, + ) + invite = await alice.post( + "/out-of-band/create-invitation", + json={ + "attachments": [{"id": offer.cred_ex_id, "type": "credential-offer"}] + }, + response=InvitationRecord, + ) + bob.event_queue.flush() + await bob.post("/out-of-band/receive-invitation", json=invite.invitation) + bob_cred_ex = await bob.event_with_values( + topic="issue_credential_v2_0", + state="offer-received", + event_type=ConnectionlessV20CredExRecord, + ) + bob_cred_ex_id = bob_cred_ex.cred_ex_id + + alice.event_queue.flush() + bob_cred_ex = await bob.post( + f"/issue-credential-2.0/records/{bob_cred_ex_id}/send-request", + response=ConnectionlessV20CredExRecord, + ) + + alice_cred_ex = await alice.event_with_values( + topic="issue_credential_v2_0", + state="request-received", + event_type=ConnectionlessV20CredExRecord, + ) + alice_cred_ex_id = alice_cred_ex.cred_ex_id + + alice_cred_ex = await alice.post( + f"/issue-credential-2.0/records/{alice_cred_ex_id}/issue", + json={}, + response=V20CredExRecordDetail, + ) + + await bob.event_with_values( + topic="issue_credential_v2_0", + cred_ex_id=bob_cred_ex_id, + state="credential-received", + ) + + bob_cred_ex = await bob.post( + f"/issue-credential-2.0/records/{bob_cred_ex_id}/store", + json={}, + response=V20CredExRecordDetail, + ) + alice_cred_ex = await alice.event_with_values( + topic="issue_credential_v2_0", + event_type=ConnectionlessV20CredExRecord, + cred_ex_id=alice_cred_ex_id, + state="done", + ) + await alice.event_with_values( + topic="issue_credential_v2_0_indy", + event_type=V20CredExRecordIndy, + ) + + bob_cred_ex = await bob.event_with_values( + topic="issue_credential_v2_0", + event_type=ConnectionlessV20CredExRecord, + cred_ex_id=bob_cred_ex_id, + state="done", + ) + await bob.event_with_values( + topic="issue_credential_v2_0_indy", + event_type=V20CredExRecordIndy, + ) + + +@dataclass +class ConnectionlessV10CredExRecord(Minimal): + """Minimal record for v1 cred ex record.""" + + credential_exchange_id: str + + +async def icv1(): + """Issue credential v1.""" + async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + await indy_anoncred_onboard(alice) + _, cred_def = await indy_anoncred_credential_artifacts( + alice, ["firstname", "lastname"] + ) + + attributes = {"firstname": "Bob", "lastname": "Builder"} + offer = await alice.post( + "/issue-credential/create-offer", + json={ + "auto_issue": False, + "auto_remove": False, + "comment": "Credential from minimal example", + "trace": False, + "cred_def_id": cred_def.credential_definition_id, + "credential_preview": { + "@type": "issue-credential/1.0/credential-preview", + "attributes": [ + { + "mime_type": None, + "name": name, + "value": value, + } + for name, value in attributes.items() + ], + }, + }, + response=ConnectionlessV10CredExRecord, + ) + invite = await alice.post( + "/out-of-band/create-invitation", + json={ + "attachments": [ + {"id": offer.credential_exchange_id, "type": "credential-offer"} + ] + }, + response=InvitationRecord, + ) + bob.event_queue.flush() + await bob.post("/out-of-band/receive-invitation", json=invite.invitation) + bob_cred_ex = await bob.event_with_values( + topic="issue_credential", + state="offer_received", + event_type=ConnectionlessV10CredExRecord, + ) + bob_cred_ex_id = bob_cred_ex.credential_exchange_id + + alice.event_queue.flush() + bob_cred_ex = await bob.post( + f"/issue-credential/records/{bob_cred_ex_id}/send-request", + response=ConnectionlessV10CredExRecord, + ) + + alice_cred_ex = await alice.event_with_values( + topic="issue_credential", + state="request_received", + event_type=ConnectionlessV10CredExRecord, + ) + alice_cred_ex_id = alice_cred_ex.credential_exchange_id + + alice_cred_ex = await alice.post( + f"/issue-credential/records/{alice_cred_ex_id}/issue", + json={}, + response=ConnectionlessV10CredExRecord, + ) + + await bob.event_with_values( + topic="issue_credential", + credential_exchange_id=bob_cred_ex_id, + state="credential_received", + ) + + bob_cred_ex = await bob.post( + f"/issue-credential/records/{bob_cred_ex_id}/store", + json={}, + response=ConnectionlessV10CredExRecord, + ) + alice_cred_ex = await alice.event_with_values( + topic="issue_credential", + event_type=ConnectionlessV10CredExRecord, + credential_exchange_id=alice_cred_ex_id, + state="credential_acked", + ) + + bob_cred_ex = await bob.event_with_values( + topic="issue_credential", + event_type=ConnectionlessV10CredExRecord, + credential_exchange_id=bob_cred_ex_id, + state="credential_acked", + ) + + +async def main(): + """Run.""" + await icv1() + await icv2() + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/integration-tests/examples/json_ld/docker-compose.yml b/integration-tests/examples/json_ld/docker-compose.yml new file mode 100644 index 0000000000..3a3ae3fe52 --- /dev/null +++ b/integration-tests/examples/json_ld/docker-compose.yml @@ -0,0 +1,65 @@ + services: + alice: + image: acapy-test + ports: + - "3001:3001" + command: > + start -it http 0.0.0.0 3000 + --label Alice + -ot http + -e http://alice:3000 + --admin 0.0.0.0 3001 --admin-insecure-mode + --log-level debug + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_demonet_genesis + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --auto-provision + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 3s + timeout: 5s + retries: 5 + + + bob: + image: acapy-test + ports: + - "3002:3001" + command: > + start -it http 0.0.0.0 3000 + --label Bob + -ot http + -e http://bob:3000 + --admin 0.0.0.0 3001 --admin-insecure-mode + --log-level debug + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_demonet_genesis + --wallet-type askar + --wallet-name bob + --wallet-key insecure + --auto-provision + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 3s + timeout: 5s + retries: 5 + + example: + container_name: controller + build: + context: ../.. + environment: + - ALICE=http://alice:3001 + - BOB=http://bob:3001 + volumes: + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + alice: + condition: service_healthy + bob: + condition: service_healthy diff --git a/integration-tests/examples/json_ld/example.py b/integration-tests/examples/json_ld/example.py new file mode 100644 index 0000000000..21282bc495 --- /dev/null +++ b/integration-tests/examples/json_ld/example.py @@ -0,0 +1,319 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +from datetime import date +import json +from os import getenv +from uuid import uuid4 + +from acapy_controller import Controller +from acapy_controller.logging import logging_to_stdout, pause_for_input, section +from acapy_controller.models import DIDResult, V20PresExRecord +from acapy_controller.protocols import ( + didexchange, + indy_anoncred_onboard, + jsonld_issue_credential, + jsonld_present_proof, +) + +ALICE = getenv("ALICE", "http://alice:3001") +BOB = getenv("BOB", "http://bob:3001") + + +def presentation_summary(pres_ex: V20PresExRecord): + """Summarize a presentation.""" + pres_ex_dict = pres_ex.dict(exclude_none=True, exclude_unset=True) + return json.dumps( + { + key: pres_ex_dict.get(key) + for key in ( + "verified", + "state", + "role", + "connection_id", + "pres_request", + "pres", + ) + }, + indent=2, + ) + + +async def main(): + """Test Controller protocols.""" + async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + with section("Establish connection"): + alice_conn, bob_conn = await didexchange(alice, bob) + + with section("Prepare for issuance"): + with section("Issuer prepares issuing DIDs", character="-"): + public_did = await indy_anoncred_onboard(alice) + bls_alice_did_res = ( + await alice.post( + "/wallet/did/create", + json={"method": "key", "options": {"key_type": "bls12381g2"}}, + ) + )["result"] + assert bls_alice_did_res + bls_alice_did = bls_alice_did_res["did"] + + with section("Recipient prepares subject DIDs", character="-"): + bob_did = ( + await bob.post( + "/wallet/did/create", + json={"method": "key", "options": {"key_type": "ed25519"}}, + response=DIDResult, + ) + ).result + assert bob_did + bls_bob_did_res = ( + await bob.post( + "/wallet/did/create", + json={"method": "key", "options": {"key_type": "bls12381g2"}}, + ) + )["result"] + assert bls_bob_did_res + bls_bob_did = bls_bob_did_res["did"] + + pause_for_input() + + with section("Issue example credential using ED25519 Signature"): + issuer_cred_ex, holder_cred_ex = await jsonld_issue_credential( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + credential={ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/citizenship/v1", + ], + "type": ["VerifiableCredential", "PermanentResident"], + "issuer": "did:sov:" + public_did.did, + "issuanceDate": str(date.today()), + "credentialSubject": { + "type": ["PermanentResident"], + "id": bob_did.did, + "givenName": "Bob", + "familyName": "Builder", + "gender": "Male", + "birthCountry": "Bahamas", + "birthDate": "1958-07-17", + }, + }, + options={"proofType": "Ed25519Signature2018"}, + ) + + pause_for_input() + + with section("Present example credential"): + alice_pres_ex, bob_pres_ex = await jsonld_present_proof( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + presentation_definition={ + "input_descriptors": [ + { + "id": "citizenship_input_1", + "name": "EU Driver's License", + "schema": [ + { + "uri": "https://www.w3.org/2018/credentials#VerifiableCredential" # noqa: E501 + }, + { + "uri": "https://w3id.org/citizenship#PermanentResident" # noqa: E501 + }, + ], + "constraints": { + "is_holder": [ + { + "directive": "required", + "field_id": [ + "1f44d55f-f161-4938-a659-f8026467f126" + ], + } + ], + "fields": [ + { + "id": "1f44d55f-f161-4938-a659-f8026467f126", + "path": ["$.credentialSubject.familyName"], + "purpose": "The claim must be from one of the specified issuers", # noqa: E501 + "filter": {"const": "Builder"}, + }, + { + "path": ["$.credentialSubject.givenName"], + "purpose": "The claim must be from one of the specified issuers", # noqa: E501 + }, + ], + }, + } + ], + "id": str(uuid4()), + "format": {"ldp_vp": {"proof_type": ["Ed25519Signature2018"]}}, + }, + domain="test-degree", + ) + with section("Presentation summary", character="-"): + print(presentation_summary(alice_pres_ex.into(V20PresExRecord))) + + pause_for_input() + + with section("Issue Credential with quick context"): + issuer_cred_ex, holder_cred_ex = await jsonld_issue_credential( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + credential={ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + { + "ex": "https://example.com/examples#", + "TableTennisTournamentWin": "ex:TableTennisTournamentWin", + "dateWon": "ex:dateWon", + }, + ], + "type": ["VerifiableCredential", "TableTennisTournamentWin"], + "issuer": "did:sov:" + public_did.did, + "issuanceDate": str(date.today()), + "credentialSubject": { + "id": bob_did.did, + "dateWon": str(date.today()), + }, + }, + options={"proofType": "Ed25519Signature2018"}, + ) + + pause_for_input() + + with section("Present quick context credential"): + alice_pres_ex, bob_pres_ex = await jsonld_present_proof( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + presentation_definition={ + "input_descriptors": [ + { + "id": "ttt_win_input_1", + "name": "TableTennisTournamentWin", + "schema": [ + { + "uri": "https://www.w3.org/2018/credentials#VerifiableCredential" # noqa: E501 + }, + { + "uri": "https://example.com/examples#TableTennisTournamentWin" # noqa: E501 + }, + ], + "constraints": { + "is_holder": [ + { + "directive": "required", + "field_id": [ + "1f44d55f-f161-4938-a659-f8026467f126" + ], + } + ], + "fields": [ + { + "id": "1f44d55f-f161-4938-a659-f8026467f126", + "path": ["$.credentialSubject.dateWon"], + "purpose": "Get proof of win on date", # noqa: E501 + }, + ], + }, + } + ], + "id": str(uuid4()), + "format": {"ldp_vp": {"proof_type": ["Ed25519Signature2018"]}}, + }, + domain="test-degree", + ) + with section("Presentation summary", character="-"): + print(presentation_summary(alice_pres_ex.into(V20PresExRecord))) + + pause_for_input() + + with section("Issue BBS+ Credential"): + issuer_cred_ex, holder_cred_ex = await jsonld_issue_credential( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + credential={ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + { + "ex": "https://example.com/examples#", + "Employment": "ex:Employment", + "dateHired": "ex:dateHired", + "clearance": "ex:clearance", + }, + ], + "type": ["VerifiableCredential", "Employment"], + "issuer": bls_alice_did, + "issuanceDate": str(date.today()), + "credentialSubject": { + "id": bls_bob_did, + "dateHired": str(date.today()), + "clearance": 1, + }, + }, + options={"proofType": "BbsBlsSignature2020"}, + ) + + pause_for_input() + + with section("Present BBS+ Credential with SD"): + alice_pres_ex, bob_pres_ex = await jsonld_present_proof( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + presentation_definition={ + "input_descriptors": [ + { + "id": "building_access_1", + "name": "BuildingAccess", + "schema": [ + { + "uri": "https://www.w3.org/2018/credentials#VerifiableCredential" # noqa: E501 + }, + {"uri": "https://example.com/examples#Employment"}, + ], + "constraints": { + "limit_disclosure": "required", + "is_holder": [ + { + "directive": "required", + "field_id": [ + "1f44d55f-f161-4938-a659-f8026467f126" + ], + } + ], + "fields": [ + { + "id": "1f44d55f-f161-4938-a659-f8026467f126", + "path": ["$.credentialSubject.clearance"], + "purpose": "Get clearance", # noqa: E501 + }, + ], + }, + } + ], + "id": str(uuid4()), + "format": {"ldp_vp": {"proof_type": ["BbsBlsSignature2020"]}}, + }, + domain="building-access", + ) + with section("Presentation summary", character="-"): + print(presentation_summary(alice_pres_ex.into(V20PresExRecord))) + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/integration-tests/examples/mediation/docker-compose.yml b/integration-tests/examples/mediation/docker-compose.yml new file mode 100644 index 0000000000..b6e9dbebbb --- /dev/null +++ b/integration-tests/examples/mediation/docker-compose.yml @@ -0,0 +1,105 @@ + services: + alice: + image: acapy-test + ports: + - "3001:3001" + environment: + RUST_LOG: warn + command: > + start + --label Alice + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://alice:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --no-ledger + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + + bob: + image: acapy-test + ports: + - "3002:3001" + environment: + RUST_LOG: warn + command: > + start + --label Bob + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --no-ledger + --wallet-type askar + --wallet-name bob + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + + mediator: + image: acapy-test + ports: + - "3003:3001" + environment: + RUST_LOG: warn + command: > + start + --label Mediator + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://mediator:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --no-ledger + --wallet-type askar + --wallet-name mediator + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --enable-undelivered-queue + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + + example: + container_name: controller + build: + context: ../.. + environment: + - ALICE=http://alice:3001 + - BOB=http://bob:3001 + - MEDIATOR=http://mediator:3001 + volumes: + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + alice: + condition: service_healthy + bob: + condition: service_healthy + mediator: + condition: service_healthy diff --git a/integration-tests/examples/mediation/example.py b/integration-tests/examples/mediation/example.py new file mode 100644 index 0000000000..9a7851c04f --- /dev/null +++ b/integration-tests/examples/mediation/example.py @@ -0,0 +1,44 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +from os import getenv + +from acapy_controller import Controller +from acapy_controller.logging import logging_to_stdout +from acapy_controller.protocols import ( + connection, + didexchange, + request_mediation_v1, + trustping, +) + +ALICE = getenv("ALICE", "http://alice:3001") +BOB = getenv("BOB", "http://bob:3001") +MEDIATOR = getenv("MEDIATOR", "http://mediator:3001") + + +async def main(): + """Test Controller protocols.""" + alice = Controller(base_url=ALICE) + bob = Controller(base_url=BOB) + mediator = Controller(base_url=MEDIATOR) + + async with alice, bob, mediator: + ma, am = await didexchange(mediator, alice) + mam, amm = await request_mediation_v1( + mediator, alice, ma.connection_id, am.connection_id + ) + await alice.put(f"/mediation/{amm.mediation_id}/default-mediator") + ab, ba = await didexchange(alice, bob) + await trustping(alice, ab) + + ab, ba = await connection(alice, bob) + await trustping(alice, ab) + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/integration-tests/examples/multitenancy/docker-compose.yml b/integration-tests/examples/multitenancy/docker-compose.yml new file mode 100644 index 0000000000..0b5726971b --- /dev/null +++ b/integration-tests/examples/multitenancy/docker-compose.yml @@ -0,0 +1,61 @@ + services: + agency: + image: ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.11.0 + ports: + - "3001:3001" + command: > + start + --label Agency + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://agency:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name agency + --wallet-key insecure + --auto-provision + --multitenant + --multitenant-admin + --jwt-secret insecure + --multitenancy-config wallet_type=askar-profile key_derivation_method=RAW + --log-level debug + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + + example: + container_name: controller + build: + context: ../.. + environment: + - AGENCY=http://agency:3001 + volumes: + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + agency: + condition: service_healthy + + tails: + image: ghcr.io/bcgov/tails-server:latest + ports: + - 6543:6543 + environment: + - GENESIS_URL=https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + command: > + tails-server + --host 0.0.0.0 + --port 6543 + --storage-path /tmp/tails-files + --log-level INFO + diff --git a/integration-tests/examples/multitenancy/example.py b/integration-tests/examples/multitenancy/example.py new file mode 100644 index 0000000000..9432018c13 --- /dev/null +++ b/integration-tests/examples/multitenancy/example.py @@ -0,0 +1,81 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +from os import getenv + +from acapy_controller import Controller +from acapy_controller.logging import logging_to_stdout +from acapy_controller.models import CreateWalletResponse +from acapy_controller.protocols import ( + didexchange, + indy_anoncred_credential_artifacts, + indy_anoncred_onboard, + indy_issue_credential_v2, + indy_present_proof_v2, +) + +AGENCY = getenv("AGENCY", "http://agency:3001") + + +async def main(): + """Test Controller protocols.""" + async with Controller(base_url=AGENCY) as agency: + alice = await agency.post( + "/multitenancy/wallet", + json={ + "label": "Alice", + "wallet_type": "askar", + }, + response=CreateWalletResponse, + ) + bob = await agency.post( + "/multitenancy/wallet", + json={ + "label": "Bob", + "wallet_type": "askar", + }, + response=CreateWalletResponse, + ) + + async with Controller( + base_url=AGENCY, wallet_id=alice.wallet_id, subwallet_token=alice.token + ) as alice, Controller( + base_url=AGENCY, wallet_id=bob.wallet_id, subwallet_token=bob.token + ) as bob: + # Issuance prep + await indy_anoncred_onboard(alice) + _, cred_def = await indy_anoncred_credential_artifacts( + alice, + ["firstname", "lastname"], + support_revocation=True, + ) + + # Connecting + alice_conn, bob_conn = await didexchange(alice, bob) + + # Issue a credential + await indy_issue_credential_v2( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + cred_def.credential_definition_id, + {"firstname": "Bob", "lastname": "Builder"}, + ) + + # Present the the credential's attributes + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/integration-tests/examples/presenting_revoked_credential/docker-compose.yml b/integration-tests/examples/presenting_revoked_credential/docker-compose.yml new file mode 100644 index 0000000000..97e78bae82 --- /dev/null +++ b/integration-tests/examples/presenting_revoked_credential/docker-compose.yml @@ -0,0 +1,103 @@ + services: + alice: + image: acapy-test + # image: acapy-test-image + # build: + # context: . + # dockerfile: Dockerfile.acapy + # args: + # acapy_url: https://github.com/Indicio-tech/aries-cloudagent-python@c1fed3c13d33e65979b08dd1eaf79dc84e3ce504 + ports: + - "3001:3001" + command: > + start + --label Alice + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://alice:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --notify-revocation + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + + bob: + image: acapy-test + #image: bcgovimages/aries-cloudagent:py36-1.16-1_0.7.5 + #image: bcgovimages/aries-cloudagent:py36-1.16-1_1.0.0-rc0 + # image: acapy-test-image + # build: + # context: . + # dockerfile: Dockerfile.acapy + # args: + # acapy_url: https://github.com/Indicio-tech/aries-cloudagent-python@c1fed3c13d33e65979b08dd1eaf79dc84e3ce504 + ports: + - "3002:3001" + command: > + start + --label Bob + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name bob + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + + example: + container_name: controller + build: + context: ../.. + environment: + - ALICE=http://alice:3001 + - BOB=http://bob:3001 + volumes: + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + alice: + condition: service_healthy + bob: + condition: service_healthy + + tails: + image: ghcr.io/bcgov/tails-server:latest + ports: + - 6543:6543 + environment: + - GENESIS_URL=https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + command: > + tails-server + --host 0.0.0.0 + --port 6543 + --storage-path /tmp/tails-files + --log-level INFO + diff --git a/integration-tests/examples/presenting_revoked_credential/example.py b/integration-tests/examples/presenting_revoked_credential/example.py new file mode 100644 index 0000000000..7ee79b6c65 --- /dev/null +++ b/integration-tests/examples/presenting_revoked_credential/example.py @@ -0,0 +1,178 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +import json +from os import getenv +import time + +from acapy_controller import Controller +from acapy_controller.logging import logging_to_stdout +from acapy_controller.models import V20PresExRecord, V20PresExRecordList +from acapy_controller.protocols import ( + didexchange, + indy_anoncred_credential_artifacts, + indy_anoncred_onboard, + indy_anoncreds_publish_revocation, + indy_anoncreds_revoke, + indy_issue_credential_v2, + indy_present_proof_v2, +) + +ALICE = getenv("ALICE", "http://alice:3001") +BOB = getenv("BOB", "http://bob:3001") + + +def summary(presentation: V20PresExRecord) -> str: + """Summarize a presentation exchange record.""" + request = presentation.pres_request + return "Summary: " + json.dumps( + { + "state": presentation.state, + "verified": presentation.verified, + "presentation_request": request.dict(by_alias=True) if request else None, + }, + indent=2, + sort_keys=True, + ) + + +async def main(): + """Test Controller protocols.""" + async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + # Connecting + alice_conn, bob_conn = await didexchange(alice, bob) + + # Issuance prep + await indy_anoncred_onboard(alice) + schema, cred_def = await indy_anoncred_credential_artifacts( + alice, + ["firstname", "lastname"], + support_revocation=True, + ) + + # Issue a credential + alice_cred_ex, _ = await indy_issue_credential_v2( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + cred_def.credential_definition_id, + {"firstname": "Bob", "lastname": "Builder"}, + ) + issued_time = int(time.time()) + + # Present the the credential's attributes + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + + # Revoke credential + await indy_anoncreds_revoke( + alice, + cred_ex=alice_cred_ex, + holder_connection_id=alice_conn.connection_id, + notify=True, + ) + await indy_anoncreds_publish_revocation(alice, cred_ex=alice_cred_ex) + # TODO: Make this into a helper in protocols.py? + await bob.record(topic="revocation-notification") + revoked_time = int(time.time()) + + # Request proof from holder again after revoking, + # using the interval before cred revoked + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[ + { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + } + ], + non_revoked={"from": issued_time, "to": issued_time}, + ) + + # Request proof, no interval + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[ + { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + } + ], + ) + + # Request proof, using invalid/revoked interval but using + # local non_revoked override (in requsted attrs) + # ("LOCAL"-->requested attrs) + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[ + { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + "non_revoked": { + "from": issued_time, + "to": issued_time, + }, + } + ], + non_revoked={"from": revoked_time - 1, "to": revoked_time}, + ) + + # Request proof, just local invalid interval + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[ + { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + "non_revoked": { + "from": revoked_time, + "to": revoked_time, + }, + } + ], + ) + + # Query presentations + presentations = await alice.get( + "/present-proof-2.0/records", + response=V20PresExRecordList, + ) + + # Presentation summary + for i, pres in enumerate(presentations.results): + print(summary(pres)) + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/integration-tests/examples/self_attested/docker-compose.yml b/integration-tests/examples/self_attested/docker-compose.yml new file mode 100644 index 0000000000..b261fb76ac --- /dev/null +++ b/integration-tests/examples/self_attested/docker-compose.yml @@ -0,0 +1,102 @@ + services: + alice: + image: acapy-test + # image: acapy-test-image + # build: + # context: . + # dockerfile: Dockerfile.acapy + # args: + # acapy_url: https://github.com/Indicio-tech/aries-cloudagent-python@c1fed3c13d33e65979b08dd1eaf79dc84e3ce504 + ports: + - "3001:3001" + command: > + start + --label Alice + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://alice:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + + bob: + image: acapy-test + #image: bcgovimages/aries-cloudagent:py36-1.16-1_0.7.5 + #image: bcgovimages/aries-cloudagent:py36-1.16-1_1.0.0-rc0 + # image: acapy-test-image + # build: + # context: . + # dockerfile: Dockerfile.acapy + # args: + # acapy_url: https://github.com/Indicio-tech/aries-cloudagent-python@c1fed3c13d33e65979b08dd1eaf79dc84e3ce504 + ports: + - "3002:3001" + command: > + start + --label Bob + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name bob + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + + example: + container_name: controller + build: + context: ../.. + environment: + - ALICE=http://alice:3001 + - BOB=http://bob:3001 + volumes: + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + alice: + condition: service_healthy + bob: + condition: service_healthy + + tails: + image: ghcr.io/bcgov/tails-server:latest + ports: + - 6543:6543 + environment: + - GENESIS_URL=https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + command: > + tails-server + --host 0.0.0.0 + --port 6543 + --storage-path /tmp/tails-files + --log-level INFO + diff --git a/integration-tests/examples/self_attested/example.py b/integration-tests/examples/self_attested/example.py new file mode 100644 index 0000000000..1cfa7e641c --- /dev/null +++ b/integration-tests/examples/self_attested/example.py @@ -0,0 +1,152 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +from os import getenv +from secrets import randbelow +from typing import List +from uuid import uuid4 + +from acapy_controller import Controller +from acapy_controller.logging import logging_to_stdout +from acapy_controller.models import V10PresentationExchange +from acapy_controller.protocols import ( + IndyCredPrecis, + didexchange, + indy_anoncred_credential_artifacts, + indy_anoncred_onboard, + indy_auto_select_credentials_for_presentation_request, + indy_issue_credential_v2, +) + +ALICE = getenv("ALICE", "http://alice:3001") +BOB = getenv("BOB", "http://bob:3001") + + +async def main(): + """Test Controller protocols.""" + async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + # Connecting + alice_conn, bob_conn = await didexchange(alice, bob) + + # Issuance prep + await indy_anoncred_onboard(alice) + schema, cred_def = await indy_anoncred_credential_artifacts( + alice, + ["firstname", "lastname"], + support_revocation=True, + ) + schema, cred_def_age = await indy_anoncred_credential_artifacts( + alice, + ["age"], + support_revocation=True, + ) + + # Issue a credential + await indy_issue_credential_v2( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + cred_def.credential_definition_id, + {"firstname": "Bob", "lastname": "Builder"}, + ) + await indy_issue_credential_v2( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + cred_def_age.credential_definition_id, + {"age": "42"}, + ) + + # Present the thing + self_uuid = str(uuid4()) + alice_pres_ex = await alice.post( + "/present-proof/send-request", + json={ + "auto_verify": False, + "comment": "Presentation request from minimal", + "connection_id": alice_conn.connection_id, + "proof_request": { + "name": "proof", + "version": "0.1.0", + "nonce": str(randbelow(10**10)), + "requested_attributes": { + str(uuid4()): { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + }, + str(uuid4()): { + "name": "age", + "restrictions": [ + {"cred_def_id": cred_def_age.credential_definition_id} + ], + }, + self_uuid: {"name": "self-attested"}, + }, + "requested_predicates": {}, + "non_revoked": None, + }, + "trace": False, + }, + response=V10PresentationExchange, + ) + alice_pres_ex_id = alice_pres_ex.presentation_exchange_id + + bob_pres_ex = await bob.record_with_values( + topic="present_proof", + record_type=V10PresentationExchange, + connection_id=bob_conn.connection_id, + state="request_received", + ) + assert bob_pres_ex.presentation_request + bob_pres_ex_id = bob_pres_ex.presentation_exchange_id + + relevant_creds = await bob.get( + f"/present-proof/records/{bob_pres_ex_id}/credentials", + response=List[IndyCredPrecis], + ) + pres_spec = indy_auto_select_credentials_for_presentation_request( + bob_pres_ex.presentation_request.serialize(), relevant_creds + ) + pres_spec.self_attested_attributes = {self_uuid: "self-attested data goes here"} + bob_pres_ex = await bob.post( + f"/present-proof/records/{bob_pres_ex_id}/send-presentation", + json=pres_spec, + response=V10PresentationExchange, + ) + + await alice.record_with_values( + topic="present_proof", + record_type=V10PresentationExchange, + presentation_exchange_id=alice_pres_ex_id, + state="presentation_received", + ) + alice_pres_ex = await alice.post( + f"/present-proof/records/{alice_pres_ex_id}/verify-presentation", + json={}, + response=V10PresentationExchange, + ) + alice_pres_ex = await alice.record_with_values( + topic="present_proof", + record_type=V10PresentationExchange, + presentation_exchange_id=alice_pres_ex_id, + state="verified", + ) + + bob_pres_ex = await bob.record_with_values( + topic="present_proof", + record_type=V10PresentationExchange, + presentation_exchange_id=bob_pres_ex_id, + state="presentation_acked", + ) + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/integration-tests/examples/simple/docker-compose.yml b/integration-tests/examples/simple/docker-compose.yml new file mode 100644 index 0000000000..95702ed09c --- /dev/null +++ b/integration-tests/examples/simple/docker-compose.yml @@ -0,0 +1,91 @@ + services: + alice: + image: acapy-test + ports: + - "3001:3001" + environment: + RUST_LOG: 'aries-askar::log::target=error' + command: > + start + --label Alice + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://alice:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + + bob: + image: acapy-test + ports: + - "3002:3001" + environment: + RUST_LOG: 'aries-askar::log::target=error' + command: > + start + --label Bob + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name bob + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + + tails: + image: ghcr.io/bcgov/tails-server:latest + ports: + - 6543:6543 + environment: + - GENESIS_URL=https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + command: > + tails-server + --host 0.0.0.0 + --port 6543 + --storage-path /tmp/tails-files + --log-level INFO + + example: + container_name: controller + build: + context: ../.. + environment: + - ALICE=http://alice:3001 + - BOB=http://bob:3001 + volumes: + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + alice: + condition: service_healthy + bob: + condition: service_healthy diff --git a/integration-tests/examples/simple/example.py b/integration-tests/examples/simple/example.py new file mode 100644 index 0000000000..20830dfcc9 --- /dev/null +++ b/integration-tests/examples/simple/example.py @@ -0,0 +1,26 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +from os import getenv + +from acapy_controller import Controller +from acapy_controller.logging import logging_to_stdout +from acapy_controller.protocols import connection, didexchange + +ALICE = getenv("ALICE", "http://alice:3001") +BOB = getenv("BOB", "http://bob:3001") + + +async def main(): + """Test Controller protocols.""" + async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + await connection(alice, bob) + await didexchange(alice, bob) + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/integration-tests/examples/tunnels/__skip__ b/integration-tests/examples/tunnels/__skip__ new file mode 100644 index 0000000000..e69de29bb2 diff --git a/integration-tests/examples/tunnels/docker-compose.yml b/integration-tests/examples/tunnels/docker-compose.yml new file mode 100644 index 0000000000..72d9da2308 --- /dev/null +++ b/integration-tests/examples/tunnels/docker-compose.yml @@ -0,0 +1,126 @@ + services: + alice: + image: acapy-test + ports: + - "3001:3001" + volumes: + - ./tunnel_endpoint.sh:/tunnel_endpoint.sh:ro,z + environment: + AGENT_TUNNEL_ENDPOINT: http://tunnel-alice:4040 + TAILS_TUNNEL_ENDPOINT: http://tunnel-tails:4040 + entrypoint: > + /bin/sh -c '/tunnel_endpoint.sh aca-py "$$@"' -- + command: > + start + --label Alice + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + tunnel-alice: + condition: service_started + + bob: + image: acapy-test + ports: + - "3002:3001" + volumes: + - ./tunnel_endpoint.sh:/tunnel_endpoint.sh:ro,z + environment: + AGENT_TUNNEL_ENDPOINT: http://tunnel-bob:4040 + TAILS_TUNNEL_ENDPOINT: http://tunnel-tails:4040 + entrypoint: > + /bin/sh -c '/tunnel_endpoint.sh aca-py "$$@"' -- + command: > + start + --label Bob + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + --wallet-type askar + --wallet-name bob + --wallet-key insecure + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + tunnel-bob: + condition: service_started + + tunnel-alice: + image: dbluhm/agent-tunnel + command: -s alice:3000 -p 4040 -h ${AGENT_TUNNEL_HOST} + + tunnel-bob: + image: dbluhm/agent-tunnel + command: -s bob:3000 -p 4040 -h ${AGENT_TUNNEL_HOST} + + example: + container_name: controller + build: + context: ../.. + environment: + - ALICE=http://alice:3001 + - BOB=http://bob:3001 + volumes: + - ../../controller:/usr/src/app/controller:ro,z + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + alice: + condition: service_healthy + bob: + condition: service_healthy + + tunnel-tails: + image: ngrok/ngrok + command: start --all + environment: + - NGROK_CONFIG=/etc/ngrok.yml + volumes: + - ./ngrok.yml:/etc/ngrok.yml + + tails: + image: ghcr.io/bcgov/tails-server:latest + ports: + - 6543:6543 + environment: + - GENESIS_URL=https://raw.githubusercontent.com/Indicio-tech/indicio-network/main/genesis_files/pool_transactions_testnet_genesis + command: > + tails + --host 0.0.0.0 + --port 6543 + --storage-path /tmp/tails-files + --log-level INFO + depends_on: + tunnel-tails: + condition: service_started diff --git a/integration-tests/examples/tunnels/example.py b/integration-tests/examples/tunnels/example.py new file mode 100644 index 0000000000..7ee79b6c65 --- /dev/null +++ b/integration-tests/examples/tunnels/example.py @@ -0,0 +1,178 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +import json +from os import getenv +import time + +from acapy_controller import Controller +from acapy_controller.logging import logging_to_stdout +from acapy_controller.models import V20PresExRecord, V20PresExRecordList +from acapy_controller.protocols import ( + didexchange, + indy_anoncred_credential_artifacts, + indy_anoncred_onboard, + indy_anoncreds_publish_revocation, + indy_anoncreds_revoke, + indy_issue_credential_v2, + indy_present_proof_v2, +) + +ALICE = getenv("ALICE", "http://alice:3001") +BOB = getenv("BOB", "http://bob:3001") + + +def summary(presentation: V20PresExRecord) -> str: + """Summarize a presentation exchange record.""" + request = presentation.pres_request + return "Summary: " + json.dumps( + { + "state": presentation.state, + "verified": presentation.verified, + "presentation_request": request.dict(by_alias=True) if request else None, + }, + indent=2, + sort_keys=True, + ) + + +async def main(): + """Test Controller protocols.""" + async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + # Connecting + alice_conn, bob_conn = await didexchange(alice, bob) + + # Issuance prep + await indy_anoncred_onboard(alice) + schema, cred_def = await indy_anoncred_credential_artifacts( + alice, + ["firstname", "lastname"], + support_revocation=True, + ) + + # Issue a credential + alice_cred_ex, _ = await indy_issue_credential_v2( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + cred_def.credential_definition_id, + {"firstname": "Bob", "lastname": "Builder"}, + ) + issued_time = int(time.time()) + + # Present the the credential's attributes + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + + # Revoke credential + await indy_anoncreds_revoke( + alice, + cred_ex=alice_cred_ex, + holder_connection_id=alice_conn.connection_id, + notify=True, + ) + await indy_anoncreds_publish_revocation(alice, cred_ex=alice_cred_ex) + # TODO: Make this into a helper in protocols.py? + await bob.record(topic="revocation-notification") + revoked_time = int(time.time()) + + # Request proof from holder again after revoking, + # using the interval before cred revoked + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[ + { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + } + ], + non_revoked={"from": issued_time, "to": issued_time}, + ) + + # Request proof, no interval + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[ + { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + } + ], + ) + + # Request proof, using invalid/revoked interval but using + # local non_revoked override (in requsted attrs) + # ("LOCAL"-->requested attrs) + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[ + { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + "non_revoked": { + "from": issued_time, + "to": issued_time, + }, + } + ], + non_revoked={"from": revoked_time - 1, "to": revoked_time}, + ) + + # Request proof, just local invalid interval + await indy_present_proof_v2( + bob, + alice, + bob_conn.connection_id, + alice_conn.connection_id, + requested_attributes=[ + { + "name": "firstname", + "restrictions": [ + {"cred_def_id": cred_def.credential_definition_id} + ], + "non_revoked": { + "from": revoked_time, + "to": revoked_time, + }, + } + ], + ) + + # Query presentations + presentations = await alice.get( + "/present-proof-2.0/records", + response=V20PresExRecordList, + ) + + # Presentation summary + for i, pres in enumerate(presentations.results): + print(summary(pres)) + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/integration-tests/examples/tunnels/ngrok.yml b/integration-tests/examples/tunnels/ngrok.yml new file mode 100644 index 0000000000..a318dc2b4d --- /dev/null +++ b/integration-tests/examples/tunnels/ngrok.yml @@ -0,0 +1,8 @@ +log: stdout +tunnels: + tails: + addr: tails:6543 + inspect: false + proto: http +version: 2 +web_addr: 0.0.0.0:4040 diff --git a/integration-tests/examples/tunnels/tunnel_endpoint.sh b/integration-tests/examples/tunnels/tunnel_endpoint.sh new file mode 100755 index 0000000000..ff415fa974 --- /dev/null +++ b/integration-tests/examples/tunnels/tunnel_endpoint.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +AGENT_TUNNEL_ENDPOINT=${AGENT_TUNNEL_ENDPOINT:-http://localhost:4040} +TAILS_TUNNEL_ENDPOINT=${TAILS_TUNNEL_ENDPOINT:-http://localhost:4040} + +WAIT_INTERVAL=${WAIT_INTERVAL:-3} +WAIT_ATTEMPTS=${WAIT_ATTEMPTS:-10} + +liveliness_check () { + for CURRENT_ATTEMPT in $(seq 1 "$WAIT_ATTEMPTS"); do + if ! curl -s -o /dev/null -w '%{http_code}' "${1}/status" | grep "200" > /dev/null; then + if [[ $CURRENT_ATTEMPT -gt $WAIT_ATTEMPTS ]] + then + echo "Failed while waiting for 200 status from ${1}" + exit 1 + fi + + echo "Waiting for tunnel..." 1>&2 + sleep "$WAIT_INTERVAL" & + wait $! + else + break + fi + done +} + + +liveliness_check ${AGENT_TUNNEL_ENDPOINT} +liveliness_check ${TAILS_TUNNEL_ENDPOINT} + +ACAPY_ENDPOINT=$(curl --silent "${AGENT_TUNNEL_ENDPOINT}/url" | python -c "import sys, json; print(json.load(sys.stdin)['url'])") +ACAPY_TAILS_SERVER_BASE_URL=$(curl --silent "${TAILS_TUNNEL_ENDPOINT}/api/tunnels" | python -c "import sys, json; print(json.load(sys.stdin)['tunnels'][0]['public_url'])") +export ACAPY_ENDPOINT=${ACAPY_ENDPOINT} +export ACAPY_TAILS_SERVER_BASE_URL=${ACAPY_TAILS_SERVER_BASE_URL} +exec "$@" + diff --git a/integration-tests/pyproject.toml b/integration-tests/pyproject.toml new file mode 100644 index 0000000000..c7e645ab3a --- /dev/null +++ b/integration-tests/pyproject.toml @@ -0,0 +1,20 @@ +[tool.poetry] +name = "integration-tests" +version = "0.1.0" +description = "" +authors = [] +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.10" +acapy-controller = {git = "https://github.com/indicio-tech/acapy-minimal-example.git"} +pytest = "^8.3.2" +pytest-asyncio = "^0.23.8" +pydantic = "^2.8.2" + +[tool.pytest.ini_options] +markers = "examples: test the examples" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/mkdocs.yml b/mkdocs.yml index e25fd638a4..aea28af754 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -145,7 +145,7 @@ nav: - Testing/Troubleshooting: - Running and Creating Unit Tests: testing/UnitTests.md - Managing Logging: testing/Logging.md - - ACA-Py Integration Tests: testing/INTEGRATION-TESTS.md + - ACA-Py Integration BDD Tests: testing/BDDTests.md - Protocol Tracing: testing/AgentTracing.md - Troubleshooting: testing/Troubleshooting.md - Contributing: