diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 74302d3ee4..1f7584e464 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -17,5 +17,5 @@ jobs: - name: Ruff Format and Lint Check uses: chartboost/ruff-action@v1 with: - version: 0.5.7 + version: 0.8.0 args: "format --check" diff --git a/.github/workflows/sonar-pr.yml b/.github/workflows/sonar-pr.yml index 51558d2ad6..df9f5e06ff 100644 --- a/.github/workflows/sonar-pr.yml +++ b/.github/workflows/sonar-pr.yml @@ -15,7 +15,7 @@ jobs: with: fetch-depth: 0 - name: Download PR number artifact - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@v7 with: workflow: Tests run_id: ${{ github.event.workflow_run.id }} @@ -26,7 +26,7 @@ jobs: with: path: ./PR_NUMBER - name: Download Test Coverage - uses: dawidd6/action-download-artifact@v6 + uses: dawidd6/action-download-artifact@v7 with: workflow: Tests run_id: ${{ github.event.workflow_run.id }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9b9edb79c9..2cc9bec01f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook - rev: v9.16.0 + rev: v9.18.0 hooks: - id: commitlint stages: [commit-msg] @@ -8,7 +8,7 @@ repos: additional_dependencies: ['@commitlint/config-conventional'] - repo: https://github.com/astral-sh/ruff-pre-commit # Ensure this is synced with pyproject.toml - rev: v0.5.7 + rev: v0.8.1 hooks: # Run the linter - id: ruff diff --git a/CHANGELOG.md b/CHANGELOG.md index f4be55b250..a418c79077 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,79 @@ # Aries Cloud Agent Python Changelog +## 1.1.1rc0 + +### December 3, 2024 + +Release 1.1.1 is a patch update to ACA-Py that contains a lengthy list of adjustments, improvements and fixes, with a focus on removing Technical Debt. The most visible change is the removal of the "in-memory wallet" implementation in favour of using the SQLite in-memory wallet (`sqlite://:memory:`), including removing the logic for handling that extra wallet type. While arguably a breaking change (and we mention it below), we're confident no one is using the in-memory wallet (right?!?) any where other than in tests. In removing the in-memory wallet, all of the unit and integration tests that used the in-memory wallet were updated to use SQLite's in-memory wallet. + +The first step to full support of [did:tdw](https://identity.foundation/trustdidweb/) (soon to be renamed to `did:webvh` for "`did:web` + Verifiable History") has been added to ACA-Py -- a resolver. We're working on adding new DID Registration for it and other DID Methods, enabling ACA-Py to be used easily with a variety of DID Methods. + +The move to the [OpenWallet Foundation](https://openwallet.foundation/) is now complete. For up to date details on what the repo move means for ACA-Py users, including steps for updating deployments, please see latest in [GitHub Issue #3250]. + +[GitHub Issue #3250]: https://github.com/hyperledger/aries-cloudagent-python/issues/3250 + +### 1.1.1 Deprecation Notices + +The same **[deprecation notices](#101-deprecation-notices)** from the [1.1.0](#110) release about AIP 1.0 protocols still apply. The protocols remain in the 1.1.1 release, but will be moved out of the core and into plugins soon. Please review these notifications carefully! + +### 1.1.1 Breaking Changes + +While there are no breaking changes in this release that might impact production deployments, the removal of the "in-memory" wallet implementation might be break some test scripts. Rather than using the in-memory wallet, tests should be updated to use SQLite's special `sqlite://:memory:` database instead. This results in a better alignment between tests and a production environment. + + +#### 1.1.1 Categorized List of Pull Requests + +- AnonCreds VC Issuance and Presentation Enhancement / Fixes + - Repair release bdd tests [\#3376](https://github.com/openwallet-foundation/acapy/pull/3376) [jamshale](https://github.com/jamshale) + - Fix tails upload for anoncreds multitenancy [\#3346](https://github.com/openwallet-foundation/acapy/pull/3346) [jamshale](https://github.com/jamshale) + - Fix subwallet anoncreds upgrade check [\#3345](https://github.com/openwallet-foundation/acapy/pull/3345) [jamshale](https://github.com/jamshale) + - Add anoncreds issuance and presentation format [\#3331](https://github.com/openwallet-foundation/acapy/pull/3331) [jamshale](https://github.com/jamshale) + - Fix endorsement setup with existing connection [\#3309](https://github.com/openwallet-foundation/acapy/pull/3309) [jamshale](https://github.com/jamshale) + - Update accumulator value in wallet on repair [\#3299](https://github.com/openwallet-foundation/acapy/pull/3299) [jamshale](https://github.com/jamshale) + +- Middleware Handling and Multi-tenancy + - Restore `--base-wallet-routes` flag functionality [\#3344](https://github.com/openwallet-foundation/acapy/pull/3344) [esune](https://github.com/esune) + - :white_check_mark: Re-add ready_middleware unit tests [\#3330](https://github.com/openwallet-foundation/acapy/pull/3330) [ff137](https://github.com/ff137) + - :sparkles: Handle NotFound and UnprocessableEntity errors in middleware [\#3327](https://github.com/openwallet-foundation/acapy/pull/3327) [ff137](https://github.com/ff137) + - :art: Refactor Multitenant Manager errors and exception handling [\#3323](https://github.com/openwallet-foundation/acapy/pull/3323) [ff137](https://github.com/ff137) + - Don't pass rekey to sub_wallet_profile [\#3312](https://github.com/openwallet-foundation/acapy/pull/3312) [jamshale](https://github.com/jamshale) + +- DID Registration and Resolution + - fix: check routing keys on indy_vdr endpoint refresh [\#3371](https://github.com/openwallet-foundation/acapy/pull/3371) [dbluhm](https://github.com/dbluhm) + - Fix/universal resolver [\#3354](https://github.com/openwallet-foundation/acapy/pull/3354) [jamshale](https://github.com/jamshale) + - More robust verification method selection by did [\#3279](https://github.com/openwallet-foundation/acapy/pull/3279) [dbluhm](https://github.com/dbluhm) + - did:tdw resolver [\#3237](https://github.com/openwallet-foundation/acapy/pull/3237) [jamshale](https://github.com/jamshale) + +- DIDComm Updates and Enhancements + - :bug: Rearrange connection record deletion after hangup [\#3310](https://github.com/openwallet-foundation/acapy/pull/3310) [ff137](https://github.com/ff137) + - :bug: Handle failure to resolve DIDComm services in DIDXManager [\#3298](https://github.com/openwallet-foundation/acapy/pull/3298) [ff137](https://github.com/ff137) + +- Test Suite Updates and Artifact Publishing + - Add test wallet config option [\#3355](https://github.com/openwallet-foundation/acapy/pull/3355) [jamshale](https://github.com/jamshale) + - :art: Fix current test warnings [\#3338](https://github.com/openwallet-foundation/acapy/pull/3338) [ff137](https://github.com/ff137) + - :construction_worker: Fix Nightly Publish to not run on forks [\#3333](https://github.com/openwallet-foundation/acapy/pull/3333) [ff137](https://github.com/ff137) + +- Internal Improvements / Cleanups / Tech Debt Updates + - :zap: Add class caching to DeferLoad [\#3361](https://github.com/openwallet-foundation/acapy/pull/3361) [ff137](https://github.com/ff137 + - :art: Sync Ruff version in configs and apply formatting [\#3358](https://github.com/openwallet-foundation/acapy/pull/3358) [ff137](https://github.com/ff137) + - :art: Replace deprecated ABC decorators [\#3357](https://github.com/openwallet-foundation/acapy/pull/3357) [ff137](https://github.com/ff137) + - :art: Refactor the logging module monolith [\#3319](https://github.com/openwallet-foundation/acapy/pull/3319) [ff137](https://github.com/ff137) + - :wrench: set default fixture scope for pytest-asyncio [\#3318](https://github.com/openwallet-foundation/acapy/pull/3318) [ff137](https://github.com/ff137) + - Docs (devcontainer) Change folder names [\#3317](https://github.com/openwallet-foundation/acapy/pull/3317) [loneil](https://github.com/loneil) + - :art: Refactor string concatenation in model descriptions [\#3313](https://github.com/openwallet-foundation/acapy/pull/3313) [ff137](https://github.com/ff137) + - Remove in memory wallet [\#3311](https://github.com/openwallet-foundation/acapy/pull/3311) [jamshale](https://github.com/jamshale) + +- Consolidate Dependabot updates and other library/dependency updates + - Week 49 Library upgrades [\#3368](https://github.com/openwallet-foundation/acapy/pull/3368) [jamshale](https://github.com/jamshale) + - :arrow_up: Update lock file [\#3296](https://github.com/openwallet-foundation/acapy/pull/3296) [ff137](https://github.com/ff137) + +- Release management pull requests: + - 1.1.1rc0 [\#3372](https://github.com/openwallet-foundation/acapy/pull/3372) [swcurran](https://github.com/swcurran) + +- Dependabot PRs + - [Link to list of Dependabot PRs in this release](https://github.com/openwallet-foundation/acapy/pulls?q=is%3Apr+is%3Amerged+merged%3A2024-10-15..2024-12-03+author%3Aapp%2Fdependabot+) + + ## 1.1.0 ### October 15, 2024 diff --git a/Managing-ACA-Py-Doc-Site.md b/Managing-ACA-Py-Doc-Site.md index 8d6902bd9d..5bafc5ad87 100644 --- a/Managing-ACA-Py-Doc-Site.md +++ b/Managing-ACA-Py-Doc-Site.md @@ -20,7 +20,7 @@ and mkdocs configuration. When the GitHub Action fires, it runs a container that carries out the following steps: -- Checks out the triggering branch, either `main` or `docs-v` (e.g `docs-v1.1.0`). +- Checks out the triggering branch, either `main` or `docs-v` (e.g `docs-v1.1.1`). - Runs the script [scripts/prepmkdocs.sh], which moves and updates some of the markdown files so that they fit into the generated site. See the comments in the scripts for details about the copying and editing done via the script. In @@ -97,7 +97,7 @@ To delete the documentation version, do the following: - Check your `git status` and make sure there are no changes in the branch -- e.g., new files that shouldn't be added to the `gh-pages` branch. If there are any -- delete the files so they are not added. -- Remove the folder for the RC. For example `rm -rf 1.1.0` +- Remove the folder for the RC. For example `rm -rf 1.1.1rc0` - Edit the `versions.json` file and remove the reference to the RC release in the file. - Push the changes via a PR to the ACA-Py `gh-pages` branch (don't PR them into diff --git a/PUBLISHING.md b/PUBLISHING.md index 726557bedf..e7bd48af07 100644 --- a/PUBLISHING.md +++ b/PUBLISHING.md @@ -6,7 +6,7 @@ a major, minor or patch release, per [semver](https://semver.org/) rules. Once ready to do a release, create a local branch that includes the following updates: -1. Create a local PR branch from an updated `main` branch, e.g. "1.1.0". +1. Create a local PR branch from an updated `main` branch, e.g. "1.1.1". 2. See if there are any Document Site `mkdocs` changes needed. Run the script `./scripts/prepmkdocs.sh; mkdocs`. Watch the log, noting particularly if @@ -27,7 +27,7 @@ Once ready to do a release, create a local branch that includes the following up github account. Do not include `dependabot` PRs. For those, we put a live link for the date range of the release (guidance below). - To generate the list, run the script `genChangeLog.sh` command (requires you + To generate the list, run the `./scripts/genChangeLog.sh` scripts (requires you have [gh] and [jq] installed), with the date of the day before the last release. The day before is picked to make sure you get all of the changes. The script generates the list of all PRs, minus the dependabot ones, merged since @@ -78,9 +78,9 @@ Once you have the list of PRs: - Check the dates in the `dependabot` URL to make sure the full period between the previous non-RC release to the date of the non-RC release you are preparing. - Include a PR in the list for this soon-to-be PR, initially with the "next to be issued" number for PRs/Issues. At the end output of the script is the highest numbered PR and issue. Your PR will be one higher than the highest of those two numbers. Note that you still might have to correct the number after you create the PR if someone sneaks an issue or PR in before you submit your PR. -5. Check to see if there are any other PRs that should be included in the release. +1. Check to see if there are any other PRs that should be included in the release. -6. Update the ReadTheDocs in the `/docs` folder by following the instructions in +2. Update the ReadTheDocs in the `/docs` folder by following the instructions in the `docs/UpdateRTD.md` file. That will likely add a number of new and modified files to the PR. Eliminate all of the errors in the generation process, either by mocking external dependencies or by fixing ACA-Py code. If @@ -88,7 +88,7 @@ Once you have the list of PRs: developer. Experience has demonstrated to use that documentation generation errors should be fixed in the code. -7. Search across the repository for the previous version number and update it +3. Search across the repository for the previous version number and update it everywhere that makes sense. The CHANGELOG.md entry for the previous release is a likely exception, and the `pyproject.toml` in the root **MUST** be updated. You can skip (although it won't hurt) to update the files in the @@ -101,28 +101,28 @@ Once you have the list of PRs: have dropped the previously used `-` in the release candidate version string to better follow the semver rules. -8. Regenerate openapi.json and swagger.json by running +4. Regenerate openapi.json and swagger.json by running `scripts/generate-open-api-spec` from within the `acapy_agent` folder. Command: `cd acapy_agent;../scripts/generate-open-api-spec;cd ..` Folders may not be cleaned up by the script, so the following can be run, likely with `sudo` -- `rm -rf open-api/.build`. The folder is `.gitignore`d, so there is not a danger they will be pushed, even if they are not deleted. -9. Double check all of these steps above, and then submit a PR from the branch. +5. Double check all of these steps above, and then submit a PR from the branch. Add this new PR to CHANGELOG.md so that all the PRs are included. If there are still further changes to be merged, mark the PR as "Draft", repeat **ALL** of the steps again, and then mark this PR as ready and then wait until it is merged. It's embarrassing when you have to do a whole new release just because you missed something silly...I know! -10. Immediately after it is merged, create a new GitHub tag representing the +6. Immediately after it is merged, create a new GitHub tag representing the version. The tag name and title of the release should be the same as the version in [pyproject.toml](https://github.com/openwallet-foundation/acapy/tree/main/pyproject.toml). Use the "Generate Release Notes" capability to get a sequential listing of the PRs in the release, to complement the manually curated Changelog. Verify on PyPi that the version is published. -11. New images for the release are automatically published by the GitHubAction +7. New images for the release are automatically published by the GitHubAction Workflows: [publish.yml] and [publish-indy.yml]. The actions are triggered when a release is tagged, so no manual action is needed. The images are published in the [OpenWallet Foundation Package Repository under @@ -140,7 +140,7 @@ Once you have the list of PRs: [publish-indy.yml]: https://github.com/openwallet-foundation/acapy/blob/main/.github/workflows/publish-indy.yml 1. When a new release is tagged, create a new branch at the same commit with - the branch name in the format `docs-v`, for example, `docs-v1.1.0`. + the branch name in the format `docs-v`, for example, `docs-v1.1.1`. The creation of the branch triggers the execution of the [publish-docs] GitHub Action which generates the documentation for the new release, publishing it at [https://aca-py.org]. The GitHub Action also executes when diff --git a/acapy_agent/__main__.py b/acapy_agent/__main__.py index bd0c964705..9669588b83 100644 --- a/acapy_agent/__main__.py +++ b/acapy_agent/__main__.py @@ -1,8 +1,11 @@ """acapy_agent package entry point.""" +import logging import os import sys +LOGGER = logging.getLogger(__name__) + def init_debug(args): """Initialize debugging environment.""" @@ -26,16 +29,18 @@ def init_debug(args): import debugpy debugpy.listen((DAP_HOST, DAP_PORT)) - print(f"=== Waiting for debugger to attach to {DAP_HOST}:{DAP_PORT} ===") + LOGGER.info( + f"=== Waiting for debugger to attach to {DAP_HOST}:{DAP_PORT} ===" + ) debugpy.wait_for_client() except ImportError: - print("debugpy library was not found") + LOGGER.error("debugpy library was not found") if ENABLE_PYDEVD_PYCHARM or "--debug-pycharm" in args: try: import pydevd_pycharm - print( + LOGGER.info( "aca-py remote debugging to " f"{PYDEVD_PYCHARM_HOST}:{PYDEVD_PYCHARM_AGENT_PORT}" ) @@ -47,7 +52,7 @@ def init_debug(args): suspend=False, ) except ImportError: - print("pydevd_pycharm library was not found") + LOGGER.error("pydevd_pycharm library was not found") def run(args): diff --git a/acapy_agent/admin/decorators/auth.py b/acapy_agent/admin/decorators/auth.py index 818f297d40..3d1f209893 100644 --- a/acapy_agent/admin/decorators/auth.py +++ b/acapy_agent/admin/decorators/auth.py @@ -1,6 +1,8 @@ """Authentication decorators for the admin API.""" import functools +import re +from typing import Optional, Pattern from aiohttp import web @@ -48,6 +50,8 @@ def tenant_authentication(handler): - check for a valid bearer token in the Autorization header if running in multi-tenant mode - check for a valid x-api-key header if running in single-tenant mode + - check if the base wallet has access to the requested path if running + in multi-tenant mode """ @functools.wraps(handler) @@ -61,11 +65,15 @@ async def tenant_auth(request): ) insecure_mode = bool(profile.settings.get("admin.admin_insecure_mode")) multitenant_enabled = profile.settings.get("multitenant.enabled") + base_wallet_allowed_route = _base_wallet_route_access( + profile.settings.get("multitenant.base_wallet_routes"), request.path + ) # CORS fix: allow OPTIONS method access to paths without a token if ( (multitenant_enabled and authorization_header) or (not multitenant_enabled and valid_key) + or (multitenant_enabled and valid_key and base_wallet_allowed_route) or insecure_mode or request.method == "OPTIONS" ): @@ -78,3 +86,25 @@ async def tenant_auth(request): ) return tenant_auth + + +def _base_wallet_route_access(additional_routes: str, request_path: str) -> bool: + """Check if request path matches additional routes.""" + additional_routes_pattern = _build_additional_routes_pattern(additional_routes) + return _matches_additional_routes(additional_routes_pattern, request_path) + + +def _build_additional_routes_pattern(pattern_string: str) -> Optional[Pattern]: + """Build pattern from space delimited list of paths.""" + # create array and add word boundary to avoid false positives + if pattern_string: + paths = pattern_string.split(" ") + return re.compile("^((?:)" + "|".join(paths) + ")$") + return None + + +def _matches_additional_routes(pattern: Pattern, path: str) -> bool: + """Matches request path to provided pattern.""" + if pattern and path: + return bool(pattern.match(path)) + return False diff --git a/acapy_agent/admin/server.py b/acapy_agent/admin/server.py index 84650ed11b..111d2f2a52 100644 --- a/acapy_agent/admin/server.py +++ b/acapy_agent/admin/server.py @@ -5,7 +5,7 @@ import re import warnings import weakref -from typing import Callable, Coroutine, Optional, Pattern, Sequence, cast +from typing import Callable, Coroutine, Optional import aiohttp_cors import jwt @@ -280,29 +280,6 @@ def __init__( self.websocket_queues = {} self.site = None self.multitenant_manager = context.inject_or(BaseMultitenantManager) - self._additional_route_pattern: Optional[Pattern] = None - - @property - def additional_routes_pattern(self) -> Optional[Pattern]: - """Pattern for configured additional routes to permit base wallet to access.""" - if self._additional_route_pattern: - return self._additional_route_pattern - - base_wallet_routes = self.context.settings.get("multitenant.base_wallet_routes") - base_wallet_routes = cast(Sequence[str], base_wallet_routes) - if base_wallet_routes: - self._additional_route_pattern = re.compile( - "^(?:" + "|".join(base_wallet_routes) + ")" - ) - return None - - def _matches_additional_routes(self, path: str) -> bool: - """Path matches additional_routes_pattern.""" - pattern = self.additional_routes_pattern - if pattern: - return bool(pattern.match(path)) - - return False async def make_application(self) -> web.Application: """Get the aiohttp application instance.""" diff --git a/acapy_agent/admin/tests/test_auth.py b/acapy_agent/admin/tests/test_auth.py index 1ebd0cd171..73680a1b00 100644 --- a/acapy_agent/admin/tests/test_auth.py +++ b/acapy_agent/admin/tests/test_auth.py @@ -133,3 +133,27 @@ async def test_multi_tenant_valid_auth_header(self): decor_func = tenant_authentication(self.decorated_handler) await decor_func(self.request) self.decorated_handler.assert_called_once_with(self.request) + + async def test_base_wallet_additional_route_allowed(self): + self.profile.settings["multitenant.base_wallet_routes"] = "/extra-route" + self.request = mock.MagicMock( + __getitem__=lambda _, k: self.request_dict[k], + headers={"x-api-key": "admin_api_key"}, + method="POST", + path="/extra-route", + ) + decor_func = tenant_authentication(self.decorated_handler) + await decor_func(self.request) + self.decorated_handler.assert_called_once_with(self.request) + + async def test_base_wallet_additional_route_denied(self): + self.profile.settings["multitenant.base_wallet_routes"] = "/extra-route" + self.request = mock.MagicMock( + __getitem__=lambda _, k: self.request_dict[k], + headers={"x-api-key": "admin_api_key"}, + method="POST", + path="/extra-route-wrong", + ) + decor_func = tenant_authentication(self.decorated_handler) + with self.assertRaises(web.HTTPUnauthorized): + await decor_func(self.request) diff --git a/acapy_agent/anoncreds/base.py b/acapy_agent/anoncreds/base.py index 6cb5940bb2..32c0a1c1f1 100644 --- a/acapy_agent/anoncreds/base.py +++ b/acapy_agent/anoncreds/base.py @@ -6,8 +6,8 @@ from ..config.injection_context import InjectionContext from ..core.error import BaseError from ..core.profile import Profile -from .models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult -from .models.anoncreds_revocation import ( +from .models.credential_definition import CredDef, CredDefResult, GetCredDefResult +from .models.revocation import ( GetRevListResult, GetRevRegDefResult, RevList, @@ -15,7 +15,7 @@ RevRegDef, RevRegDefResult, ) -from .models.anoncreds_schema import AnonCredsSchema, GetSchemaResult, SchemaResult +from .models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult T = TypeVar("T") diff --git a/acapy_agent/anoncreds/default/did_indy/registry.py b/acapy_agent/anoncreds/default/did_indy/registry.py index 5bef819f82..388dfe5022 100644 --- a/acapy_agent/anoncreds/default/did_indy/registry.py +++ b/acapy_agent/anoncreds/default/did_indy/registry.py @@ -7,8 +7,8 @@ from ....config.injection_context import InjectionContext from ....core.profile import Profile from ...base import BaseAnonCredsRegistrar, BaseAnonCredsResolver -from ...models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult -from ...models.anoncreds_revocation import ( +from ...models.credential_definition import CredDef, CredDefResult, GetCredDefResult +from ...models.revocation import ( GetRevListResult, GetRevRegDefResult, RevList, @@ -16,7 +16,7 @@ RevRegDef, RevRegDefResult, ) -from ...models.anoncreds_schema import AnonCredsSchema, GetSchemaResult, SchemaResult +from ...models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult LOGGER = logging.getLogger(__name__) diff --git a/acapy_agent/anoncreds/default/did_web/registry.py b/acapy_agent/anoncreds/default/did_web/registry.py index 0585e2b924..710412aa22 100644 --- a/acapy_agent/anoncreds/default/did_web/registry.py +++ b/acapy_agent/anoncreds/default/did_web/registry.py @@ -7,8 +7,8 @@ from ....config.injection_context import InjectionContext from ....core.profile import Profile from ...base import BaseAnonCredsRegistrar, BaseAnonCredsResolver -from ...models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult -from ...models.anoncreds_revocation import ( +from ...models.credential_definition import CredDef, CredDefResult, GetCredDefResult +from ...models.revocation import ( GetRevListResult, GetRevRegDefResult, RevList, @@ -16,7 +16,9 @@ RevRegDef, RevRegDefResult, ) -from ...models.anoncreds_schema import AnonCredsSchema, GetSchemaResult, SchemaResult +from ...models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult + +LOGGER = logging.getLogger(__name__) LOGGER = logging.getLogger(__name__) diff --git a/acapy_agent/anoncreds/default/legacy_indy/recover.py b/acapy_agent/anoncreds/default/legacy_indy/recover.py index cd183adf15..4c3eaf0517 100644 --- a/acapy_agent/anoncreds/default/legacy_indy/recover.py +++ b/acapy_agent/anoncreds/default/legacy_indy/recover.py @@ -9,7 +9,7 @@ import indy_vdr from anoncreds import RevocationRegistry, RevocationRegistryDefinition -from ...models.anoncreds_revocation import RevList +from ...models.revocation import RevList LOGGER = logging.getLogger(__name__) diff --git a/acapy_agent/anoncreds/default/legacy_indy/registry.py b/acapy_agent/anoncreds/default/legacy_indy/registry.py index 892a9d17fe..2f91937580 100644 --- a/acapy_agent/anoncreds/default/legacy_indy/registry.py +++ b/acapy_agent/anoncreds/default/legacy_indy/registry.py @@ -56,14 +56,14 @@ ) from ...events import RevListFinishedEvent from ...issuer import CATEGORY_CRED_DEF, AnonCredsIssuer, AnonCredsIssuerError -from ...models.anoncreds_cred_def import ( +from ...models.credential_definition import ( CredDef, CredDefResult, CredDefState, CredDefValue, GetCredDefResult, ) -from ...models.anoncreds_revocation import ( +from ...models.revocation import ( GetRevListResult, GetRevRegDefResult, RevList, @@ -74,7 +74,7 @@ RevRegDefState, RevRegDefValue, ) -from ...models.anoncreds_schema import ( +from ...models.schema import ( AnonCredsSchema, GetSchemaResult, SchemaResult, diff --git a/acapy_agent/anoncreds/default/legacy_indy/tests/test_recover.py b/acapy_agent/anoncreds/default/legacy_indy/tests/test_recover.py index 61c0a90f40..b504690c5e 100644 --- a/acapy_agent/anoncreds/default/legacy_indy/tests/test_recover.py +++ b/acapy_agent/anoncreds/default/legacy_indy/tests/test_recover.py @@ -9,9 +9,8 @@ import pytest from anoncreds import RevocationRegistryDefinition -from acapy_agent.tests import mock - -from ....models.anoncreds_revocation import RevList, RevRegDef, RevRegDefValue +from .....tests import mock +from ....models.revocation import RevList, RevRegDef, RevRegDefValue from ..recover import ( RevocRecoveryException, _check_tails_hash_for_inconsistency, diff --git a/acapy_agent/anoncreds/default/legacy_indy/tests/test_registry.py b/acapy_agent/anoncreds/default/legacy_indy/tests/test_registry.py index 2b6b6c0b76..c41eb80797 100644 --- a/acapy_agent/anoncreds/default/legacy_indy/tests/test_registry.py +++ b/acapy_agent/anoncreds/default/legacy_indy/tests/test_registry.py @@ -16,25 +16,6 @@ from .....anoncreds.base import AnonCredsSchemaAlreadyExists from .....anoncreds.default.legacy_indy import registry as test_module from .....anoncreds.issuer import AnonCredsIssuer -from .....anoncreds.models.anoncreds_cred_def import ( - CredDef, - CredDefResult, - CredDefValue, - CredDefValuePrimary, -) -from .....anoncreds.models.anoncreds_revocation import ( - RevList, - RevListResult, - RevRegDef, - RevRegDefResult, - RevRegDefState, - RevRegDefValue, -) -from .....anoncreds.models.anoncreds_schema import ( - AnonCredsSchema, - GetSchemaResult, - SchemaResult, -) from .....askar.profile_anon import ( AskarAnoncredsProfileSession, ) @@ -55,6 +36,21 @@ ) from .....tests import mock from .....utils.testing import create_test_profile +from ....models.credential_definition import ( + CredDef, + CredDefResult, + CredDefValue, + CredDefValuePrimary, +) +from ....models.revocation import ( + RevList, + RevListResult, + RevRegDef, + RevRegDefResult, + RevRegDefState, + RevRegDefValue, +) +from ....models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult B58 = alphabet if isinstance(alphabet, str) else alphabet.decode("ascii") INDY_DID = rf"^(did:sov:)?[{B58}]{{21,22}}$" diff --git a/acapy_agent/anoncreds/events.py b/acapy_agent/anoncreds/events.py index 4511b546f7..98477bf4e1 100644 --- a/acapy_agent/anoncreds/events.py +++ b/acapy_agent/anoncreds/events.py @@ -4,7 +4,7 @@ from typing import NamedTuple, Optional from ..core.event_bus import Event -from .models.anoncreds_revocation import RevRegDef +from .models.revocation import RevRegDef CRED_DEF_FINISHED_EVENT = "anoncreds::credential-definition::finished" REV_REG_DEF_FINISHED_EVENT = "anoncreds::revocation-registry-definition::finished" diff --git a/acapy_agent/anoncreds/holder.py b/acapy_agent/anoncreds/holder.py index ae14e4be5d..6da4456c72 100644 --- a/acapy_agent/anoncreds/holder.py +++ b/acapy_agent/anoncreds/holder.py @@ -23,7 +23,6 @@ from pyld.jsonld import JsonLdProcessor from uuid_utils import uuid4 -from ..anoncreds.models.anoncreds_schema import AnonCredsSchema from ..askar.profile_anon import AskarAnoncredsProfile from ..core.error import BaseError from ..core.profile import Profile @@ -33,7 +32,8 @@ from ..vc.vc_ld import VerifiableCredential from ..wallet.error import WalletNotFoundError from .error_messages import ANONCREDS_PROFILE_REQUIRED_MSG -from .models.anoncreds_cred_def import CredDef +from .models.credential_definition import CredDef +from .models.schema import AnonCredsSchema from .registry import AnonCredsRegistry LOGGER = logging.getLogger(__name__) diff --git a/acapy_agent/anoncreds/issuer.py b/acapy_agent/anoncreds/issuer.py index ad79173e16..6dc3fababa 100644 --- a/acapy_agent/anoncreds/issuer.py +++ b/acapy_agent/anoncreds/issuer.py @@ -24,8 +24,8 @@ from .base import AnonCredsSchemaAlreadyExists, BaseAnonCredsError from .error_messages import ANONCREDS_PROFILE_REQUIRED_MSG from .events import CredDefFinishedEvent -from .models.anoncreds_cred_def import CredDef, CredDefResult -from .models.anoncreds_schema import AnonCredsSchema, SchemaResult, SchemaState +from .models.credential_definition import CredDef, CredDefResult +from .models.schema import AnonCredsSchema, SchemaResult, SchemaState from .registry import AnonCredsRegistry LOGGER = logging.getLogger(__name__) diff --git a/acapy_agent/anoncreds/models/credential.py b/acapy_agent/anoncreds/models/credential.py new file mode 100644 index 0000000000..c008fc16c7 --- /dev/null +++ b/acapy_agent/anoncreds/models/credential.py @@ -0,0 +1,167 @@ +"""Credential artifacts.""" + +from typing import Mapping, Optional + +from marshmallow import EXCLUDE, ValidationError, fields + +from ...messaging.models.base import BaseModel, BaseModelSchema +from ...messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_CRED_DEF_ID_VALIDATE, + ANONCREDS_REV_REG_ID_EXAMPLE, + ANONCREDS_REV_REG_ID_VALIDATE, + ANONCREDS_SCHEMA_ID_EXAMPLE, + ANONCREDS_SCHEMA_ID_VALIDATE, + NUM_STR_ANY_EXAMPLE, + NUM_STR_ANY_VALIDATE, +) + + +class AnoncredsAttrValue(BaseModel): + """Anoncreds attribute value.""" + + class Meta: + """Anoncreds attribute value.""" + + schema_class = "AnoncredsAttrValueSchema" + + def __init__( + self, raw: Optional[str] = None, encoded: Optional[str] = None, **kwargs + ): + """Initialize anoncreds (credential) attribute value.""" + super().__init__(**kwargs) + self.raw = raw + self.encoded = encoded + + +class AnoncredsAttrValueSchema(BaseModelSchema): + """Anoncreds attribute value schema.""" + + class Meta: + """Anoncreds attribute value schema metadata.""" + + model_class = AnoncredsAttrValue + unknown = EXCLUDE + + raw = fields.Str(required=True, metadata={"description": "Attribute raw value"}) + encoded = fields.Str( + required=True, + validate=NUM_STR_ANY_VALIDATE, + metadata={ + "description": "Attribute encoded value", + "example": NUM_STR_ANY_EXAMPLE, + }, + ) + + +class DictWithAnoncredsAttrValueSchema(fields.Dict): + """Dict with anoncreds attribute value schema.""" + + def __init__(self, **kwargs): + """Initialize the custom schema for a dictionary with AnoncredsAttrValue.""" + super().__init__( + keys=fields.Str(metadata={"description": "Attribute name"}), + values=fields.Nested(AnoncredsAttrValueSchema()), + **kwargs, + ) + + def _deserialize(self, value, attr, data, **kwargs): + """Deserialize dict with anoncreds attribute value.""" + if not isinstance(value, dict): + raise ValidationError("Value must be a dict.") + + errors = {} + anoncreds_attr_value_schema = AnoncredsAttrValueSchema() + + for k, v in value.items(): + if isinstance(v, dict): + validation_errors = anoncreds_attr_value_schema.validate(v) + if validation_errors: + errors[k] = validation_errors + + if errors: + raise ValidationError(errors) + + return value + + +class AnoncredsCredential(BaseModel): + """Anoncreds credential.""" + + class Meta: + """Anoncreds credential metadata.""" + + schema_class = "AnoncredsCredentialSchema" + + def __init__( + self, + schema_id: Optional[str] = None, + cred_def_id: Optional[str] = None, + rev_reg_id: Optional[str] = None, + values: Mapping[str, AnoncredsAttrValue] = None, + signature: Optional[Mapping] = None, + signature_correctness_proof: Optional[Mapping] = None, + rev_reg: Optional[Mapping] = None, + witness: Optional[Mapping] = None, + ): + """Initialize anoncreds credential.""" + self.schema_id = schema_id + self.cred_def_id = cred_def_id + self.rev_reg_id = rev_reg_id + self.values = values + self.signature = signature + self.signature_correctness_proof = signature_correctness_proof + self.rev_reg = rev_reg + self.witness = witness + + +class AnoncredsCredentialSchema(BaseModelSchema): + """Anoncreds credential schema.""" + + class Meta: + """Anoncreds credential schemametadata.""" + + model_class = AnoncredsCredential + unknown = EXCLUDE + + schema_id = fields.Str( + required=True, + validate=ANONCREDS_SCHEMA_ID_VALIDATE, + metadata={ + "description": "Schema identifier", + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, + }, + ) + cred_def_id = fields.Str( + required=True, + validate=ANONCREDS_CRED_DEF_ID_VALIDATE, + metadata={ + "description": "Credential definition identifier", + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, + }, + ) + rev_reg_id = fields.Str( + allow_none=True, + validate=ANONCREDS_REV_REG_ID_VALIDATE, + metadata={ + "description": "Revocation registry identifier", + "example": ANONCREDS_REV_REG_ID_EXAMPLE, + }, + ) + values = DictWithAnoncredsAttrValueSchema( + required=True, + metadata={"description": "Credential attributes"}, + ) + signature = fields.Dict( + required=True, metadata={"description": "Credential signature"} + ) + signature_correctness_proof = fields.Dict( + required=True, + metadata={"description": "Credential signature correctness proof"}, + ) + rev_reg = fields.Dict( + allow_none=True, metadata={"description": "Revocation registry state"} + ) + witness = fields.Dict( + allow_none=True, metadata={"description": "Witness for revocation proof"} + ) diff --git a/acapy_agent/anoncreds/models/anoncreds_cred_def.py b/acapy_agent/anoncreds/models/credential_definition.py similarity index 97% rename from acapy_agent/anoncreds/models/anoncreds_cred_def.py rename to acapy_agent/anoncreds/models/credential_definition.py index 17d41098e7..4e543eaf57 100644 --- a/acapy_agent/anoncreds/models/anoncreds_cred_def.py +++ b/acapy_agent/anoncreds/models/credential_definition.py @@ -9,9 +9,9 @@ from ...messaging.models.base import BaseModel, BaseModelSchema from ...messaging.valid import ( - INDY_CRED_DEF_ID_EXAMPLE, - INDY_OR_KEY_DID_EXAMPLE, - INDY_SCHEMA_ID_EXAMPLE, + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_DID_EXAMPLE, + ANONCREDS_SCHEMA_ID_EXAMPLE, NUM_STR_WHOLE_EXAMPLE, NUM_STR_WHOLE_VALIDATE, ) @@ -256,7 +256,7 @@ class Meta: issuer_id = fields.Str( metadata={ "description": "Issuer Identifier of the credential definition or schema", - "example": INDY_OR_KEY_DID_EXAMPLE, + "example": ANONCREDS_DID_EXAMPLE, }, data_key="issuerId", ) @@ -264,7 +264,7 @@ class Meta: data_key="schemaId", metadata={ "description": "Schema identifier", - "example": INDY_SCHEMA_ID_EXAMPLE, + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, }, ) type = fields.Str(validate=OneOf(["CL"])) @@ -333,7 +333,7 @@ class Meta: credential_definition_id = fields.Str( metadata={ "description": "credential definition id", - "example": INDY_CRED_DEF_ID_EXAMPLE, + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, }, allow_none=True, ) @@ -434,7 +434,7 @@ class Meta: credential_definition_id = fields.Str( metadata={ "description": "credential definition id", - "example": INDY_CRED_DEF_ID_EXAMPLE, + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, }, ) credential_definition = fields.Nested( diff --git a/acapy_agent/anoncreds/models/credential_offer.py b/acapy_agent/anoncreds/models/credential_offer.py new file mode 100644 index 0000000000..c77419eba3 --- /dev/null +++ b/acapy_agent/anoncreds/models/credential_offer.py @@ -0,0 +1,149 @@ +"""Anoncreds Credential Offer format for v2.0 of the issue-credential protocol.""" + +from typing import Optional, Sequence + +from marshmallow import EXCLUDE, fields + +from ...messaging.models.base import BaseModel, BaseModelSchema +from ...messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_CRED_DEF_ID_VALIDATE, + ANONCREDS_SCHEMA_ID_EXAMPLE, + ANONCREDS_SCHEMA_ID_VALIDATE, + NUM_STR_WHOLE_EXAMPLE, + NUM_STR_WHOLE_VALIDATE, +) + + +class AnoncredsKeyCorrectnessProof(BaseModel): + """Anoncreds key correctness proof.""" + + class Meta: + """AnoncredsKeyCorrectnessProof metadata.""" + + schema_class = "AnoncredsKeyCorrectnessProofSchema" + + def __init__( + self, + c: Optional[str] = None, + xz_cap: Optional[str] = None, + xr_cap: Sequence[Sequence[str]] = None, + **kwargs, + ): + """Initialize XR cap for anoncreds key correctness proof.""" + super().__init__(**kwargs) + + self.c = c + self.xz_cap = xz_cap + self.xr_cap = xr_cap + + +class AnoncredsCorrectnessProofSchema(BaseModelSchema): + """Anoncreds key correctness proof schema.""" + + class Meta: + """Anoncreds key correctness proof schema metadata.""" + + model_class = AnoncredsKeyCorrectnessProof + unknown = EXCLUDE + + c = fields.Str( + required=True, + validate=NUM_STR_WHOLE_VALIDATE, + metadata={ + "description": "c in key correctness proof", + "example": NUM_STR_WHOLE_EXAMPLE, + }, + ) + xz_cap = fields.Str( + required=True, + validate=NUM_STR_WHOLE_VALIDATE, + metadata={ + "description": "xz_cap in key correctness proof", + "example": NUM_STR_WHOLE_EXAMPLE, + }, + ) + xr_cap = fields.List( + fields.List( + fields.Str( + required=True, + metadata={ + "description": "xr_cap component values in key correctness proof" + }, + ), + required=True, + metadata={ + "description": "xr_cap components in key correctness proof", + "many": True, + }, + ), + required=True, + metadata={"description": "xr_cap in key correctness proof", "many": True}, + ) + + +class AnoncredsCredentialOffer(BaseModel): + """Anoncreds Credential Offer.""" + + class Meta: + """AnoncredsCredentialOffer metadata.""" + + schema_class = "AnoncredsCredentialOfferSchema" + + def __init__( + self, + schema_id: Optional[str] = None, + cred_def_id: Optional[str] = None, + nonce: Optional[str] = None, + key_correctness_proof: Optional[str] = None, + **kwargs, + ): + """Initialize values .""" + super().__init__(**kwargs) + self.schema_id = schema_id + self.cred_def_id = cred_def_id + self.nonce = nonce + self.key_correctness_proof = key_correctness_proof + + +class AnoncredsCredentialOfferSchema(BaseModelSchema): + """Anoncreds Credential Offer Schema.""" + + class Meta: + """AnoncredsCredentialOffer schema metadata.""" + + model_class = AnoncredsCredentialOffer + unknown = EXCLUDE + + schema_id = fields.Str( + required=True, + validate=ANONCREDS_SCHEMA_ID_VALIDATE, + metadata={ + "description": "Schema identifier", + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, + }, + ) + + cred_def_id = fields.Str( + required=True, + validate=ANONCREDS_CRED_DEF_ID_VALIDATE, + metadata={ + "description": "Credential definition identifier", + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, + }, + ) + + nonce = fields.Str( + required=True, + validate=NUM_STR_WHOLE_VALIDATE, + metadata={ + "description": "Nonce in credential abstract", + "example": NUM_STR_WHOLE_EXAMPLE, + }, + ) + + key_correctness_proof = fields.Nested( + AnoncredsCorrectnessProofSchema(), + required=True, + metadata={"description": "Key correctness proof"}, + ) diff --git a/acapy_agent/anoncreds/models/credential_proposal.py b/acapy_agent/anoncreds/models/credential_proposal.py new file mode 100644 index 0000000000..3d41d08747 --- /dev/null +++ b/acapy_agent/anoncreds/models/credential_proposal.py @@ -0,0 +1,58 @@ +"""Anoncreds credential definition proposal.""" + +import re + +from marshmallow import fields + +from ...core.profile import Profile +from ...messaging.models.openapi import OpenAPISchema +from ...messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_CRED_DEF_ID_VALIDATE, + ANONCREDS_DID_EXAMPLE, + ANONCREDS_DID_VALIDATE, + ANONCREDS_SCHEMA_ID_EXAMPLE, + ANONCREDS_SCHEMA_ID_VALIDATE, +) + + +class AnoncredsCredentialDefinitionProposal(OpenAPISchema): + """Query string parameters for credential definition searches.""" + + schema_id = fields.Str( + required=False, + validate=ANONCREDS_SCHEMA_ID_VALIDATE, + metadata={ + "description": "Schema identifier", + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, + }, + ) + issuer_id = fields.Str( + required=False, + validate=ANONCREDS_DID_VALIDATE, + metadata={"description": "Issuer DID", "example": ANONCREDS_DID_EXAMPLE}, + ) + cred_def_id = fields.Str( + required=False, + validate=ANONCREDS_CRED_DEF_ID_VALIDATE, + metadata={ + "description": "Credential definition id", + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, + }, + ) + + +CRED_DEF_TAGS = list( + vars(AnoncredsCredentialDefinitionProposal).get("_declared_fields", []) +) + +CRED_DEF_EVENT_PREFIX = "acapy::CRED_DEF::" +EVENT_LISTENER_PATTERN = re.compile(f"^{CRED_DEF_EVENT_PREFIX}(.*)?$") + + +async def notify_cred_def_event(profile: Profile, cred_def_id: str, meta_data: dict): + """Send notification for a cred def post-process event.""" + await profile.notify( + CRED_DEF_EVENT_PREFIX + cred_def_id, + meta_data, + ) diff --git a/acapy_agent/anoncreds/models/credential_request.py b/acapy_agent/anoncreds/models/credential_request.py new file mode 100644 index 0000000000..49fd58e996 --- /dev/null +++ b/acapy_agent/anoncreds/models/credential_request.py @@ -0,0 +1,81 @@ +"""Cred request artifacts to attach to RFC 453 messages.""" + +from typing import Mapping, Optional + +from marshmallow import EXCLUDE, fields + +from ...messaging.models.base import BaseModel, BaseModelSchema +from ...messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_CRED_DEF_ID_VALIDATE, + NUM_STR_WHOLE_EXAMPLE, + NUM_STR_WHOLE_VALIDATE, + UUID4_EXAMPLE, +) + + +class AnoncredsCredRequest(BaseModel): + """Anoncreds credential request.""" + + class Meta: + """Anoncreds credential request metadata.""" + + schema_class = "AnoncredsCredRequestSchema" + + def __init__( + self, + prover_did: Optional[str] = None, + cred_def_id: Optional[str] = None, + blinded_ms: Optional[Mapping] = None, + blinded_ms_correctness_proof: Optional[Mapping] = None, + nonce: Optional[str] = None, + **kwargs, + ): + """Initialize anoncreds credential request.""" + super().__init__(**kwargs) + self.prover_did = prover_did + self.cred_def_id = cred_def_id + self.blinded_ms = blinded_ms + self.blinded_ms_correctness_proof = blinded_ms_correctness_proof + self.nonce = nonce + + +class AnoncredsCredRequestSchema(BaseModelSchema): + """Anoncreds credential request schema.""" + + class Meta: + """Anoncreds credential request schema metadata.""" + + model_class = AnoncredsCredRequest + unknown = EXCLUDE + + prover_did = fields.Str( + required=True, + metadata={ + "description": "Prover DID/Random String/UUID", + "example": UUID4_EXAMPLE, + }, + ) + cred_def_id = fields.Str( + required=True, + validate=ANONCREDS_CRED_DEF_ID_VALIDATE, + metadata={ + "description": "Credential definition identifier", + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, + }, + ) + blinded_ms = fields.Dict( + required=True, metadata={"description": "Blinded master secret"} + ) + blinded_ms_correctness_proof = fields.Dict( + required=True, + metadata={"description": "Blinded master secret correctness proof"}, + ) + nonce = fields.Str( + required=True, + validate=NUM_STR_WHOLE_VALIDATE, + metadata={ + "description": "Nonce in credential request", + "example": NUM_STR_WHOLE_EXAMPLE, + }, + ) diff --git a/acapy_agent/anoncreds/models/non_rev_interval.py b/acapy_agent/anoncreds/models/non_rev_interval.py new file mode 100644 index 0000000000..a224891189 --- /dev/null +++ b/acapy_agent/anoncreds/models/non_rev_interval.py @@ -0,0 +1,78 @@ +"""Anoncreds non-revocation interval.""" + +from time import time +from typing import Optional + +from marshmallow import EXCLUDE, fields + +from ...messaging.models.base import BaseModel, BaseModelSchema +from ...messaging.valid import INT_EPOCH_EXAMPLE, INT_EPOCH_VALIDATE + + +class AnoncredsNonRevocationInterval(BaseModel): + """Anoncreds non-revocation interval.""" + + class Meta: + """NonRevocationInterval metadata.""" + + schema_class = "AnoncredsNonRevocationIntervalSchema" + + def __init__(self, fro: Optional[int] = None, to: Optional[int] = None, **kwargs): + """Initialize non-revocation interval. + + Args: + fro: earliest time of interest + to: latest time of interest + kwargs: additional attributes + + """ + super().__init__(**kwargs) + self.fro = fro + self.to = to + + def covers(self, timestamp: Optional[int] = None) -> bool: + """Whether input timestamp (default now) lies within non-revocation interval. + + Args: + timestamp: time of interest + + Returns: + whether input time satisfies non-revocation interval + + """ + timestamp = timestamp or int(time()) + return (self.fro or 0) <= timestamp <= (self.to or timestamp) + + def timestamp(self) -> bool: + """Return a timestamp that the non-revocation interval covers.""" + return self.to or self.fro or int(time()) + + +class AnoncredsNonRevocationIntervalSchema(BaseModelSchema): + """Schema to allow serialization/deserialization of non-revocation intervals.""" + + class Meta: + """AnoncredsNonRevocationIntervalSchema metadata.""" + + model_class = AnoncredsNonRevocationInterval + unknown = EXCLUDE + + fro = fields.Int( + required=False, + data_key="from", + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": "Earliest time of interest in non-revocation interval", + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ) + to = fields.Int( + required=False, + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": "Latest time of interest in non-revocation interval", + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ) diff --git a/acapy_agent/anoncreds/models/predicate.py b/acapy_agent/anoncreds/models/predicate.py new file mode 100644 index 0000000000..9810a7bb78 --- /dev/null +++ b/acapy_agent/anoncreds/models/predicate.py @@ -0,0 +1,82 @@ +"""Utilities for dealing with predicates.""" + +from collections import namedtuple +from enum import Enum +from typing import Any + +Relation = namedtuple("Relation", "fortran wql math yes no") + + +class Predicate(Enum): + """Enum for predicate types that anoncreds-sdk supports.""" + + LT = Relation( + "LT", + "$lt", + "<", + lambda x, y: Predicate.to_int(x) < Predicate.to_int(y), + lambda x, y: Predicate.to_int(x) >= Predicate.to_int(y), + ) + LE = Relation( + "LE", + "$lte", + "<=", + lambda x, y: Predicate.to_int(x) <= Predicate.to_int(y), + lambda x, y: Predicate.to_int(x) > Predicate.to_int(y), + ) + GE = Relation( + "GE", + "$gte", + ">=", + lambda x, y: Predicate.to_int(x) >= Predicate.to_int(y), + lambda x, y: Predicate.to_int(x) < Predicate.to_int(y), + ) + GT = Relation( + "GT", + "$gt", + ">", + lambda x, y: Predicate.to_int(x) > Predicate.to_int(y), + lambda x, y: Predicate.to_int(x) <= Predicate.to_int(y), + ) + + @property + def fortran(self) -> str: + """Fortran nomenclature.""" + return self.value.fortran + + @property + def wql(self) -> str: + """WQL nomenclature.""" + return self.value.wql + + @property + def math(self) -> str: + """Mathematical nomenclature.""" + return self.value.math + + @staticmethod + def get(relation: str) -> "Predicate": + """Return enum instance corresponding to input relation string.""" + + for pred in Predicate: + if relation.upper() in ( + pred.value.fortran, + pred.value.wql.upper(), + pred.value.math, + ): + return pred + return None + + @staticmethod + def to_int(value: Any) -> int: + """Cast a value as its equivalent int for anoncreds predicate argument. + + Raise ValueError for any input but int, stringified int, or boolean. + + Args: + value: value to coerce + """ + + if isinstance(value, (bool, int)): + return int(value) + return int(str(value)) # kick out floats diff --git a/acapy_agent/anoncreds/models/presentation_request.py b/acapy_agent/anoncreds/models/presentation_request.py new file mode 100644 index 0000000000..12855e1ee6 --- /dev/null +++ b/acapy_agent/anoncreds/models/presentation_request.py @@ -0,0 +1,306 @@ +"""Classes to represent anoncreds presentation request.""" + +from typing import Mapping, Optional + +from marshmallow import ( + EXCLUDE, + Schema, + ValidationError, + fields, + validate, + validates_schema, +) + +from ...messaging.models.base import BaseModel, BaseModelSchema +from ...messaging.models.openapi import OpenAPISchema +from ...messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + INT_EPOCH_EXAMPLE, + INT_EPOCH_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, + NUM_STR_NATURAL_EXAMPLE, + NUM_STR_NATURAL_VALIDATE, + PREDICATE_EXAMPLE, + PREDICATE_VALIDATE, +) + + +class AnoncredsPresentationReqPredSpecSchema(OpenAPISchema): + """Schema for predicate specification in anoncreds proof request.""" + + name = fields.Str( + required=True, metadata={"example": "index", "description": "Attribute name"} + ) + p_type = fields.Str( + required=True, + validate=PREDICATE_VALIDATE, + metadata={ + "description": "Predicate type ('<', '<=', '>=', or '>')", + "example": PREDICATE_EXAMPLE, + }, + ) + p_value = fields.Int( + required=True, metadata={"description": "Threshold value", "strict": True} + ) + restrictions = fields.List( + fields.Dict( + keys=fields.Str( + validate=validate.Regexp( + "^schema_id|schema_issuer_did|schema_name|schema_version|issuer_did|" + "cred_def_id|attr::.+::value$" + ), + metadata={"example": "cred_def_id"}, + ), + values=fields.Str(metadata={"example": ANONCREDS_CRED_DEF_ID_EXAMPLE}), + ), + required=False, + metadata={ + "description": ( + "If present, credential must satisfy one of given restrictions: specify" + " schema_id, schema_issuer_did, schema_name, schema_version," + " issuer_did, cred_def_id, and/or attr::::value where" + " represents a credential attribute name" + ) + }, + ) + non_revoked = fields.Nested( + Schema.from_dict( + { + "from": fields.Int( + required=False, + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": ( + "Earliest time of interest in non-revocation interval" + ), + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ), + "to": fields.Int( + required=False, + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": ( + "Latest time of interest in non-revocation interval" + ), + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ), + }, + name="AnoncredsPresentationReqPredSpecNonRevokedSchema", + ), + allow_none=True, + required=False, + ) + + +class AnoncredsPresentationReqAttrSpecSchema(OpenAPISchema): + """Schema for attribute specification in anoncreds proof request.""" + + name = fields.Str( + required=False, + metadata={"example": "favouriteDrink", "description": "Attribute name"}, + ) + names = fields.List( + fields.Str(metadata={"example": "age"}), + required=False, + metadata={"description": "Attribute name group"}, + ) + restrictions = fields.List( + fields.Dict( + keys=fields.Str( + validate=validate.Regexp( + "^schema_id|schema_issuer_did|schema_name|schema_version|issuer_did|" + "cred_def_id|attr::.+::value$" + ), + metadata={"example": "cred_def_id"}, + ), + values=fields.Str(metadata={"example": ANONCREDS_CRED_DEF_ID_EXAMPLE}), + ), + required=False, + metadata={ + "description": ( + "If present, credential must satisfy one of given restrictions: specify" + " schema_id, schema_issuer_did, schema_name, schema_version," + " issuer_did, cred_def_id, and/or attr::::value where" + " represents a credential attribute name" + ) + }, + ) + non_revoked = fields.Nested( + Schema.from_dict( + { + "from": fields.Int( + required=False, + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": ( + "Earliest time of interest in non-revocation interval" + ), + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ), + "to": fields.Int( + required=False, + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": ( + "Latest time of interest in non-revocation interval" + ), + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ), + }, + name="AnoncredsPresentationReqAttrSpecNonRevokedSchema", + ), + allow_none=True, + required=False, + ) + + @validates_schema + def validate_fields(self, data, **kwargs): + """Validate schema fields. + + Data must have exactly one of name or names; if names then restrictions are + mandatory. + + Args: + data: The data to validate + kwargs: Additional keyword arguments + + Raises: + ValidationError: if data has both or neither of name and names + + """ + if ("name" in data) == ("names" in data): + raise ValidationError( + "Attribute specification must have either name or names but not both" + ) + restrictions = data.get("restrictions") + if ("names" in data) and (not restrictions or all(not r for r in restrictions)): + raise ValidationError( + "Attribute specification on 'names' must have non-empty restrictions" + ) + + +class AnoncredsPresentationRequest(BaseModel): + """anoncreds proof request.""" + + class Meta: + """Anoncreds proof request metadata.""" + + schema_class = "AnoncredsPresentationRequestSchema" + + def __init__( + self, + nonce: Optional[str] = None, + name: Optional[str] = None, + version: Optional[str] = None, + requested_attributes: Optional[Mapping] = None, + requested_predicates: Optional[Mapping] = None, + non_revoked: Optional[Mapping] = None, + **kwargs, + ): + """Initialize anoncreds cred abstract object. + + Args: + nonce (str): The nonce value. + name (str): The name of the proof request. + version (str): The version of the proof request. + requested_attributes (Mapping): A mapping of attribute names to attribute + constraints. + requested_predicates (Mapping): A mapping of predicate names to predicate + constraints. + non_revoked (Mapping): A mapping of non-revocation timestamps. + kwargs: Keyword arguments for BaseModel + + """ + super().__init__(**kwargs) + self.nonce = nonce + self.name = name + self.version = version + self.requested_attributes = requested_attributes + self.requested_predicates = requested_predicates + self.non_revoked = non_revoked + + +class AnoncredsPresentationRequestSchema(BaseModelSchema): + """Schema for anoncreds proof request.""" + + class Meta: + """Anoncreds proof request schema metadata.""" + + model_class = AnoncredsPresentationRequest + unknown = EXCLUDE + + nonce = fields.Str( + required=False, + validate=NUM_STR_NATURAL_VALIDATE, + metadata={"description": "Nonce", "example": NUM_STR_NATURAL_EXAMPLE}, + ) + name = fields.Str( + required=False, + dump_default="Proof request", + metadata={"description": "Proof request name", "example": "Proof request"}, + ) + version = fields.Str( + required=False, + dump_default="1.0", + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Proof request version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, + ) + requested_attributes = fields.Dict( + required=True, + keys=fields.Str( + metadata={"decription": "Attribute referent", "example": "0_legalname_uuid"} + ), + values=fields.Nested(AnoncredsPresentationReqAttrSpecSchema()), + metadata={"description": "Requested attribute specifications of proof request"}, + ) + requested_predicates = fields.Dict( + required=True, + keys=fields.Str( + metadata={"description": "Predicate referent", "example": "0_age_GE_uuid"} + ), + values=fields.Nested(AnoncredsPresentationReqPredSpecSchema()), + metadata={"description": "Requested predicate specifications of proof request"}, + ) + non_revoked = fields.Nested( + Schema.from_dict( + { + "from": fields.Int( + required=False, + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": ( + "Earliest time of interest in non-revocation interval" + ), + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ), + "to": fields.Int( + required=False, + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": ( + "Latest time of interest in non-revocation interval" + ), + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ), + }, + name="AnoncredsPresentationRequestNonRevokedSchema", + ), + allow_none=True, + required=False, + ) diff --git a/acapy_agent/anoncreds/models/proof.py b/acapy_agent/anoncreds/models/proof.py new file mode 100644 index 0000000000..817b947cc5 --- /dev/null +++ b/acapy_agent/anoncreds/models/proof.py @@ -0,0 +1,749 @@ +"""Marshmallow bindings for anoncreds proofs.""" + +from typing import Mapping, Optional, Sequence + +from marshmallow import EXCLUDE, fields, validate + +from ...messaging.models.base import BaseModel, BaseModelSchema +from ...messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_CRED_DEF_ID_VALIDATE, + ANONCREDS_REV_REG_ID_EXAMPLE, + ANONCREDS_REV_REG_ID_VALIDATE, + ANONCREDS_SCHEMA_ID_EXAMPLE, + ANONCREDS_SCHEMA_ID_VALIDATE, + INT_EPOCH_EXAMPLE, + INT_EPOCH_VALIDATE, + NUM_STR_ANY_EXAMPLE, + NUM_STR_ANY_VALIDATE, + NUM_STR_WHOLE_EXAMPLE, + NUM_STR_WHOLE_VALIDATE, +) +from ...utils.tracing import AdminAPIMessageTracingSchema +from .predicate import Predicate +from .requested_credentials import ( + AnoncredsRequestedCredsRequestedAttrSchema, + AnoncredsRequestedCredsRequestedPredSchema, +) + + +class AnoncredsEQProof(BaseModel): + """Equality proof for anoncreds primary proof.""" + + class Meta: + """Equality proof metadata.""" + + schema_class = "AnoncredsEQProofMeta" + + def __init__( + self, + revealed_attrs: Mapping[str, str] = None, + a_prime: Optional[str] = None, + e: Optional[str] = None, + v: Optional[str] = None, + m: Mapping[str, str] = None, + m2: Optional[str] = None, + **kwargs, + ): + """Initialize equality proof object.""" + super().__init__(**kwargs) + self.revealed_attrs = revealed_attrs + self.a_prime = a_prime + self.e = e + self.v = v + self.m = m + self.m2 = m2 + + +class AnoncredsEQProofSchema(BaseModelSchema): + """Anoncreds equality proof schema.""" + + class Meta: + """Anoncreds equality proof metadata.""" + + model_class = AnoncredsEQProof + unknown = EXCLUDE + + revealed_attrs = fields.Dict( + keys=fields.Str(metadata={"example": "preference"}), + values=fields.Str( + validate=NUM_STR_ANY_VALIDATE, metadata={"example": NUM_STR_ANY_EXAMPLE} + ), + ) + a_prime = fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ) + e = fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ) + v = fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ) + m = fields.Dict( + keys=fields.Str(metadata={"example": "master_secret"}), + values=fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ), + ) + m2 = fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ) + + +class AnoncredsGEProofPred(BaseModel): + """Anoncreds GE proof predicate.""" + + class Meta: + """Anoncreds GE proof predicate metadata.""" + + schema_class = "AnoncredsGEProofPredSchema" + + def __init__( + self, + attr_name: Optional[str] = None, + p_type: Optional[str] = None, + value: Optional[int] = None, + **kwargs, + ): + """Initialize anoncreds GE proof predicate.""" + super().__init__(**kwargs) + self.attr_name = attr_name + self.p_type = p_type + self.value = value + + +class AnoncredsGEProofPredSchema(BaseModelSchema): + """Anoncreds GE proof predicate schema.""" + + class Meta: + """Anoncreds GE proof predicate metadata.""" + + model_class = AnoncredsGEProofPred + unknown = EXCLUDE + + attr_name = fields.Str( + metadata={"description": "Attribute name, anoncreds-canonicalized"} + ) + p_type = fields.Str( + validate=validate.OneOf([p.fortran for p in Predicate]), + metadata={"description": "Predicate type"}, + ) + value = fields.Integer( + metadata={"strict": True, "description": "Predicate threshold value"} + ) + + +class AnoncredsGEProof(BaseModel): + """Greater-than-or-equal-to proof for anoncreds primary proof.""" + + class Meta: + """GE proof metadata.""" + + schema_class = "AnoncredsGEProofMeta" + + def __init__( + self, + u: Mapping[str, str] = None, + r: Mapping[str, str] = None, + mj: Optional[str] = None, + alpha: Optional[str] = None, + t: Mapping[str, str] = None, + predicate: Optional[AnoncredsGEProofPred] = None, + **kwargs, + ): + """Initialize GE proof object.""" + super().__init__(**kwargs) + self.u = u + self.r = r + self.mj = mj + self.alpha = alpha + self.t = t + self.predicate = predicate + + +class AnoncredsGEProofSchema(BaseModelSchema): + """Anoncreds GE proof schema.""" + + class Meta: + """Anoncreds GE proof schema metadata.""" + + model_class = AnoncredsGEProof + unknown = EXCLUDE + + u = fields.Dict( + keys=fields.Str(), + values=fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ), + ) + r = fields.Dict( + keys=fields.Str(), + values=fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ), + ) + mj = fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ) + alpha = fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ) + t = fields.Dict( + keys=fields.Str(), + values=fields.Str( + validate=NUM_STR_WHOLE_VALIDATE, metadata={"example": NUM_STR_WHOLE_EXAMPLE} + ), + ) + predicate = fields.Nested(AnoncredsGEProofPredSchema) + + +class AnoncredsPrimaryProof(BaseModel): + """Anoncreds primary proof.""" + + class Meta: + """Anoncreds primary proof metadata.""" + + schema_class = "AnoncredsPrimaryProofSchema" + + def __init__( + self, + eq_proof: Optional[AnoncredsEQProof] = None, + ge_proofs: Sequence[AnoncredsGEProof] = None, + **kwargs, + ): + """Initialize anoncreds primary proof.""" + super().__init__(**kwargs) + self.eq_proof = eq_proof + self.ge_proofs = ge_proofs + + +class AnoncredsPrimaryProofSchema(BaseModelSchema): + """Anoncreds primary proof schema.""" + + class Meta: + """Anoncreds primary proof schema metadata.""" + + model_class = AnoncredsPrimaryProof + unknown = EXCLUDE + + eq_proof = fields.Nested( + AnoncredsEQProofSchema, + allow_none=True, + metadata={"description": "Anoncreds equality proof"}, + ) + ge_proofs = fields.Nested( + AnoncredsGEProofSchema, + many=True, + allow_none=True, + metadata={"description": "Anoncreds GE proofs"}, + ) + + +class AnoncredsNonRevocProof(BaseModel): + """Anoncreds non-revocation proof.""" + + class Meta: + """Anoncreds non-revocation proof metadata.""" + + schema_class = "AnoncredsNonRevocProofSchema" + + def __init__( + self, + x_list: Optional[Mapping] = None, + c_list: Optional[Mapping] = None, + **kwargs, + ): + """Initialize anoncreds non-revocation proof.""" + super().__init__(**kwargs) + self.x_list = x_list + self.c_list = c_list + + +class AnoncredsNonRevocProofSchema(BaseModelSchema): + """Anoncreds non-revocation proof schema.""" + + class Meta: + """Anoncreds non-revocation proof schema metadata.""" + + model_class = AnoncredsNonRevocProof + unknown = EXCLUDE + + x_list = fields.Dict(keys=fields.Str(), values=fields.Str()) + c_list = fields.Dict(keys=fields.Str(), values=fields.Str()) + + +class AnoncredsProofProofProofsProof(BaseModel): + """Anoncreds proof.proof.proofs constituent proof.""" + + class Meta: + """Anoncreds proof.proof.proofs constituent proof schema.""" + + schema_class = "AnoncredsProofProofProofsProofSchema" + + def __init__( + self, + primary_proof: Optional[AnoncredsPrimaryProof] = None, + non_revoc_proof: Optional[AnoncredsNonRevocProof] = None, + **kwargs, + ): + """Initialize proof.proof.proofs constituent proof.""" + super().__init__(**kwargs) + self.primary_proof = primary_proof + self.non_revoc_proof = non_revoc_proof + + +class AnoncredsProofProofProofsProofSchema(BaseModelSchema): + """Anoncreds proof.proof.proofs constituent proof schema.""" + + class Meta: + """Anoncreds proof.proof.proofs constituent proof schema metadata.""" + + model_class = AnoncredsProofProofProofsProof + unknown = EXCLUDE + + primary_proof = fields.Nested( + AnoncredsPrimaryProofSchema, metadata={"description": "Anoncreds primary proof"} + ) + non_revoc_proof = fields.Nested( + AnoncredsNonRevocProofSchema, + allow_none=True, + metadata={"description": "Anoncreds non-revocation proof"}, + ) + + +class AnoncredsProofProofAggregatedProof(BaseModel): + """Anoncreds proof.proof aggregated proof.""" + + class Meta: + """Anoncreds proof.proof aggregated proof metadata.""" + + schema_class = "AnoncredsProofProofAggregatedProofSchema" + + def __init__( + self, + c_hash: Optional[str] = None, + c_list: Sequence[Sequence[int]] = None, + **kwargs, + ): + """Initialize anoncreds proof.proof agreggated proof.""" + super().__init__(**kwargs) + self.c_hash = c_hash + self.c_list = c_list + + +class AnoncredsProofProofAggregatedProofSchema(BaseModelSchema): + """Anoncreds proof.proof aggregated proof schema.""" + + class Meta: + """Anoncreds proof.proof aggregated proof schema metadata.""" + + model_class = AnoncredsProofProofAggregatedProof + unknown = EXCLUDE + + c_hash = fields.Str(metadata={"description": "c_hash value"}) + c_list = fields.List( + fields.List(fields.Int(metadata={"strict": True})), + metadata={"description": "c_list value"}, + ) + + +class AnoncredsProofProof(BaseModel): + """Anoncreds proof.proof content.""" + + class Meta: + """Anoncreds proof.proof content metadata.""" + + schema_class = "AnoncredsProofProofSchema" + + def __init__( + self, + proofs: Sequence[AnoncredsProofProofProofsProof] = None, + aggregated_proof: Optional[AnoncredsProofProofAggregatedProof] = None, + **kwargs, + ): + """Initialize anoncreds proof.proof content.""" + super().__init__(**kwargs) + self.proofs = proofs + self.aggregated_proof = aggregated_proof + + +class AnoncredsProofProofSchema(BaseModelSchema): + """Anoncreds proof.proof content schema.""" + + class Meta: + """Anoncreds proof.proof content schema metadata.""" + + model_class = AnoncredsProofProof + unknown = EXCLUDE + + proofs = fields.Nested( + AnoncredsProofProofProofsProofSchema, + many=True, + metadata={"description": "Anoncreds proof proofs"}, + ) + aggregated_proof = fields.Nested( + AnoncredsProofProofAggregatedProofSchema, + metadata={"description": "Anoncreds proof aggregated proof"}, + ) + + +class RawEncoded(BaseModel): + """Raw and encoded attribute values.""" + + class Meta: + """Raw and encoded attribute values metadata.""" + + schema_class = "RawEncodedSchema" + + def __init__( + self, + raw: Optional[str] = None, + encoded: Optional[str] = None, + **kwargs, + ): + """Initialize raw and encoded attribute values.""" + super().__init__(**kwargs) + self.raw = raw + self.encoded = encoded + + +class RawEncodedSchema(BaseModelSchema): + """Raw and encoded attribute values schema.""" + + class Meta: + """Raw and encoded attribute values schema metadata.""" + + model_class = RawEncoded + unknown = EXCLUDE + + raw = fields.Str(metadata={"description": "Raw value"}) + encoded = fields.Str( + validate=NUM_STR_ANY_VALIDATE, + metadata={"description": "Encoded value", "example": NUM_STR_ANY_EXAMPLE}, + ) + + +class AnoncredsProofRequestedProofRevealedAttr(RawEncoded): + """Anoncreds proof requested proof revealed attr.""" + + class Meta: + """Anoncreds proof requested proof revealed attr metadata.""" + + schema_class = "AnoncredsProofRequestedProofRevealedAttrSchema" + + def __init__( + self, + sub_proof_index: Optional[int] = None, + **kwargs, + ): + """Initialize anoncreds proof requested proof revealed attr.""" + super().__init__(**kwargs) + self.sub_proof_index = sub_proof_index + + +class AnoncredsProofRequestedProofRevealedAttrSchema(RawEncodedSchema): + """Anoncreds proof requested proof revealed attr schema.""" + + class Meta: + """Anoncreds proof requested proof revealed attr schema metadata.""" + + model_class = AnoncredsProofRequestedProofRevealedAttr + unknown = EXCLUDE + + sub_proof_index = fields.Int( + metadata={"strict": True, "description": "Sub-proof index"} + ) + + +class AnoncredsProofRequestedProofRevealedAttrGroup(BaseModel): + """Anoncreds proof requested proof revealed attr group.""" + + class Meta: + """Anoncreds proof requested proof revealed attr group metadata.""" + + schema_class = "AnoncredsProofRequestedProofRevealedAttrGroupSchema" + + def __init__( + self, + sub_proof_index: Optional[int] = None, + values: Mapping[str, RawEncoded] = None, + **kwargs, + ): + """Initialize anoncreds proof requested proof revealed attr.""" + super().__init__(**kwargs) + self.sub_proof_index = sub_proof_index + self.values = values + + +class AnoncredsProofRequestedProofRevealedAttrGroupSchema(BaseModelSchema): + """Anoncreds proof requested proof revealed attr group schema.""" + + class Meta: + """Anoncreds proof requested proof revealed attr group schema metadata.""" + + model_class = AnoncredsProofRequestedProofRevealedAttrGroup + unknown = EXCLUDE + + sub_proof_index = fields.Int( + metadata={"strict": True, "description": "Sub-proof index"} + ) + values = fields.Dict( + keys=fields.Str(), + values=fields.Nested(RawEncodedSchema), + metadata={ + "description": "Anoncreds proof requested proof revealed attr groups group value" # noqa: E501 + }, + ) + + +class AnoncredsProofRequestedProofPredicate(BaseModel): + """Anoncreds proof requested proof predicate.""" + + class Meta: + """Anoncreds proof requested proof requested proof predicate metadata.""" + + schema_class = "AnoncredsProofRequestedProofPredicateSchema" + + def __init__( + self, + sub_proof_index: Optional[int] = None, + **kwargs, + ): + """Initialize anoncreds proof requested proof predicate.""" + super().__init__(**kwargs) + self.sub_proof_index = sub_proof_index + + +class AnoncredsProofRequestedProofPredicateSchema(BaseModelSchema): + """Anoncreds proof requested prrof predicate schema.""" + + class Meta: + """Anoncreds proof requested proof requested proof predicate schema metadata.""" + + model_class = AnoncredsProofRequestedProofPredicate + unknown = EXCLUDE + + sub_proof_index = fields.Int( + metadata={"strict": True, "description": "Sub-proof index"} + ) + + +class AnoncredsProofRequestedProof(BaseModel): + """Anoncreds proof.requested_proof content.""" + + class Meta: + """Anoncreds proof.requested_proof content metadata.""" + + schema_class = "AnoncredsProofRequestedProofSchema" + + def __init__( + self, + revealed_attrs: Mapping[str, AnoncredsProofRequestedProofRevealedAttr] = None, + revealed_attr_groups: Mapping[ + str, + AnoncredsProofRequestedProofRevealedAttrGroup, + ] = None, + self_attested_attrs: Optional[Mapping] = None, + unrevealed_attrs: Optional[Mapping] = None, + predicates: Mapping[str, AnoncredsProofRequestedProofPredicate] = None, + **kwargs, + ): + """Initialize anoncreds proof requested proof.""" + super().__init__(**kwargs) + self.revealed_attrs = revealed_attrs + self.revealed_attr_groups = revealed_attr_groups + self.self_attested_attrs = self_attested_attrs + self.unrevealed_attrs = unrevealed_attrs + self.predicates = predicates + + +class AnoncredsProofRequestedProofSchema(BaseModelSchema): + """Anoncreds proof requested proof schema.""" + + class Meta: + """Anoncreds proof requested proof schema metadata.""" + + model_class = AnoncredsProofRequestedProof + unknown = EXCLUDE + + revealed_attrs = fields.Dict( + keys=fields.Str(), + values=fields.Nested(AnoncredsProofRequestedProofRevealedAttrSchema), + allow_none=True, + metadata={"description": "Proof requested proof revealed attributes"}, + ) + revealed_attr_groups = fields.Dict( + keys=fields.Str(), + values=fields.Nested(AnoncredsProofRequestedProofRevealedAttrGroupSchema), + allow_none=True, + metadata={"description": "Proof requested proof revealed attribute groups"}, + ) + self_attested_attrs = fields.Dict( + metadata={"description": "Proof requested proof self-attested attributes"} + ) + unrevealed_attrs = fields.Dict(metadata={"description": "Unrevealed attributes"}) + predicates = fields.Dict( + keys=fields.Str(), + values=fields.Nested(AnoncredsProofRequestedProofPredicateSchema), + metadata={"description": "Proof requested proof predicates."}, + ) + + +class AnoncredsProofIdentifier(BaseModel): + """Anoncreds proof identifier.""" + + class Meta: + """Anoncreds proof identifier metadata.""" + + schema_class = "AnoncredsProofIdentifierSchema" + + def __init__( + self, + schema_id: Optional[str] = None, + cred_def_id: Optional[str] = None, + rev_reg_id: Optional[str] = None, + timestamp: Optional[int] = None, + **kwargs, + ): + """Initialize anoncreds proof identifier.""" + super().__init__(**kwargs) + self.schema_id = schema_id + self.cred_def_id = cred_def_id + self.rev_reg_id = rev_reg_id + self.timestamp = timestamp + + +class AnoncredsProofIdentifierSchema(BaseModelSchema): + """Anoncreds proof identifier schema.""" + + class Meta: + """Anoncreds proof identifier schema metadata.""" + + model_class = AnoncredsProofIdentifier + unknown = EXCLUDE + + schema_id = fields.Str( + validate=ANONCREDS_SCHEMA_ID_VALIDATE, + metadata={ + "description": "Schema identifier", + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, + }, + ) + cred_def_id = fields.Str( + validate=ANONCREDS_CRED_DEF_ID_VALIDATE, + metadata={ + "description": "Credential definition identifier", + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, + }, + ) + rev_reg_id = fields.Str( + allow_none=True, + validate=ANONCREDS_REV_REG_ID_VALIDATE, + metadata={ + "description": "Revocation registry identifier", + "example": ANONCREDS_REV_REG_ID_EXAMPLE, + }, + ) + timestamp = fields.Int( + allow_none=True, + validate=INT_EPOCH_VALIDATE, + metadata={ + "strict": True, + "description": "Timestamp epoch", + "example": INT_EPOCH_EXAMPLE, + }, + ) + + +class AnoncredsProof(BaseModel): + """Anoncreds proof.""" + + class Meta: + """Anoncreds proof metadata.""" + + schema_class = "AnoncredsProofSchema" + + def __init__( + self, + proof: Optional[AnoncredsProofProof] = None, + requested_proof: Optional[AnoncredsProofRequestedProof] = None, + identifiers: Sequence[AnoncredsProofIdentifier] = None, + **kwargs, + ): + """Initialize anoncreds proof.""" + super().__init__(**kwargs) + self.proof = proof + self.requested_proof = requested_proof + self.identifiers = identifiers + + +class AnoncredsProofSchema(BaseModelSchema): + """Anoncreds proof schema.""" + + class Meta: + """Anoncreds proof schema metadata.""" + + model_class = AnoncredsProof + unknown = EXCLUDE + + proof = fields.Nested( + AnoncredsProofProofSchema, + metadata={"description": "Anoncreds proof.proof content"}, + ) + requested_proof = fields.Nested( + AnoncredsProofRequestedProofSchema, + metadata={"description": "Anoncreds proof.requested_proof content"}, + ) + identifiers = fields.Nested( + AnoncredsProofIdentifierSchema, + many=True, + metadata={"description": "Anoncreds proof.identifiers content"}, + ) + + +class AnoncredsPresSpecSchema(AdminAPIMessageTracingSchema): + """Request schema for anoncreds proof specification to send as presentation.""" + + self_attested_attributes = fields.Dict( + required=True, + keys=fields.Str(metadata={"example": "attr_name"}), + values=fields.Str( + metadata={ + "example": "self_attested_value", + "description": ( + "Self-attested attribute values to use in requested-credentials" + " structure for proof construction" + ), + } + ), + metadata={"description": "Self-attested attributes to build into proof"}, + ) + requested_attributes = fields.Dict( + required=True, + keys=fields.Str(metadata={"example": "attr_referent"}), + values=fields.Nested(AnoncredsRequestedCredsRequestedAttrSchema), + metadata={ + "description": ( + "Nested object mapping proof request attribute referents to" + " requested-attribute specifiers" + ) + }, + ) + requested_predicates = fields.Dict( + required=True, + keys=fields.Str(metadata={"example": "pred_referent"}), + values=fields.Nested(AnoncredsRequestedCredsRequestedPredSchema), + metadata={ + "description": ( + "Nested object mapping proof request predicate referents to" + " requested-predicate specifiers" + ) + }, + ) + trace = fields.Bool( + required=False, + metadata={ + "description": "Whether to trace event (default false)", + "example": False, + }, + ) diff --git a/acapy_agent/anoncreds/models/requested_credentials.py b/acapy_agent/anoncreds/models/requested_credentials.py new file mode 100644 index 0000000000..ac0fcf3d33 --- /dev/null +++ b/acapy_agent/anoncreds/models/requested_credentials.py @@ -0,0 +1,47 @@ +"""Admin routes for presentations.""" + +from marshmallow import fields + +from ...messaging.models.openapi import OpenAPISchema +from ...messaging.valid import INT_EPOCH_EXAMPLE, INT_EPOCH_VALIDATE + + +class AnoncredsRequestedCredsRequestedAttrSchema(OpenAPISchema): + """Schema for requested attributes within anoncreds requested creds structure.""" + + cred_id = fields.Str( + required=True, + metadata={ + "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "description": ( + "Wallet credential identifier (typically but not necessarily a UUID)" + ), + }, + ) + revealed = fields.Bool( + dump_default=True, + metadata={"description": "Whether to reveal attribute in proof (default true)"}, + ) + + +class AnoncredsRequestedCredsRequestedPredSchema(OpenAPISchema): + """Schema for requested predicates within anoncreds requested creds structure.""" + + cred_id = fields.Str( + required=True, + metadata={ + "description": ( + "Wallet credential identifier (typically but not necessarily a UUID)" + ), + "example": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + }, + ) + timestamp = fields.Int( + required=False, + validate=INT_EPOCH_VALIDATE, + metadata={ + "description": "Epoch timestamp of interest for non-revocation proof", + "strict": True, + "example": INT_EPOCH_EXAMPLE, + }, + ) diff --git a/acapy_agent/anoncreds/models/anoncreds_revocation.py b/acapy_agent/anoncreds/models/revocation.py similarity index 96% rename from acapy_agent/anoncreds/models/anoncreds_revocation.py rename to acapy_agent/anoncreds/models/revocation.py index cc90469eac..94c75a525a 100644 --- a/acapy_agent/anoncreds/models/anoncreds_revocation.py +++ b/acapy_agent/anoncreds/models/revocation.py @@ -7,15 +7,14 @@ from marshmallow.validate import OneOf from typing_extensions import Literal -from acapy_agent.messaging.valid import ( - INDY_CRED_DEF_ID_EXAMPLE, - INDY_ISO8601_DATETIME_EXAMPLE, - INDY_OR_KEY_DID_EXAMPLE, - INDY_RAW_PUBLIC_KEY_EXAMPLE, - INDY_REV_REG_ID_EXAMPLE, -) - from ...messaging.models.base import BaseModel, BaseModelSchema +from ...messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_DID_EXAMPLE, + ANONCREDS_REV_REG_ID_EXAMPLE, + ISO8601_DATETIME_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, +) class RevRegDefValue(BaseModel): @@ -60,7 +59,7 @@ class Meta: unknown = EXCLUDE public_keys = fields.Dict( - data_key="publicKeys", metadata={"example": INDY_RAW_PUBLIC_KEY_EXAMPLE} + data_key="publicKeys", metadata={"example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE} ) max_cred_num = fields.Int(data_key="maxCredNum", metadata={"example": 777}) tails_location = fields.Str( @@ -131,7 +130,7 @@ class Meta: issuer_id = fields.Str( metadata={ "description": "Issuer Identifier of the credential definition or schema", - "example": INDY_OR_KEY_DID_EXAMPLE, + "example": ANONCREDS_DID_EXAMPLE, }, data_key="issuerId", ) @@ -139,7 +138,7 @@ class Meta: cred_def_id = fields.Str( metadata={ "description": "Credential definition identifier", - "example": INDY_CRED_DEF_ID_EXAMPLE, + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, }, data_key="credDefId", ) @@ -209,7 +208,7 @@ class Meta: revocation_registry_definition_id = fields.Str( metadata={ "description": "revocation registry definition id", - "example": INDY_REV_REG_ID_EXAMPLE, + "example": ANONCREDS_REV_REG_ID_EXAMPLE, } ) revocation_registry_definition = fields.Nested( @@ -380,14 +379,14 @@ class Meta: issuer_id = fields.Str( metadata={ "description": "Issuer Identifier of the credential definition or schema", - "example": INDY_OR_KEY_DID_EXAMPLE, + "example": ANONCREDS_DID_EXAMPLE, }, data_key="issuerId", ) rev_reg_def_id = fields.Str( metadata={ "description": "The ID of the revocation registry definition", - "example": INDY_REV_REG_ID_EXAMPLE, + "example": ANONCREDS_REV_REG_ID_EXAMPLE, }, data_key="revRegDefId", ) @@ -409,7 +408,7 @@ class Meta: timestamp = fields.Int( metadata={ "description": "Timestamp at which revocation list is applicable", - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, required=False, ) diff --git a/acapy_agent/anoncreds/models/anoncreds_schema.py b/acapy_agent/anoncreds/models/schema.py similarity index 95% rename from acapy_agent/anoncreds/models/anoncreds_schema.py rename to acapy_agent/anoncreds/models/schema.py index b2383ff60f..6a3f56bc03 100644 --- a/acapy_agent/anoncreds/models/anoncreds_schema.py +++ b/acapy_agent/anoncreds/models/schema.py @@ -7,7 +7,10 @@ from marshmallow.validate import OneOf from ...messaging.models.base import BaseModel, BaseModelSchema -from ...messaging.valid import INDY_OR_KEY_DID_EXAMPLE, INDY_SCHEMA_ID_EXAMPLE +from ...messaging.valid import ( + ANONCREDS_DID_EXAMPLE, + ANONCREDS_SCHEMA_ID_EXAMPLE, +) class AnonCredsSchema(BaseModel): @@ -58,7 +61,7 @@ class Meta: issuer_id = fields.Str( metadata={ "description": "Issuer Identifier of the credential definition or schema", - "example": INDY_OR_KEY_DID_EXAMPLE, + "example": ANONCREDS_DID_EXAMPLE, }, data_key="issuerId", ) @@ -129,7 +132,10 @@ class Meta: schema_value = fields.Nested(AnonCredsSchemaSchema(), data_key="schema") schema_id = fields.Str( - metadata={"description": "Schema identifier", "example": INDY_SCHEMA_ID_EXAMPLE} + metadata={ + "description": "Schema identifier", + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, + } ) resolution_metadata = fields.Dict() schema_metadata = fields.Dict() @@ -185,7 +191,7 @@ class Meta: schema_id = fields.Str( metadata={ "description": "Schema identifier", - "example": INDY_SCHEMA_ID_EXAMPLE, + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, } ) schema_value = fields.Nested(AnonCredsSchemaSchema(), data_key="schema") diff --git a/acapy_agent/anoncreds/models/utils.py b/acapy_agent/anoncreds/models/utils.py new file mode 100644 index 0000000000..ac5797190c --- /dev/null +++ b/acapy_agent/anoncreds/models/utils.py @@ -0,0 +1,99 @@ +"""Utilities to deal with anoncreds objects.""" + +from ..holder import AnonCredsHolder + + +def _get_value_error_msg(proof_request: dict, referent: str) -> str: + return ( + "Could not automatically construct presentation for " + + f"presentation request {proof_request['name']}" + + f":{proof_request['version']} because referent " + + f"{referent} did not produce any credentials." + ) + + +async def get_requested_creds_from_proof_request_preview( + proof_request: dict, + *, + holder: AnonCredsHolder, +): + """Build anoncreds requested-credentials structure. + + Given input proof request and presentation preview, use credentials in + holder's wallet to build anoncreds requested credentials structure for input + to proof creation. + + Args: + proof_request: anoncreds proof request + preview: preview from presentation proposal, if applicable + holder: holder injected into current context + + """ + req_creds = { + "self_attested_attributes": {}, + "requested_attributes": {}, + "requested_predicates": {}, + } + + for referent, _ in proof_request["requested_attributes"].items(): + credentials = await holder.get_credentials_for_presentation_request_by_referent( + presentation_request=proof_request, + referents=(referent,), + offset=0, + limit=100, + ) + if not credentials: + raise ValueError(_get_value_error_msg(proof_request, referent)) + + cred_match = credentials[0] # holder sorts + + if "restrictions" in proof_request["requested_attributes"][referent]: + req_creds["requested_attributes"][referent] = { + "cred_id": cred_match["cred_info"]["referent"], + "revealed": True, + } + else: + req_creds["self_attested_attributes"][referent] = cred_match["cred_info"][ + "attrs" + ][proof_request["requested_attributes"][referent]["name"]] + + for referent in proof_request["requested_predicates"]: + credentials = await holder.get_credentials_for_presentation_request_by_referent( + presentation_request=proof_request, + referents=(referent,), + offset=0, + limit=100, + ) + if not credentials: + raise ValueError(_get_value_error_msg(proof_request, referent)) + + cred_match = credentials[0] # holder sorts + if "restrictions" in proof_request["requested_predicates"][referent]: + req_creds["requested_predicates"][referent] = { + "cred_id": cred_match["cred_info"]["referent"], + "revealed": True, + } + else: + req_creds["self_attested_attributes"][referent] = cred_match["cred_info"][ + "attrs" + ][proof_request["requested_predicates"][referent]["name"]] + + return req_creds + + +def extract_non_revocation_intervals_from_proof_request(proof_req: dict): + """Return non-revocation intervals by requested item referent in proof request.""" + non_revoc_intervals = {} + for req_item_type in ("requested_attributes", "requested_predicates"): + for reft, req_item in proof_req[req_item_type].items(): + interval = req_item.get( + "non_revoked", + proof_req.get("non_revoked"), + ) + if interval: + timestamp_from = interval.get("from") + timestamp_to = interval.get("to") + if (timestamp_to is not None) and timestamp_from == timestamp_to: + interval["from"] = 0 # accommodate verify=False if from=to + non_revoc_intervals[reft] = interval + return non_revoc_intervals diff --git a/acapy_agent/anoncreds/registry.py b/acapy_agent/anoncreds/registry.py index 79aba036cc..c355b447cd 100644 --- a/acapy_agent/anoncreds/registry.py +++ b/acapy_agent/anoncreds/registry.py @@ -11,8 +11,8 @@ BaseAnonCredsRegistrar, BaseAnonCredsResolver, ) -from .models.anoncreds_cred_def import CredDef, CredDefResult, GetCredDefResult -from .models.anoncreds_revocation import ( +from .models.credential_definition import CredDef, CredDefResult, GetCredDefResult +from .models.revocation import ( GetRevListResult, GetRevRegDefResult, RevList, @@ -20,7 +20,7 @@ RevRegDef, RevRegDefResult, ) -from .models.anoncreds_schema import AnonCredsSchema, GetSchemaResult, SchemaResult +from .models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult LOGGER = logging.getLogger(__name__) diff --git a/acapy_agent/anoncreds/revocation.py b/acapy_agent/anoncreds/revocation.py index 56b19d222d..e9cc88293f 100644 --- a/acapy_agent/anoncreds/revocation.py +++ b/acapy_agent/anoncreds/revocation.py @@ -26,12 +26,12 @@ from requests import RequestException, Session from uuid_utils import uuid4 -from acapy_agent.anoncreds.models.anoncreds_cred_def import CredDef - from ..askar.profile_anon import AskarAnoncredsProfile, AskarAnoncredsProfileSession from ..core.error import BaseError from ..core.event_bus import Event, EventBus from ..core.profile import Profile, ProfileSession +from ..multitenant.base import BaseMultitenantManager +from ..tails.anoncreds_tails_server import AnonCredsTailsServer from ..tails.base import BaseTailsServer from .error_messages import ANONCREDS_PROFILE_REQUIRED_MSG from .events import RevListFinishedEvent, RevRegDefFinishedEvent @@ -41,7 +41,8 @@ STATE_FINISHED, AnonCredsIssuer, ) -from .models.anoncreds_revocation import ( +from .models.credential_definition import CredDef +from .models.revocation import ( RevList, RevListResult, RevListState, @@ -694,7 +695,12 @@ def get_local_tails_path(self, rev_reg_def: RevRegDef) -> str: async def upload_tails_file(self, rev_reg_def: RevRegDef): """Upload the local tails file to the tails server.""" - tails_server = self.profile.inject_or(BaseTailsServer) + multitenant_mgr = self.profile.inject_or(BaseMultitenantManager) + if multitenant_mgr: + tails_server = AnonCredsTailsServer() + else: + tails_server = self.profile.inject_or(BaseTailsServer) + if not tails_server: raise AnonCredsRevocationError("Tails server not configured") if not Path(self.get_local_tails_path(rev_reg_def)).is_file(): diff --git a/acapy_agent/anoncreds/routes.py b/acapy_agent/anoncreds/routes.py index 9cf1d6ad98..9a8fe04669 100644 --- a/acapy_agent/anoncreds/routes.py +++ b/acapy_agent/anoncreds/routes.py @@ -16,13 +16,12 @@ from ..admin.decorators.auth import tenant_authentication from ..admin.request_context import AdminRequestContext from ..core.event_bus import EventBus -from ..ledger.error import LedgerError from ..messaging.models.openapi import OpenAPISchema from ..messaging.valid import ( - INDY_CRED_DEF_ID_EXAMPLE, - INDY_OR_KEY_DID_EXAMPLE, - INDY_REV_REG_ID_EXAMPLE, - INDY_SCHEMA_ID_EXAMPLE, + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_DID_EXAMPLE, + ANONCREDS_REV_REG_ID_EXAMPLE, + ANONCREDS_SCHEMA_ID_EXAMPLE, UUIDFour, ) from ..revocation.error import RevocationNotSupportedError @@ -35,9 +34,9 @@ AnonCredsResolutionError, ) from .issuer import AnonCredsIssuer, AnonCredsIssuerError -from .models.anoncreds_cred_def import CredDefResultSchema, GetCredDefResultSchema -from .models.anoncreds_revocation import RevListResultSchema, RevRegDefResultSchema -from .models.anoncreds_schema import ( +from .models.credential_definition import CredDefResultSchema, GetCredDefResultSchema +from .models.revocation import RevListResultSchema, RevRegDefResultSchema +from .models.schema import ( AnonCredsSchemaSchema, GetSchemaResultSchema, SchemaResultSchema, @@ -69,7 +68,7 @@ class SchemaIdMatchInfo(OpenAPISchema): schema_id = fields.Str( metadata={ "description": "Schema identifier", - "example": INDY_SCHEMA_ID_EXAMPLE, + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, } ) @@ -112,7 +111,7 @@ class SchemasQueryStringSchema(OpenAPISchema): schema_issuer_id = fields.Str( metadata={ "description": "Schema issuer identifier", - "example": INDY_OR_KEY_DID_EXAMPLE, + "example": ANONCREDS_DID_EXAMPLE, } ) @@ -124,7 +123,7 @@ class GetSchemasResponseSchema(OpenAPISchema): fields.Str( metadata={ "description": "Schema identifiers", - "example": INDY_SCHEMA_ID_EXAMPLE, + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, } ) ) @@ -137,7 +136,7 @@ class SchemaPostRequestSchema(OpenAPISchema): options = fields.Nested(SchemaPostOptionSchema()) -@docs(tags=["anoncreds - schemas"], summary="Create a schema on the connected ledger") +@docs(tags=["anoncreds - schemas"], summary="Create a schema on the connected datastore") @request_schema(SchemaPostRequestSchema()) @response_schema(SchemaResultSchema(), 200, description="") @tenant_authentication @@ -278,7 +277,7 @@ class CredIdMatchInfo(OpenAPISchema): cred_def_id = fields.Str( metadata={ "description": "Credential definition identifier", - "example": INDY_CRED_DEF_ID_EXAMPLE, + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, }, required=True, ) @@ -297,7 +296,7 @@ class InnerCredDefSchema(OpenAPISchema): schema_id = fields.Str( metadata={ "description": "Schema identifier", - "example": INDY_SCHEMA_ID_EXAMPLE, + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, }, required=True, data_key="schemaId", @@ -305,7 +304,7 @@ class InnerCredDefSchema(OpenAPISchema): issuer_id = fields.Str( metadata={ "description": "Issuer Identifier of the credential definition", - "example": INDY_OR_KEY_DID_EXAMPLE, + "example": ANONCREDS_DID_EXAMPLE, }, required=True, data_key="issuerId", @@ -357,13 +356,13 @@ class CredDefsQueryStringSchema(OpenAPISchema): issuer_id = fields.Str( metadata={ "description": "Issuer Identifier of the credential definition", - "example": INDY_OR_KEY_DID_EXAMPLE, + "example": ANONCREDS_DID_EXAMPLE, } ) schema_id = fields.Str( metadata={ "description": "Schema identifier", - "example": INDY_SCHEMA_ID_EXAMPLE, + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, } ) schema_name = fields.Str( @@ -382,7 +381,7 @@ class CredDefsQueryStringSchema(OpenAPISchema): @docs( tags=["anoncreds - credential definitions"], - summary="Create a credential definition on the connected ledger", + summary="Create a credential definition on the connected datastore", ) @request_schema(CredDefPostRequestSchema()) @response_schema(CredDefResultSchema(), 200, description="") @@ -522,14 +521,14 @@ class InnerRevRegDefSchema(OpenAPISchema): issuer_id = fields.Str( metadata={ "description": "Issuer Identifier of the credential definition or schema", - "example": INDY_OR_KEY_DID_EXAMPLE, + "example": ANONCREDS_DID_EXAMPLE, }, data_key="issuerId", ) cred_def_id = fields.Str( metadata={ "description": "Credential definition identifier", - "example": INDY_SCHEMA_ID_EXAMPLE, + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, }, data_key="credDefId", ) @@ -573,7 +572,7 @@ class RevRegCreateRequestSchemaAnoncreds(OpenAPISchema): @docs( tags=["anoncreds - revocation"], - summary="Create and publish a registration revocation on the connected ledger", + summary="Create and publish a registration revocation on the connected datastore", ) @request_schema(RevRegCreateRequestSchemaAnoncreds()) @response_schema(RevRegDefResultSchema(), 200, description="") @@ -649,7 +648,7 @@ class RevListCreateRequestSchema(OpenAPISchema): rev_reg_def_id = fields.Str( metadata={ "description": "Revocation registry definition identifier", - "example": INDY_REV_REG_ID_EXAMPLE, + "example": ANONCREDS_REV_REG_ID_EXAMPLE, } ) options = fields.Nested(RevListOptionsSchema) @@ -657,7 +656,7 @@ class RevListCreateRequestSchema(OpenAPISchema): @docs( tags=["anoncreds - revocation"], - summary="Create and publish a revocation status list on the connected ledger", + summary="Create and publish a revocation status list on the connected datastore", ) @request_schema(RevListCreateRequestSchema()) @response_schema(RevListResultSchema(), 200, description="") @@ -687,7 +686,7 @@ async def rev_list_post(request: web.BaseRequest): handle_value_error(e) except StorageNotFoundError as err: raise web.HTTPNotFound(reason=err.roll_up) from err - except (AnonCredsRevocationError, LedgerError) as err: + except AnonCredsRevocationError as err: raise web.HTTPBadRequest(reason=err.roll_up) from err diff --git a/acapy_agent/anoncreds/tests/test_holder.py b/acapy_agent/anoncreds/tests/test_holder.py index 6f8dae681d..c894b21e3f 100644 --- a/acapy_agent/anoncreds/tests/test_holder.py +++ b/acapy_agent/anoncreds/tests/test_holder.py @@ -45,8 +45,8 @@ from ...wallet.error import WalletNotFoundError from .. import holder as test_module from ..holder import CATEGORY_CREDENTIAL, AnonCredsHolder, AnonCredsHolderError -from ..models.anoncreds_cred_def import CredDef, CredDefValue, CredDefValuePrimary -from ..models.anoncreds_revocation import GetRevListResult, RevList +from ..models.credential_definition import CredDef, CredDefValue, CredDefValuePrimary +from ..models.revocation import GetRevListResult, RevList from ..registry import AnonCredsRegistry diff --git a/acapy_agent/anoncreds/tests/test_issuer.py b/acapy_agent/anoncreds/tests/test_issuer.py index f165f178d6..7442ffd2ae 100644 --- a/acapy_agent/anoncreds/tests/test_issuer.py +++ b/acapy_agent/anoncreds/tests/test_issuer.py @@ -10,7 +10,7 @@ AnonCredsObjectAlreadyExists, AnonCredsSchemaAlreadyExists, ) -from ...anoncreds.models.anoncreds_cred_def import ( +from ...anoncreds.models.credential_definition import ( CredDef, CredDefResult, CredDefState, @@ -19,7 +19,7 @@ CredDefValueRevocation, GetCredDefResult, ) -from ...anoncreds.models.anoncreds_schema import ( +from ...anoncreds.models.schema import ( AnonCredsSchema, GetSchemaResult, SchemaResult, diff --git a/acapy_agent/anoncreds/tests/test_revocation.py b/acapy_agent/anoncreds/tests/test_revocation.py index 5de4ef368e..2d9bc62e15 100644 --- a/acapy_agent/anoncreds/tests/test_revocation.py +++ b/acapy_agent/anoncreds/tests/test_revocation.py @@ -16,8 +16,8 @@ from requests import RequestException, Session from ...anoncreds.issuer import AnonCredsIssuer -from ...anoncreds.models.anoncreds_cred_def import CredDef -from ...anoncreds.models.anoncreds_revocation import ( +from ...anoncreds.models.credential_definition import CredDef +from ...anoncreds.models.revocation import ( RevList, RevListResult, RevListState, @@ -26,7 +26,7 @@ RevRegDefState, RevRegDefValue, ) -from ...anoncreds.models.anoncreds_schema import ( +from ...anoncreds.models.schema import ( AnonCredsSchema, GetSchemaResult, ) @@ -48,7 +48,7 @@ "accum_key": {"z": "1 0BB...386"}, }, tails_hash="58NNWYnVxVFzAfUztwGSNBL4551XNq6nXk56pCiKJxxt", - tails_location="http://tails-server.com", + tails_location="https://tails-server.com", ), issuer_id="CsQY9MGeD3CQP4EyuVFo5m", type="CL_ACCUM", @@ -836,21 +836,40 @@ def test_generate_public_tails_uri(self): async def test_upload_tails_file(self): self.profile.inject_or = mock.Mock( - return_value=mock.MagicMock( - upload_tails_file=mock.CoroutineMock( - side_effect=[ - (True, "http://tails-server.com"), - (None, "http://tails-server.com"), - (True, "not-http://tails-server.com"), - ] - ) - ) + side_effect=[ + None, + mock.MagicMock( + upload_tails_file=mock.CoroutineMock( + return_value=(True, "https://tails-server.com") + ) + ), + ] ) # valid await self.revocation.upload_tails_file(rev_reg_def) # upload fails + self.profile.inject_or = mock.Mock( + side_effect=[ + None, + mock.MagicMock( + upload_tails_file=mock.CoroutineMock( + return_value=(None, "https://tails-server.com"), + ) + ), + ] + ) with self.assertRaises(test_module.AnonCredsRevocationError): await self.revocation.upload_tails_file(rev_reg_def) + self.profile.inject_or = mock.Mock( + side_effect=[ + None, + mock.MagicMock( + upload_tails_file=mock.CoroutineMock( + return_value=(True, "not-http://tails-server.com"), + ) + ), + ] + ) # tails location does not match with self.assertRaises(test_module.AnonCredsRevocationError): await self.revocation.upload_tails_file(rev_reg_def) diff --git a/acapy_agent/anoncreds/tests/test_revocation_setup.py b/acapy_agent/anoncreds/tests/test_revocation_setup.py index e56291efeb..357899f4c9 100644 --- a/acapy_agent/anoncreds/tests/test_revocation_setup.py +++ b/acapy_agent/anoncreds/tests/test_revocation_setup.py @@ -11,7 +11,7 @@ RevRegDefFinishedEvent, RevRegDefFinishedPayload, ) -from ..models.anoncreds_revocation import RevRegDef, RevRegDefValue +from ..models.revocation import RevRegDef, RevRegDefValue from ..revocation import AnonCredsRevocation diff --git a/acapy_agent/anoncreds/tests/test_routes.py b/acapy_agent/anoncreds/tests/test_routes.py index 17c4d15bee..607b81f4ae 100644 --- a/acapy_agent/anoncreds/tests/test_routes.py +++ b/acapy_agent/anoncreds/tests/test_routes.py @@ -7,7 +7,7 @@ from ...admin.request_context import AdminRequestContext from ...anoncreds.base import AnonCredsObjectNotFound from ...anoncreds.issuer import AnonCredsIssuer -from ...anoncreds.models.anoncreds_schema import ( +from ...anoncreds.models.schema import ( AnonCredsSchema, SchemaResult, SchemaState, diff --git a/acapy_agent/anoncreds/tests/test_verifier.py b/acapy_agent/anoncreds/tests/test_verifier.py index 8f912a3f0f..0ff11fcb95 100644 --- a/acapy_agent/anoncreds/tests/test_verifier.py +++ b/acapy_agent/anoncreds/tests/test_verifier.py @@ -3,21 +3,21 @@ import pytest -from ...anoncreds.models.anoncreds_cred_def import ( +from ...anoncreds.models.credential_definition import ( CredDef, CredDefValue, CredDefValuePrimary, CredDefValueRevocation, GetCredDefResult, ) -from ...anoncreds.models.anoncreds_revocation import ( +from ...anoncreds.models.revocation import ( GetRevListResult, GetRevRegDefResult, RevList, RevRegDef, RevRegDefValue, ) -from ...anoncreds.models.anoncreds_schema import ( +from ...anoncreds.models.schema import ( AnonCredsSchema, GetSchemaResult, ) diff --git a/acapy_agent/anoncreds/verifier.py b/acapy_agent/anoncreds/verifier.py index 4f7972371d..849c44ab5b 100644 --- a/acapy_agent/anoncreds/verifier.py +++ b/acapy_agent/anoncreds/verifier.py @@ -1,4 +1,4 @@ -"""Indy-Credx verifier implementation.""" +"""Anoncreds verifier implementation.""" import asyncio import logging @@ -9,10 +9,10 @@ from anoncreds import AnoncredsError, Presentation, W3cPresentation from ..core.profile import Profile -from ..indy.models.xform import indy_proof_req2non_revoc_intervals from ..messaging.util import canon, encode from ..vc.vc_ld.validation_result import PresentationVerificationResult -from .models.anoncreds_cred_def import GetCredDefResult +from .models.credential_definition import GetCredDefResult +from .models.utils import extract_non_revocation_intervals_from_proof_request from .registry import AnonCredsRegistry LOGGER = logging.getLogger(__name__) @@ -45,7 +45,7 @@ def non_revoc_intervals(self, pres_req: dict, pres: dict, cred_defs: dict) -> li """Remove superfluous non-revocation intervals in presentation request. Irrevocable credentials constitute proof of non-revocation, but - indy rejects proof requests with non-revocation intervals lining up + anoncreds rejects proof requests with non-revocation intervals lining up with non-revocable credentials in proof: seek and remove. Args: @@ -116,13 +116,15 @@ async def check_timestamps( Args: profile: relevant profile - pres_req: indy proof request - pres: indy proof request + pres_req: anoncreds proof request + pres: anoncreds proof request rev_reg_defs: rev reg defs by rev reg id, augmented with transaction times """ msgs = [] now = int(time()) - non_revoc_intervals = indy_proof_req2non_revoc_intervals(pres_req) + non_revoc_intervals = extract_non_revocation_intervals_from_proof_request( + pres_req + ) LOGGER.debug(f">>> got non-revoc intervals: {non_revoc_intervals}") # timestamp for irrevocable credential diff --git a/acapy_agent/askar/profile.py b/acapy_agent/askar/profile.py index e80bc569f1..e23dce1ab8 100644 --- a/acapy_agent/askar/profile.py +++ b/acapy_agent/askar/profile.py @@ -41,13 +41,25 @@ def __init__( *, profile_id: Optional[str] = None, ): - """Create a new AskarProfile instance.""" + """Private constructor. Use 'create' to instantiate.""" super().__init__(context=context, name=opened.name, created=opened.created) self.opened = opened self.ledger_pool: Optional[IndyVdrLedgerPool] = None self.profile_id = profile_id - self.init_ledger_pool() - self.bind_providers() + + @classmethod + async def create( + cls, + opened: AskarOpenStore, + context: Optional[InjectionContext] = None, + *, + profile_id: Optional[str] = None, + ) -> "AskarProfile": + """Asynchronously create a new AskarProfile instance.""" + profile = cls(opened, context, profile_id=profile_id) + await profile.init_ledger_pool() + await profile.bind_providers() + return profile @property def name(self) -> str: @@ -64,7 +76,7 @@ async def remove(self): if self.profile_id: await self.store.remove_profile(self.profile_id) - def init_ledger_pool(self): + async def init_ledger_pool(self): """Initialize the ledger pool.""" if self.settings.get("ledger.disabled"): LOGGER.info("Ledger support is disabled") @@ -78,8 +90,8 @@ def init_ledger_pool(self): LOGGER.warning("Note: setting ledger to read-only mode") genesis_transactions = self.settings.get("ledger.genesis_transactions") cache = self.context.injector.inject_or(BaseCache) - self.ledger_pool = IndyVdrLedgerPool( - pool_name, + self.ledger_pool = await IndyVdrLedgerPool.get_or_create( + name=pool_name, keepalive=keepalive, cache=cache, genesis_transactions=genesis_transactions, @@ -87,7 +99,7 @@ def init_ledger_pool(self): socks_proxy=socks_proxy, ) - def bind_providers(self): + async def bind_providers(self): """Initialize the profile-level instance providers.""" injector = self._context.injector @@ -134,23 +146,17 @@ def bind_providers(self): settings=self.settings ) cache = self.context.injector.inject_or(BaseCache) + ledger_pool = await IndyVdrLedgerPool.get_or_create( + name=write_ledger_config.get("pool_name") + or write_ledger_config.get("id"), + keepalive=write_ledger_config.get("keepalive"), + cache=cache, + genesis_transactions=write_ledger_config.get("genesis_transactions"), + read_only=write_ledger_config.get("read_only"), + socks_proxy=write_ledger_config.get("socks_proxy"), + ) injector.bind_provider( - BaseLedger, - ClassProvider( - IndyVdrLedger, - IndyVdrLedgerPool( - write_ledger_config.get("pool_name") - or write_ledger_config.get("id"), - keepalive=write_ledger_config.get("keepalive"), - cache=cache, - genesis_transactions=write_ledger_config.get( - "genesis_transactions" - ), - read_only=write_ledger_config.get("read_only"), - socks_proxy=write_ledger_config.get("socks_proxy"), - ), - ref(self), - ), + BaseLedger, ClassProvider(IndyVdrLedger, ledger_pool, ref(self)) ) self.settings["ledger.write_ledger"] = write_ledger_config.get("id") if ( @@ -324,16 +330,20 @@ async def provision( ) -> Profile: """Provision a new instance of a profile.""" store_config = AskarStoreConfig(config) - opened = await store_config.open_store(provision=True) - return AskarProfile(opened, context) + opened = await store_config.open_store( + provision=True, in_memory=config.get("test") + ) + return await AskarProfile.create(opened, context) async def open( self, context: InjectionContext, config: Mapping[str, Any] = None ) -> Profile: """Open an instance of an existing profile.""" store_config = AskarStoreConfig(config) - opened = await store_config.open_store(provision=False) - return AskarProfile(opened, context) + opened = await store_config.open_store( + provision=False, in_memory=config.get("test") + ) + return await AskarProfile.create(opened, context) @classmethod async def generate_store_key(self, seed: Optional[str] = None) -> str: diff --git a/acapy_agent/askar/profile_anon.py b/acapy_agent/askar/profile_anon.py index eea73d876f..802b393bf5 100644 --- a/acapy_agent/askar/profile_anon.py +++ b/acapy_agent/askar/profile_anon.py @@ -43,13 +43,25 @@ def __init__( *, profile_id: Optional[str] = None, ): - """Create a new AskarProfile instance.""" + """Create a new AskarAnoncredsProfile instance.""" super().__init__(context=context, name=opened.name, created=opened.created) self.opened = opened self.ledger_pool: Optional[IndyVdrLedgerPool] = None self.profile_id = profile_id - self.init_ledger_pool() - self.bind_providers() + + @classmethod + async def create( + cls, + opened: AskarOpenStore, + context: Optional[InjectionContext] = None, + *, + profile_id: Optional[str] = None, + ) -> "AskarAnoncredsProfile": + """Asynchronously create a new AskarAnoncredsProfile instance.""" + profile = cls(opened, context, profile_id=profile_id) + await profile.init_ledger_pool() + await profile.bind_providers() + return profile @property def name(self) -> str: @@ -66,7 +78,7 @@ async def remove(self): if self.profile_id: await self.store.remove_profile(self.profile_id) - def init_ledger_pool(self): + async def init_ledger_pool(self): """Initialize the ledger pool.""" if self.settings.get("ledger.disabled"): LOGGER.info("Ledger support is disabled") @@ -80,8 +92,8 @@ def init_ledger_pool(self): LOGGER.warning("Note: setting ledger to read-only mode") genesis_transactions = self.settings.get("ledger.genesis_transactions") cache = self.context.injector.inject_or(BaseCache) - self.ledger_pool = IndyVdrLedgerPool( - pool_name, + self.ledger_pool = await IndyVdrLedgerPool.get_or_create( + name=pool_name, keepalive=keepalive, cache=cache, genesis_transactions=genesis_transactions, @@ -89,7 +101,7 @@ def init_ledger_pool(self): socks_proxy=socks_proxy, ) - def bind_providers(self): + async def bind_providers(self): """Initialize the profile-level instance providers.""" injector = self._context.injector @@ -123,23 +135,17 @@ def bind_providers(self): settings=self.settings ) cache = self.context.injector.inject_or(BaseCache) + ledger_pool = await IndyVdrLedgerPool.get_or_create( + name=write_ledger_config.get("pool_name") + or write_ledger_config.get("id"), + keepalive=write_ledger_config.get("keepalive"), + cache=cache, + genesis_transactions=write_ledger_config.get("genesis_transactions"), + read_only=write_ledger_config.get("read_only"), + socks_proxy=write_ledger_config.get("socks_proxy"), + ) injector.bind_provider( - BaseLedger, - ClassProvider( - IndyVdrLedger, - IndyVdrLedgerPool( - write_ledger_config.get("pool_name") - or write_ledger_config.get("id"), - keepalive=write_ledger_config.get("keepalive"), - cache=cache, - genesis_transactions=write_ledger_config.get( - "genesis_transactions" - ), - read_only=write_ledger_config.get("read_only"), - socks_proxy=write_ledger_config.get("socks_proxy"), - ), - ref(self), - ), + BaseLedger, ClassProvider(IndyVdrLedger, ledger_pool, ref(self)) ) self.settings["ledger.write_ledger"] = write_ledger_config.get("id") if ( @@ -277,16 +283,20 @@ async def provision( ) -> Profile: """Provision a new instance of a profile.""" store_config = AskarStoreConfig(config) - opened = await store_config.open_store(provision=True) - return AskarAnoncredsProfile(opened, context) + opened = await store_config.open_store( + provision=True, in_memory=config.get("test") + ) + return await AskarAnoncredsProfile.create(opened, context) async def open( self, context: InjectionContext, config: Mapping[str, Any] = None ) -> Profile: """Open an instance of an existing profile.""" store_config = AskarStoreConfig(config) - opened = await store_config.open_store(provision=False) - return AskarAnoncredsProfile(opened, context) + opened = await store_config.open_store( + provision=False, in_memory=config.get("test") + ) + return await AskarAnoncredsProfile.create(opened, context) @classmethod async def generate_store_key(self, seed: Optional[str] = None) -> str: diff --git a/acapy_agent/askar/tests/test_profile.py b/acapy_agent/askar/tests/test_profile.py index 38a0326ded..1ecbe0ac47 100644 --- a/acapy_agent/askar/tests/test_profile.py +++ b/acapy_agent/askar/tests/test_profile.py @@ -3,10 +3,11 @@ import pytest -from ...askar.profile import AskarProfile +from ...askar.profile import AskarProfile, AskarProfileManager from ...config.injection_context import InjectionContext from ...ledger.base import BaseLedger from .. import profile as test_module +from ..profile_anon import AskarAnonProfileManager @pytest.fixture @@ -16,7 +17,7 @@ def open_store(): @pytest.mark.asyncio async def test_init_success(open_store): - askar_profile = AskarProfile( + askar_profile = await AskarProfile.create( open_store, ) @@ -44,7 +45,7 @@ async def test_init_multi_ledger(open_store): ] } ) - askar_profile = AskarProfile( + askar_profile = await AskarProfile.create( open_store, context=context, ) @@ -67,7 +68,7 @@ async def test_remove_success(open_store): "wallet.askar_profile": profile_id, "ledger.genesis_transactions": mock.MagicMock(), } - askar_profile = AskarProfile(openStore, context, profile_id=profile_id) + askar_profile = await AskarProfile.create(openStore, context, profile_id=profile_id) remove_profile_stub = asyncio.Future() remove_profile_stub.set_result(True) openStore.store.remove_profile.return_value = remove_profile_stub @@ -82,7 +83,7 @@ async def test_remove_profile_not_removed_if_wallet_type_not_askar_profile(open_ openStore = open_store context = InjectionContext() context.settings = {"multitenant.wallet_type": "basic"} - askar_profile = AskarProfile(openStore, context) + askar_profile = await AskarProfile.create(openStore, context) await askar_profile.remove() @@ -94,7 +95,7 @@ async def test_profile_manager_transaction(): profile = "profileId" with mock.patch("acapy_agent.askar.profile.AskarProfile") as AskarProfile: - askar_profile = AskarProfile(None, True, profile_id=profile) + askar_profile = await AskarProfile.create(None, True, profile_id=profile) askar_profile.profile_id = profile askar_profile_transaction = mock.MagicMock() askar_profile.store.transaction.return_value = askar_profile_transaction @@ -107,15 +108,17 @@ async def test_profile_manager_transaction(): @pytest.mark.asyncio async def test_profile_manager_store(): - profile = "profileId" - - with mock.patch("acapy_agent.askar.profile.AskarProfile") as AskarProfile: - askar_profile = AskarProfile(None, False, profile_id=profile) - askar_profile.profile_id = profile - askar_profile_session = mock.MagicMock() - askar_profile.store.session.return_value = askar_profile_session - - sessionProfile = test_module.AskarProfileSession(askar_profile, False) - - assert sessionProfile._opener == askar_profile_session - askar_profile.store.session.assert_called_once_with(profile) + config = { + "test": True, + } + context = InjectionContext( + settings=config, + ) + await AskarProfileManager().provision( + context=context, + config=config, + ) + await AskarAnonProfileManager().provision( + context=context, + config=config, + ) diff --git a/acapy_agent/commands/provision.py b/acapy_agent/commands/provision.py index 962b38dc8e..f0fb7cf561 100644 --- a/acapy_agent/commands/provision.py +++ b/acapy_agent/commands/provision.py @@ -1,6 +1,7 @@ """Provision command for setting up agent settings before starting.""" import asyncio +import logging from typing import Sequence from configargparse import ArgumentParser @@ -22,6 +23,8 @@ from ..storage.base import BaseStorage from . import PROG +LOGGER = logging.getLogger(__name__) + class ProvisionError(BaseError): """Base exception for provisioning errors.""" @@ -58,9 +61,9 @@ async def provision(settings: dict): ) if await ledger_config(root_profile, public_did and public_did.did, True): - print("Ledger configured") + LOGGER.info("Ledger configured") else: - print("Ledger not configured") + LOGGER.warning("Ledger not configured") await root_profile.close() except BaseError as e: diff --git a/acapy_agent/commands/start.py b/acapy_agent/commands/start.py index f30fc5c582..fb8652314c 100644 --- a/acapy_agent/commands/start.py +++ b/acapy_agent/commands/start.py @@ -31,7 +31,7 @@ async def start_app(conductor: Conductor): async def shutdown_app(conductor: Conductor): """Shut down.""" - print("\nShutting down") + LOGGER.info("Shutting down") await conductor.stop() @@ -59,7 +59,7 @@ def execute(argv: Sequence[str] = None): # Run the application if uvloop: uvloop.install() - print("uvloop installed") + LOGGER.info("uvloop installed") run_loop(start_app(conductor), shutdown_app(conductor)) diff --git a/acapy_agent/commands/tests/test_help.py b/acapy_agent/commands/tests/test_help.py index 562b371ee2..1e1360328f 100644 --- a/acapy_agent/commands/tests/test_help.py +++ b/acapy_agent/commands/tests/test_help.py @@ -5,11 +5,10 @@ class TestHelp(IsolatedAsyncioTestCase): def test_exec_help(self): - with mock.patch.object( - command.ArgumentParser, "print_help" - ) as mock_print_help, mock.patch( - "builtins.print", mock.MagicMock() - ) as mock_print: + with ( + mock.patch.object(command.ArgumentParser, "print_help") as mock_print_help, + mock.patch("builtins.print", mock.MagicMock()) as mock_print, + ): command.execute([]) mock_print_help.assert_called_once() @@ -17,10 +16,9 @@ def test_exec_help(self): mock_print.assert_called_once_with(command.__version__) def test_main(self): - with mock.patch.object( - command, "__name__", "__main__" - ) as mock_name, mock.patch.object( - command, "execute", mock.MagicMock() - ) as mock_execute: + with ( + mock.patch.object(command, "__name__", "__main__") as mock_name, + mock.patch.object(command, "execute", mock.MagicMock()) as mock_execute, + ): command.main() mock_execute.assert_called_once diff --git a/acapy_agent/commands/tests/test_provision.py b/acapy_agent/commands/tests/test_provision.py index 65d0d488bd..ed50bb9eb8 100644 --- a/acapy_agent/commands/tests/test_provision.py +++ b/acapy_agent/commands/tests/test_provision.py @@ -21,17 +21,20 @@ def test_bad_calls(self): async def test_provision_ledger_configured(self): profile = mock.MagicMock(close=mock.CoroutineMock()) - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), + ), + mock.patch.object( + test_module, "ledger_config", mock.CoroutineMock(return_value=True) ), - ), mock.patch.object( - test_module, "ledger_config", mock.CoroutineMock(return_value=True) ): await test_module.provision({}) @@ -44,9 +47,10 @@ async def test_provision_config_x(self): await test_module.provision({}) def test_main(self): - with mock.patch.object(test_module, "__name__", "__main__"), mock.patch.object( - test_module, "execute", mock.MagicMock() - ) as mock_execute: + with ( + mock.patch.object(test_module, "__name__", "__main__"), + mock.patch.object(test_module, "execute", mock.MagicMock()) as mock_execute, + ): test_module.main() mock_execute.assert_called_once @@ -55,12 +59,13 @@ async def test_provision_should_store_provided_mediation_invite(self): mediation_invite = "test-invite" test_profile = await create_test_profile() - with mock.patch.object( - test_module.MediationInviteStore, "store" - ) as invite_store, mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock(return_value=(test_profile, mock.MagicMock())), + with ( + mock.patch.object(test_module.MediationInviteStore, "store") as invite_store, + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock(return_value=(test_profile, mock.MagicMock())), + ), ): # when await test_module.provision({"mediation.invite": mediation_invite}) diff --git a/acapy_agent/commands/tests/test_start.py b/acapy_agent/commands/tests/test_start.py index 451ab584bb..4c9fe32bcb 100644 --- a/acapy_agent/commands/tests/test_start.py +++ b/acapy_agent/commands/tests/test_start.py @@ -25,22 +25,23 @@ async def test_start_shutdown_app(self): await test_module.shutdown_app(mock_conductor) def test_exec_start(self): - with mock.patch.object( - # Normally this would be a CoroutineMock. However, it is awaited by - # run_loop, which is mocked out. So we mock it as a MagicMock. - test_module, - "start_app", - mock.MagicMock(), - ) as start_app, mock.patch.object( - test_module, "run_loop" - ) as run_loop, mock.patch.object( - # Same here as note above - test_module, - "shutdown_app", - mock.MagicMock(), - ) as shutdown_app, mock.patch.object( - test_module, "uvloop", mock.MagicMock() - ) as mock_uvloop: + with ( + mock.patch.object( + # Normally this would be a CoroutineMock. However, it is awaited by + # run_loop, which is mocked out. So we mock it as a MagicMock. + test_module, + "start_app", + mock.MagicMock(), + ) as start_app, + mock.patch.object(test_module, "run_loop") as run_loop, + mock.patch.object( + # Same here as note above + test_module, + "shutdown_app", + mock.MagicMock(), + ) as shutdown_app, + mock.patch.object(test_module, "uvloop", mock.MagicMock()) as mock_uvloop, + ): mock_uvloop.install = mock.MagicMock() test_module.execute( [ @@ -54,6 +55,7 @@ def test_exec_start(self): "0.0.0.0", "80", "--no-ledger", + "--wallet-test", ] ) start_app.assert_called_once() @@ -102,11 +104,10 @@ async def test_run_loop_init_x(self): startup_call = startup() shutdown = mock.CoroutineMock() shutdown_call = shutdown() - with mock.patch.object( - test_module, "asyncio", autospec=True - ) as mock_asyncio, mock.patch.object( - test_module, "LOGGER", autospec=True - ) as mock_logger: + with ( + mock.patch.object(test_module, "asyncio", autospec=True) as mock_asyncio, + mock.patch.object(test_module, "LOGGER", autospec=True) as mock_logger, + ): test_module.run_loop(startup_call, shutdown_call) mock_add = mock_asyncio.get_event_loop.return_value.add_signal_handler mock_add.assert_called_once() @@ -135,10 +136,9 @@ async def test_run_loop_init_x(self): mock_logger.exception.assert_called_once() def test_main(self): - with mock.patch.object( - test_module, "__name__", "__main__" - ) as mock_name, mock.patch.object( - test_module, "execute", mock.MagicMock() - ) as mock_execute: + with ( + mock.patch.object(test_module, "__name__", "__main__") as mock_name, + mock.patch.object(test_module, "execute", mock.MagicMock()) as mock_execute, + ): test_module.main() mock_execute.assert_called_once diff --git a/acapy_agent/commands/tests/test_upgrade.py b/acapy_agent/commands/tests/test_upgrade.py index 51a33640a3..8d24bbc723 100644 --- a/acapy_agent/commands/tests/test_upgrade.py +++ b/acapy_agent/commands/tests/test_upgrade.py @@ -47,20 +47,24 @@ def test_bad_calls(self): test_module.execute(["bad"]) async def test_upgrade_storage_from_version_included(self): - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), + ), + mock.patch.object( + ConnRecord, + "query", + mock.CoroutineMock(return_value=[ConnRecord()]), ), - ), mock.patch.object( - ConnRecord, - "query", - mock.CoroutineMock(return_value=[ConnRecord()]), - ), mock.patch.object(ConnRecord, "save", mock.CoroutineMock()): + mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), + ): await test_module.upgrade( settings={ "upgrade.config_path": "./acapy_agent/commands/default_version_upgrade_config.yml", @@ -69,20 +73,24 @@ async def test_upgrade_storage_from_version_included(self): ) async def test_upgrade_storage_missing_from_version(self): - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), + ), + mock.patch.object( + ConnRecord, + "query", + mock.CoroutineMock(return_value=[ConnRecord()]), ), - ), mock.patch.object( - ConnRecord, - "query", - mock.CoroutineMock(return_value=[ConnRecord()]), - ), mock.patch.object(ConnRecord, "save", mock.CoroutineMock()): + mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), + ): await test_module.upgrade(settings={}) async def test_upgrade_from_version(self): @@ -91,11 +99,14 @@ async def test_upgrade_from_version(self): "upgrade.from_version": "v0.7.2", } ) - with mock.patch.object( - ConnRecord, - "query", - mock.CoroutineMock(return_value=[ConnRecord()]), - ), mock.patch.object(ConnRecord, "save", mock.CoroutineMock()): + with ( + mock.patch.object( + ConnRecord, + "query", + mock.CoroutineMock(return_value=[ConnRecord()]), + ), + mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), + ): await test_module.upgrade( profile=self.profile, ) @@ -109,11 +120,14 @@ async def test_upgrade_all_subwallets(self): "upgrade.page_size": 1, } ) - with mock.patch.object( - ConnRecord, - "query", - mock.CoroutineMock(return_value=[ConnRecord()]), - ), mock.patch.object(ConnRecord, "save", mock.CoroutineMock()): + with ( + mock.patch.object( + ConnRecord, + "query", + mock.CoroutineMock(return_value=[ConnRecord()]), + ), + mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), + ): await test_module.upgrade( profile=self.profile, ) @@ -131,11 +145,14 @@ async def test_upgrade_specified_subwallets(self): "upgrade.force_upgrade": True, } ) - with mock.patch.object( - ConnRecord, - "query", - mock.CoroutineMock(return_value=[ConnRecord()]), - ), mock.patch.object(ConnRecord, "save", mock.CoroutineMock()): + with ( + mock.patch.object( + ConnRecord, + "query", + mock.CoroutineMock(return_value=[ConnRecord()]), + ), + mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), + ): await test_module.upgrade( profile=self.profile, ) @@ -148,11 +165,14 @@ async def test_upgrade_specified_subwallets(self): "upgrade.page_size": 1, } ) - with mock.patch.object( - ConnRecord, - "query", - mock.CoroutineMock(return_value=[ConnRecord()]), - ), mock.patch.object(ConnRecord, "save", mock.CoroutineMock()): + with ( + mock.patch.object( + ConnRecord, + "query", + mock.CoroutineMock(return_value=[ConnRecord()]), + ), + mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), + ): await test_module.upgrade( profile=self.profile, ) @@ -164,29 +184,32 @@ async def test_upgrade_callable(self): type_filter="acapy_version", tag_query={} ) await storage.delete_record(version_storage_record) - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), ), - ), mock.patch.object( - test_module.yaml, - "safe_load", - mock.MagicMock( - return_value={ - "v0.7.2": { - "resave_records": { - "base_record_path": [ - "acapy_agent.connections.models.conn_record.ConnRecord" - ] + mock.patch.object( + test_module.yaml, + "safe_load", + mock.MagicMock( + return_value={ + "v0.7.2": { + "resave_records": { + "base_record_path": [ + "acapy_agent.connections.models.conn_record.ConnRecord" + ] + }, + "update_existing_records": True, }, - "update_existing_records": True, - }, - } + } + ), ), ): await test_module.upgrade( @@ -202,30 +225,33 @@ async def test_upgrade_callable_named_tag(self): type_filter="acapy_version", tag_query={} ) await storage.delete_record(version_storage_record) - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), ), - ), mock.patch.object( - test_module.yaml, - "safe_load", - mock.MagicMock( - return_value={ - "v0.7.2": { - "resave_records": { - "base_record_path": [ - "acapy_agent.connections.models.conn_record.ConnRecord" - ] + mock.patch.object( + test_module.yaml, + "safe_load", + mock.MagicMock( + return_value={ + "v0.7.2": { + "resave_records": { + "base_record_path": [ + "acapy_agent.connections.models.conn_record.ConnRecord" + ] + }, + "update_existing_records": True, }, - "update_existing_records": True, - }, - "fix_issue_rev_reg": {"fix_issue_rev_reg_records": True}, - } + "fix_issue_rev_reg": {"fix_issue_rev_reg_records": True}, + } + ), ), ): await test_module.upgrade( @@ -265,20 +291,24 @@ async def test_upgrade_missing_from_version(self): type_filter="acapy_version", tag_query={} ) await storage.delete_record(version_storage_record) - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), + ), + mock.patch.object( + ConnRecord, + "query", + mock.CoroutineMock(return_value=[ConnRecord()]), ), - ), mock.patch.object( - ConnRecord, - "query", - mock.CoroutineMock(return_value=[ConnRecord()]), - ), mock.patch.object(ConnRecord, "save", mock.CoroutineMock()): + mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), + ): with self.assertRaises(UpgradeError) as ctx: await test_module.upgrade( settings={ @@ -296,30 +326,33 @@ async def test_upgrade_x_callable_not_set(self): type_filter="acapy_version", tag_query={} ) await storage.delete_record(version_storage_record) - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), ), - ), mock.patch.object( - test_module.yaml, - "safe_load", - mock.MagicMock( - return_value={ - "v0.7.2": { - "resave_records": { - "base_record_path": [ - "acapy_agent.connections.models.conn_record.ConnRecord" - ] + mock.patch.object( + test_module.yaml, + "safe_load", + mock.MagicMock( + return_value={ + "v0.7.2": { + "resave_records": { + "base_record_path": [ + "acapy_agent.connections.models.conn_record.ConnRecord" + ] + }, + "update_existing_records": True, }, - "update_existing_records": True, - }, - "v0.6.0": {"update_existing_records_b": True}, - } + "v0.6.0": {"update_existing_records_b": True}, + } + ), ), ): with self.assertRaises(UpgradeError) as ctx: @@ -331,28 +364,31 @@ async def test_upgrade_x_callable_not_set(self): assert "No function specified for" in str(ctx.exception) async def test_upgrade_x_class_not_found(self): - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), ), - ), mock.patch.object( - test_module.yaml, - "safe_load", - mock.MagicMock( - return_value={ - "v0.7.2": { - "resave_records": { - "base_record_path": [ - "acapy_agent.connections.models.conn_record.Invalid" - ], - } - }, - } + mock.patch.object( + test_module.yaml, + "safe_load", + mock.MagicMock( + return_value={ + "v0.7.2": { + "resave_records": { + "base_record_path": [ + "acapy_agent.connections.models.conn_record.Invalid" + ], + } + }, + } + ), ), ): with self.assertRaises(UpgradeError) as ctx: @@ -364,28 +400,34 @@ async def test_upgrade_x_class_not_found(self): assert "Unknown Record type" in str(ctx.exception) async def test_execute(self): - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), + ), + mock.patch.object( + ConnRecord, + "query", + mock.CoroutineMock(return_value=[ConnRecord()]), + ), + mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), + mock.patch.object( + asyncio, "get_event_loop", mock.MagicMock() + ) as mock_get_event_loop, + mock.patch.object( + # Normally, this would be a CoroutingMock. However, the coroutine + # is awaited by run_until_complete, which is mocked out. + # Use MagicMock to prevent unawaited coroutine warnings. + test_module, + "upgrade", + mock.MagicMock(), ), - ), mock.patch.object( - ConnRecord, - "query", - mock.CoroutineMock(return_value=[ConnRecord()]), - ), mock.patch.object(ConnRecord, "save", mock.CoroutineMock()), mock.patch.object( - asyncio, "get_event_loop", mock.MagicMock() - ) as mock_get_event_loop, mock.patch.object( - # Normally, this would be a CoroutingMock. However, the coroutine - # is awaited by run_until_complete, which is mocked out. - # Use MagicMock to prevent unawaited coroutine warnings. - test_module, - "upgrade", - mock.MagicMock(), ): mock_get_event_loop.return_value = mock.MagicMock( run_until_complete=mock.MagicMock(), @@ -397,32 +439,36 @@ async def test_execute(self): "--from-version", "v0.7.0", "--force-upgrade", + "--wallet-test", ] ) async def test_upgrade_x_invalid_record_type(self): - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), ), - ), mock.patch.object( - test_module.yaml, - "safe_load", - mock.MagicMock( - return_value={ - "v0.7.2": { - "resave_records": { - "base_exch_record_path": [ - "acapy_agent.connections.models.connection_target.ConnectionTarget" - ], + mock.patch.object( + test_module.yaml, + "safe_load", + mock.MagicMock( + return_value={ + "v0.7.2": { + "resave_records": { + "base_exch_record_path": [ + "acapy_agent.connections.models.connection_target.ConnectionTarget" + ], + } } } - } + ), ), ): with self.assertRaises(UpgradeError) as ctx: @@ -434,35 +480,38 @@ async def test_upgrade_x_invalid_record_type(self): assert "Only BaseRecord can be resaved" in str(ctx.exception) async def test_upgrade_force(self): - with mock.patch.object( - test_module, - "wallet_config", - mock.CoroutineMock( - return_value=( - self.profile, - mock.CoroutineMock(did="public DID", verkey="verkey"), - ) + with ( + mock.patch.object( + test_module, + "wallet_config", + mock.CoroutineMock( + return_value=( + self.profile, + mock.CoroutineMock(did="public DID", verkey="verkey"), + ) + ), ), - ), mock.patch.object( - test_module.yaml, - "safe_load", - mock.MagicMock( - return_value={ - "v0.7.2": { - "resave_records": { - "base_record_path": [ - "acapy_agent.connections.models.conn_record.ConnRecord" - ], + mock.patch.object( + test_module.yaml, + "safe_load", + mock.MagicMock( + return_value={ + "v0.7.2": { + "resave_records": { + "base_record_path": [ + "acapy_agent.connections.models.conn_record.ConnRecord" + ], + }, + "update_existing_records": True, }, - "update_existing_records": True, - }, - "v0.7.3": { - "update_existing_records": True, - }, - "v0.7.1": { - "update_existing_records": False, - }, - } + "v0.7.3": { + "update_existing_records": True, + }, + "v0.7.1": { + "update_existing_records": False, + }, + } + ), ), ): await test_module.upgrade( @@ -511,9 +560,10 @@ async def test_upgrade_x_params(self): assert "upgrade requires either profile or settings" in str(ctx.exception) def test_main(self): - with mock.patch.object(test_module, "__name__", "__main__"), mock.patch.object( - test_module, "execute", mock.MagicMock() - ) as mock_execute: + with ( + mock.patch.object(test_module, "__name__", "__main__"), + mock.patch.object(test_module, "execute", mock.MagicMock()) as mock_execute, + ): test_module.main() mock_execute.assert_called_once @@ -711,30 +761,31 @@ async def test_upgrade_explicit_check(self): await test_module.upgrade(profile=self.profile) assert "Explicit upgrade flag with critical value found" in str(ctx.exception) - with mock.patch.object( - test_module, "LOGGER", mock.MagicMock() - ) as mock_logger, mock.patch.object( - test_module.yaml, - "safe_load", - mock.MagicMock( - return_value={ - "v0.7.2": { - "resave_records": { - "base_record_path": [ - "acapy_agent.connections.models.conn_record.ConnRecord" - ], + with ( + mock.patch.object(test_module, "LOGGER", mock.MagicMock()) as mock_logger, + mock.patch.object( + test_module.yaml, + "safe_load", + mock.MagicMock( + return_value={ + "v0.7.2": { + "resave_records": { + "base_record_path": [ + "acapy_agent.connections.models.conn_record.ConnRecord" + ], + }, + "update_existing_records": True, }, - "update_existing_records": True, - }, - "v0.7.3": { - "update_existing_records": True, - "explicit_upgrade": "warning", - }, - "v0.7.1": { - "update_existing_records": True, - "explicit_upgrade": "warning", - }, - } + "v0.7.3": { + "update_existing_records": True, + "explicit_upgrade": "warning", + }, + "v0.7.1": { + "update_existing_records": True, + "explicit_upgrade": "warning", + }, + } + ), ), ): await test_module.upgrade(profile=self.profile) diff --git a/acapy_agent/config/argparse.py b/acapy_agent/config/argparse.py index 0d231f2307..4af52ca619 100644 --- a/acapy_agent/config/argparse.py +++ b/acapy_agent/config/argparse.py @@ -63,7 +63,7 @@ def get_registered(cls, category: Optional[str] = None): def create_argument_parser(*, prog: Optional[str] = None): - """Create am instance of an arg parser, force yaml format for external config.""" + """Create an instance of an arg parser, force yaml format for external config.""" return ArgumentParser(config_file_parser_class=YAMLConfigFileParser, prog=prog) @@ -1618,13 +1618,13 @@ def add_arguments(self, parser: ArgumentParser): "--wallet-type", type=str, metavar="", - default="basic", + default="askar", env_var="ACAPY_WALLET_TYPE", help=( "Specifies the type of wallet provider to use. " - "Supported internal storage types are 'basic' (memory), 'askar' " + "Supported internal storage types are 'askar' " "and 'askar-anoncreds'." - "The default (if not specified) is 'basic'." + "The default (if not specified) is 'askar'." ), ) parser.add_argument( @@ -1635,11 +1635,23 @@ def add_arguments(self, parser: ArgumentParser): env_var="ACAPY_WALLET_STORAGE_TYPE", help=( "Specifies the type of wallet backend to use. " - "Supported internal storage types are 'basic' (memory), " - "'default' (sqlite), and 'postgres_storage'. The default, " + "Supported internal storage types are 'default' (sqlite), " + "and 'postgres_storage'. The default, " "if not specified, is 'default'." ), ) + parser.add_argument( + "--wallet-test", + action="store_true", + default=False, + env_var="ACAPY_WALLET_TEST", + help=( + "Using this option will create a wallet with an in-memory askar wallet " + "storage with a random name. This is useful for testing purposes. " + "The data will not be persisted after the agent is stopped. The default " + "is False. " + ), + ) parser.add_argument( "--wallet-storage-config", type=str, @@ -1722,6 +1734,8 @@ def get_settings(self, args: Namespace) -> dict: settings["wallet.storage_type"] = args.wallet_storage_type if args.wallet_type: settings["wallet.type"] = args.wallet_type + if args.wallet_test: + settings["wallet.test"] = True if args.wallet_key_derivation_method: settings["wallet.key_derivation_method"] = args.wallet_key_derivation_method if args.wallet_rekey_derivation_method: @@ -1739,7 +1753,7 @@ def get_settings(self, args: Namespace) -> dict: # check required settings for persistent wallets if settings["wallet.type"] in ["askar", "askar-anoncreds"]: # requires name, key - if not args.wallet_name or not args.wallet_key: + if not args.wallet_test and (not args.wallet_name or not args.wallet_key): raise ArgsParseError( "Parameters --wallet-name and --wallet-key must be provided " "for persistent wallets" diff --git a/acapy_agent/config/default_context.py b/acapy_agent/config/default_context.py index 136c79791d..8f28b0eaee 100644 --- a/acapy_agent/config/default_context.py +++ b/acapy_agent/config/default_context.py @@ -1,5 +1,7 @@ """Classes for configuring the default injection context.""" +import logging + from ..anoncreds.registry import AnonCredsRegistry from ..cache.base import BaseCache from ..cache.in_memory import InMemoryCache @@ -26,17 +28,22 @@ from .injection_context import InjectionContext from .provider import CachedProvider, ClassProvider +LOGGER = logging.getLogger(__name__) + class DefaultContextBuilder(ContextBuilder): """Default context builder.""" async def build_context(self) -> InjectionContext: """Build the base injection context; set DIDComm prefix to emit.""" + LOGGER.debug("Building new injection context") + context = InjectionContext(settings=self.settings) context.settings.set_default("default_label", "Aries Cloud Agent") if context.settings.get("timing.enabled"): timing_log = context.settings.get("timing.log_file") + LOGGER.debug("Enabling timing collector with log file: %s", timing_log) collector = Collector(log_path=timing_log) context.injector.bind_instance(Collector, collector) @@ -63,11 +70,8 @@ async def build_context(self) -> InjectionContext: # DIDComm Messaging if context.settings.get("experiment.didcomm_v2"): - from didcomm_messaging import ( - CryptoService, - PackagingService, - RoutingService, - ) + LOGGER.info("DIDComm v2 experimental mode enabled") + from didcomm_messaging import CryptoService, PackagingService, RoutingService from didcomm_messaging.crypto.backend.askar import AskarCryptoService context.injector.bind_instance(CryptoService, AskarCryptoService()) @@ -81,11 +85,13 @@ async def build_context(self) -> InjectionContext: async def bind_providers(self, context: InjectionContext): """Bind various class providers.""" + LOGGER.debug("Begin binding providers to context") context.injector.bind_provider(ProfileManager, ProfileManagerProvider()) wallet_type = self.settings.get("wallet.type") if wallet_type == "askar-anoncreds": + LOGGER.debug("Using AnonCreds tails server") context.injector.bind_provider( BaseTailsServer, ClassProvider( @@ -93,6 +99,7 @@ async def bind_providers(self, context: InjectionContext): ), ) else: + LOGGER.debug("Using Indy tails server") context.injector.bind_provider( BaseTailsServer, ClassProvider( @@ -104,12 +111,7 @@ async def bind_providers(self, context: InjectionContext): context.injector.bind_provider( BaseWireFormat, CachedProvider( - # StatsProvider( ClassProvider("acapy_agent.transport.pack_format.PackWireFormat"), - # ( - # "encode_message", "parse_message" - # ), - # ) ), ) @@ -120,6 +122,7 @@ async def bind_providers(self, context: InjectionContext): async def load_plugins(self, context: InjectionContext): """Set up plugin registry and load plugins.""" + LOGGER.debug("Initializing plugin registry") plugin_registry = PluginRegistry( blocklist=self.settings.get("blocked_plugins", []) ) @@ -130,18 +133,18 @@ async def load_plugins(self, context: InjectionContext): if not self.settings.get("transport.disabled"): plugin_registry.register_package("acapy_agent.protocols") - # Currently providing admin routes only - plugin_registry.register_plugin("acapy_agent.holder") - - plugin_registry.register_plugin("acapy_agent.ledger") - - plugin_registry.register_plugin("acapy_agent.messaging.jsonld") - plugin_registry.register_plugin("acapy_agent.resolver") - plugin_registry.register_plugin("acapy_agent.settings") - plugin_registry.register_plugin("acapy_agent.vc") - plugin_registry.register_plugin("acapy_agent.vc.data_integrity") - plugin_registry.register_plugin("acapy_agent.wallet") - plugin_registry.register_plugin("acapy_agent.wallet.keys") + # Define plugin groups + default_plugins = [ + "acapy_agent.holder", + "acapy_agent.ledger", + "acapy_agent.messaging.jsonld", + "acapy_agent.resolver", + "acapy_agent.settings", + "acapy_agent.vc", + "acapy_agent.vc.data_integrity", + "acapy_agent.wallet", + "acapy_agent.wallet.keys", + ] anoncreds_plugins = [ "acapy_agent.anoncreds", @@ -157,26 +160,34 @@ async def load_plugins(self, context: InjectionContext): "acapy_agent.revocation", ] - def register_askar_plugins(): - for plugin in askar_plugins: + def register_plugins(plugins: list[str], plugin_type: str): + """Register a group of plugins with logging.""" + LOGGER.debug("Registering %s plugins", plugin_type) + for plugin in plugins: plugin_registry.register_plugin(plugin) + def register_askar_plugins(): + register_plugins(askar_plugins, "askar") + def register_anoncreds_plugins(): - for plugin in anoncreds_plugins: - plugin_registry.register_plugin(plugin) + register_plugins(anoncreds_plugins, "anoncreds") - if wallet_type == "askar-anoncreds": - register_anoncreds_plugins() - else: - register_askar_plugins() + register_plugins(default_plugins, "default") if context.settings.get("multitenant.admin_enabled"): + LOGGER.debug("Multitenant admin enabled - registering additional plugins") plugin_registry.register_plugin("acapy_agent.multitenant.admin") register_askar_plugins() register_anoncreds_plugins() + else: + if wallet_type == "askar-anoncreds": + register_anoncreds_plugins() + else: + register_askar_plugins() # Register external plugins for plugin_path in self.settings.get("external_plugins", []): + LOGGER.debug("Registering external plugin: %s", plugin_path) plugin_registry.register_plugin(plugin_path) # Register message protocols diff --git a/acapy_agent/config/ledger.py b/acapy_agent/config/ledger.py index 7d7acb1e7e..ab335913b9 100644 --- a/acapy_agent/config/ledger.py +++ b/acapy_agent/config/ledger.py @@ -34,14 +34,18 @@ async def fetch_genesis_transactions(genesis_url: str) -> str: # https://github.com/openwallet-foundation/acapy/issues/1745 return await fetch(genesis_url, headers=headers, max_attempts=20) except FetchError as e: + LOGGER.error("Error retrieving genesis transactions from %s: %s", genesis_url, e) raise ConfigError("Error retrieving ledger genesis transactions") from e async def get_genesis_transactions(settings: Settings) -> str: """Fetch genesis transactions if necessary.""" + LOGGER.debug("Getting genesis transactions from settings") txns = settings.get("ledger.genesis_transactions") + LOGGER.debug("Genesis transactions from settings: %s", "found" if txns else "absent") if not txns: + LOGGER.debug("No genesis transactions found in settings") if settings.get("ledger.genesis_url"): txns = await fetch_genesis_transactions(settings["ledger.genesis_url"]) elif settings.get("ledger.genesis_file"): @@ -51,8 +55,10 @@ async def get_genesis_transactions(settings: Settings) -> str: with open(genesis_path, "r") as genesis_file: txns = genesis_file.read() except IOError as e: + LOGGER.error("Failed to read genesis file: %s", str(e)) raise ConfigError("Error reading ledger genesis transactions") from e if txns: + LOGGER.debug("Storing genesis transactions in settings") settings["ledger.genesis_transactions"] = txns return txns @@ -63,6 +69,8 @@ async def load_multiple_genesis_transactions_from_config(settings: Settings): ledger_config_list = settings.get("ledger.ledger_config_list") ledger_txns_list = [] write_ledger_set = False + LOGGER.debug("Processing %d ledger configs", len(ledger_config_list)) + for config in ledger_config_list: txns = None if "genesis_transactions" in config: @@ -74,11 +82,12 @@ async def load_multiple_genesis_transactions_from_config(settings: Settings): try: genesis_path = config.get("genesis_file") LOGGER.info( - "Reading ledger genesis transactions from: %s", genesis_path + "Reading ledger genesis transactions from file: %s", genesis_path ) with open(genesis_path, "r") as genesis_file: txns = genesis_file.read() except IOError as e: + LOGGER.error("Failed to read genesis file: %s", str(e)) raise ConfigError("Error reading ledger genesis transactions") from e is_write_ledger = ( False if config.get("is_write") is None else config.get("is_write") @@ -119,6 +128,7 @@ async def load_multiple_genesis_transactions_from_config(settings: Settings): " genesis_file and genesis_transactions provided." ) settings["ledger.ledger_config_list"] = ledger_txns_list + LOGGER.debug("Processed %d ledger configs successfully", len(ledger_txns_list)) async def ledger_config( @@ -126,6 +136,10 @@ async def ledger_config( ) -> bool: """Perform Indy ledger configuration.""" + LOGGER.debug( + "Configuring ledger for profile %s and public_did %s", profile.name, public_did + ) + session = await profile.session() ledger = session.inject_or(BaseLedger) @@ -136,32 +150,46 @@ async def ledger_config( async with ledger: # Check transaction author agreement acceptance if not ledger.read_only: + LOGGER.debug("Checking transaction author agreement") taa_info = await ledger.get_txn_author_agreement() if taa_info["taa_required"] and public_did: + LOGGER.debug("TAA acceptance required") taa_accepted = await ledger.get_latest_txn_author_acceptance() if ( not taa_accepted or taa_info["taa_record"]["digest"] != taa_accepted["digest"] ): + LOGGER.info("TAA acceptance needed - performing acceptance") if not await accept_taa(ledger, profile, taa_info, provision): + LOGGER.warning("TAA acceptance failed") return False + LOGGER.info("TAA acceptance completed") # Publish endpoints if necessary - skipped if TAA is required but not accepted endpoint = session.settings.get("default_endpoint") if public_did: wallet = session.inject(BaseWallet) try: + LOGGER.debug("Setting DID endpoint to: %s", endpoint) await wallet.set_did_endpoint(public_did, endpoint, ledger) except LedgerError as x_ledger: + LOGGER.error("Error setting DID endpoint: %s", x_ledger.message) raise ConfigError(x_ledger.message) from x_ledger # e.g., read-only # Publish profile endpoint if ledger is NOT read-only profile_endpoint = session.settings.get("profile_endpoint") if profile_endpoint and not ledger.read_only: + LOGGER.debug( + "Publishing profile endpoint: %s for DID: %s", + profile_endpoint, + public_did, + ) await ledger.update_endpoint_for_did( public_did, profile_endpoint, EndpointType.PROFILE ) + LOGGER.info("Profile endpoint published successfully") + LOGGER.info("Ledger configuration complete") return True diff --git a/acapy_agent/config/logging/configurator.py b/acapy_agent/config/logging/configurator.py index 11763dca08..128ccf5e49 100644 --- a/acapy_agent/config/logging/configurator.py +++ b/acapy_agent/config/logging/configurator.py @@ -32,6 +32,8 @@ TimedRotatingFileMultiProcessHandler, ) +LOGGER = logging.getLogger(__name__) + def load_resource(path: str, encoding: Optional[str] = None): """Open a resource file located in a python package or the local filesystem. @@ -57,7 +59,8 @@ def load_resource(path: str, encoding: Optional[str] = None): return io.TextIOWrapper(bstream, encoding=encoding) return bstream except IOError: - pass + LOGGER.warning("Resource not found: %s", path) + return None def dictConfig(config, new_file_path=None): @@ -95,18 +98,7 @@ def fileConfig( raise RuntimeError(f"{fname} is invalid: {e}") if new_file_path and cp.has_section("handler_timed_file_handler"): - cp.set( - "handler_timed_file_handler", - "args", - str( - ( - f"{new_file_path}", - "d", - 7, - 1, - ) - ), - ) + cp.set("handler_timed_file_handler", "args", str((new_file_path, "d", 7, 1))) formatters = _create_formatters(cp) with logging._lock: diff --git a/acapy_agent/config/tests/test_argparse.py b/acapy_agent/config/tests/test_argparse.py index b80e478032..c3965de392 100644 --- a/acapy_agent/config/tests/test_argparse.py +++ b/acapy_agent/config/tests/test_argparse.py @@ -525,10 +525,7 @@ async def test_wallet_key_derivation_method_value_parsing(self): group.add_arguments(parser) result = parser.parse_args( - [ - "--wallet-key-derivation-method", - key_derivation_method, - ] + ["--wallet-key-derivation-method", key_derivation_method, "--wallet-test"] ) settings = group.get_settings(result) @@ -545,6 +542,7 @@ async def test_wallet_key_value_parsing(self): [ "--wallet-key", key_value, + "--wallet-test", ] ) diff --git a/acapy_agent/config/tests/test_ledger.py b/acapy_agent/config/tests/test_ledger.py index 5c2940305b..813e9c5d88 100644 --- a/acapy_agent/config/tests/test_ledger.py +++ b/acapy_agent/config/tests/test_ledger.py @@ -317,11 +317,14 @@ async def test_load_multiple_genesis_transactions_from_config_a(self): }, ], } - with mock.patch.object( - test_module, - "fetch_genesis_transactions", - mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), - ), mock.patch("builtins.open", mock.MagicMock()) as mock_open: + with ( + mock.patch.object( + test_module, + "fetch_genesis_transactions", + mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), + ), + mock.patch("builtins.open", mock.MagicMock()) as mock_open, + ): mock_open.return_value = mock.MagicMock( __enter__=mock.MagicMock( return_value=mock.MagicMock( @@ -412,11 +415,14 @@ async def test_load_multiple_genesis_transactions_from_config_b(self): ], "ledger.genesis_url": "http://localhost:9000/genesis", } - with mock.patch.object( - test_module, - "fetch_genesis_transactions", - mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), - ), mock.patch("builtins.open", mock.MagicMock()) as mock_open: + with ( + mock.patch.object( + test_module, + "fetch_genesis_transactions", + mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), + ), + mock.patch("builtins.open", mock.MagicMock()) as mock_open, + ): mock_open.return_value = mock.MagicMock( __enter__=mock.MagicMock( return_value=mock.MagicMock( @@ -474,11 +480,14 @@ async def test_load_multiple_genesis_transactions_config_error_a(self): }, ], } - with mock.patch.object( - test_module, - "fetch_genesis_transactions", - mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), - ), mock.patch("builtins.open", mock.MagicMock()) as mock_open: + with ( + mock.patch.object( + test_module, + "fetch_genesis_transactions", + mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), + ), + mock.patch("builtins.open", mock.MagicMock()) as mock_open, + ): mock_open.return_value = mock.MagicMock( __enter__=mock.MagicMock( return_value=mock.MagicMock( @@ -537,11 +546,14 @@ async def test_load_multiple_genesis_transactions_multiple_write(self): }, ] } - with mock.patch.object( - test_module, - "fetch_genesis_transactions", - mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), - ), mock.patch("builtins.open", mock.MagicMock()) as mock_open: + with ( + mock.patch.object( + test_module, + "fetch_genesis_transactions", + mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), + ), + mock.patch("builtins.open", mock.MagicMock()) as mock_open, + ): mock_open.return_value = mock.MagicMock( __enter__=mock.MagicMock( return_value=mock.MagicMock( @@ -596,11 +608,14 @@ async def test_load_multiple_genesis_transactions_from_config_io_x(self): }, ], } - with mock.patch.object( - test_module, - "fetch_genesis_transactions", - mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), - ), mock.patch("builtins.open", mock.MagicMock()) as mock_open: + with ( + mock.patch.object( + test_module, + "fetch_genesis_transactions", + mock.CoroutineMock(return_value=TEST_GENESIS_TXNS), + ), + mock.patch("builtins.open", mock.MagicMock()) as mock_open, + ): mock_open.side_effect = IOError("no read permission") with self.assertRaises(test_module.ConfigError): await test_module.load_multiple_genesis_transactions_from_config(settings) @@ -629,31 +644,38 @@ async def test_ledger_accept_taa_tty(self, mock_stdout): "aml_record": {"aml": ["wallet_agreement", "on_file"]}, } - with mock.patch.object( - test_module, "use_asyncio_event_loop", mock.MagicMock() - ), mock.patch.object( - test_module.prompt_toolkit, "prompt", mock.CoroutineMock() - ) as mock_prompt: + with ( + mock.patch.object(test_module, "use_asyncio_event_loop", mock.MagicMock()), + mock.patch.object( + test_module.prompt_toolkit, "prompt", mock.CoroutineMock() + ) as mock_prompt, + ): mock_prompt.side_effect = EOFError() assert not await test_module.accept_taa( None, self.profile, taa_info, provision=False ) - with mock.patch.object( - test_module, "use_asyncio_event_loop", mock.MagicMock() - ) as mock_use_aio_loop, mock.patch.object( - test_module.prompt_toolkit, "prompt", mock.CoroutineMock() - ) as mock_prompt: + with ( + mock.patch.object( + test_module, "use_asyncio_event_loop", mock.MagicMock() + ) as mock_use_aio_loop, + mock.patch.object( + test_module.prompt_toolkit, "prompt", mock.CoroutineMock() + ) as mock_prompt, + ): mock_prompt.return_value = "x" assert not await test_module.accept_taa( None, self.profile, taa_info, provision=False ) - with mock.patch.object( - test_module, "use_asyncio_event_loop", mock.MagicMock() - ) as mock_use_aio_loop, mock.patch.object( - test_module.prompt_toolkit, "prompt", mock.CoroutineMock() - ) as mock_prompt: + with ( + mock.patch.object( + test_module, "use_asyncio_event_loop", mock.MagicMock() + ) as mock_use_aio_loop, + mock.patch.object( + test_module.prompt_toolkit, "prompt", mock.CoroutineMock() + ) as mock_prompt, + ): mock_ledger = mock.MagicMock(accept_txn_author_agreement=mock.CoroutineMock()) mock_prompt.return_value = "" assert await test_module.accept_taa( diff --git a/acapy_agent/config/tests/test_logging.py b/acapy_agent/config/tests/test_logging.py index cf23074568..0f027b2124 100644 --- a/acapy_agent/config/tests/test_logging.py +++ b/acapy_agent/config/tests/test_logging.py @@ -126,9 +126,10 @@ def test_load_resource(self): assert result is None # Testing package resource access with encoding (text mode) - with mock.patch("importlib.resources.files") as mock_files, mock.patch( - "io.TextIOWrapper", mock.MagicMock() - ) as mock_text_io_wrapper: + with ( + mock.patch("importlib.resources.files") as mock_files, + mock.patch("io.TextIOWrapper", mock.MagicMock()) as mock_text_io_wrapper, + ): # Setup the mocks mock_resource_path = mock.MagicMock() mock_files.return_value.joinpath.return_value = mock_resource_path diff --git a/acapy_agent/config/tests/test_wallet.py b/acapy_agent/config/tests/test_wallet.py index 3fbcae8593..6f360dcf06 100644 --- a/acapy_agent/config/tests/test_wallet.py +++ b/acapy_agent/config/tests/test_wallet.py @@ -67,10 +67,13 @@ async def test_wallet_config_existing_replace(self): ) self.injector.bind_instance(BaseWallet, mock_wallet) - with mock.patch.object( - test_module, "seed_to_did", mock.MagicMock() - ) as mock_seed_to_did, mock.patch.object( - test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "seed_to_did", mock.MagicMock() + ) as mock_seed_to_did, + mock.patch.object( + test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + ), ): mock_seed_to_did.return_value = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" @@ -106,10 +109,13 @@ async def test_wallet_config_existing_open(self): self.context.injector.bind_instance(ProfileManager, MockManager(self.profile)) - with mock.patch.object( - test_module, "seed_to_did", mock.MagicMock() - ) as mock_seed_to_did, mock.patch.object( - test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "seed_to_did", mock.MagicMock() + ) as mock_seed_to_did, + mock.patch.object( + test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + ), ): mock_seed_to_did.return_value = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" @@ -135,10 +141,11 @@ async def test_wallet_config_auto_provision(self): ) self.injector.bind_instance(BaseWallet, mock_wallet) - with mock.patch.object( - MockManager, "open", mock.CoroutineMock() - ) as mock_mgr_open, mock.patch.object( - test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + with ( + mock.patch.object(MockManager, "open", mock.CoroutineMock()) as mock_mgr_open, + mock.patch.object( + test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + ), ): mock_mgr_open.side_effect = test_module.ProfileNotFoundError() @@ -180,12 +187,15 @@ async def test_wallet_config_bad_seed_x(self): ) self.injector.bind_instance(BaseWallet, mock_wallet) - with mock.patch.object( - test_module, - "seed_to_did", - mock.MagicMock(return_value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"), - ), mock.patch.object( - test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, + "seed_to_did", + mock.MagicMock(return_value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"), + ), + mock.patch.object( + test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + ), ): with self.assertRaises(test_module.ConfigError): await test_module.wallet_config(self.context, provision=True) @@ -206,10 +216,13 @@ async def test_wallet_config_seed_local(self): ) self.injector.bind_instance(BaseWallet, mock_wallet) - with mock.patch.object( - test_module, "seed_to_did", mock.MagicMock() - ) as mock_seed_to_did, mock.patch.object( - test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "seed_to_did", mock.MagicMock() + ) as mock_seed_to_did, + mock.patch.object( + test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + ), ): mock_seed_to_did.return_value = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" @@ -230,12 +243,15 @@ async def test_wallet_config_seed_public(self): ) self.injector.bind_instance(BaseWallet, mock_wallet) - with mock.patch.object( - test_module, - "seed_to_did", - mock.MagicMock(return_value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"), - ), mock.patch.object( - test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, + "seed_to_did", + mock.MagicMock(return_value="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"), + ), + mock.patch.object( + test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + ), ): await test_module.wallet_config(self.context, provision=True) @@ -249,10 +265,13 @@ async def test_wallet_config_seed_no_public_did(self): ) self.injector.bind_instance(BaseWallet, mock_wallet) - with mock.patch.object( - test_module, "seed_to_did", mock.MagicMock() - ) as mock_seed_to_did, mock.patch.object( - test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "seed_to_did", mock.MagicMock() + ) as mock_seed_to_did, + mock.patch.object( + test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + ), ): mock_seed_to_did.return_value = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" @@ -275,10 +294,13 @@ async def test_wallet_config_for_key_derivation_method(self): ) self.injector.bind_instance(BaseWallet, mock_wallet) - with mock.patch.object( - MockManager, "provision", mock.CoroutineMock() - ) as mock_mgr_provision, mock.patch.object( - test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + with ( + mock.patch.object( + MockManager, "provision", mock.CoroutineMock() + ) as mock_mgr_provision, + mock.patch.object( + test_module, "add_or_update_version_to_storage", mock.CoroutineMock() + ), ): mock_mgr_provision.return_value = self.profile diff --git a/acapy_agent/config/wallet.py b/acapy_agent/config/wallet.py index f857b07847..c0a91741e3 100644 --- a/acapy_agent/config/wallet.py +++ b/acapy_agent/config/wallet.py @@ -26,6 +26,7 @@ "storage_config", "storage_creds", "storage_type", + "test", } @@ -61,11 +62,11 @@ async def wallet_config( if provision: if profile.created: - print("Created new profile") + LOGGER.info("Created new profile") else: - print("Opened existing profile") - print("Profile backend:", profile.backend) - print("Profile name:", profile.name) + LOGGER.info("Opened existing profile") + LOGGER.info("Profile backend: %s", profile.backend) + LOGGER.info("Profile name: %s", profile.name) wallet_seed = context.settings.get("wallet.seed") wallet_local_did = context.settings.get("wallet.local_did") @@ -84,8 +85,8 @@ async def wallet_config( ) public_did = replace_did_info.did await wallet.set_public_did(public_did) - print(f"Created new public DID: {public_did}") - print(f"Verkey: {replace_did_info.verkey}") + LOGGER.info(f"Created new public DID: {public_did}") + LOGGER.info(f"Verkey: {replace_did_info.verkey}") else: # If we already have a registered public did and it doesn't match # the one derived from `wallet_seed` then we error out. @@ -107,20 +108,20 @@ async def wallet_config( ) local_did = local_did_info.did if provision: - print(f"Created new local DID: {local_did}") - print(f"Verkey: {local_did_info.verkey}") + LOGGER.info(f"Created new local DID: {local_did}") + LOGGER.info(f"Verkey: {local_did_info.verkey}") else: public_did_info = await wallet.create_public_did( method=SOV, key_type=ED25519, seed=wallet_seed ) public_did = public_did_info.did if provision: - print(f"Created new public DID: {public_did}") - print(f"Verkey: {public_did_info.verkey}") + LOGGER.info(f"Created new public DID: {public_did}") + LOGGER.info(f"Verkey: {public_did_info.verkey}") # wait until ledger config to set public DID endpoint - wallet goes first if provision and not wallet_local_did and not public_did: - print("No public DID") + LOGGER.info("No public DID") # Debug settings test_seed = context.settings.get("debug.seed") diff --git a/acapy_agent/connections/models/conn_record.py b/acapy_agent/connections/models/conn_record.py index 874d8c3d7f..e27be92c4f 100644 --- a/acapy_agent/connections/models/conn_record.py +++ b/acapy_agent/connections/models/conn_record.py @@ -11,8 +11,8 @@ from ...messaging.valid import ( GENERIC_DID_EXAMPLE, GENERIC_DID_VALIDATE, - INDY_RAW_PUBLIC_KEY_EXAMPLE, - INDY_RAW_PUBLIC_KEY_VALIDATE, + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, UUID4_EXAMPLE, ) from ...protocols.connections.v1_0.message_types import ARIES_PROTOCOL as CONN_PROTO @@ -725,10 +725,10 @@ class Meta: ) invitation_key = fields.Str( required=False, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Public key for connection", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) invitation_msg_id = fields.Str( diff --git a/acapy_agent/connections/models/connection_target.py b/acapy_agent/connections/models/connection_target.py index ad7219db0a..bc81adc42e 100644 --- a/acapy_agent/connections/models/connection_target.py +++ b/acapy_agent/connections/models/connection_target.py @@ -8,8 +8,8 @@ from ...messaging.valid import ( GENERIC_DID_EXAMPLE, GENERIC_DID_VALIDATE, - INDY_RAW_PUBLIC_KEY_EXAMPLE, - INDY_RAW_PUBLIC_KEY_VALIDATE, + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, ) @@ -75,10 +75,10 @@ class Meta: ) recipient_keys = fields.List( fields.Str( - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Recipient public key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ), required=False, @@ -86,10 +86,10 @@ class Meta: ) routing_keys = fields.List( fields.Str( - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Routing key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ), data_key="routingKeys", @@ -98,9 +98,9 @@ class Meta: ) sender_key = fields.Str( required=False, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Sender public key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) diff --git a/acapy_agent/connections/tests/test_base_manager.py b/acapy_agent/connections/tests/test_base_manager.py index 84089929ca..12aa05d8a7 100644 --- a/acapy_agent/connections/tests/test_base_manager.py +++ b/acapy_agent/connections/tests/test_base_manager.py @@ -1190,11 +1190,14 @@ async def test_resolve_inbound_connection(self): mock_conn = mock.MagicMock() mock_conn.connection_id = "dummy" - with mock.patch.object( - AskarWallet, "get_local_did_for_verkey", mock.CoroutineMock() - ) as mock_wallet_get_local_did_for_verkey, mock.patch.object( - self.manager, "find_connection", mock.CoroutineMock() - ) as mock_mgr_find_conn: + with ( + mock.patch.object( + AskarWallet, "get_local_did_for_verkey", mock.CoroutineMock() + ) as mock_wallet_get_local_did_for_verkey, + mock.patch.object( + self.manager, "find_connection", mock.CoroutineMock() + ) as mock_mgr_find_conn, + ): mock_wallet_get_local_did_for_verkey.return_value = DIDInfo( self.test_did, self.test_verkey, @@ -1216,11 +1219,14 @@ async def test_resolve_inbound_connection_injector_error(self): mock_conn = mock.MagicMock() mock_conn.connection_id = "dummy" - with mock.patch.object( - AskarWallet, "get_local_did_for_verkey", mock.CoroutineMock() - ) as mock_wallet_get_local_did_for_verkey, mock.patch.object( - self.manager, "find_connection", mock.CoroutineMock() - ) as mock_mgr_find_conn: + with ( + mock.patch.object( + AskarWallet, "get_local_did_for_verkey", mock.CoroutineMock() + ) as mock_wallet_get_local_did_for_verkey, + mock.patch.object( + self.manager, "find_connection", mock.CoroutineMock() + ) as mock_mgr_find_conn, + ): mock_wallet_get_local_did_for_verkey.side_effect = InjectionError() mock_mgr_find_conn.return_value = mock_conn @@ -1236,11 +1242,14 @@ async def test_resolve_inbound_connection_wallet_not_found_error(self): mock_conn = mock.MagicMock() mock_conn.connection_id = "dummy" - with mock.patch.object( - AskarWallet, "get_local_did_for_verkey", mock.CoroutineMock() - ) as mock_wallet_get_local_did_for_verkey, mock.patch.object( - self.manager, "find_connection", mock.CoroutineMock() - ) as mock_mgr_find_conn: + with ( + mock.patch.object( + AskarWallet, "get_local_did_for_verkey", mock.CoroutineMock() + ) as mock_wallet_get_local_did_for_verkey, + mock.patch.object( + self.manager, "find_connection", mock.CoroutineMock() + ) as mock_mgr_find_conn, + ): mock_wallet_get_local_did_for_verkey.side_effect = WalletNotFoundError() mock_mgr_find_conn.return_value = mock_conn @@ -1339,11 +1348,14 @@ async def test_get_connection_targets_retrieve_connection(self): retrieve_invitation=mock.CoroutineMock(return_value=conn_invite), ) - with mock.patch.object( - ConnectionTarget, "serialize", autospec=True - ) as mock_conn_target_ser, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id: + with ( + mock.patch.object( + ConnectionTarget, "serialize", autospec=True + ) as mock_conn_target_ser, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn mock_conn_target_ser.return_value = {"serialized": "value"} targets = await self.manager.get_connection_targets( @@ -1383,13 +1395,17 @@ async def test_get_connection_targets_from_cache(self): state=ConnRecord.State.COMPLETED.rfc160, ) - with mock.patch.object( - ConnectionTarget, "serialize", autospec=True - ) as mock_conn_target_ser, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - self.manager, "fetch_connection_targets", mock.CoroutineMock() - ) as mock_fetch_connection_targets: + with ( + mock.patch.object( + ConnectionTarget, "serialize", autospec=True + ) as mock_conn_target_ser, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object( + self.manager, "fetch_connection_targets", mock.CoroutineMock() + ) as mock_fetch_connection_targets, + ): mock_fetch_connection_targets.return_value = [ConnectionTarget()] mock_conn_rec_retrieve_by_id.return_value = mock_conn mock_conn_target_ser.return_value = {"serialized": "value"} @@ -1428,13 +1444,17 @@ async def test_get_connection_targets_no_cache(self): state=ConnRecord.State.COMPLETED.rfc160, ) - with mock.patch.object( - ConnectionTarget, "serialize", autospec=True - ) as mock_conn_target_ser, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - self.manager, "fetch_connection_targets", mock.CoroutineMock() - ) as mock_fetch_connection_targets: + with ( + mock.patch.object( + ConnectionTarget, "serialize", autospec=True + ) as mock_conn_target_ser, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object( + self.manager, "fetch_connection_targets", mock.CoroutineMock() + ) as mock_fetch_connection_targets, + ): mock_fetch_connection_targets.return_value = [ConnectionTarget()] mock_conn_rec_retrieve_by_id.return_value = mock_conn mock_conn_target_ser.return_value = {"serialized": "value"} @@ -1522,9 +1542,12 @@ async def test_create_static_connection_multitenant(self): self.multitenant_mgr.get_default_mediator.return_value = None self.route_manager.route_static = mock.CoroutineMock() - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - AskarWallet, "create_local_did", autospec=True - ) as mock_wallet_create_local_did: + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + AskarWallet, "create_local_did", autospec=True + ) as mock_wallet_create_local_did, + ): mock_wallet_create_local_did.return_value = DIDInfo( self.test_did, self.test_verkey, @@ -1552,11 +1575,15 @@ async def test_create_static_connection_multitenant_auto_disclose_features(self) ) self.multitenant_mgr.get_default_mediator.return_value = None self.route_manager.route_static = mock.CoroutineMock() - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - AskarWallet, "create_local_did", autospec=True - ) as mock_wallet_create_local_did, mock.patch.object( - V20DiscoveryMgr, "proactive_disclose_features", mock.CoroutineMock() - ) as mock_proactive_disclose_features: + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + AskarWallet, "create_local_did", autospec=True + ) as mock_wallet_create_local_did, + mock.patch.object( + V20DiscoveryMgr, "proactive_disclose_features", mock.CoroutineMock() + ) as mock_proactive_disclose_features, + ): mock_wallet_create_local_did.return_value = DIDInfo( self.test_did, self.test_verkey, @@ -1581,12 +1608,15 @@ async def test_create_static_connection_multitenant_mediator(self): default_mediator = mock.MagicMock() self.route_manager.route_static = mock.CoroutineMock() - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - AskarWallet, "create_local_did", autospec=True - ) as mock_wallet_create_local_did, mock.patch.object( - BaseConnectionManager, "create_did_document" - ) as create_did_document, mock.patch.object( - BaseConnectionManager, "store_did_document" + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + AskarWallet, "create_local_did", autospec=True + ) as mock_wallet_create_local_did, + mock.patch.object( + BaseConnectionManager, "create_did_document" + ) as create_did_document, + mock.patch.object(BaseConnectionManager, "store_did_document"), ): mock_wallet_create_local_did.return_value = DIDInfo( self.test_did, @@ -1675,11 +1705,14 @@ async def test_find_connection_retrieve_by_did(self): async def test_find_connection_retrieve_by_did_auto_disclose_features(self): self.context.update_settings({"auto_disclose_features": True}) - with mock.patch.object( - ConnRecord, "retrieve_by_did", mock.CoroutineMock() - ) as mock_conn_retrieve_by_did, mock.patch.object( - V20DiscoveryMgr, "proactive_disclose_features", mock.CoroutineMock() - ) as mock_proactive_disclose_features: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_did", mock.CoroutineMock() + ) as mock_conn_retrieve_by_did, + mock.patch.object( + V20DiscoveryMgr, "proactive_disclose_features", mock.CoroutineMock() + ) as mock_proactive_disclose_features, + ): mock_conn_retrieve_by_did.return_value = mock.MagicMock( state=ConnRecord.State.RESPONSE.rfc23, save=mock.CoroutineMock(), @@ -1695,11 +1728,14 @@ async def test_find_connection_retrieve_by_did_auto_disclose_features(self): mock_proactive_disclose_features.assert_called_once() async def test_find_connection_retrieve_by_invitation_key(self): - with mock.patch.object( - ConnRecord, "retrieve_by_did", mock.CoroutineMock() - ) as mock_conn_retrieve_by_did, mock.patch.object( - ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_invitation_msg_id: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_did", mock.CoroutineMock() + ) as mock_conn_retrieve_by_did, + mock.patch.object( + ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_invitation_msg_id, + ): mock_conn_retrieve_by_did.side_effect = StorageNotFoundError() mock_conn_retrieve_by_invitation_msg_id.return_value = mock.MagicMock( state=ConnRecord.State.RESPONSE, @@ -1714,11 +1750,14 @@ async def test_find_connection_retrieve_by_invitation_key(self): assert conn_rec async def test_find_connection_retrieve_none_by_invitation_key(self): - with mock.patch.object( - ConnRecord, "retrieve_by_did", mock.CoroutineMock() - ) as mock_conn_retrieve_by_did, mock.patch.object( - ConnRecord, "retrieve_by_invitation_key", mock.CoroutineMock() - ) as mock_conn_retrieve_by_invitation_msg_id: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_did", mock.CoroutineMock() + ) as mock_conn_retrieve_by_did, + mock.patch.object( + ConnRecord, "retrieve_by_invitation_key", mock.CoroutineMock() + ) as mock_conn_retrieve_by_invitation_msg_id, + ): mock_conn_retrieve_by_did.side_effect = StorageNotFoundError() mock_conn_retrieve_by_invitation_msg_id.return_value = None @@ -1732,13 +1771,17 @@ async def test_find_connection_retrieve_none_by_invitation_key(self): async def test_get_endpoints(self): conn_id = "dummy" - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - AskarWallet, "get_local_did", autospec=True - ) as mock_wallet_get_local_did, mock.patch.object( - self.manager, "get_connection_targets", mock.CoroutineMock() - ) as mock_get_conn_targets: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object( + AskarWallet, "get_local_did", autospec=True + ) as mock_wallet_get_local_did, + mock.patch.object( + self.manager, "get_connection_targets", mock.CoroutineMock() + ) as mock_get_conn_targets, + ): mock_retrieve.return_value = mock.MagicMock() mock_wallet_get_local_did.return_value = mock.MagicMock( metadata={"endpoint": "localhost:8020"} diff --git a/acapy_agent/core/conductor.py b/acapy_agent/core/conductor.py index feffb04074..199101b8c8 100644 --- a/acapy_agent/core/conductor.py +++ b/acapy_agent/core/conductor.py @@ -42,10 +42,7 @@ from ..messaging.responder import BaseResponder from ..multitenant.base import BaseMultitenantManager from ..multitenant.manager_provider import MultitenantManagerProvider -from ..protocols.connections.v1_0.manager import ( - ConnectionManager, - ConnectionManagerError, -) +from ..protocols.connections.v1_0.manager import ConnectionManager, ConnectionManagerError from ..protocols.connections.v1_0.messages.connection_invitation import ( ConnectionInvitation, ) @@ -80,7 +77,7 @@ from ..wallet.anoncreds_upgrade import upgrade_wallet_to_anoncreds_if_requested from ..wallet.did_info import DIDInfo from .dispatcher import Dispatcher -from .error import StartupError +from .error import ProfileError, StartupError from .oob_processor import OobMessageProcessor from .util import SHUTDOWN_EVENT_TOPIC, STARTUP_EVENT_TOPIC @@ -124,41 +121,60 @@ def context(self) -> InjectionContext: async def setup(self): """Initialize the global request context.""" + LOGGER.debug("Starting setup of the Conductor") context = await self.context_builder.build_context() + LOGGER.debug("Context built successfully") if self.force_agent_anoncreds: + LOGGER.debug( + "Force agent anoncreds is enabled. " + "Setting wallet type to 'askar-anoncreds'." + ) context.settings.set_value("wallet.type", "askar-anoncreds") # Fetch genesis transactions if necessary if context.settings.get("ledger.ledger_config_list"): + LOGGER.debug( + "Ledger config list found. Loading multiple genesis transactions" + ) await load_multiple_genesis_transactions_from_config(context.settings) if ( context.settings.get("ledger.genesis_transactions") or context.settings.get("ledger.genesis_file") or context.settings.get("ledger.genesis_url") ): + LOGGER.debug( + "Genesis transactions/configurations found. Fetching genesis transactions" + ) await get_genesis_transactions(context.settings) # Configure the root profile + LOGGER.debug("Configuring the root profile and setting up public DID") self.root_profile, self.setup_public_did = await wallet_config(context) context = self.root_profile.context + LOGGER.debug("Root profile configured successfully") # Multiledger Setup - if ( - context.settings.get("ledger.ledger_config_list") - and len(context.settings.get("ledger.ledger_config_list")) > 0 - ): + ledger_config_list = context.settings.get("ledger.ledger_config_list") + if ledger_config_list and len(ledger_config_list) > 0: + LOGGER.debug("Setting up multiledger manager") context.injector.bind_provider( BaseMultipleLedgerManager, MultiIndyLedgerManagerProvider(self.root_profile), ) - if not (context.settings.get("ledger.genesis_transactions")): + if not context.settings.get("ledger.genesis_transactions"): ledger = context.injector.inject(BaseLedger) + LOGGER.debug( + "Ledger backend: %s, Profile backend: %s", + ledger.BACKEND_NAME, + self.root_profile.BACKEND_NAME, + ) if ( self.root_profile.BACKEND_NAME == "askar" and ledger.BACKEND_NAME == "indy-vdr" ): + LOGGER.debug("Binding IndyCredxVerifier for 'askar' backend.") context.injector.bind_provider( IndyVerifier, ClassProvider( @@ -170,6 +186,9 @@ async def setup(self): self.root_profile.BACKEND_NAME == "askar-anoncreds" and ledger.BACKEND_NAME == "indy-vdr" ): + LOGGER.debug( + "Binding IndyCredxVerifier for 'askar-anoncreds' backend." + ) context.injector.bind_provider( IndyVerifier, ClassProvider( @@ -178,6 +197,7 @@ async def setup(self): ), ) else: + LOGGER.error("Unsupported ledger backend for multiledger setup.") raise MultipleLedgerManagerError( "Multiledger is supported only for Indy SDK or Askar " "[Indy VDR] profile" @@ -187,13 +207,17 @@ async def setup(self): ) # Configure the ledger - if not await ledger_config( + ledger_configured = await ledger_config( self.root_profile, self.setup_public_did and self.setup_public_did.did - ): - LOGGER.warning("No ledger configured") + ) + if not ledger_configured: + LOGGER.warning("No ledger configured.") + else: + LOGGER.debug("Ledger configured successfully.") if not context.settings.get("transport.disabled"): # Register all inbound transports if enabled + LOGGER.debug("Transport not disabled. Setting up inbound transports.") self.inbound_transport_manager = InboundTransportManager( self.root_profile, self.inbound_message_router, self.handle_not_returned ) @@ -201,45 +225,54 @@ async def setup(self): context.injector.bind_instance( InboundTransportManager, self.inbound_transport_manager ) + LOGGER.debug("Inbound transports registered successfully.") - if not context.settings.get("transport.disabled"): # Register all outbound transports + LOGGER.debug("Setting up outbound transports.") self.outbound_transport_manager = OutboundTransportManager( self.root_profile, self.handle_not_delivered ) await self.outbound_transport_manager.setup() + LOGGER.debug("Outbound transports registered successfully.") # Initialize dispatcher + LOGGER.debug("Initializing dispatcher.") self.dispatcher = Dispatcher(self.root_profile) await self.dispatcher.setup() + LOGGER.debug("Dispatcher initialized successfully.") wire_format = context.inject_or(BaseWireFormat) if wire_format and hasattr(wire_format, "task_queue"): wire_format.task_queue = self.dispatcher.task_queue + LOGGER.debug("Wire format task queue bound to dispatcher.") # Bind manager for multitenancy related tasks if context.settings.get("multitenant.enabled"): + LOGGER.debug("Multitenant is enabled. Binding MultitenantManagerProvider.") context.injector.bind_provider( BaseMultitenantManager, MultitenantManagerProvider(self.root_profile) ) # Bind route manager provider + LOGGER.debug("Binding RouteManagerProvider.") context.injector.bind_provider( RouteManager, RouteManagerProvider(self.root_profile) ) - # Bind oob message processor to be able to receive and process un-encrypted - # messages + # Bind OobMessageProcessor to be able to receive and process unencrypted messages + LOGGER.debug("Binding OobMessageProcessor.") context.injector.bind_instance( OobMessageProcessor, OobMessageProcessor(inbound_message_router=self.inbound_message_router), ) # Bind default PyLD document loader + LOGGER.debug("Binding default DocumentLoader.") context.injector.bind_instance(DocumentLoader, DocumentLoader(self.root_profile)) # Admin API if context.settings.get("admin.enabled"): + LOGGER.debug("Admin API is enabled. Attempting to register admin server.") try: admin_host = context.settings.get("admin.host", "0.0.0.0") admin_port = context.settings.get("admin.port", "80") @@ -255,13 +288,15 @@ async def setup(self): self.get_stats, ) context.injector.bind_instance(BaseAdminServer, self.admin_server) + LOGGER.debug("Admin server registered on %s:%s", admin_host, admin_port) except Exception: - LOGGER.exception("Unable to register admin server") + LOGGER.exception("Unable to register admin server.") raise # Fetch stats collector, if any collector = context.inject_or(Collector) if collector: + LOGGER.debug("Stats collector found. Wrapping methods for collection.") # add stats to our own methods collector.wrap( self, @@ -280,32 +315,40 @@ async def setup(self): "find_inbound_connection", ), ) + LOGGER.debug("Methods wrapped with stats collector.") async def start(self) -> None: """Start the agent.""" - + LOGGER.debug("Starting the Conductor agent.") context = self.root_profile.context await self.check_for_valid_wallet_type(self.root_profile) + LOGGER.debug("Wallet type validated.") if not context.settings.get("transport.disabled"): # Start up transports if enabled try: + LOGGER.debug("Transport not disabled. Starting inbound transports.") await self.inbound_transport_manager.start() + LOGGER.debug("Inbound transports started successfully.") except Exception: - LOGGER.exception("Unable to start inbound transports") + LOGGER.exception("Unable to start inbound transports.") raise try: + LOGGER.debug("Starting outbound transports.") await self.outbound_transport_manager.start() + LOGGER.debug("Outbound transports started successfully.") except Exception: - LOGGER.exception("Unable to start outbound transports") + LOGGER.exception("Unable to start outbound transports.") raise # Start up Admin server if self.admin_server: + LOGGER.debug("Admin server present. Starting admin server.") try: await self.admin_server.start() + LOGGER.debug("Admin server started successfully.") except Exception: - LOGGER.exception("Unable to start administration API") + LOGGER.exception("Unable to start administration API.") # Make admin responder available during message parsing # This allows webhooks to be called when a connection is marked active, # for example @@ -314,10 +357,12 @@ async def start(self) -> None: self.admin_server.outbound_message_router, ) context.injector.bind_instance(BaseResponder, responder) + LOGGER.debug("Admin responder bound to injector.") # Get agent label default_label = context.settings.get("default_label") public_did = self.setup_public_did and self.setup_public_did.did + LOGGER.debug("Agent label: %s", default_label) if context.settings.get("log.banner", True): if context.settings.get("transport.disabled"): @@ -352,6 +397,7 @@ async def start(self) -> None: from_version_storage = None from_version = None agent_version = f"v{__version__}" + LOGGER.debug("Recording ACA-Py version in wallet if needed.") async with self.root_profile.session() as session: storage: BaseStorage = session.context.inject(BaseStorage) try: @@ -366,10 +412,16 @@ async def start(self) -> None: ) except StorageNotFoundError: LOGGER.warning("Wallet version storage record not found.") + from_version_config = self.root_profile.settings.get("upgrade.from_version") force_upgrade_flag = ( self.root_profile.settings.get("upgrade.force_upgrade") or False ) + LOGGER.debug( + "Force upgrade flag: %s, From version config: %s", + force_upgrade_flag, + from_version_config, + ) if force_upgrade_flag and from_version_config: if from_version_storage: @@ -381,8 +433,13 @@ async def start(self) -> None: from_version = from_version_storage else: from_version = from_version_config + LOGGER.debug( + "Determined from_version based on force_upgrade: %s", from_version + ) else: from_version = from_version_storage or from_version_config + LOGGER.debug("Determined from_version: %s", from_version) + if not from_version: LOGGER.warning( ( @@ -393,17 +450,27 @@ async def start(self) -> None: ) from_version = DEFAULT_ACAPY_VERSION self.root_profile.settings.set_value("upgrade.from_version", from_version) + LOGGER.debug("Set upgrade.from_version to default: %s", from_version) + config_available_list = get_upgrade_version_list( config_path=self.root_profile.settings.get("upgrade.config_path"), from_version=from_version, ) + LOGGER.debug("Available upgrade versions: %s", config_available_list) + if len(config_available_list) >= 1: + LOGGER.info("Upgrade configurations available. Initiating upgrade.") await upgrade(profile=self.root_profile) elif not (from_version_storage and from_version_storage == agent_version): + LOGGER.debug("No upgrades needed. Adding version record.") await add_version_record(profile=self.root_profile, version=agent_version) # Create a static connection for use by the test-suite if context.settings.get("debug.test_suite_endpoint"): + LOGGER.debug( + "Test suite endpoint configured. " + "Creating static connection for test suite." + ) mgr = ConnectionManager(self.root_profile) their_endpoint = context.settings["debug.test_suite_endpoint"] test_conn = await mgr.create_static_connection( @@ -412,32 +479,38 @@ async def start(self) -> None: their_endpoint=their_endpoint, alias="test-suite", ) - print("Created static connection for test suite") - print(" - My DID:", test_conn.my_did) - print(" - Their DID:", test_conn.their_did) - print(" - Their endpoint:", their_endpoint) - print() + LOGGER.info( + "Created static connection for test suite\n" + f" - My DID: {test_conn.my_did}\n" + f" - Their DID: {test_conn.their_did}\n" + f" - Their endpoint: {their_endpoint}\n" + ) del mgr + LOGGER.debug("Static connection for test suite created and manager deleted.") # Clear default mediator if context.settings.get("mediation.clear"): + LOGGER.debug("Mediation clear flag set. Clearing default mediator.") mediation_mgr = MediationManager(self.root_profile) await mediation_mgr.clear_default_mediator() - print("Default mediator cleared.") + LOGGER.info("Default mediator cleared.") - # Clear default mediator # Set default mediator by id default_mediator_id = context.settings.get("mediation.default_id") if default_mediator_id: + LOGGER.debug("Setting default mediator to ID: %s", default_mediator_id) mediation_mgr = MediationManager(self.root_profile) try: await mediation_mgr.set_default_mediator_by_id(default_mediator_id) - print(f"Default mediator set to {default_mediator_id}") + LOGGER.info(f"Default mediator set to {default_mediator_id}") except Exception: - LOGGER.exception("Error updating default mediator") + LOGGER.exception("Error updating default mediator.") # Print an invitation to the terminal if context.settings.get("debug.print_invitation"): + LOGGER.debug( + "Debug flag for printing invitation is set. Creating invitation." + ) try: mgr = OutOfBandManager(self.root_profile) invi_rec = await mgr.create_invitation( @@ -451,17 +524,20 @@ async def start(self) -> None: ) base_url = context.settings.get("invite_base_url") invite_url = invi_rec.invitation.to_url(base_url) - print("Invitation URL:") - print(invite_url, flush=True) + LOGGER.info(f"Invitation URL:\n{invite_url}") qr = QRCode(border=1) qr.add_data(invite_url) qr.print_ascii(invert=True) del mgr except Exception: - LOGGER.exception("Error creating invitation") + LOGGER.exception("Error creating invitation.") # Print connections protocol invitation to the terminal if context.settings.get("debug.print_connections_invitation"): + LOGGER.debug( + "Debug flag for printing connections invitation is set. " + "Creating connections invitation." + ) try: mgr = ConnectionManager(self.root_profile) _record, invite = await mgr.create_invitation( @@ -474,17 +550,17 @@ async def start(self) -> None: ) base_url = context.settings.get("invite_base_url") invite_url = invite.to_url(base_url) - print("Invitation URL (Connections protocol):") - print(invite_url, flush=True) + LOGGER.info(f"Invitation URL (Connections protocol):\n{invite_url}") qr = QRCode(border=1) qr.add_data(invite_url) qr.print_ascii(invert=True) del mgr except Exception: - LOGGER.exception("Error creating invitation") + LOGGER.exception("Error creating connections protocol invitation.") # mediation connection establishment provided_invite: str = context.settings.get("mediation.invite") + LOGGER.debug("Mediation invite provided: %s", provided_invite) try: async with self.root_profile.session() as session: @@ -492,16 +568,24 @@ async def start(self) -> None: mediation_invite_record = await invite_store.get_mediation_invite_record( provided_invite ) + LOGGER.debug("Mediation invite record retrieved successfully.") except Exception: - LOGGER.exception("Error retrieving mediator invitation") + LOGGER.exception("Error retrieving mediator invitation.") mediation_invite_record = None # Accept mediation invitation if one was specified or stored if mediation_invite_record is not None: + LOGGER.debug( + "Mediation invite record found. " + "Attempting to accept mediation invitation." + ) try: mediation_connections_invite = context.settings.get( "mediation.connections_invite", False ) + LOGGER.debug( + "Mediation connections invite flag: %s", mediation_connections_invite + ) invitation_handler = ( ConnectionInvitation if mediation_connections_invite @@ -509,8 +593,11 @@ async def start(self) -> None: ) if not mediation_invite_record.used: - # clear previous mediator configuration before establishing a - # new one + # clear previous mediator configuration before establishing a new one + LOGGER.debug( + "Mediation invite not used. " + "Clearing default mediator before accepting new invite." + ) await MediationManager(self.root_profile).clear_default_mediator() mgr = ( @@ -518,6 +605,7 @@ async def start(self) -> None: if mediation_connections_invite else OutOfBandManager(self.root_profile) ) + LOGGER.debug("Receiving mediation invitation.") record = await mgr.receive_invitation( invitation=invitation_handler.from_url( mediation_invite_record.invite @@ -528,6 +616,7 @@ async def start(self) -> None: await MediationInviteStore( session.context.inject(BaseStorage) ).mark_default_invite_as_used() + LOGGER.debug("Marked mediation invite as used.") await record.metadata_set( session, MediationManager.SEND_REQ_AFTER_CONNECTION, True @@ -535,48 +624,66 @@ async def start(self) -> None: await record.metadata_set( session, MediationManager.SET_TO_DEFAULT_ON_GRANTED, True ) + LOGGER.debug("Set mediation metadata after connection.") - print("Attempting to connect to mediator...") + LOGGER.info("Attempting to connect to mediator...") del mgr + LOGGER.debug("Mediation manager deleted after setting up mediator.") except Exception: - LOGGER.exception("Error accepting mediation invitation") + LOGGER.exception("Error accepting mediation invitation.") try: + LOGGER.debug("Checking for wallet upgrades in progress.") await self.check_for_wallet_upgrades_in_progress() - except Exception: - LOGGER.exception( - "An exception was caught while checking for wallet upgrades in progress" + LOGGER.debug("Wallet upgrades check completed.") + except Exception as e: + LOGGER.warning( + "An exception was caught while checking for wallet upgrades in progress.", + exc_info=e, ) # notify protocols of startup status + LOGGER.debug("Notifying protocols of startup status.") await self.root_profile.notify(STARTUP_EVENT_TOPIC, {}) + LOGGER.debug("Startup notification sent.") async def stop(self, timeout=1.0): """Stop the agent.""" + LOGGER.info("Stopping the Conductor agent.") # notify protocols that we are shutting down if self.root_profile: + LOGGER.debug("Notifying protocols of shutdown.") await self.root_profile.notify(SHUTDOWN_EVENT_TOPIC, {}) + LOGGER.debug("Shutdown notification sent.") shutdown = TaskQueue() if self.dispatcher: + LOGGER.debug("Initiating shutdown of dispatcher.") shutdown.run(self.dispatcher.complete()) if self.admin_server: + LOGGER.debug("Initiating shutdown of admin server.") shutdown.run(self.admin_server.stop()) if self.inbound_transport_manager: + LOGGER.debug("Initiating shutdown of inbound transport manager.") shutdown.run(self.inbound_transport_manager.stop()) if self.outbound_transport_manager: + LOGGER.debug("Initiating shutdown of outbound transport manager.") shutdown.run(self.outbound_transport_manager.stop()) if self.root_profile: # close multitenant profiles multitenant_mgr = self.context.inject_or(BaseMultitenantManager) if multitenant_mgr: + LOGGER.debug("Closing multitenant profiles.") for profile in multitenant_mgr.open_profiles: + LOGGER.debug("Closing profile: %s", profile.name) shutdown.run(profile.close()) - + LOGGER.debug("Closing root profile.") shutdown.run(self.root_profile.close()) + LOGGER.debug("Waiting for shutdown tasks to complete with timeout=%f.", timeout) await shutdown.complete(timeout) + LOGGER.info("Conductor agent stopped successfully.") def inbound_message_router( self, @@ -618,22 +725,26 @@ def inbound_message_router( def dispatch_complete(self, message: InboundMessage, completed: CompletedTask): """Handle completion of message dispatch.""" if completed.exc_info: - LOGGER.exception("Exception in message handler:", exc_info=completed.exc_info) - if isinstance(completed.exc_info[1], LedgerConfigError) or isinstance( - completed.exc_info[1], LedgerTransactionError - ): - LOGGER.error( + exc_class, exc, _ = completed.exc_info + if isinstance(exc, (LedgerConfigError, LedgerTransactionError)): + LOGGER.fatal( "%shutdown on ledger error %s", "S" if self.admin_server else "No admin server to s", - str(completed.exc_info[1]), + str(exc), + exc_info=completed.exc_info, ) if self.admin_server: self.admin_server.notify_fatal_error() + elif isinstance(exc, (ProfileError, StorageNotFoundError)): + LOGGER.warning( + "Storage error occurred in message handler: %s: %s", + exc_class.__name__, + str(exc), + exc_info=completed.exc_info, + ) else: - LOGGER.error( - "DON'T shutdown on %s %s", - completed.exc_info[0].__name__, - str(completed.exc_info[1]), + LOGGER.exception( + "Exception in message handler:", exc_info=completed.exc_info ) self.inbound_transport_manager.dispatch_complete(message, completed) @@ -867,19 +978,7 @@ async def check_for_valid_wallet_type(self, profile): async def check_for_wallet_upgrades_in_progress(self): """Check for upgrade and upgrade if needed.""" - - # We need to use the correct multitenant manager for single vs multiple wallets - # here because the multitenant provider hasn't been initialized yet. - manager_type = self.context.settings.get_value( - "multitenant.wallet_type", default="basic" - ).lower() - - manager_class = MultitenantManagerProvider.MANAGER_TYPES.get( - manager_type, manager_type - ) - - multitenant_mgr = self.context.inject_or(manager_class) - if multitenant_mgr: + if self.context.settings.get_value("multitenant.enabled"): subwallet_profiles = await get_subwallet_profiles_from_storage( self.root_profile ) diff --git a/acapy_agent/core/dispatcher.py b/acapy_agent/core/dispatcher.py index 962b69d97c..e430fe9f32 100644 --- a/acapy_agent/core/dispatcher.py +++ b/acapy_agent/core/dispatcher.py @@ -32,7 +32,7 @@ from ..utils.stats import Collector from ..utils.task_queue import CompletedTask, PendingTask, TaskQueue from ..utils.tracing import get_timer, trace_event -from .error import ProtocolMinorVersionNotSupported +from .error import ProfileError, ProtocolMinorVersionNotSupported from .protocol_registry import ProtocolRegistry @@ -84,9 +84,14 @@ def log_task(self, task: CompletedTask): """Log a completed task using the stats collector.""" if task.exc_info and not issubclass(task.exc_info[0], HTTPException): # skip errors intentionally returned to HTTP clients - self.logger.exception( - "Handler error: %s", task.ident or "", exc_info=task.exc_info - ) + if not issubclass(task.exc_info[0], ProfileError): + self.logger.exception( + "Handler error: %s", task.ident or "", exc_info=task.exc_info + ) + else: + self.logger.warning( + "Handler error: %s", task.ident or "", exc_info=task.exc_info + ) if self.collector: timing = task.timing if "queued" in timing: @@ -176,9 +181,6 @@ async def handle_v1_message( inbound_message: The inbound message instance send_outbound: Async function to send outbound messages - # Raises: - # MessageParseError: If the message type version is not supported - Returns: The response from the handler @@ -193,7 +195,9 @@ async def handle_v1_message( except ProblemReportParseError: pass # avoid problem report recursion except MessageParseError as e: - self.logger.error(f"Message parsing failed: {str(e)}, sending problem report") + self.logger.warning( + f"Message parsing failed: {str(e)}, sending problem report", exc_info=e + ) error_result = ProblemReport( description={ "en": str(e), @@ -288,7 +292,9 @@ async def make_message(self, profile: Profile, parsed_msg: dict) -> BaseMessage: message_type = parsed_msg.get("@type") if not message_type: - raise MessageParseError("Message does not contain '@type' parameter") + raise MessageParseError( + f"Message does not contain '@type' parameter. Got: {parsed_msg}" + ) if message_type.startswith("did:sov"): warnings.warn( diff --git a/acapy_agent/core/plugin_registry.py b/acapy_agent/core/plugin_registry.py index b3fa709386..55bf1d08a1 100644 --- a/acapy_agent/core/plugin_registry.py +++ b/acapy_agent/core/plugin_registry.py @@ -3,7 +3,7 @@ import logging from collections import OrderedDict from types import ModuleType -from typing import Iterable, Optional, Sequence +from typing import Optional, Sequence, Set from ..config.injection_context import InjectionContext from ..core.event_bus import EventBus @@ -18,10 +18,10 @@ class PluginRegistry: """Plugin registry for indexing application plugins.""" - def __init__(self, blocklist: Iterable[str] = []): + def __init__(self, blocklist: Optional[Set[str]] = None): """Initialize a `PluginRegistry` instance.""" - self._plugins = OrderedDict() - self._blocklist = set(blocklist) + self._plugins: OrderedDict[str, ModuleType] = OrderedDict() + self._blocklist: Set[str] = set(blocklist) if blocklist else set() @property def plugin_names(self) -> Sequence[str]: @@ -57,7 +57,6 @@ def validate_version(self, version_list, module_name): for version_dict in version_list: # Dicts must have correct format - try: if not ( isinstance(version_dict["major_version"], int) @@ -89,8 +88,8 @@ def validate_version(self, version_list, module_name): > version_dict["current_minor_version"] ): raise ProtocolDefinitionValidationError( - "Minimum supported minor version cannot" - + " be greater than current minor version" + "Minimum supported minor version cannot " + "be greater than current minor version" ) # There can only be one definition per major version @@ -102,7 +101,7 @@ def validate_version(self, version_list, module_name): if count > 1: raise ProtocolDefinitionValidationError( "There can only be one definition per major version. " - + f"Found {count} for major version {major_version}." + f"Found {count} for major version {major_version}." ) # Specified module must be loadable @@ -111,97 +110,126 @@ def validate_version(self, version_list, module_name): if not mod: raise ProtocolDefinitionValidationError( - "Version module path is not " - + f"loadable: {module_name}, {version_path}" + f"Version module path is not loadable: {module_name}, {version_path}" ) return True - def register_plugin(self, module_name: str) -> ModuleType: + def register_plugin(self, module_name: str) -> Optional[ModuleType]: """Register a plugin module.""" - if module_name in self._plugins: - mod = self._plugins[module_name] - elif module_name in self._blocklist: - LOGGER.debug(f"Blocked {module_name} from loading due to blocklist") + if self._is_already_registered(module_name): + return self._plugins.get(module_name) + + if self._is_blocked(module_name): return None - else: - try: - mod = ClassLoader.load_module(module_name) - LOGGER.debug(f"Loaded module: {module_name}") - except ModuleLoadError as e: - LOGGER.error(f"Error loading plugin module: {e}") - return None - # Module must exist - if not mod: - LOGGER.error(f"Module doesn't exist: {module_name}") - return None - - # Any plugin with a setup method is considered valid. - if hasattr(mod, "setup"): - self._plugins[module_name] = mod - return mod - - # Make an exception for non-protocol modules - # that contain admin routes and for old-style protocol - # modules without version support - routes = ClassLoader.load_module("routes", module_name) - message_types = ClassLoader.load_module("message_types", module_name) - if routes or message_types: - self._plugins[module_name] = mod - return mod - - definition = ClassLoader.load_module("definition", module_name) - - # definition.py must exist in protocol - if not definition: - LOGGER.error(f"Protocol does not include definition.py: {module_name}") - return None - - # definition.py must include versions attribute - if not hasattr(definition, "versions"): - LOGGER.error( - "Protocol definition does not include " - f"versions attribute: {module_name}" - ) - return None + mod = self._load_module(module_name) + if not mod: + LOGGER.error("Module doesn't exist: %s", module_name) + return None - # Definition list must not be malformed - try: - self.validate_version(definition.versions, module_name) - except ProtocolDefinitionValidationError as e: - LOGGER.error(f"Protocol versions definition is malformed. {e}") - return None + if self._is_valid_plugin(mod, module_name): + self._plugins[module_name] = mod + LOGGER.debug("Registered plugin: %s", module_name) + return mod - self._plugins[module_name] = mod - return mod + LOGGER.warning("Failed to register plugin: %s", module_name) + return None - # # Load each version as a separate plugin - # for version in definition.versions: - # mod = ClassLoader.load_module(f"{module_name}.{version['path']}") - # self._plugins[module_name] = mod - # return mod + def _is_already_registered(self, module_name: str) -> bool: + """Check if the plugin is already registered.""" + if module_name in self._plugins: + LOGGER.debug("Plugin %s is already registered.", module_name) + return True + return False + + def _is_blocked(self, module_name: str) -> bool: + """Check if the plugin is in the blocklist.""" + if module_name in self._blocklist: + LOGGER.debug("Blocked %s from loading due to blocklist.", module_name) + return True + return False + + def _load_module(self, module_name: str) -> Optional[ModuleType]: + """Load the plugin module using ClassLoader.""" + try: + mod = ClassLoader.load_module(module_name) + return mod + except ModuleLoadError as e: + LOGGER.error("Error loading plugin module '%s': %s", module_name, e) + return None + + def _is_valid_plugin(self, mod: ModuleType, module_name: str) -> bool: + """Validate the plugin based on various criteria.""" + # Check if the plugin has a 'setup' method + if hasattr(mod, "setup"): + return True + + # Check for 'routes' or 'message_types' modules + # This makes an exception for non-protocol modules that contain admin routes + # and for old-style protocol modules without version support + routes = ClassLoader.load_module("routes", module_name) + message_types = ClassLoader.load_module("message_types", module_name) + if routes or message_types: + return True + + # Check for 'definition' module with 'versions' attribute + definition = ClassLoader.load_module("definition", module_name) + if not definition: + LOGGER.error( + "Protocol does not include 'definition.py' for module: %s", + module_name, + ) + return False + + if not hasattr(definition, "versions"): + LOGGER.error( + "Protocol definition does not include versions attribute for module: %s", + module_name, + ) + return False + + # Validate the 'versions' attribute + try: + self.validate_version(definition.versions, module_name) + return True + except ProtocolDefinitionValidationError as e: + LOGGER.error( + "Protocol versions definition is malformed for module '%s': %s", + module_name, + e, + ) + return False def register_package(self, package_name: str) -> Sequence[ModuleType]: """Register all modules (sub-packages) under a given package name.""" + LOGGER.debug("Registering package: %s", package_name) try: module_names = ClassLoader.scan_subpackages(package_name) except ModuleLoadError: LOGGER.error("Plugin module package not found: %s", package_name) module_names = [] - return list( - filter( - None, - ( - self.register_plugin(module_name) - for module_name in module_names - if module_name.split(".")[-1] != "tests" - ), - ) - ) - async def init_context(self, context: InjectionContext): + registered_plugins = [] + for module_name in module_names: + # Skip any module whose last segment is 'tests' + if module_name.split(".")[-1] == "tests": + continue + + plugin = self.register_plugin(module_name) + if plugin: + registered_plugins.append(plugin) + else: + LOGGER.warning( + "Failed to register %s under %s", module_name, package_name + ) + + return registered_plugins + + async def init_context(self, context: InjectionContext) -> None: """Call plugin setup methods on the current context.""" + LOGGER.debug("Initializing plugin context for %d plugins", len(self._plugins)) + for plugin in self._plugins.values(): if hasattr(plugin, "setup"): await plugin.setup(context) @@ -216,25 +244,29 @@ async def load_protocol_version( context: InjectionContext, mod: ModuleType, version_definition: Optional[dict] = None, - ): + ) -> None: """Load a particular protocol version.""" protocol_registry = context.inject(ProtocolRegistry) goal_code_registry = context.inject(GoalCodeRegistry) + if hasattr(mod, "MESSAGE_TYPES"): protocol_registry.register_message_types( mod.MESSAGE_TYPES, version_definition=version_definition ) + if hasattr(mod, "CONTROLLERS"): protocol_registry.register_controllers(mod.CONTROLLERS) goal_code_registry.register_controllers(mod.CONTROLLERS) - async def load_protocols(self, context: InjectionContext, plugin: ModuleType): + async def load_protocols(self, context: InjectionContext, plugin: ModuleType) -> None: """For modules that don't implement setup, register protocols manually.""" + plugin_name = plugin.__name__ # If this module contains message_types, then assume that # this is a valid module of the old style (not versioned) try: - mod = ClassLoader.load_module(plugin.__name__ + ".message_types") + message_types_path = f"{plugin_name}.message_types" + mod = ClassLoader.load_module(message_types_path) except ModuleLoadError as e: LOGGER.error("Error loading plugin module message types: %s", e) return @@ -242,106 +274,134 @@ async def load_protocols(self, context: InjectionContext, plugin: ModuleType): if mod: await self.load_protocol_version(context, mod) else: - # Otherwise, try check for definition.py for versioned - # protocol packages + # Otherwise, try check for definition.py for versioned protocol packages try: - definition = ClassLoader.load_module(plugin.__name__ + ".definition") + definition_path = f"{plugin_name}.definition" + definition = ClassLoader.load_module(definition_path) except ModuleLoadError as e: LOGGER.error("Error loading plugin definition module: %s", e) return if definition: for protocol_version in definition.versions: + version_path = ( + f"{plugin_name}.{protocol_version['path']}.message_types" + ) try: - mod = ClassLoader.load_module( - f"{plugin.__name__}.{protocol_version['path']}" - + ".message_types" - ) - await self.load_protocol_version(context, mod, protocol_version) - + mod = ClassLoader.load_module(version_path) except ModuleLoadError as e: - LOGGER.error("Error loading plugin module message types: %s", e) + LOGGER.error( + "Error loading plugin module message types from %s: %s", + version_path, + e, + ) return - async def register_admin_routes(self, app): + if mod: + await self.load_protocol_version(context, mod, protocol_version) + else: + LOGGER.debug("Failed to load %s", version_path) + + async def register_admin_routes(self, app) -> None: """Call route registration methods on the current context.""" + LOGGER.debug("Registering admin routes for %d plugins", len(self._plugins)) + for plugin in self._plugins.values(): - definition = ClassLoader.load_module("definition", plugin.__name__) + plugin_name = plugin.__name__ + mod = None + definition = ClassLoader.load_module("definition", plugin_name) if definition: # Load plugin routes that are in a versioned package. for plugin_version in definition.versions: + version_path = f"{plugin_name}.{plugin_version['path']}.routes" try: - mod = ClassLoader.load_module( - f"{plugin.__name__}.{plugin_version['path']}.routes" - ) + mod = ClassLoader.load_module(version_path) except ModuleLoadError as e: - LOGGER.error("Error loading admin routes: %s", e) + LOGGER.error( + "Error loading admin routes from %s: %s", version_path, e + ) continue + if mod and hasattr(mod, "register"): await mod.register(app) else: # Load plugin routes that aren't in a versioned package. + routes_path = f"{plugin_name}.routes" try: - mod = ClassLoader.load_module(f"{plugin.__name__}.routes") + mod = ClassLoader.load_module(routes_path) except ModuleLoadError as e: - LOGGER.error("Error loading admin routes: %s", e) + LOGGER.error("Error loading admin routes from %s: %s", routes_path, e) continue + if mod and hasattr(mod, "register"): await mod.register(app) - def register_protocol_events(self, context: InjectionContext): + def register_protocol_events(self, context: InjectionContext) -> None: """Call route register_events methods on the current context.""" + LOGGER.debug("Registering protocol events for %d plugins", len(self._plugins)) + event_bus = context.inject_or(EventBus) if not event_bus: LOGGER.error("No event bus in context") return + for plugin in self._plugins.values(): - definition = ClassLoader.load_module("definition", plugin.__name__) + plugin_name = plugin.__name__ + mod = None + definition = ClassLoader.load_module("definition", plugin_name) if definition: # Load plugin routes that are in a versioned package. for plugin_version in definition.versions: + version_path = f"{plugin_name}.{plugin_version['path']}.routes" try: - mod = ClassLoader.load_module( - f"{plugin.__name__}.{plugin_version['path']}.routes" - ) + mod = ClassLoader.load_module(version_path) except ModuleLoadError as e: - LOGGER.error("Error loading admin routes: %s", e) + LOGGER.error("Error loading events from %s: %s", version_path, e) continue + if mod and hasattr(mod, "register_events"): mod.register_events(event_bus) else: # Load plugin routes that aren't in a versioned package. + routes_path = f"{plugin_name}.routes" try: - mod = ClassLoader.load_module(f"{plugin.__name__}.routes") + mod = ClassLoader.load_module(routes_path) except ModuleLoadError as e: - LOGGER.error("Error loading admin routes: %s", e) + LOGGER.error("Error loading events from %s: %s", routes_path, e) continue + if mod and hasattr(mod, "register_events"): mod.register_events(event_bus) - def post_process_routes(self, app): + def post_process_routes(self, app) -> None: """Call route binary file response OpenAPI fixups if applicable.""" + LOGGER.debug("Post-processing routes for %d plugins", len(self._plugins)) + for plugin in self._plugins.values(): - definition = ClassLoader.load_module("definition", plugin.__name__) + plugin_name = plugin.__name__ + mod = None + definition = ClassLoader.load_module("definition", plugin_name) if definition: # Set binary file responses for routes that are in a versioned package. for plugin_version in definition.versions: + version_path = f"{plugin_name}.{plugin_version['path']}.routes" try: - mod = ClassLoader.load_module( - f"{plugin.__name__}.{plugin_version['path']}.routes" - ) + mod = ClassLoader.load_module(version_path) except ModuleLoadError as e: - LOGGER.error("Error loading admin routes: %s", e) + LOGGER.error("Error loading routes from %s: %s", version_path, e) continue + if mod and hasattr(mod, "post_process_routes"): mod.post_process_routes(app) else: # Set binary file responses for routes not in a versioned package. + routes_path = f"{plugin_name}.routes" try: - mod = ClassLoader.load_module(f"{plugin.__name__}.routes") + mod = ClassLoader.load_module(routes_path) except ModuleLoadError as e: - LOGGER.error("Error loading admin routes: %s", e) + LOGGER.error("Error loading routes from %s: %s", routes_path, e) continue + if mod and hasattr(mod, "post_process_routes"): mod.post_process_routes(app) diff --git a/acapy_agent/core/tests/test_conductor.py b/acapy_agent/core/tests/test_conductor.py index 875623deee..6d8530a4e5 100644 --- a/acapy_agent/core/tests/test_conductor.py +++ b/acapy_agent/core/tests/test_conductor.py @@ -1,5 +1,5 @@ -from io import StringIO from unittest import IsolatedAsyncioTestCase +from unittest.mock import call import pytest @@ -120,26 +120,32 @@ async def test_startup_version_record_exists(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, - "get_upgrade_version_list", - mock.MagicMock( - return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] - ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, "LoggingConfigurator", autospec=True - ) as mock_logger: + mock.patch.object( + test_module, + "get_upgrade_version_list", + mock.MagicMock( + return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] + ), + ), + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, "LoggingConfigurator", autospec=True + ) as mock_logger, + ): await conductor.setup() mock_inbound_mgr.return_value.setup.assert_awaited_once() @@ -178,24 +184,29 @@ async def test_startup_version_no_upgrade_add_record(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, - "get_upgrade_version_list", - mock.MagicMock( - return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] - ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, + "get_upgrade_version_list", + mock.MagicMock( + return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] + ), + ), + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -218,26 +229,34 @@ async def test_startup_version_force_upgrade(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, - "get_upgrade_version_list", - mock.MagicMock( - return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] - ), - ), mock.patch.object( - test_module, "upgrade_wallet_to_anoncreds_if_requested", return_value=False - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, + "get_upgrade_version_list", + mock.MagicMock( + return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] + ), + ), + mock.patch.object( + test_module, + "upgrade_wallet_to_anoncreds_if_requested", + return_value=False, + ), + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -255,27 +274,36 @@ async def test_startup_version_force_upgrade(self): await conductor.stop() test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, "LoggingConfigurator", autospec=True - ) as mock_logger, mock.patch.object( - test_module, "upgrade_wallet_to_anoncreds_if_requested", return_value=False - ), mock.patch.object( - test_module, - "get_upgrade_version_list", - mock.MagicMock(return_value=["v0.8.0-rc1", "v8.0.0", "v0.8.1-rc1"]), - ), mock.patch.object(test_module, "ledger_config"), mock.patch.object( - test_module.Conductor, "check_for_valid_wallet_type" + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, "LoggingConfigurator", autospec=True + ) as mock_logger, + mock.patch.object( + test_module, + "upgrade_wallet_to_anoncreds_if_requested", + return_value=False, + ), + mock.patch.object( + test_module, + "get_upgrade_version_list", + mock.MagicMock(return_value=["v0.8.0-rc1", "v8.0.0", "v0.8.1-rc1"]), + ), + mock.patch.object(test_module, "ledger_config"), + mock.patch.object(test_module.Conductor, "check_for_valid_wallet_type"), ): await conductor.setup() mock_inbound_mgr.return_value.registered_transports = {} @@ -290,35 +318,46 @@ async def test_startup_version_record_not_exists(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), + ), + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, "LoggingConfigurator", autospec=True + ) as mock_logger, + mock.patch.object( + test_module, + "upgrade_wallet_to_anoncreds_if_requested", + return_value=False, + ), + mock.patch.object( + BaseStorage, + "find_record", + mock.CoroutineMock( + side_effect=[mock.MagicMock(value="askar"), StorageNotFoundError()] + ), + ), + mock.patch.object( + test_module, + "get_upgrade_version_list", + mock.MagicMock(return_value=["v0.8.0-rc1", "v8.0.0", "v0.8.1-rc1"]), + ), + mock.patch.object( + test_module, + "upgrade", + mock.CoroutineMock(), ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, "LoggingConfigurator", autospec=True - ) as mock_logger, mock.patch.object( - test_module, "upgrade_wallet_to_anoncreds_if_requested", return_value=False - ), mock.patch.object( - BaseStorage, - "find_record", - mock.CoroutineMock( - side_effect=[mock.MagicMock(value="askar"), StorageNotFoundError()] - ), - ), mock.patch.object( - test_module, - "get_upgrade_version_list", - mock.MagicMock(return_value=["v0.8.0-rc1", "v8.0.0", "v0.8.1-rc1"]), - ), mock.patch.object( - test_module, - "upgrade", - mock.CoroutineMock(), ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) @@ -348,20 +387,23 @@ async def test_startup_admin_server_x(self): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, "LoggingConfigurator", autospec=True - ), mock.patch.object( - test_module, "AdminServer", mock.MagicMock() - ) as mock_admin_server: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object(test_module, "LoggingConfigurator", autospec=True), + mock.patch.object( + test_module, "AdminServer", mock.MagicMock() + ) as mock_admin_server, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -375,21 +417,29 @@ async def test_startup_no_public_did(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), + ), + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, "LoggingConfigurator", autospec=True + ) as mock_logger, + mock.patch.object( + test_module, + "upgrade_wallet_to_anoncreds_if_requested", + return_value=False, ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, "LoggingConfigurator", autospec=True - ) as mock_logger, mock.patch.object( - test_module, "upgrade_wallet_to_anoncreds_if_requested", return_value=False ): mock_outbound_mgr.return_value.registered_transports = {} mock_outbound_mgr.return_value.enqueue_message = mock.CoroutineMock() @@ -422,19 +472,26 @@ async def test_stats(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), + ), + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, + "upgrade_wallet_to_anoncreds_if_requested", + return_value=False, ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, "upgrade_wallet_to_anoncreds_if_requested", return_value=False ): mock_inbound_mgr.return_value.sessions = ["dummy"] mock_outbound_mgr.return_value.outbound_buffer = [ @@ -466,16 +523,19 @@ async def test_inbound_message_handler(self): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -504,26 +564,32 @@ async def test_inbound_message_handler_ledger_x(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } await conductor.setup() - with mock.patch.object( - conductor.dispatcher, "queue_message", autospec=True - ) as mock_dispatch_q, mock.patch.object( - conductor.admin_server, "notify_fatal_error", mock.MagicMock() - ) as mock_notify: + with ( + mock.patch.object( + conductor.dispatcher, "queue_message", autospec=True + ) as mock_dispatch_q, + mock.patch.object( + conductor.admin_server, "notify_fatal_error", mock.MagicMock() + ) as mock_notify, + ): mock_dispatch_q.side_effect = test_module.LedgerConfigError("ledger down") message_body = "{}" @@ -583,16 +649,19 @@ async def test_outbound_message_handler_with_target(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -623,18 +692,22 @@ async def test_outbound_message_handler_with_connection(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as conn_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as conn_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -672,16 +745,19 @@ async def test_outbound_message_handler_with_verkey_no_target(self): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -717,16 +793,19 @@ async def test_handle_nots(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", mock.MagicMock() - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", mock.MagicMock() + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value = mock.MagicMock( setup=mock.CoroutineMock(), enqueue_message=mock.CoroutineMock(), @@ -743,11 +822,12 @@ async def test_handle_nots(self): conductor.handle_not_returned(conductor.root_profile, message) - with mock.patch.object( - test_module, "ConnectionManager" - ) as mock_conn_mgr, mock.patch.object( - conductor.dispatcher, "run_task", mock.MagicMock() - ) as mock_run_task: + with ( + mock.patch.object(test_module, "ConnectionManager") as mock_conn_mgr, + mock.patch.object( + conductor.dispatcher, "run_task", mock.MagicMock() + ) as mock_run_task, + ): # Normally this should be a coroutine mock; however, the coroutine # is awaited by dispatcher.run_task, which is mocked here. MagicMock # to prevent unawaited coroutine warning. @@ -795,25 +875,31 @@ async def test_handle_not_returned_ledger_x(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } await conductor.setup() - with mock.patch.object( - conductor.dispatcher, "run_task", mock.MagicMock() - ) as mock_dispatch_run, mock.patch.object( - conductor.admin_server, "notify_fatal_error", mock.MagicMock() - ) as mock_notify: + with ( + mock.patch.object( + conductor.dispatcher, "run_task", mock.MagicMock() + ) as mock_dispatch_run, + mock.patch.object( + conductor.admin_server, "notify_fatal_error", mock.MagicMock() + ) as mock_notify, + ): mock_dispatch_run.side_effect = test_module.LedgerConfigError( "No such ledger" ) @@ -837,28 +923,35 @@ async def test_queue_outbound_ledger_x(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } await conductor.setup() - with mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as conn_mgr, mock.patch.object( - conductor.dispatcher, "run_task", mock.MagicMock() - ) as mock_dispatch_run, mock.patch.object( - conductor.admin_server, "notify_fatal_error", mock.MagicMock() - ) as mock_notify: + with ( + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as conn_mgr, + mock.patch.object( + conductor.dispatcher, "run_task", mock.MagicMock() + ) as mock_dispatch_run, + mock.patch.object( + conductor.admin_server, "notify_fatal_error", mock.MagicMock() + ) as mock_notify, + ): # Normally this should be a coroutine mock; however, the coroutine # is awaited by dispatcher.run_task, which is mocked here. MagicMock # to prevent unawaited coroutine warning. @@ -886,16 +979,19 @@ async def test_admin(self): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -903,9 +999,10 @@ async def test_admin(self): admin = conductor.context.inject(BaseAdminServer) assert admin is conductor.admin_server - with mock.patch.object( - admin, "start", autospec=True - ) as admin_start, mock.patch.object(admin, "stop", autospec=True) as admin_stop: + with ( + mock.patch.object(admin, "start", autospec=True) as admin_start, + mock.patch.object(admin, "stop", autospec=True) as admin_stop, + ): await conductor.start() admin_start.assert_awaited_once_with() @@ -925,16 +1022,19 @@ async def test_admin_startx(self): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -942,13 +1042,12 @@ async def test_admin_startx(self): admin = conductor.context.inject(BaseAdminServer) assert admin is conductor.admin_server - with mock.patch.object( - admin, "start", autospec=True - ) as admin_start, mock.patch.object( - admin, "stop", autospec=True - ) as admin_stop, mock.patch.object( - test_module, "OutOfBandManager" - ) as oob_mgr, mock.patch.object(test_module, "ConnectionManager") as conn_mgr: + with ( + mock.patch.object(admin, "start", autospec=True) as admin_start, + mock.patch.object(admin, "stop", autospec=True) as admin_stop, + mock.patch.object(test_module, "OutOfBandManager") as oob_mgr, + mock.patch.object(test_module, "ConnectionManager") as conn_mgr, + ): admin_start.side_effect = KeyError("trouble") oob_mgr.return_value.create_invitation = mock.CoroutineMock( side_effect=KeyError("double trouble") @@ -967,16 +1066,19 @@ async def test_setup_collector(self): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -989,18 +1091,20 @@ async def test_start_static(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "ConnectionManager" - ) as mock_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object(test_module, "ConnectionManager") as mock_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1017,20 +1121,21 @@ async def test_start_x_in(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "ConnectionManager" - ) as mock_mgr, mock.patch.object( - test_module, "InboundTransportManager" - ) as mock_intx_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object(test_module, "ConnectionManager") as mock_mgr, + mock.patch.object(test_module, "InboundTransportManager") as mock_intx_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_intx_mgr.return_value = mock.MagicMock( setup=mock.CoroutineMock(), start=mock.CoroutineMock(side_effect=KeyError("trouble")), @@ -1050,18 +1155,18 @@ async def test_start_x_out_a(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "ConnectionManager" - ) as mock_mgr, mock.patch.object( - test_module, "OutboundTransportManager" - ) as mock_outx_mgr: + mock.patch.object(test_module, "ConnectionManager") as mock_mgr, + mock.patch.object(test_module, "OutboundTransportManager") as mock_outx_mgr, + ): mock_outx_mgr.return_value = mock.MagicMock( setup=mock.CoroutineMock(), start=mock.CoroutineMock(side_effect=KeyError("trouble")), @@ -1078,18 +1183,18 @@ async def test_start_x_out_b(self): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "ConnectionManager" - ) as mock_mgr, mock.patch.object( - test_module, "OutboundTransportManager" - ) as mock_outx_mgr: + mock.patch.object(test_module, "ConnectionManager") as mock_mgr, + mock.patch.object(test_module, "OutboundTransportManager") as mock_outx_mgr, + ): mock_outx_mgr.return_value = mock.MagicMock( setup=mock.CoroutineMock(), start=mock.CoroutineMock(side_effect=KeyError("trouble")), @@ -1123,16 +1228,19 @@ async def test_dispatch_complete_non_fatal_x(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1165,16 +1273,19 @@ async def test_dispatch_complete_fatal_x(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1203,26 +1314,58 @@ async def test_print_invite_connection(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + # Define expected invitation URLs + expected_oob_url = "http://localhost?oob=test_oob_invite" + expected_ci_url = "http://localhost?c_i=test_ci_invite" + + # Mock the InvitationRecord returned by create_invitation for OOB + mock_oob_invitation = mock.MagicMock() + mock_oob_invitation.invitation.to_url.return_value = expected_oob_url + + # Mock the InvitationRecord returned by create_invitation for Connections Protocol + mock_ci_invitation = mock.MagicMock() + mock_ci_invitation.to_url.return_value = expected_ci_url + + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch("sys.stdout", new=StringIO()) as captured, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object(test_module, "OutOfBandManager") as oob_mgr, + mock.patch.object(test_module, "ConnectionManager") as conn_mgr, + mock.patch.object(test_module.LOGGER, "info") as mock_logger_info, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } + + # Configure create_invitation to return the mocked invitations + oob_mgr.return_value.create_invitation = mock.CoroutineMock( + return_value=mock_oob_invitation + ) + conn_mgr.return_value.create_invitation = mock.CoroutineMock( + return_value=(None, mock_ci_invitation) + ) + + # Execute the conductor lifecycle await conductor.setup() await conductor.start() await conductor.stop() - value = captured.getvalue() - assert "http://localhost?oob=" in value - assert "http://localhost?c_i=" in value + + # Assert that LOGGER.info was called twice with the expected URLs + expected_calls = [ + call(f"Invitation URL:\n{expected_oob_url}"), + call(f"Invitation URL (Connections protocol):\n{expected_ci_url}"), + ] + mock_logger_info.assert_has_calls(expected_calls, any_order=True) async def test_clear_default_mediator(self): builder: ContextBuilder = StubContextBuilder(self.test_settings) @@ -1231,16 +1374,19 @@ async def test_clear_default_mediator(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1262,34 +1408,41 @@ async def test_set_default_mediator(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } await conductor.setup() - with mock.patch.object( - test_module, - "MediationManager", - return_value=mock.MagicMock(set_default_mediator_by_id=mock.CoroutineMock()), - ) as mock_mgr, mock.patch.object( - MediationRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object( - test_module, - "LOGGER", - mock.MagicMock( - exception=mock.MagicMock( - side_effect=Exception("This method should not have been called") - ) + with ( + mock.patch.object( + test_module, + "MediationManager", + return_value=mock.MagicMock( + set_default_mediator_by_id=mock.CoroutineMock() + ), + ) as mock_mgr, + mock.patch.object(MediationRecord, "retrieve_by_id", mock.CoroutineMock()), + mock.patch.object( + test_module, + "LOGGER", + mock.MagicMock( + exception=mock.MagicMock( + side_effect=Exception("This method should not have been called") + ) + ), ), ): await conductor.start() @@ -1303,26 +1456,32 @@ async def test_set_default_mediator_x(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } await conductor.setup() - with mock.patch.object( - MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=Exception()), - ), mock.patch.object(test_module, "LOGGER") as mock_logger: + with ( + mock.patch.object( + MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=Exception()), + ), + mock.patch.object(test_module, "LOGGER") as mock_logger, + ): await conductor.start() await conductor.stop() mock_logger.exception.assert_called_once() @@ -1341,16 +1500,19 @@ async def test_webhook_router(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1386,16 +1548,19 @@ async def test_shutdown_multitenant_profiles(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1456,16 +1621,19 @@ async def test_mediator_invitation_0160(self, mock_from_url, _): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1473,18 +1641,24 @@ async def test_mediator_invitation_0160(self, mock_from_url, _): mock_conn_record = mock.MagicMock() - with mock.patch.object( - test_module, - "ConnectionManager", - mock.MagicMock( - return_value=mock.MagicMock( - receive_invitation=mock.CoroutineMock(return_value=mock_conn_record) - ) + with ( + mock.patch.object( + test_module, + "ConnectionManager", + mock.MagicMock( + return_value=mock.MagicMock( + receive_invitation=mock.CoroutineMock( + return_value=mock_conn_record + ) + ) + ), + ) as mock_mgr, + mock.patch.object(mock_conn_record, "metadata_set", mock.CoroutineMock()), + mock.patch.object( + test_module, + "upgrade_wallet_to_anoncreds_if_requested", + return_value=False, ), - ) as mock_mgr, mock.patch.object( - mock_conn_record, "metadata_set", mock.CoroutineMock() - ), mock.patch.object( - test_module, "upgrade_wallet_to_anoncreds_if_requested", return_value=False ): await conductor.start() await conductor.stop() @@ -1502,16 +1676,19 @@ async def test_mediator_invitation_0434(self, mock_from_url, _): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1537,16 +1714,21 @@ async def test_mediator_invitation_0434(self, mock_from_url, _): state=OobRecord.STATE_INITIAL, ) - with mock.patch.object( - test_module, - "OutOfBandManager", - mock.MagicMock( - return_value=mock.MagicMock( - receive_invitation=mock.CoroutineMock(return_value=oob_record) - ) + with ( + mock.patch.object( + test_module, + "OutOfBandManager", + mock.MagicMock( + return_value=mock.MagicMock( + receive_invitation=mock.CoroutineMock(return_value=oob_record) + ) + ), + ) as mock_mgr, + mock.patch.object( + test_module, + "upgrade_wallet_to_anoncreds_if_requested", + return_value=False, ), - ) as mock_mgr, mock.patch.object( - test_module, "upgrade_wallet_to_anoncreds_if_requested", return_value=False ): assert not conductor.root_profile.settings["mediation.connections_invite"] await conductor.start() @@ -1572,16 +1754,19 @@ async def test_mediation_invitation_should_use_stored_invitation( conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1598,12 +1783,14 @@ async def test_mediation_invitation_should_use_stored_invitation( ) # when - with mock.patch.object( - test_module, "ConnectionManager", return_value=connection_manager_mock - ), mock.patch.object( - mock_conn_record, "metadata_set", mock.CoroutineMock() - ), mock.patch.object( - test_module, "MediationManager", return_value=mock_mediation_manager + with ( + mock.patch.object( + test_module, "ConnectionManager", return_value=connection_manager_mock + ), + mock.patch.object(mock_conn_record, "metadata_set", mock.CoroutineMock()), + mock.patch.object( + test_module, "MediationManager", return_value=mock_mediation_manager + ), ): await conductor.start() await conductor.stop() @@ -1627,16 +1814,19 @@ async def test_mediation_invitation_should_not_create_connection_for_old_invitat conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1665,26 +1855,32 @@ async def test_mediator_invitation_x(self, _): conductor = test_module.Conductor(builder) test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr: + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } await conductor.setup() - with mock.patch.object( - test_module.ConnectionInvitation, - "from_url", - mock.MagicMock(side_effect=Exception()), - ) as mock_from_url, mock.patch.object(test_module, "LOGGER") as mock_logger: + with ( + mock.patch.object( + test_module.ConnectionInvitation, + "from_url", + mock.MagicMock(side_effect=Exception()), + ) as mock_from_url, + mock.patch.object(test_module, "LOGGER") as mock_logger, + ): await conductor.start() await conductor.stop() mock_from_url.assert_called_once_with("test-invite") @@ -1711,22 +1907,28 @@ async def test_setup_ledger_both_multiple_and_base(self): BaseLedger, mock.MagicMock(BaseLedger, autospec=True) ) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, - "load_multiple_genesis_transactions_from_config", - mock.CoroutineMock(), - ) as mock_multiple_genesis_load, mock.patch.object( - test_module, "get_genesis_transactions", mock.CoroutineMock() - ) as mock_genesis_load, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object(test_module, "ledger_config"): + mock.patch.object( + test_module, + "load_multiple_genesis_transactions_from_config", + mock.CoroutineMock(), + ) as mock_multiple_genesis_load, + mock.patch.object( + test_module, "get_genesis_transactions", mock.CoroutineMock() + ) as mock_genesis_load, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object(test_module, "ledger_config"), + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1741,18 +1943,23 @@ async def test_setup_ledger_only_base(self): test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "get_genesis_transactions", mock.CoroutineMock() - ) as mock_genesis_load, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object(test_module, "ledger_config"): + mock.patch.object( + test_module, "get_genesis_transactions", mock.CoroutineMock() + ) as mock_genesis_load, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object(test_module, "ledger_config"), + ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) } @@ -1765,21 +1972,26 @@ async def test_startup_storage_type_anoncreds_and_config_askar_re_calls_setup(se test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), + ), + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, + "upgrade", + mock.CoroutineMock(), ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, - "upgrade", - mock.CoroutineMock(), ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) @@ -1811,27 +2023,33 @@ async def test_startup_storage_type_does_not_exist_and_existing_agent_then_set_t test_profile = await create_test_profile(None, await builder.build_context()) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, - "get_upgrade_version_list", - mock.MagicMock( - return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, + "get_upgrade_version_list", + mock.MagicMock( + return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] + ), + ), + mock.patch.object( + test_module, + "upgrade", + mock.CoroutineMock(), ), - ), mock.patch.object( - test_module, - "upgrade", - mock.CoroutineMock(), ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) @@ -1866,27 +2084,33 @@ async def test_startup_storage_type_does_not_exist_and_new_anoncreds_agent( test_settings, await builder.build_context() ) - with mock.patch.object( - test_module, - "wallet_config", - return_value=( - test_profile, - DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + with ( + mock.patch.object( + test_module, + "wallet_config", + return_value=( + test_profile, + DIDInfo("did", "verkey", metadata={}, method=SOV, key_type=ED25519), + ), ), - ), mock.patch.object( - test_module, "InboundTransportManager", autospec=True - ) as mock_inbound_mgr, mock.patch.object( - test_module, "OutboundTransportManager", autospec=True - ) as mock_outbound_mgr, mock.patch.object( - test_module, - "get_upgrade_version_list", - mock.MagicMock( - return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] + mock.patch.object( + test_module, "InboundTransportManager", autospec=True + ) as mock_inbound_mgr, + mock.patch.object( + test_module, "OutboundTransportManager", autospec=True + ) as mock_outbound_mgr, + mock.patch.object( + test_module, + "get_upgrade_version_list", + mock.MagicMock( + return_value=["v0.7.4", "0.7.5", "v0.8.0-rc1", "v8.0.0", "v0.8.1-rc2"] + ), + ), + mock.patch.object( + test_module, + "upgrade", + mock.CoroutineMock(), ), - ), mock.patch.object( - test_module, - "upgrade", - mock.CoroutineMock(), ): mock_outbound_mgr.return_value.registered_transports = { "test": mock.MagicMock(schemes=["http"]) diff --git a/acapy_agent/core/tests/test_dispatcher.py b/acapy_agent/core/tests/test_dispatcher.py index c352192f19..b941e584e3 100644 --- a/acapy_agent/core/tests/test_dispatcher.py +++ b/acapy_agent/core/tests/test_dispatcher.py @@ -105,11 +105,14 @@ async def test_dispatch(self): "@type": DIDCommPrefix.qualify_current(StubAgentMessage.Meta.message_type) } - with mock.patch.object( - StubAgentMessageHandler, "handle", autospec=True - ) as handler_mock, mock.patch.object( - test_module, "BaseConnectionManager", autospec=True - ) as conn_mgr_mock: + with ( + mock.patch.object( + StubAgentMessageHandler, "handle", autospec=True + ) as handler_mock, + mock.patch.object( + test_module, "BaseConnectionManager", autospec=True + ) as conn_mgr_mock, + ): conn_mgr_mock.return_value = mock.MagicMock( find_inbound_connection=mock.CoroutineMock( return_value=mock.MagicMock(connection_id="dummy") @@ -148,10 +151,11 @@ async def test_dispatch_versioned_message(self): "@type": DIDCommPrefix.qualify_current(StubAgentMessage.Meta.message_type) } - with mock.patch.object( - StubAgentMessageHandler, "handle", autospec=True - ) as handler_mock, mock.patch.object( - test_module, "BaseConnectionManager", autospec=True + with ( + mock.patch.object( + StubAgentMessageHandler, "handle", autospec=True + ) as handler_mock, + mock.patch.object(test_module, "BaseConnectionManager", autospec=True), ): await dispatcher.queue_message( dispatcher.profile, make_inbound(message), rcv.send @@ -217,11 +221,12 @@ async def test_dispatch_versioned_message_message_class_deserialize_x(self): rcv = Receiver() message = {"@type": "doc/proto-name/1.1/no-such-message-type"} - with mock.patch.object( - StubAgentMessageHandler, "handle", autospec=True - ), mock.patch.object( - registry, "resolve_message_class", mock.MagicMock() - ) as mock_resolve: + with ( + mock.patch.object(StubAgentMessageHandler, "handle", autospec=True), + mock.patch.object( + registry, "resolve_message_class", mock.MagicMock() + ) as mock_resolve, + ): mock_resolve.return_value = mock.MagicMock( deserialize=mock.MagicMock(side_effect=test_module.BaseModelError()) ) @@ -258,10 +263,11 @@ async def test_dispatch_versioned_message_handle_greater_succeeds(self): "@type": DIDCommPrefix.qualify_current(StubV1_2AgentMessage.Meta.message_type) } - with mock.patch.object( - StubAgentMessageHandler, "handle", autospec=True - ) as handler_mock, mock.patch.object( - test_module, "BaseConnectionManager", autospec=True + with ( + mock.patch.object( + StubAgentMessageHandler, "handle", autospec=True + ) as handler_mock, + mock.patch.object(test_module, "BaseConnectionManager", autospec=True), ): await dispatcher.queue_message( dispatcher.profile, make_inbound(message), rcv.send @@ -393,12 +399,13 @@ async def test_create_send_outbound(self): outbound_message = await responder.create_outbound( json.dumps(message.serialize()) ) - with mock.patch.object( - responder, "_send", mock.CoroutineMock() - ), mock.patch.object( - test_module.BaseResponder, - "conn_rec_active_state_check", - mock.CoroutineMock(return_value=True), + with ( + mock.patch.object(responder, "_send", mock.CoroutineMock()), + mock.patch.object( + test_module.BaseResponder, + "conn_rec_active_state_check", + mock.CoroutineMock(return_value=True), + ), ): await responder.send_outbound(outbound_message) @@ -418,12 +425,13 @@ async def test_create_send_outbound_with_msg_attrs(self): message = StubAgentMessage() responder = test_module.DispatcherResponder(context, message, None) outbound_message = await responder.create_outbound(message) - with mock.patch.object( - responder, "_send", mock.CoroutineMock() - ), mock.patch.object( - test_module.BaseResponder, - "conn_rec_active_state_check", - mock.CoroutineMock(return_value=True), + with ( + mock.patch.object(responder, "_send", mock.CoroutineMock()), + mock.patch.object( + test_module.BaseResponder, + "conn_rec_active_state_check", + mock.CoroutineMock(return_value=True), + ), ): await responder.send_outbound( message=outbound_message, diff --git a/acapy_agent/core/tests/test_oob_processor.py b/acapy_agent/core/tests/test_oob_processor.py index f3a9541f78..4b3e85bedb 100644 --- a/acapy_agent/core/tests/test_oob_processor.py +++ b/acapy_agent/core/tests/test_oob_processor.py @@ -426,17 +426,20 @@ async def test_find_oob_record_for_inbound_message_sender_connection_id_no_match mock_retrieve.assert_called_once_with(ANY, {"invi_msg_id": "the-pthid"}) # Connection id is not the same, state is AWAIT_RESPONSE. oob has connection_id - with mock.patch.object( - OobRecord, - "retrieve_by_tag_filter", - mock.CoroutineMock(return_value=self.oob_record), - ) as mock_retrieve, mock.patch.object( - ConnRecord, - "retrieve_by_id", - mock.CoroutineMock( - return_value=mock.MagicMock(delete_record=mock.CoroutineMock()) - ), - ) as mock_retrieve_conn: + with ( + mock.patch.object( + OobRecord, + "retrieve_by_tag_filter", + mock.CoroutineMock(return_value=self.oob_record), + ) as mock_retrieve, + mock.patch.object( + ConnRecord, + "retrieve_by_id", + mock.CoroutineMock( + return_value=mock.MagicMock(delete_record=mock.CoroutineMock()) + ), + ) as mock_retrieve_conn, + ): self.oob_record.role = OobRecord.ROLE_SENDER self.oob_record.state = OobRecord.STATE_AWAIT_RESPONSE self.context.connection_record = mock.MagicMock( diff --git a/acapy_agent/core/tests/test_plugin_registry.py b/acapy_agent/core/tests/test_plugin_registry.py index b5727a4546..4e870fbdfb 100644 --- a/acapy_agent/core/tests/test_plugin_registry.py +++ b/acapy_agent/core/tests/test_plugin_registry.py @@ -537,6 +537,7 @@ async def test_load_protocols_load_mod(self): mock_mod = mock.MagicMock() mock_mod.MESSAGE_TYPES = mock.MagicMock() mock_mod.CONTROLLERS = mock.MagicMock() + mock_mod.__name__ = "test_mod" with mock.patch.object( ClassLoader, "load_module", mock.MagicMock() @@ -595,6 +596,7 @@ async def test_load_protocols_no_mod_def_message_types(self): mock_mod = mock.MagicMock() mock_mod.MESSAGE_TYPES = mock.MagicMock() mock_mod.CONTROLLERS = mock.MagicMock() + mock_mod.__name__ = "test_mod" with mock.patch.object( ClassLoader, "load_module", mock.MagicMock() diff --git a/acapy_agent/indy/models/cred_def.py b/acapy_agent/indy/models/cred_def.py index dbdaea2b2d..4c5547f96e 100644 --- a/acapy_agent/indy/models/cred_def.py +++ b/acapy_agent/indy/models/cred_def.py @@ -6,8 +6,8 @@ from ...messaging.valid import ( INDY_CRED_DEF_ID_EXAMPLE, INDY_CRED_DEF_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, NUM_STR_WHOLE_EXAMPLE, NUM_STR_WHOLE_VALIDATE, ) @@ -92,10 +92,10 @@ class CredentialDefinitionSchema(OpenAPISchema): """Marshmallow schema for indy cred def.""" ver = fields.Str( - validate=INDY_VERSION_VALIDATE, + validate=MAJOR_MINOR_VERSION_VALIDATE, metadata={ "description": "Node protocol version", - "example": INDY_VERSION_EXAMPLE, + "example": MAJOR_MINOR_VERSION_EXAMPLE, }, ) ident = fields.Str( diff --git a/acapy_agent/indy/models/pres_preview.py b/acapy_agent/indy/models/pres_preview.py index 496c1e93cd..d9e740193e 100644 --- a/acapy_agent/indy/models/pres_preview.py +++ b/acapy_agent/indy/models/pres_preview.py @@ -16,8 +16,8 @@ from ...messaging.valid import ( INDY_CRED_DEF_ID_EXAMPLE, INDY_CRED_DEF_ID_VALIDATE, - INDY_PREDICATE_EXAMPLE, - INDY_PREDICATE_VALIDATE, + PREDICATE_EXAMPLE, + PREDICATE_VALIDATE, ) from ...multitenant.base import BaseMultitenantManager from ...protocols.didcomm_prefix import DIDCommPrefix @@ -100,10 +100,10 @@ class Meta: ) predicate = fields.Str( required=True, - validate=INDY_PREDICATE_VALIDATE, + validate=PREDICATE_VALIDATE, metadata={ "description": "Predicate type ('<', '<=', '>=', or '>')", - "example": INDY_PREDICATE_EXAMPLE, + "example": PREDICATE_EXAMPLE, }, ) threshold = fields.Int( diff --git a/acapy_agent/indy/models/proof_request.py b/acapy_agent/indy/models/proof_request.py index 1c87ecf454..f27ac5a8f6 100644 --- a/acapy_agent/indy/models/proof_request.py +++ b/acapy_agent/indy/models/proof_request.py @@ -15,14 +15,14 @@ from ...messaging.models.openapi import OpenAPISchema from ...messaging.valid import ( INDY_CRED_DEF_ID_EXAMPLE, - INDY_PREDICATE_EXAMPLE, - INDY_PREDICATE_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, INT_EPOCH_EXAMPLE, INT_EPOCH_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, NUM_STR_NATURAL_EXAMPLE, NUM_STR_NATURAL_VALIDATE, + PREDICATE_EXAMPLE, + PREDICATE_VALIDATE, ) @@ -125,10 +125,10 @@ class IndyProofReqPredSpecSchema(OpenAPISchema): ) p_type = fields.Str( required=True, - validate=INDY_PREDICATE_VALIDATE, + validate=PREDICATE_VALIDATE, metadata={ "description": "Predicate type ('<', '<=', '>=', or '>')", - "example": INDY_PREDICATE_EXAMPLE, + "example": PREDICATE_EXAMPLE, }, ) p_value = fields.Int( @@ -251,10 +251,10 @@ class Meta: version = fields.Str( required=False, dump_default="1.0", - validate=INDY_VERSION_VALIDATE, + validate=MAJOR_MINOR_VERSION_VALIDATE, metadata={ "description": "Proof request version", - "example": INDY_VERSION_EXAMPLE, + "example": MAJOR_MINOR_VERSION_EXAMPLE, }, ) requested_attributes = fields.Dict( diff --git a/acapy_agent/indy/models/revocation.py b/acapy_agent/indy/models/revocation.py index a7a2795fbd..14c5617709 100644 --- a/acapy_agent/indy/models/revocation.py +++ b/acapy_agent/indy/models/revocation.py @@ -12,8 +12,8 @@ INDY_CRED_DEF_ID_VALIDATE, INDY_REV_REG_ID_EXAMPLE, INDY_REV_REG_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, NATURAL_NUM_EXAMPLE, NATURAL_NUM_VALIDATE, ) @@ -180,10 +180,10 @@ class Meta: unknown = EXCLUDE ver = fields.Str( - validate=INDY_VERSION_VALIDATE, + validate=MAJOR_MINOR_VERSION_VALIDATE, metadata={ "description": "Version of revocation registry definition", - "example": INDY_VERSION_EXAMPLE, + "example": MAJOR_MINOR_VERSION_EXAMPLE, }, ) id_ = fields.Str( @@ -294,10 +294,10 @@ class Meta: unknown = EXCLUDE ver = fields.Str( - validate=INDY_VERSION_VALIDATE, + validate=MAJOR_MINOR_VERSION_VALIDATE, metadata={ "description": "Version of revocation registry entry", - "example": INDY_VERSION_EXAMPLE, + "example": MAJOR_MINOR_VERSION_EXAMPLE, }, ) value = fields.Nested( diff --git a/acapy_agent/indy/models/schema.py b/acapy_agent/indy/models/schema.py index 5dff944356..df91802bc7 100644 --- a/acapy_agent/indy/models/schema.py +++ b/acapy_agent/indy/models/schema.py @@ -6,8 +6,8 @@ from ...messaging.valid import ( INDY_SCHEMA_ID_EXAMPLE, INDY_SCHEMA_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, NATURAL_NUM_EXAMPLE, NATURAL_NUM_VALIDATE, ) @@ -17,10 +17,10 @@ class SchemaSchema(OpenAPISchema): """Marshmallow schema for indy schema.""" ver = fields.Str( - validate=INDY_VERSION_VALIDATE, + validate=MAJOR_MINOR_VERSION_VALIDATE, metadata={ "description": "Node protocol version", - "example": INDY_VERSION_EXAMPLE, + "example": MAJOR_MINOR_VERSION_EXAMPLE, }, ) ident = fields.Str( @@ -38,8 +38,11 @@ class SchemaSchema(OpenAPISchema): } ) version = fields.Str( - validate=INDY_VERSION_VALIDATE, - metadata={"description": "Schema version", "example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, ) attr_names = fields.List( fields.Str(metadata={"description": "Attribute name", "example": "score"}), diff --git a/acapy_agent/indy/tests/test_verifier.py b/acapy_agent/indy/tests/test_verifier.py index c038daa3d3..54762cb636 100644 --- a/acapy_agent/indy/tests/test_verifier.py +++ b/acapy_agent/indy/tests/test_verifier.py @@ -436,11 +436,12 @@ async def test_check_timestamps(self): proof_req_x = deepcopy(INDY_PROOF_REQ_NAME) proof_req_x["non_revoked"] = {"from": 1600000000, "to": 1600001000} proof_x["identifiers"][0]["timestamp"] = 1579890000 - with mock.patch.object( - test_module, "LOGGER", mock.MagicMock() - ) as mock_logger, mock.patch.object( - IndyLedgerRequestsExecutor, "get_ledger_for_identifier" - ) as mock_get_ledger: + with ( + mock.patch.object(test_module, "LOGGER", mock.MagicMock()) as mock_logger, + mock.patch.object( + IndyLedgerRequestsExecutor, "get_ledger_for_identifier" + ) as mock_get_ledger, + ): mock_get_ledger.return_value = (None, self.ledger) pre_logger_calls = mock_logger.info.call_count await self.verifier.check_timestamps( diff --git a/acapy_agent/ledger/indy_vdr.py b/acapy_agent/ledger/indy_vdr.py index d26734ec6f..b81e4952d0 100644 --- a/acapy_agent/ledger/indy_vdr.py +++ b/acapy_agent/ledger/indy_vdr.py @@ -11,7 +11,7 @@ from io import StringIO from pathlib import Path from time import time -from typing import List, Optional, Tuple, Union +from typing import Dict, List, Optional, Tuple, Union from indy_vdr import Pool, Request, VdrError, ledger, open_pool @@ -40,36 +40,48 @@ def _normalize_txns(txns: str) -> str: """Normalize a set of genesis transactions.""" + LOGGER.debug("Normalizing genesis transactions") lines = StringIO() for line in txns.splitlines(): line = line.strip() if line: lines.write(line) lines.write("\n") + LOGGER.debug("Finished normalizing genesis transactions") return lines.getvalue() def _write_safe(path: Path, content: str): """Atomically write to a file path.""" + LOGGER.debug("Writing content safely to path: %s", path) dir_path = path.parent with tempfile.NamedTemporaryFile(dir=dir_path, delete=False) as tmp: + LOGGER.debug("Created temporary file: %s", tmp.name) tmp.write(content.encode("utf-8")) tmp_name = tmp.name + LOGGER.debug("Renaming temporary file to target path") os.rename(tmp_name, path) + LOGGER.debug("Successfully wrote content to: %s", path) def _hash_txns(txns: str) -> str: """Obtain a hash of a set of genesis transactions.""" - return hashlib.sha256(txns.encode("utf-8")).hexdigest()[-16:] + LOGGER.debug("Calculating hash of genesis transactions") + hash_value = hashlib.sha256(txns.encode("utf-8")).hexdigest()[-16:] + LOGGER.debug("Generated transaction hash: %s", hash_value) + return hash_value class IndyVdrLedgerPool: - """Indy-VDR ledger pool manager.""" + """Indy-VDR ledger pool manager with singleton behavior based on configuration.""" + + _instances: Dict[tuple, "IndyVdrLedgerPool"] = {} + _lock = asyncio.Lock() def __init__( self, - name: str, *, + name: str, keepalive: int = 0, cache: Optional[BaseCache] = None, cache_duration: int = 600, @@ -77,69 +89,225 @@ def __init__( read_only: bool = False, socks_proxy: Optional[str] = None, ): - """Initialize an IndyLedger instance. + """Private constructor. Use 'create_instance' to instantiate.""" + LOGGER.debug( + "Initializing IndyVdrLedgerPool with name: %s, keepalive: %s, " + "cache_duration: %s, read_only: %s", + name, + keepalive, + cache_duration, + read_only, + ) - Args: - name: The pool ledger configuration name - keepalive: How many seconds to keep the ledger open - cache: The cache instance to use - cache_duration: The TTL for ledger cache entries - genesis_transactions: The ledger genesis transaction as a string - read_only: Prevent any ledger write operations - socks_proxy: Specifies socks proxy for ZMQ to connect to ledger pool - """ - self.ref_count = 0 - self.ref_lock = asyncio.Lock() + # Instance attributes + self.name = name self.keepalive = keepalive - self.close_task: asyncio.Future = None self.cache = cache - self.cache_duration: int = cache_duration + self.cache_duration = cache_duration + self.genesis_transactions = genesis_transactions + self.read_only = read_only + self.socks_proxy = socks_proxy + + self.ref_count = 0 + self.ref_lock = asyncio.Lock() + self.close_task: Optional[asyncio.Task] = None self.handle: Optional[Pool] = None - self.name = name self.cfg_path_cache: Optional[Path] = None self.genesis_hash_cache: Optional[str] = None self.genesis_txns_cache = genesis_transactions self.init_config = bool(genesis_transactions) self.taa_cache: Optional[str] = None - self.read_only: bool = read_only - self.socks_proxy: str = socks_proxy + + LOGGER.debug("Pool %s initialization staged", name) + + @classmethod + async def get_or_create( + cls, + *, + name: str, + keepalive: int = 0, + cache: Optional[BaseCache] = None, + cache_duration: int = 600, + genesis_transactions: Optional[str] = None, + read_only: bool = False, + socks_proxy: Optional[str] = None, + ) -> "IndyVdrLedgerPool": + """Asynchronously get or create the singleton instance based on configuration. + + Args: + name: The pool ledger configuration name. + keepalive: How many seconds to keep the ledger open. + cache: The cache instance to use. + cache_duration: The TTL for ledger cache entries. + genesis_transactions: The ledger genesis transaction as a string. + read_only: Prevent any ledger write operations. + socks_proxy: Specifies socks proxy for ZMQ to connect to ledger pool. + + Returns: + An initialized instance of IndyVdrLedgerPool. + """ + LOGGER.debug( + "Creating or retrieving IndyVdrLedgerPool instance with params: name=%s, " + "keepalive=%s, cache_duration=%s, read_only=%s, socks_proxy=%s", + name, + keepalive, + cache_duration, + read_only, + socks_proxy, + ) + + config_key = (name, keepalive, cache_duration, read_only, socks_proxy) + LOGGER.debug("Generated config key: %s", config_key) + + async with cls._lock: + if config_key not in cls._instances: + LOGGER.debug( + "No existing instance found for config key, creating new instance" + ) + instance = cls( + name=name, + keepalive=keepalive, + cache=cache, + cache_duration=cache_duration, + genesis_transactions=genesis_transactions, + read_only=read_only, + socks_proxy=socks_proxy, + ) + try: + LOGGER.debug("Initializing new IndyVdrLedgerPool instance") + await instance.initialize() + except Exception as e: + LOGGER.exception( + "Initialization failed for IndyVdrLedgerPool with config: %s", + config_key, + exc_info=e, + ) + raise + cls._instances[config_key] = instance + LOGGER.debug( + "Successfully created and stored new IndyVdrLedgerPool instance: %s", + config_key, + ) + else: + LOGGER.debug( + "Found existing IndyVdrLedgerPool instance for config: %s", config_key + ) + instance = cls._instances[config_key] + + async with instance.ref_lock: + instance.ref_count += 1 + LOGGER.debug( + "Incremented reference count to %s for instance %s", + instance.ref_count, + config_key, + ) + + LOGGER.debug( + "Returning IndyVdrLedgerPool instance with ref_count: %s", + instance.ref_count, + ) + return instance + + async def initialize(self): + """Initialize the ledger pool.""" + LOGGER.debug("Beginning pool initialization") + if self.init_config: + LOGGER.debug("Creating pool config with genesis transactions") + await self.create_pool_config(self.genesis_txns_cache, recreate=True) + self.init_config = False + LOGGER.debug("Opening pool connection") + await self.open() + LOGGER.debug("Pool initialization complete") + + @classmethod + async def release_instance(cls, instance: "IndyVdrLedgerPool"): + """Release a reference to the instance and possibly remove it from the registry. + + Args: + instance: The IndyVdrLedgerPool instance to release. + """ + LOGGER.debug("Beginning instance release process for pool: %s", instance.name) + config_key = ( + instance.name, + instance.keepalive, + instance.cache_duration, + instance.genesis_transactions, + instance.read_only, + instance.socks_proxy, + ) + LOGGER.debug("Generated config key for release: %s", config_key) + + async with cls._lock: + async with instance.ref_lock: + instance.ref_count -= 1 + LOGGER.debug( + "Decremented reference count to %s for instance %s", + instance.ref_count, + config_key, + ) + if instance.ref_count <= 0: + LOGGER.debug( + "Reference count is zero or negative, cleaning up instance" + ) + await instance.close() + del cls._instances[config_key] + LOGGER.debug( + "Successfully removed IndyVdrLedgerPool instance: %s", config_key + ) + else: + LOGGER.debug( + "Instance still has active references: %s", instance.ref_count + ) @property def cfg_path(self) -> Path: """Get the path to the configuration file, ensuring it's created.""" if not self.cfg_path_cache: + LOGGER.debug("Creating configuration path cache") self.cfg_path_cache = storage_path("vdr", create=True) + LOGGER.debug("Configuration path set to: %s", self.cfg_path_cache) return self.cfg_path_cache @property def genesis_hash(self) -> str: """Get the hash of the configured genesis transactions.""" if not self.genesis_hash_cache: + LOGGER.debug("Calculating genesis transactions hash") self.genesis_hash_cache = _hash_txns(self.genesis_txns) + LOGGER.debug("Genesis hash calculated: %s", self.genesis_hash_cache) return self.genesis_hash_cache @property def genesis_txns(self) -> str: """Get the configured genesis transactions.""" if not self.genesis_txns_cache: + LOGGER.debug("Loading genesis transactions from file") try: path = self.cfg_path.joinpath(self.name, "genesis") + LOGGER.debug("Reading genesis file from: %s", path) self.genesis_txns_cache = _normalize_txns(open(path).read()) + LOGGER.debug("Successfully loaded genesis transactions") except FileNotFoundError: + LOGGER.error("Pool config '%s' not found", self.name) raise LedgerConfigError("Pool config '%s' not found", self.name) from None return self.genesis_txns_cache async def create_pool_config(self, genesis_transactions: str, recreate: bool = False): """Create the pool ledger configuration.""" + LOGGER.debug("Creating pool config for '%s', recreate=%s", self.name, recreate) cfg_pool = self.cfg_path.joinpath(self.name) cfg_pool.mkdir(exist_ok=True) + LOGGER.debug("Created pool configuration directory: %s", cfg_pool) + genesis = _normalize_txns(genesis_transactions) if not genesis: + LOGGER.error("Empty genesis transactions provided") raise LedgerConfigError("Empty genesis transactions") genesis_path = cfg_pool.joinpath("genesis") try: + LOGGER.debug("Checking existing genesis file: %s", genesis_path) cmp_genesis = open(genesis_path).read() if _normalize_txns(cmp_genesis) == genesis: LOGGER.debug( @@ -148,66 +316,94 @@ async def create_pool_config(self, genesis_transactions: str, recreate: bool = F ) return elif not recreate: + LOGGER.error( + "Pool ledger '%s' exists with different genesis transactions", + self.name, + ) raise LedgerConfigError( f"Pool ledger '{self.name}' exists with " "different genesis transactions" ) except FileNotFoundError: + LOGGER.debug("No existing genesis file found") pass try: + LOGGER.debug("Writing genesis transactions to: %s", genesis_path) _write_safe(genesis_path, genesis) except OSError as err: + LOGGER.exception("Error writing genesis transactions", exc_info=err) raise LedgerConfigError("Error writing genesis transactions") from err - LOGGER.debug("Wrote pool ledger config '%s'", self.name) + LOGGER.debug("Successfully wrote pool ledger config '%s'", self.name) self.genesis_txns_cache = genesis async def open(self): """Open the pool ledger, creating it if necessary.""" + LOGGER.debug("Opening pool ledger: %s", self.name) if self.init_config: + LOGGER.debug("Initializing pool config with genesis transactions") await self.create_pool_config(self.genesis_txns_cache, recreate=True) self.init_config = False genesis_hash = self.genesis_hash + LOGGER.debug("Using genesis hash: %s", genesis_hash) cfg_pool = self.cfg_path.joinpath(self.name) cfg_pool.mkdir(exist_ok=True) cache_path = cfg_pool.joinpath(f"cache-{genesis_hash}") try: + LOGGER.debug("Attempting to read cached transactions from: %s", cache_path) txns = open(cache_path).read() cached = True + LOGGER.debug("Successfully read cached transactions") except FileNotFoundError: + LOGGER.debug("No cached transactions found, using genesis transactions") txns = self.genesis_txns cached = False + LOGGER.debug("Opening pool with transactions, socks_proxy=%s", self.socks_proxy) self.handle = await open_pool(transactions=txns, socks_proxy=self.socks_proxy) + LOGGER.debug("Pool opened successfully") + upd_txns = _normalize_txns(await self.handle.get_transactions()) if not cached or upd_txns != txns: + LOGGER.debug("Updating cached transactions") try: _write_safe(cache_path, upd_txns) + LOGGER.debug("Successfully wrote updated cached transactions") except OSError: LOGGER.exception("Error writing cached genesis transactions") async def close(self): """Close the pool ledger.""" if self.handle: + LOGGER.debug("Attempting to close pool ledger") exc = None for attempt in range(3): try: + LOGGER.debug("Close attempt %s/3", attempt + 1) self.handle.close() except VdrError as err: + LOGGER.warning( + "Error closing pool ledger (attempt %s/3): %s", + attempt + 1, + str(err), + ) await asyncio.sleep(0.01) exc = err continue self.handle = None exc = None + LOGGER.debug("Successfully closed pool ledger") break if exc: - LOGGER.exception("Exception when closing pool ledger", exc_info=exc) + LOGGER.exception( + "Failed to close pool ledger after 3 attempts", exc_info=exc + ) self.ref_count += 1 # if we are here, we should have self.ref_lock self.close_task = None raise LedgerError("Exception when closing pool ledger") from exc @@ -227,18 +423,43 @@ async def context_close(self): async def closer(timeout: int): """Close the pool ledger after a timeout.""" - await asyncio.sleep(timeout) - async with self.ref_lock: - if not self.ref_count: - LOGGER.debug("Closing pool ledger after timeout") - await self.close() + try: + LOGGER.debug( + "Coroutine will sleep for %d seconds before closing the pool.", + timeout, + ) + await asyncio.sleep(timeout) + async with self.ref_lock: + if not self.ref_count: + LOGGER.debug( + "No more references. Proceeding to close the pool ledger." + ) + await self.close() + else: + LOGGER.debug( + "Reference count is %d. Not closing the pool yet.", + self.ref_count, + ) + except Exception as e: + LOGGER.exception( + "Exception occurred in closer coroutine during pool closure.", + exc_info=e, + ) async with self.ref_lock: self.ref_count -= 1 + LOGGER.debug("Decremented ref_count to %d.", self.ref_count) if not self.ref_count: if self.keepalive: - self.close_task = asyncio.ensure_future(closer(self.keepalive)) + LOGGER.debug( + "Scheduling closer coroutine with keepalive=%s", + self.keepalive, + ) + self.close_task = asyncio.create_task(closer(self.keepalive)) else: + LOGGER.debug( + "No keepalive set. Proceeding to close the pool immediately." + ) await self.close() @@ -624,7 +845,7 @@ async def credential_definition_id2schema_id(self, credential_definition_id): seq_no = tokens[3] return (await self.get_schema(seq_no))["id"] - async def get_key_for_did(self, did: str) -> str: + async def get_key_for_did(self, did: str) -> Optional[str]: """Fetch the verkey for a ledger DID. Args: @@ -739,8 +960,11 @@ async def update_endpoint_for_did( if all_exist_endpoints else None ) + existing_routing_keys = ( + all_exist_endpoints.get("routingKeys") if all_exist_endpoints else None + ) - if exist_endpoint_of_type != endpoint: + if exist_endpoint_of_type != endpoint or existing_routing_keys != routing_keys: if self.read_only: raise LedgerError( "Error cannot update endpoint when ledger is in read only mode" diff --git a/acapy_agent/ledger/multiple_ledger/tests/test_indy_ledger_requests.py b/acapy_agent/ledger/multiple_ledger/tests/test_indy_ledger_requests.py index 4feb805b31..917a48e923 100644 --- a/acapy_agent/ledger/multiple_ledger/tests/test_indy_ledger_requests.py +++ b/acapy_agent/ledger/multiple_ledger/tests/test_indy_ledger_requests.py @@ -24,7 +24,8 @@ async def asyncSetUp(self): "genesis_transactions": "genesis_transactions", } ] - self.ledger = IndyVdrLedger(IndyVdrLedgerPool("test_prod_1"), self.profile) + pool = await IndyVdrLedgerPool.get_or_create(name="test_prod_1") + self.ledger = IndyVdrLedger(pool, self.profile) mock_ledger_manger = mock.MagicMock(BaseMultipleLedgerManager, autospec=True) mock_ledger_manger.extract_did_from_identifier = mock.MagicMock( return_value="WgWxqztrNooG92RXvxSTWv" diff --git a/acapy_agent/ledger/multiple_ledger/tests/test_indy_vdr_manager.py b/acapy_agent/ledger/multiple_ledger/tests/test_indy_vdr_manager.py index a64f20a8b7..1451a5fabb 100644 --- a/acapy_agent/ledger/multiple_ledger/tests/test_indy_vdr_manager.py +++ b/acapy_agent/ledger/multiple_ledger/tests/test_indy_vdr_manager.py @@ -63,17 +63,19 @@ async def asyncSetUp(self): self.context.injector.bind_instance(BaseResponder, self.responder) self.production_ledger = OrderedDict() self.non_production_ledger = OrderedDict() - test_prod_ledger = IndyVdrLedger(IndyVdrLedgerPool("test_prod_1"), self.profile) + test_prod_ledger = IndyVdrLedger( + await IndyVdrLedgerPool.get_or_create(name="test_prod_1"), self.profile + ) writable_ledgers = set() self.production_ledger["test_prod_1"] = test_prod_ledger self.production_ledger["test_prod_2"] = IndyVdrLedger( - IndyVdrLedgerPool("test_prod_2"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_prod_2"), self.profile ) self.non_production_ledger["test_non_prod_1"] = IndyVdrLedger( - IndyVdrLedgerPool("test_non_prod_1"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_non_prod_1"), self.profile ) self.non_production_ledger["test_non_prod_2"] = IndyVdrLedger( - IndyVdrLedgerPool("test_non_prod_2"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_non_prod_2"), self.profile ) writable_ledgers.add("test_prod_1") writable_ledgers.add("test_prod_2") @@ -195,10 +197,10 @@ async def test_get_ledger_by_did_self_cert_b( ): self.non_production_ledger = OrderedDict() self.non_production_ledger["test_non_prod_1"] = IndyVdrLedger( - IndyVdrLedgerPool("test_non_prod_1"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_non_prod_1"), self.profile ) self.non_production_ledger["test_non_prod_2"] = IndyVdrLedger( - IndyVdrLedgerPool("test_non_prod_2"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_non_prod_2"), self.profile ) self.manager = MultiIndyVDRLedgerManager( self.profile, @@ -239,11 +241,14 @@ async def test_get_ledger_by_did_not_self_cert( "verkey": "ABUF7uxYTxZ6qYdZ4G9e1Gi", } ) - with mock.patch.object( - test_module.asyncio, "wait", mock.CoroutineMock() - ) as mock_wait, mock.patch.object( - test_module.SubTrie, "verify_spv_proof", mock.CoroutineMock() - ) as mock_verify_spv_proof: + with ( + mock.patch.object( + test_module.asyncio, "wait", mock.CoroutineMock() + ) as mock_wait, + mock.patch.object( + test_module.SubTrie, "verify_spv_proof", mock.CoroutineMock() + ) as mock_verify_spv_proof, + ): mock_build_get_nym_req.return_value = mock.MagicMock() mock_submit.return_value = get_nym_reply mock_wait.return_value = mock_submit.return_value @@ -354,11 +359,14 @@ async def test_get_ledger_by_did_not_self_cert_not_self_cert_prod( ): get_nym_reply = deepcopy(GET_NYM_INDY_VDR_REPLY) get_nym_reply["data"]["verkey"] = "ABUF7uxYTxZ6qYdZ4G9e1Gi" - with mock.patch.object( - test_module.asyncio, "wait", mock.CoroutineMock() - ) as mock_wait, mock.patch.object( - test_module.SubTrie, "verify_spv_proof", mock.CoroutineMock() - ) as mock_verify_spv_proof: + with ( + mock.patch.object( + test_module.asyncio, "wait", mock.CoroutineMock() + ) as mock_wait, + mock.patch.object( + test_module.SubTrie, "verify_spv_proof", mock.CoroutineMock() + ) as mock_verify_spv_proof, + ): mock_build_get_nym_req.return_value = mock.MagicMock() mock_submit.return_value = get_nym_reply mock_wait.return_value = mock_submit.return_value @@ -381,10 +389,10 @@ async def test_lookup_did_in_configured_ledgers_self_cert_non_prod( ): self.non_production_ledger = OrderedDict() self.non_production_ledger["test_non_prod_1"] = IndyVdrLedger( - IndyVdrLedgerPool("test_non_prod_1"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_non_prod_1"), self.profile ) self.non_production_ledger["test_non_prod_2"] = IndyVdrLedger( - IndyVdrLedgerPool("test_non_prod_2"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_non_prod_2"), self.profile ) self.manager = MultiIndyVDRLedgerManager( self.profile, @@ -414,10 +422,10 @@ async def test_get_ledger_by_did_not_self_cert_non_prod( ): self.non_production_ledger = OrderedDict() self.non_production_ledger["test_non_prod_1"] = IndyVdrLedger( - IndyVdrLedgerPool("test_non_prod_1"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_non_prod_1"), self.profile ) self.non_production_ledger["test_non_prod_2"] = IndyVdrLedger( - IndyVdrLedgerPool("test_non_prod_2"), self.profile + await IndyVdrLedgerPool.get_or_create(name="test_non_prod_2"), self.profile ) self.manager = MultiIndyVDRLedgerManager( self.profile, @@ -425,11 +433,14 @@ async def test_get_ledger_by_did_not_self_cert_non_prod( ) get_nym_reply = deepcopy(GET_NYM_REPLY) get_nym_reply["result"]["data"]["verkey"] = "ABUF7uxYTxZ6qYdZ4G9e1Gi" - with mock.patch.object( - test_module.asyncio, "wait", mock.CoroutineMock() - ) as mock_wait, mock.patch.object( - test_module.SubTrie, "verify_spv_proof", mock.CoroutineMock() - ) as mock_verify_spv_proof: + with ( + mock.patch.object( + test_module.asyncio, "wait", mock.CoroutineMock() + ) as mock_wait, + mock.patch.object( + test_module.SubTrie, "verify_spv_proof", mock.CoroutineMock() + ) as mock_verify_spv_proof, + ): mock_build_get_nym_req.return_value = mock.MagicMock() mock_submit.return_value = get_nym_reply mock_wait.return_value = mock_submit.return_value @@ -450,11 +461,14 @@ async def test_get_ledger_by_did_not_self_cert_non_prod( async def test_lookup_did_in_configured_ledgers_x( self, mock_submit, mock_build_get_nym_req, mock_close, mock_open ): - with mock.patch.object( - test_module.asyncio, "wait", mock.CoroutineMock() - ) as mock_wait, mock.patch.object( - test_module.SubTrie, "verify_spv_proof", mock.CoroutineMock() - ) as mock_verify_spv_proof: + with ( + mock.patch.object( + test_module.asyncio, "wait", mock.CoroutineMock() + ) as mock_wait, + mock.patch.object( + test_module.SubTrie, "verify_spv_proof", mock.CoroutineMock() + ) as mock_verify_spv_proof, + ): mock_build_get_nym_req.return_value = mock.MagicMock() mock_submit.return_value = GET_NYM_INDY_VDR_REPLY mock_wait.return_value = mock_submit.return_value diff --git a/acapy_agent/ledger/multiple_ledger/tests/test_manager_provider.py b/acapy_agent/ledger/multiple_ledger/tests/test_manager_provider.py index ce9cc002a6..639c46c37f 100644 --- a/acapy_agent/ledger/multiple_ledger/tests/test_manager_provider.py +++ b/acapy_agent/ledger/multiple_ledger/tests/test_manager_provider.py @@ -57,7 +57,8 @@ async def test_provide_askar_manager(self): context = InjectionContext() profile = await create_test_profile() context.injector.bind_instance( - BaseLedger, IndyVdrLedger(IndyVdrLedgerPool("name"), profile) + BaseLedger, + IndyVdrLedger(await IndyVdrLedgerPool.get_or_create(name="name"), profile), ) provider = MultiIndyLedgerManagerProvider(profile) context.settings["ledger.ledger_config_list"] = LEDGER_CONFIG diff --git a/acapy_agent/ledger/routes.py b/acapy_agent/ledger/routes.py index 4d63eb5af3..fee5e15261 100644 --- a/acapy_agent/ledger/routes.py +++ b/acapy_agent/ledger/routes.py @@ -25,10 +25,10 @@ ENDPOINT_VALIDATE, INDY_DID_EXAMPLE, INDY_DID_VALIDATE, - INDY_RAW_PUBLIC_KEY_EXAMPLE, - INDY_RAW_PUBLIC_KEY_VALIDATE, INT_EPOCH_EXAMPLE, INT_EPOCH_VALIDATE, + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, UUID4_EXAMPLE, ) from ..multitenant.base import BaseMultitenantManager @@ -133,10 +133,10 @@ class RegisterLedgerNymQueryStringSchema(OpenAPISchema): ) verkey = fields.Str( required=True, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Verification key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) alias = fields.Str( @@ -230,10 +230,10 @@ class GetDIDVerkeyResponseSchema(OpenAPISchema): verkey = fields.Str( allow_none=True, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Full verification key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) diff --git a/acapy_agent/ledger/tests/test_indy_vdr.py b/acapy_agent/ledger/tests/test_indy_vdr.py index 927498c707..079c444a39 100644 --- a/acapy_agent/ledger/tests/test_indy_vdr.py +++ b/acapy_agent/ledger/tests/test_indy_vdr.py @@ -43,7 +43,9 @@ async def ledger(): profile.context.injector.bind_instance(BaseCache, InMemoryCache()) profile.context.injector.bind_instance(KeyTypes, KeyTypes()) - ledger = IndyVdrLedger(IndyVdrLedgerPool("test-ledger"), profile) + ledger = IndyVdrLedger( + await IndyVdrLedgerPool.get_or_create(name="test-ledger"), profile + ) async def open(): ledger.pool.handle = mock.MagicMock(indy_vdr.Pool) @@ -51,10 +53,12 @@ async def open(): async def close(): ledger.pool.handle = None - with mock.patch.object(ledger.pool, "open", open), mock.patch.object( - ledger.pool, "close", close - ), mock.patch.object( - ledger, "is_ledger_read_only", mock.CoroutineMock(return_value=False) + with ( + mock.patch.object(ledger.pool, "open", open), + mock.patch.object(ledger.pool, "close", close), + mock.patch.object( + ledger, "is_ledger_read_only", mock.CoroutineMock(return_value=False) + ), ): yield ledger @@ -338,14 +342,17 @@ async def test_send_schema_ledger_read_only( async with ledger: ledger.pool.read_only = True - with mock.patch.object( - ledger, - "check_existing_schema", - mock.CoroutineMock(return_value=False), - ), mock.patch.object( - ledger, - "is_ledger_read_only", - mock.CoroutineMock(return_value=True), + with ( + mock.patch.object( + ledger, + "check_existing_schema", + mock.CoroutineMock(return_value=False), + ), + mock.patch.object( + ledger, + "is_ledger_read_only", + mock.CoroutineMock(return_value=True), + ), ): with pytest.raises(LedgerError): await ledger.create_and_send_schema( @@ -768,25 +775,28 @@ async def test_update_endpoint_for_did_calls_attr_json(self, ledger: IndyVdrLedg test_did = await wallet.create_public_did(SOV, ED25519) async with ledger: - with mock.patch.object( - ledger, - "_construct_attr_json", - mock.CoroutineMock( - return_value=json.dumps( - { - "endpoint": { + with ( + mock.patch.object( + ledger, + "_construct_attr_json", + mock.CoroutineMock( + return_value=json.dumps( + { "endpoint": { - "endpoint": "https://url", - "routingKeys": [], + "endpoint": { + "endpoint": "https://url", + "routingKeys": [], + } } } - } - ) + ) + ), + ) as mock_construct_attr_json, + mock.patch.object( + ledger, + "get_all_endpoints_for_did", + mock.CoroutineMock(return_value={}), ), - ) as mock_construct_attr_json, mock.patch.object( - ledger, - "get_all_endpoints_for_did", - mock.CoroutineMock(return_value={}), ): await ledger.update_endpoint_for_did( test_did.did, diff --git a/acapy_agent/ledger/tests/test_routes.py b/acapy_agent/ledger/tests/test_routes.py index 00adc0952b..70e1092b56 100644 --- a/acapy_agent/ledger/tests/test_routes.py +++ b/acapy_agent/ledger/tests/test_routes.py @@ -134,13 +134,16 @@ async def test_get_verkey_multitenant(self): IndyLedgerRequestsExecutor, self.mock_ledger_requests_executor, ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as json_response: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as json_response, + ): self.ledger.get_key_for_did.return_value = self.test_verkey result = await test_module.get_did_verkey(self.request) json_response.assert_called_once_with( @@ -208,13 +211,16 @@ async def test_get_endpoint_multitenant(self): mock.MagicMock(MultitenantManager, autospec=True), ) self.request.query = {"did": self.test_did} - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as json_response: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as json_response, + ): self.ledger.get_endpoint_for_did.return_value = self.test_endpoint result = await test_module.get_did_endpoint(self.request) json_response.assert_called_once_with( @@ -327,13 +333,17 @@ async def test_register_nym_create_transaction_for_endorser(self): "conn_id": "dummy", } - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( create_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -371,13 +381,17 @@ async def test_register_nym_create_transaction_for_endorser_no_public_did(self): } self.profile.context.settings["endorser.author"] = True - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( create_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -414,11 +428,14 @@ async def test_register_nym_create_transaction_for_endorser_storage_x(self): "conn_id": "dummy", } - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( create_record=mock.CoroutineMock(side_effect=test_module.StorageError()) ) @@ -583,13 +600,16 @@ async def test_get_nym_role_multitenant(self): ) self.request.query = {"did": self.test_did} - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as json_response: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as json_response, + ): self.ledger.get_nym_role.return_value = Role.USER result = await test_module.get_nym_role(self.request) json_response.assert_called_once_with( diff --git a/acapy_agent/messaging/base_message.py b/acapy_agent/messaging/base_message.py index 91df02cb1f..766aa47898 100644 --- a/acapy_agent/messaging/base_message.py +++ b/acapy_agent/messaging/base_message.py @@ -1,6 +1,6 @@ """Base message.""" -from abc import ABC, abstractclassmethod, abstractmethod, abstractproperty +from abc import ABC, abstractmethod from enum import Enum, auto from typing import TYPE_CHECKING, Optional, Type @@ -23,15 +23,18 @@ class BaseMessage(ABC): the context of the plugin. """ - @abstractproperty + @property + @abstractmethod def _type(self) -> str: """Return message type.""" - @abstractproperty + @property + @abstractmethod def _id(self) -> str: """Return message id.""" - @abstractproperty + @property + @abstractmethod def _thread_id(self) -> Optional[str]: """Return message thread id.""" @@ -39,10 +42,12 @@ def _thread_id(self) -> Optional[str]: def serialize(self, msg_format: DIDCommVersion = DIDCommVersion.v1) -> dict: """Return serialized message in format specified.""" - @abstractclassmethod + @classmethod + @abstractmethod def deserialize(cls, value: dict, msg_format: DIDCommVersion = DIDCommVersion.v1): """Return message object deserialized from value in format specified.""" - @abstractproperty + @property + @abstractmethod def Handler(self) -> Type["BaseHandler"]: """Return reference to handler class.""" diff --git a/acapy_agent/messaging/credential_definitions/tests/test_routes.py b/acapy_agent/messaging/credential_definitions/tests/test_routes.py index 93ad921c48..65fb61e0b1 100644 --- a/acapy_agent/messaging/credential_definitions/tests/test_routes.py +++ b/acapy_agent/messaging/credential_definitions/tests/test_routes.py @@ -103,13 +103,17 @@ async def test_send_credential_definition_create_transaction_for_endorser(self): "conn_id": "dummy", } - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( create_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -152,11 +156,14 @@ async def test_send_credential_definition_create_transaction_for_endorser_storag "conn_id": "dummy", } - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -356,11 +363,14 @@ async def test_get_credential_definition_multitenant(self): mock.MagicMock(MultitenantManager, autospec=True), ) self.request.match_info = {"cred_def_id": CRED_DEF_ID} - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): result = await test_module.credential_definitions_get_credential_definition( self.request ) diff --git a/acapy_agent/messaging/credential_definitions/util.py b/acapy_agent/messaging/credential_definitions/util.py index fb732ecd44..1cca544747 100644 --- a/acapy_agent/messaging/credential_definitions/util.py +++ b/acapy_agent/messaging/credential_definitions/util.py @@ -13,8 +13,8 @@ INDY_DID_VALIDATE, INDY_SCHEMA_ID_EXAMPLE, INDY_SCHEMA_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, ) CRED_DEF_SENT_RECORD_TYPE = "cred_def_sent" @@ -41,8 +41,11 @@ class CredDefQueryStringSchema(OpenAPISchema): ) schema_version = fields.Str( required=False, - validate=INDY_VERSION_VALIDATE, - metadata={"description": "Schema version", "example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, ) issuer_did = fields.Str( required=False, diff --git a/acapy_agent/messaging/decorators/attach_decorator.py b/acapy_agent/messaging/decorators/attach_decorator.py index 98fc177996..7b17c6f670 100644 --- a/acapy_agent/messaging/decorators/attach_decorator.py +++ b/acapy_agent/messaging/decorators/attach_decorator.py @@ -29,8 +29,8 @@ BASE64_VALIDATE, BASE64URL_NO_PAD_EXAMPLE, BASE64URL_NO_PAD_VALIDATE, - INDY_ISO8601_DATETIME_EXAMPLE, - INDY_ISO8601_DATETIME_VALIDATE, + ISO8601_DATETIME_EXAMPLE, + ISO8601_DATETIME_VALIDATE, JWS_HEADER_KID_EXAMPLE, JWS_HEADER_KID_VALIDATE, SHA256_EXAMPLE, @@ -778,12 +778,12 @@ class Meta: ) lastmod_time = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": ( "Hint regarding last modification datetime, in ISO-8601 format" ), - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) description = fields.Str( diff --git a/acapy_agent/messaging/decorators/service_decorator.py b/acapy_agent/messaging/decorators/service_decorator.py index 0a4695a01c..e4f94b90e3 100644 --- a/acapy_agent/messaging/decorators/service_decorator.py +++ b/acapy_agent/messaging/decorators/service_decorator.py @@ -9,7 +9,10 @@ from marshmallow import EXCLUDE, fields from ..models.base import BaseModel, BaseModelSchema -from ..valid import INDY_RAW_PUBLIC_KEY_EXAMPLE, INDY_RAW_PUBLIC_KEY_VALIDATE +from ..valid import ( + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, +) class ServiceDecorator(BaseModel): @@ -82,10 +85,10 @@ class Meta: recipient_keys = fields.List( fields.Str( - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Recipient public key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ), data_key="recipientKeys", @@ -102,10 +105,10 @@ class Meta: ) routing_keys = fields.List( fields.Str( - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Routing key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ), data_key="routingKeys", diff --git a/acapy_agent/messaging/decorators/signature_decorator.py b/acapy_agent/messaging/decorators/signature_decorator.py index 22ec1b38c1..ed7a217611 100644 --- a/acapy_agent/messaging/decorators/signature_decorator.py +++ b/acapy_agent/messaging/decorators/signature_decorator.py @@ -3,7 +3,7 @@ import json import struct import time -from typing import Optional +from typing import Optional, Tuple from marshmallow import EXCLUDE, fields @@ -15,8 +15,8 @@ from ..valid import ( BASE64URL_EXAMPLE, BASE64URL_VALIDATE, - INDY_RAW_PUBLIC_KEY_EXAMPLE, - INDY_RAW_PUBLIC_KEY_VALIDATE, + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, ) @@ -86,7 +86,7 @@ async def create( signer=signer, ) - def decode(self) -> (object, int): + def decode(self) -> Tuple[object, int]: """Decode the signature to its timestamp and value. Returns: @@ -164,9 +164,9 @@ class Meta: ) signer = fields.Str( required=True, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Signer verification key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) diff --git a/acapy_agent/messaging/decorators/timing_decorator.py b/acapy_agent/messaging/decorators/timing_decorator.py index 7ad8fc8c86..cd8dd829d7 100644 --- a/acapy_agent/messaging/decorators/timing_decorator.py +++ b/acapy_agent/messaging/decorators/timing_decorator.py @@ -11,7 +11,7 @@ from ..models.base import BaseModel, BaseModelSchema from ..util import datetime_to_str -from ..valid import INDY_ISO8601_DATETIME_EXAMPLE, INDY_ISO8601_DATETIME_VALIDATE +from ..valid import ISO8601_DATETIME_EXAMPLE, ISO8601_DATETIME_VALIDATE class TimingDecorator(BaseModel): @@ -62,34 +62,34 @@ class Meta: in_time = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": "Time of message receipt", - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) out_time = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": "Time of message dispatch", - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) stale_time = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": "Time when message should be considered stale", - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) expires_time = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": "Time when message should be considered expired", - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) delay_milli = fields.Int( @@ -102,9 +102,9 @@ class Meta: ) wait_until_time = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": "Earliest time at which to perform processing", - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) diff --git a/acapy_agent/messaging/jsonld/tests/test_routes.py b/acapy_agent/messaging/jsonld/tests/test_routes.py index 992b907a49..a98d0818f2 100644 --- a/acapy_agent/messaging/jsonld/tests/test_routes.py +++ b/acapy_agent/messaging/jsonld/tests/test_routes.py @@ -353,13 +353,13 @@ async def test_verify_credential(self): mock_response.assert_called_once_with({"valid": True}) # expected response # compact, expand take a LONG TIME: do them once above, mock for error cases - with mock.patch.object( - jsonld, "compact", mock.MagicMock() - ) as mock_compact, mock.patch.object( - jsonld, "expand", mock.MagicMock() - ) as mock_expand, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object(jsonld, "compact", mock.MagicMock()) as mock_compact, + mock.patch.object(jsonld, "expand", mock.MagicMock()) as mock_expand, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_expand.return_value = [mock.MagicMock()] mock_compact.return_value = { "@context": "...", @@ -388,13 +388,13 @@ async def test_verify_credential(self): result = await test_module.verify(self.request) assert "error" in json.loads(result) - with mock.patch.object( - jsonld, "compact", mock.MagicMock() - ) as mock_compact, mock.patch.object( - jsonld, "expand", mock.MagicMock() - ) as mock_expand, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object(jsonld, "compact", mock.MagicMock()) as mock_compact, + mock.patch.object(jsonld, "expand", mock.MagicMock()) as mock_expand, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_expand.return_value = [mock.MagicMock()] mock_compact.return_value = { "@context": "...", @@ -503,13 +503,13 @@ async def test_sign_credential(self): # compact, expand take a LONG TIME: do them once above, mock for error cases posted_request = deepcopy(POSTED_REQUEST) self.request.json = mock.CoroutineMock(return_value=posted_request) - with mock.patch.object( - jsonld, "compact", mock.MagicMock() - ) as mock_compact, mock.patch.object( - jsonld, "expand", mock.MagicMock() - ) as mock_expand, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object(jsonld, "compact", mock.MagicMock()) as mock_compact, + mock.patch.object(jsonld, "expand", mock.MagicMock()) as mock_expand, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_expand.return_value = [mock.MagicMock()] mock_compact.return_value = {} # drop all attributes mock_response.side_effect = lambda x: json.dumps(x) diff --git a/acapy_agent/messaging/models/base_record.py b/acapy_agent/messaging/models/base_record.py index 100135486c..f32a8e0c4e 100644 --- a/acapy_agent/messaging/models/base_record.py +++ b/acapy_agent/messaging/models/base_record.py @@ -20,7 +20,7 @@ ) from ...storage.record import StorageRecord from ..util import datetime_to_str, time_now -from ..valid import INDY_ISO8601_DATETIME_EXAMPLE, INDY_ISO8601_DATETIME_VALIDATE +from ..valid import ISO8601_DATETIME_EXAMPLE, ISO8601_DATETIME_VALIDATE from .base import BaseModel, BaseModelError, BaseModelSchema LOGGER = logging.getLogger(__name__) @@ -591,18 +591,18 @@ class Meta: ) created_at = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": "Time of record creation", - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) updated_at = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": "Time of last record update", - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) diff --git a/acapy_agent/messaging/schemas/routes.py b/acapy_agent/messaging/schemas/routes.py index d8128a5398..c31983d264 100644 --- a/acapy_agent/messaging/schemas/routes.py +++ b/acapy_agent/messaging/schemas/routes.py @@ -49,8 +49,8 @@ B58, INDY_SCHEMA_ID_EXAMPLE, INDY_SCHEMA_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, UUID4_EXAMPLE, ) from .util import ( @@ -70,8 +70,11 @@ class SchemaSendRequestSchema(OpenAPISchema): ) schema_version = fields.Str( required=True, - validate=INDY_VERSION_VALIDATE, - metadata={"description": "Schema version", "example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, ) attributes = fields.List( fields.Str(metadata={"description": "attribute name", "example": "score"}), diff --git a/acapy_agent/messaging/schemas/tests/test_routes.py b/acapy_agent/messaging/schemas/tests/test_routes.py index eb29c9cf31..a84a05171d 100644 --- a/acapy_agent/messaging/schemas/tests/test_routes.py +++ b/acapy_agent/messaging/schemas/tests/test_routes.py @@ -104,13 +104,17 @@ async def test_send_schema_create_transaction_for_endorser(self): "conn_id": "dummy", } - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( create_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -155,11 +159,14 @@ async def test_send_schema_create_transaction_for_endorser_storage_x(self): "conn_id": "dummy", } - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( create_record=mock.CoroutineMock(side_effect=test_module.StorageError()) ) @@ -339,11 +346,14 @@ async def test_get_schema_multitenant(self): mock.MagicMock(MultitenantManager, autospec=True), ) self.request.match_info = {"schema_id": SCHEMA_ID} - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): result = await test_module.schemas_get_schema(self.request) assert result == mock_response.return_value mock_response.assert_called_once_with( diff --git a/acapy_agent/messaging/schemas/util.py b/acapy_agent/messaging/schemas/util.py index 35f8ce5bae..9a3e0cf989 100644 --- a/acapy_agent/messaging/schemas/util.py +++ b/acapy_agent/messaging/schemas/util.py @@ -11,8 +11,8 @@ INDY_DID_VALIDATE, INDY_SCHEMA_ID_EXAMPLE, INDY_SCHEMA_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, ) @@ -37,8 +37,11 @@ class SchemaQueryStringSchema(OpenAPISchema): ) schema_version = fields.Str( required=False, - validate=INDY_VERSION_VALIDATE, - metadata={"description": "Schema version", "example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, ) diff --git a/acapy_agent/messaging/tests/test_valid.py b/acapy_agent/messaging/tests/test_valid.py index 8983d27964..4e4a348c8e 100644 --- a/acapy_agent/messaging/tests/test_valid.py +++ b/acapy_agent/messaging/tests/test_valid.py @@ -18,20 +18,20 @@ INDY_CRED_REV_ID_VALIDATE, INDY_DID_VALIDATE, INDY_EXTRA_WQL_VALIDATE, - INDY_ISO8601_DATETIME_VALIDATE, - INDY_PREDICATE_VALIDATE, - INDY_RAW_PUBLIC_KEY_VALIDATE, INDY_REV_REG_ID_VALIDATE, INDY_REV_REG_SIZE_VALIDATE, INDY_SCHEMA_ID_VALIDATE, - INDY_VERSION_VALIDATE, INDY_WQL_VALIDATE, INT_EPOCH_VALIDATE, + ISO8601_DATETIME_VALIDATE, JWS_HEADER_KID_VALIDATE, JWT_VALIDATE, + MAJOR_MINOR_VERSION_VALIDATE, NATURAL_NUM_VALIDATE, NUM_STR_NATURAL_VALIDATE, NUM_STR_WHOLE_VALIDATE, + PREDICATE_VALIDATE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, SHA256_VALIDATE, UUID4_VALIDATE, WHOLE_NUM_VALIDATE, @@ -122,9 +122,11 @@ def test_indy_raw_public_key(self): ] for non_indy_raw_public_key in non_indy_raw_public_keys: with self.assertRaises(ValidationError): - INDY_RAW_PUBLIC_KEY_VALIDATE(non_indy_raw_public_key) + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE(non_indy_raw_public_key) - INDY_RAW_PUBLIC_KEY_VALIDATE("Q4zqM7aXqm7gDQkUVLng9hQ4zqM7aXqm7gDQkUVLng9h") + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE( + "Q4zqM7aXqm7gDQkUVLng9hQ4zqM7aXqm7gDQkUVLng9h" + ) def test_jws_header_kid(self): non_kids = [ @@ -264,12 +266,12 @@ def test_version(self): non_versions = ["-1", "", "3_5", "3.5a"] for non_version in non_versions: with self.assertRaises(ValidationError): - INDY_VERSION_VALIDATE(non_version) + MAJOR_MINOR_VERSION_VALIDATE(non_version) - INDY_VERSION_VALIDATE("1.0") - INDY_VERSION_VALIDATE(".05") - INDY_VERSION_VALIDATE("1.2.3") - INDY_VERSION_VALIDATE("..") # perverse but technically OK + MAJOR_MINOR_VERSION_VALIDATE("1.0") + MAJOR_MINOR_VERSION_VALIDATE(".05") + MAJOR_MINOR_VERSION_VALIDATE("1.2.3") + MAJOR_MINOR_VERSION_VALIDATE("..") # perverse but technically OK def test_schema_id(self): non_schema_ids = [ @@ -292,12 +294,12 @@ def test_predicate(self): non_predicates = [">>", "", " >= ", "<<<=", "==", "=", "!="] for non_predicate in non_predicates: with self.assertRaises(ValidationError): - INDY_PREDICATE_VALIDATE(non_predicate) + PREDICATE_VALIDATE(non_predicate) - INDY_PREDICATE_VALIDATE("<") - INDY_PREDICATE_VALIDATE("<=") - INDY_PREDICATE_VALIDATE(">=") - INDY_PREDICATE_VALIDATE(">") + PREDICATE_VALIDATE("<") + PREDICATE_VALIDATE("<=") + PREDICATE_VALIDATE(">=") + PREDICATE_VALIDATE(">") def test_indy_date(self): non_datetimes = [ @@ -310,17 +312,17 @@ def test_indy_date(self): ] for non_datetime in non_datetimes: with self.assertRaises(ValidationError): - INDY_ISO8601_DATETIME_VALIDATE(non_datetime) - - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00Z") - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01T00:00:00Z") - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01T00:00:00") - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00") - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00+00:00") - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00-00:00") - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01 00:00-00:00") - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00.1-00:00") - INDY_ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00.123456-00:00") + ISO8601_DATETIME_VALIDATE(non_datetime) + + ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00Z") + ISO8601_DATETIME_VALIDATE("2020-01-01T00:00:00Z") + ISO8601_DATETIME_VALIDATE("2020-01-01T00:00:00") + ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00") + ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00+00:00") + ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00-00:00") + ISO8601_DATETIME_VALIDATE("2020-01-01 00:00-00:00") + ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00.1-00:00") + ISO8601_DATETIME_VALIDATE("2020-01-01 00:00:00.123456-00:00") def test_indy_wql(self): non_wqls = [ diff --git a/acapy_agent/messaging/valid.py b/acapy_agent/messaging/valid.py index 894c1a819b..398ec5a9b9 100644 --- a/acapy_agent/messaging/valid.py +++ b/acapy_agent/messaging/valid.py @@ -348,6 +348,21 @@ def __init__(self): ) +class AnoncredsDID(Regexp): + """Validate value against indy DID.""" + + EXAMPLE = "did:(method):WgWxqztrNooG92RXvxSTWv" + PATTERN = re.compile("^(did:[a-z]:.+$)?$") + + def __init__(self): + """Initialize the instance.""" + + super().__init__( + IndyDID.PATTERN, + error="Value {input} is not an decentralized identifier (DID)", + ) + + class DIDValidation(Regexp): """Validate value against any valid DID spec.""" @@ -386,8 +401,8 @@ def __init__(self): ) -class IndyRawPublicKey(Regexp): - """Validate value against indy (Ed25519VerificationKey2018) raw public key.""" +class RawPublicEd25519VerificationKey2018(Regexp): + """Validate value against (Ed25519VerificationKey2018) raw public key.""" EXAMPLE = "H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV" PATTERN = rf"^[{B58}]{{43,44}}$" @@ -396,7 +411,7 @@ def __init__(self): """Initialize the instance.""" super().__init__( - IndyRawPublicKey.PATTERN, + RawPublicEd25519VerificationKey2018.PATTERN, error="Value {input} is not a raw Ed25519VerificationKey2018 key", ) @@ -409,7 +424,9 @@ class RoutingKey(Regexp): """ EXAMPLE = DIDKey.EXAMPLE - PATTERN = re.compile(DIDKey.PATTERN.pattern + "|" + IndyRawPublicKey.PATTERN) + PATTERN = re.compile( + DIDKey.PATTERN.pattern + "|" + RawPublicEd25519VerificationKey2018.PATTERN + ) def __init__(self): """Initialize the instance.""" @@ -444,8 +461,23 @@ def __init__(self): ) -class IndyVersion(Regexp): - """Validate value against indy version specification.""" +class AnoncredsCredDefId(Regexp): + """Validate value against anoncreds credential definition identifier specification.""" + + EXAMPLE = "did:(method):3:CL:20:tag" + PATTERN = r"^(.+$)" + + def __init__(self): + """Initialize the instance.""" + + super().__init__( + IndyCredDefId.PATTERN, + error="Value {input} is not an anoncreds credential definition identifier", + ) + + +class MajorMinorVersion(Regexp): + """Validate value against major minor version specification.""" EXAMPLE = "1.0" PATTERN = r"^[0-9.]+$" @@ -454,8 +486,8 @@ def __init__(self): """Initialize the instance.""" super().__init__( - IndyVersion.PATTERN, - error="Value {input} is not an indy version (use only digits and '.')", + MajorMinorVersion.PATTERN, + error="Value {input} is not a valid version major minor version (use only digits and '.')", # noqa: E501 ) @@ -474,6 +506,21 @@ def __init__(self): ) +class AnoncredsSchemaId(Regexp): + """Validate value against indy schema identifier specification.""" + + EXAMPLE = "did:(method):2:schema_name:1.0" + PATTERN = r"^(.+$)" + + def __init__(self): + """Initialize the instance.""" + + super().__init__( + IndySchemaId.PATTERN, + error="Value {input} is not an anoncreds schema identifier", + ) + + class IndyRevRegId(Regexp): """Validate value against indy revocation registry identifier specification.""" @@ -494,6 +541,21 @@ def __init__(self): ) +class AnoncredsRevRegId(Regexp): + """Validate value against anoncreds revocation registry identifier specification.""" + + EXAMPLE = "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0" + PATTERN = r"^(.+$)" + + def __init__(self): + """Initialize the instance.""" + + super().__init__( + AnoncredsRevRegId.PATTERN, + error="Value {input} is not an anoncreds revocation registry identifier", + ) + + class IndyCredRevId(Regexp): """Validate value against indy credential revocation identifier specification.""" @@ -509,8 +571,8 @@ def __init__(self): ) -class IndyPredicate(OneOf): - """Validate value against indy predicate.""" +class Predicate(OneOf): + """Validate value against predicate.""" EXAMPLE = ">=" @@ -523,8 +585,8 @@ def __init__(self): ) -class IndyISO8601DateTime(Regexp): - """Validate value against ISO 8601 datetime format, indy profile.""" +class ISO8601DateTime(Regexp): + """Validate value against ISO 8601 datetime format.""" EXAMPLE = epoch_to_str(EXAMPLE_TIMESTAMP) PATTERN = ( @@ -536,7 +598,7 @@ def __init__(self): """Initialize the instance.""" super().__init__( - IndyISO8601DateTime.PATTERN, + ISO8601DateTime.PATTERN, error="Value {input} is not a date in valid format", ) @@ -943,29 +1005,38 @@ def __init__( GENERIC_DID_VALIDATE = MaybeIndyDID() GENERIC_DID_EXAMPLE = MaybeIndyDID.EXAMPLE -INDY_RAW_PUBLIC_KEY_VALIDATE = IndyRawPublicKey() -INDY_RAW_PUBLIC_KEY_EXAMPLE = IndyRawPublicKey.EXAMPLE +RAW_ED25519_2018_PUBLIC_KEY_VALIDATE = RawPublicEd25519VerificationKey2018() +RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE = RawPublicEd25519VerificationKey2018.EXAMPLE INDY_SCHEMA_ID_VALIDATE = IndySchemaId() INDY_SCHEMA_ID_EXAMPLE = IndySchemaId.EXAMPLE +ANONCREDS_SCHEMA_ID_VALIDATE = AnoncredsSchemaId() +ANONCREDS_SCHEMA_ID_EXAMPLE = AnoncredsSchemaId.EXAMPLE + INDY_CRED_DEF_ID_VALIDATE = IndyCredDefId() INDY_CRED_DEF_ID_EXAMPLE = IndyCredDefId.EXAMPLE +ANONCREDS_CRED_DEF_ID_VALIDATE = AnoncredsCredDefId() +ANONCREDS_CRED_DEF_ID_EXAMPLE = AnoncredsCredDefId.EXAMPLE + INDY_REV_REG_ID_VALIDATE = IndyRevRegId() INDY_REV_REG_ID_EXAMPLE = IndyRevRegId.EXAMPLE +ANONCREDS_REV_REG_ID_VALIDATE = AnoncredsRevRegId() +ANONCREDS_REV_REG_ID_EXAMPLE = AnoncredsRevRegId.EXAMPLE + INDY_CRED_REV_ID_VALIDATE = IndyCredRevId() INDY_CRED_REV_ID_EXAMPLE = IndyCredRevId.EXAMPLE -INDY_VERSION_VALIDATE = IndyVersion() -INDY_VERSION_EXAMPLE = IndyVersion.EXAMPLE +MAJOR_MINOR_VERSION_VALIDATE = MajorMinorVersion() +MAJOR_MINOR_VERSION_EXAMPLE = MajorMinorVersion.EXAMPLE -INDY_PREDICATE_VALIDATE = IndyPredicate() -INDY_PREDICATE_EXAMPLE = IndyPredicate.EXAMPLE +PREDICATE_VALIDATE = Predicate() +PREDICATE_EXAMPLE = Predicate.EXAMPLE -INDY_ISO8601_DATETIME_VALIDATE = IndyISO8601DateTime() -INDY_ISO8601_DATETIME_EXAMPLE = IndyISO8601DateTime.EXAMPLE +ISO8601_DATETIME_VALIDATE = ISO8601DateTime() +ISO8601_DATETIME_EXAMPLE = ISO8601DateTime.EXAMPLE RFC3339_DATETIME_VALIDATE = RFC3339DateTime() RFC3339_DATETIME_EXAMPLE = RFC3339DateTime.EXAMPLE @@ -1020,3 +1091,6 @@ def __init__( INDY_OR_KEY_DID_VALIDATE = IndyOrKeyDID() INDY_OR_KEY_DID_EXAMPLE = IndyOrKeyDID.EXAMPLE + +ANONCREDS_DID_VALIDATE = AnoncredsDID() +ANONCREDS_DID_EXAMPLE = AnoncredsDID.EXAMPLE diff --git a/acapy_agent/multitenant/admin/tests/test_routes.py b/acapy_agent/multitenant/admin/tests/test_routes.py index 0dc4101267..6f24c863de 100644 --- a/acapy_agent/multitenant/admin/tests/test_routes.py +++ b/acapy_agent/multitenant/admin/tests/test_routes.py @@ -51,11 +51,12 @@ async def test_format_wallet_record_removes_wallet_key(self): assert "wallet.key" not in formatted["settings"] async def test_wallets_list(self): - with mock.patch.object( - test_module, "WalletRecord", autospec=True - ) as mock_wallet_record, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "WalletRecord", autospec=True + ) as mock_wallet_record, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): wallets = [ mock.MagicMock( serialize=mock.MagicMock( @@ -110,11 +111,12 @@ async def test_wallets_list_x(self): async def test_wallets_list_query(self): self.request.query = {"wallet_name": "test"} - with mock.patch.object( - test_module, "WalletRecord", autospec=True - ) as mock_wallet_record, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "WalletRecord", autospec=True + ) as mock_wallet_record, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): wallets = [ mock.MagicMock( serialize=mock.MagicMock( @@ -654,11 +656,12 @@ async def test_wallet_get(self): return_value={"settings": {}, "wallet_id": "dummy"} ) - with mock.patch.object( - test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_wallet_record_retrieve_by_id, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_wallet_record_retrieve_by_id, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_wallet_record_retrieve_by_id.return_value = mock_wallet_record await test_module.wallet_get(self.request) @@ -698,11 +701,12 @@ async def test_wallet_create_token_managed(self): return_value={"settings": {}, "wallet_id": "dummy"} ) - with mock.patch.object( - test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_wallet_record_retrieve_by_id, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_wallet_record_retrieve_by_id, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_wallet_record_retrieve_by_id.return_value = mock_wallet_record mock_multitenant_mgr = mock.AsyncMock(BaseMultitenantManager, autospec=True) mock_multitenant_mgr.create_auth_token = mock.CoroutineMock( @@ -727,11 +731,12 @@ async def test_wallet_create_token_unmanaged(self): return_value={"settings": {}, "wallet_id": "dummy"} ) - with mock.patch.object( - test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_wallet_record_retrieve_by_id, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_wallet_record_retrieve_by_id, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_wallet_record_retrieve_by_id.return_value = mock_wallet_record mock_multitenant_mgr = mock.AsyncMock(BaseMultitenantManager, autospec=True) mock_multitenant_mgr.create_auth_token = mock.CoroutineMock( @@ -803,10 +808,11 @@ async def test_wallet_remove_managed(self): BaseMultitenantManager, mock_multitenant_mgr ) - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() + ), ): result = await test_module.wallet_remove(self.request) @@ -822,10 +828,11 @@ async def test_wallet_remove_unmanaged(self): self.profile.context.injector.bind_instance( BaseMultitenantManager, mock_multitenant_mgr ) - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + test_module.WalletRecord, "retrieve_by_id", mock.CoroutineMock() + ), ): result = await test_module.wallet_remove(self.request) diff --git a/acapy_agent/multitenant/manager.py b/acapy_agent/multitenant/manager.py index 1a6bda9030..8137e9dbe9 100644 --- a/acapy_agent/multitenant/manager.py +++ b/acapy_agent/multitenant/manager.py @@ -88,7 +88,7 @@ async def get_wallet_profile( # return anoncreds profile if explicitly set as wallet type if profile.context.settings.get("wallet.type") == "askar-anoncreds": - return AskarAnoncredsProfile( + return await AskarAnoncredsProfile.create( profile.opened, profile.context, ) diff --git a/acapy_agent/multitenant/single_wallet_askar_manager.py b/acapy_agent/multitenant/single_wallet_askar_manager.py index 157bd287e0..417bdfb572 100644 --- a/acapy_agent/multitenant/single_wallet_askar_manager.py +++ b/acapy_agent/multitenant/single_wallet_askar_manager.py @@ -107,13 +107,13 @@ async def get_wallet_profile( # return anoncreds profile if explicitly set as wallet type if profile_context.settings.get("wallet.type") == "askar-anoncreds": - return AskarAnoncredsProfile( + return await AskarAnoncredsProfile.create( self._multitenant_profile.opened, profile_context, profile_id=wallet_record.wallet_id, ) - return AskarProfile( + return await AskarProfile.create( self._multitenant_profile.opened, profile_context, profile_id=wallet_record.wallet_id, diff --git a/acapy_agent/multitenant/tests/test_base.py b/acapy_agent/multitenant/tests/test_base.py index 88834434f0..dbfb40a85c 100644 --- a/acapy_agent/multitenant/tests/test_base.py +++ b/acapy_agent/multitenant/tests/test_base.py @@ -210,11 +210,10 @@ async def test_create_wallet_saves_wallet_record_creates_profile(self): mock_route_manager.route_verkey = mock.CoroutineMock() self.context.injector.bind_instance(RouteManager, mock_route_manager) - with mock.patch.object( - WalletRecord, "save" - ) as wallet_record_save, mock.patch.object( - self.manager, "get_wallet_profile" - ) as get_wallet_profile: + with ( + mock.patch.object(WalletRecord, "save") as wallet_record_save, + mock.patch.object(self.manager, "get_wallet_profile") as get_wallet_profile, + ): get_wallet_profile.return_value = await create_test_profile() wallet_record = await self.manager.create_wallet( @@ -247,13 +246,11 @@ async def test_create_wallet_adds_wallet_route(self): mock_route_manager = mock.MagicMock() mock_route_manager.route_verkey = mock.CoroutineMock() - with mock.patch.object( - WalletRecord, "save" - ) as wallet_record_save, mock.patch.object( - self.manager, "get_wallet_profile" - ) as get_wallet_profile, mock.patch.object( - BaseWallet, "get_public_did" - ) as get_public_did: + with ( + mock.patch.object(WalletRecord, "save") as wallet_record_save, + mock.patch.object(self.manager, "get_wallet_profile") as get_wallet_profile, + mock.patch.object(BaseWallet, "get_public_did") as get_public_did, + ): mock_profile = await create_test_profile() mock_profile.context.injector.bind_instance(RouteManager, mock_route_manager) get_wallet_profile.return_value = mock_profile @@ -277,11 +274,10 @@ async def test_create_wallet_adds_wallet_route(self): assert wallet_record.wallet_key == "test_key" async def test_update_wallet(self): - with mock.patch.object( - WalletRecord, "retrieve_by_id" - ) as retrieve_by_id, mock.patch.object( - WalletRecord, "save" - ) as wallet_record_save: + with ( + mock.patch.object(WalletRecord, "retrieve_by_id") as retrieve_by_id, + mock.patch.object(WalletRecord, "save") as wallet_record_save, + ): wallet_id = "test-wallet-id" retrieve_by_id.return_value = WalletRecord( wallet_id=wallet_id, @@ -315,17 +311,15 @@ async def test_remove_wallet_fails_no_wallet_key_but_required(self): await self.manager.remove_wallet("test") async def test_remove_wallet_removes_profile_wallet_storage_records(self): - with mock.patch.object( - WalletRecord, "retrieve_by_id" - ) as retrieve_by_id, mock.patch.object( - self.manager, "get_wallet_profile" - ) as get_wallet_profile, mock.patch.object( - self.manager, "remove_wallet_profile" - ) as remove_wallet_profile, mock.patch.object( - WalletRecord, "delete_record" - ) as wallet_delete_record, mock.patch.object( - AskarStorage, "delete_all_records" - ) as delete_all_records: + with ( + mock.patch.object(WalletRecord, "retrieve_by_id") as retrieve_by_id, + mock.patch.object(self.manager, "get_wallet_profile") as get_wallet_profile, + mock.patch.object( + self.manager, "remove_wallet_profile" + ) as remove_wallet_profile, + mock.patch.object(WalletRecord, "delete_record") as wallet_delete_record, + mock.patch.object(AskarStorage, "delete_all_records") as delete_all_records, + ): wallet_record = WalletRecord( wallet_id="test", key_management_mode=WalletRecord.MODE_UNMANAGED, @@ -555,10 +549,9 @@ async def test_get_profile_for_token_managed_wallet_x_iat_no_match(self): algorithm="HS256", ) - with mock.patch.object( - self.manager, "get_wallet_profile" - ) as get_wallet_profile, self.assertRaises( - MultitenantManagerError, msg="Token not valid" + with ( + mock.patch.object(self.manager, "get_wallet_profile") as get_wallet_profile, + self.assertRaises(MultitenantManagerError, msg="Token not valid"), ): await self.manager.get_profile_for_token(self.profile.context, token) @@ -632,12 +625,15 @@ async def test_get_wallets_by_message(self): async def test_get_profile_for_key(self): mock_wallet = mock.MagicMock() mock_wallet.requires_external_key = False - with mock.patch.object( - self.manager, - "_get_wallet_by_key", - mock.CoroutineMock(return_value=mock_wallet), - ), mock.patch.object( - self.manager, "get_wallet_profile", mock.CoroutineMock() - ) as mock_get_wallet_profile: + with ( + mock.patch.object( + self.manager, + "_get_wallet_by_key", + mock.CoroutineMock(return_value=mock_wallet), + ), + mock.patch.object( + self.manager, "get_wallet_profile", mock.CoroutineMock() + ) as mock_get_wallet_profile, + ): profile = await self.manager.get_profile_for_key(self.context, "test-verkey") assert profile == mock_get_wallet_profile.return_value diff --git a/acapy_agent/multitenant/tests/test_manager.py b/acapy_agent/multitenant/tests/test_manager.py index 7cd92e5bc7..cc633d2e09 100644 --- a/acapy_agent/multitenant/tests/test_manager.py +++ b/acapy_agent/multitenant/tests/test_manager.py @@ -169,11 +169,10 @@ async def side_effect(context, provision): assert profile.settings.get("mediation.clear") is True async def test_update_wallet_update_wallet_profile(self): - with mock.patch.object( - WalletRecord, "retrieve_by_id" - ) as retrieve_by_id, mock.patch.object( - WalletRecord, "save" - ) as wallet_record_save: + with ( + mock.patch.object(WalletRecord, "retrieve_by_id") as retrieve_by_id, + mock.patch.object(WalletRecord, "save") as wallet_record_save, + ): wallet_id = "test-wallet-id" wallet_profile = await create_test_profile() self.manager._profiles.put("test-wallet-id", wallet_profile) diff --git a/acapy_agent/multitenant/tests/test_route_manager.py b/acapy_agent/multitenant/tests/test_route_manager.py index 3a3218199d..4dad3d9dce 100644 --- a/acapy_agent/multitenant/tests/test_route_manager.py +++ b/acapy_agent/multitenant/tests/test_route_manager.py @@ -61,11 +61,16 @@ async def test_route_for_key_sub_mediator_no_base_mediator( mediation_id="test-mediation-id", connection_id="test-mediator-conn-id" ) - with mock.patch.object( - route_manager, "get_base_wallet_mediator", mock.CoroutineMock(return_value=None) - ), mock.patch.object( - RoutingManager, "create_route_record", mock.CoroutineMock() - ) as mock_create_route_record: + with ( + mock.patch.object( + route_manager, + "get_base_wallet_mediator", + mock.CoroutineMock(return_value=None), + ), + mock.patch.object( + RoutingManager, "create_route_record", mock.CoroutineMock() + ) as mock_create_route_record, + ): keylist_update = await route_manager._route_for_key( sub_profile, TEST_VERKEY, @@ -102,13 +107,16 @@ async def test_route_for_key_sub_mediator_and_base_mediator( connection_id="test-base-mediator-conn-id", ) - with mock.patch.object( - route_manager, - "get_base_wallet_mediator", - mock.CoroutineMock(return_value=base_mediation_record), - ), mock.patch.object( - RoutingManager, "create_route_record", mock.CoroutineMock() - ) as mock_create_route_record: + with ( + mock.patch.object( + route_manager, + "get_base_wallet_mediator", + mock.CoroutineMock(return_value=base_mediation_record), + ), + mock.patch.object( + RoutingManager, "create_route_record", mock.CoroutineMock() + ) as mock_create_route_record, + ): keylist_update = await route_manager._route_for_key( sub_profile, TEST_VERKEY, @@ -142,13 +150,16 @@ async def test_route_for_key_base_mediator_no_sub_mediator( connection_id="test-base-mediator-conn-id", ) - with mock.patch.object( - route_manager, - "get_base_wallet_mediator", - mock.CoroutineMock(return_value=base_mediation_record), - ), mock.patch.object( - RoutingManager, "create_route_record", mock.CoroutineMock() - ) as mock_create_route_record: + with ( + mock.patch.object( + route_manager, + "get_base_wallet_mediator", + mock.CoroutineMock(return_value=base_mediation_record), + ), + mock.patch.object( + RoutingManager, "create_route_record", mock.CoroutineMock() + ) as mock_create_route_record, + ): keylist_update = await route_manager._route_for_key( sub_profile, TEST_VERKEY, diff --git a/acapy_agent/multitenant/tests/test_single_wallet_askar_manager.py b/acapy_agent/multitenant/tests/test_single_wallet_askar_manager.py index 6ac3cbb77f..c59f098f18 100644 --- a/acapy_agent/multitenant/tests/test_single_wallet_askar_manager.py +++ b/acapy_agent/multitenant/tests/test_single_wallet_askar_manager.py @@ -43,13 +43,16 @@ async def test_get_wallet_profile_should_open_store_and_return_profile_with_wall }, ) - with mock.patch( - "acapy_agent.multitenant.single_wallet_askar_manager.wallet_config" - ) as wallet_config, mock.patch( - "acapy_agent.multitenant.single_wallet_askar_manager.AskarProfile", - ) as AskarProfile: + with ( + mock.patch( + "acapy_agent.multitenant.single_wallet_askar_manager.wallet_config" + ) as wallet_config, + mock.patch( + "acapy_agent.multitenant.single_wallet_askar_manager.AskarProfile", + ) as AskarProfile, + ): sub_wallet_profile_context = InjectionContext() - sub_wallet_profile = AskarProfile(None, None) + sub_wallet_profile = await AskarProfile.create(None, None) sub_wallet_profile.context.copy.return_value = sub_wallet_profile_context def side_effect(context, provision): @@ -115,13 +118,16 @@ async def test_get_anoncreds_wallet_profile_should_open_store_and_return_anoncre }, ) - with mock.patch( - "acapy_agent.multitenant.single_wallet_askar_manager.wallet_config" - ) as wallet_config, mock.patch( - "acapy_agent.multitenant.single_wallet_askar_manager.AskarAnoncredsProfile", - ) as AskarAnoncredsProfile: + with ( + mock.patch( + "acapy_agent.multitenant.single_wallet_askar_manager.wallet_config" + ) as wallet_config, + mock.patch( + "acapy_agent.multitenant.single_wallet_askar_manager.AskarAnoncredsProfile", + ) as AskarAnoncredsProfile, + ): sub_wallet_profile_context = InjectionContext() - sub_wallet_profile = AskarAnoncredsProfile(None, None) + sub_wallet_profile = await AskarAnoncredsProfile.create(None, None) sub_wallet_profile.context.copy.return_value = sub_wallet_profile_context def side_effect(context, provision): @@ -144,7 +150,7 @@ async def test_get_wallet_profile_should_create_profile(self): with mock.patch( "acapy_agent.multitenant.single_wallet_askar_manager.AskarProfile" ) as AskarProfile: - sub_wallet_profile = AskarProfile(None, None) + sub_wallet_profile = await AskarProfile.create(None, None) sub_wallet_profile.context.copy.return_value = InjectionContext() sub_wallet_profile.store.create_profile.return_value = create_profile_stub self.manager._multitenant_profile = sub_wallet_profile @@ -170,7 +176,7 @@ async def test_get_wallet_profile_should_use_custom_subwallet_name(self): with mock.patch( "acapy_agent.multitenant.single_wallet_askar_manager.AskarProfile" ) as AskarProfile: - sub_wallet_profile = AskarProfile(None, None) + sub_wallet_profile = await AskarProfile.create(None, None) sub_wallet_profile.context.copy.return_value = InjectionContext() def side_effect(context, provision): @@ -201,7 +207,7 @@ async def test_open_profiles(self): with mock.patch( "acapy_agent.multitenant.single_wallet_askar_manager.AskarProfile" ) as AskarProfile: - sub_wallet_profile = AskarProfile(None, None) + sub_wallet_profile = await AskarProfile.create(None, None) sub_wallet_profile.context.copy.return_value = InjectionContext() sub_wallet_profile.store.create_profile.return_value = create_profile_stub self.manager._multitenant_profile = sub_wallet_profile diff --git a/acapy_agent/protocols/actionmenu/v1_0/tests/test_routes.py b/acapy_agent/protocols/actionmenu/v1_0/tests/test_routes.py index 1b76449de6..268a252711 100644 --- a/acapy_agent/protocols/actionmenu/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/actionmenu/v1_0/tests/test_routes.py @@ -73,13 +73,13 @@ async def test_actionmenu_perform(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object( - test_module, "Perform", autospec=True - ) as mock_perform, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Perform", autospec=True) as mock_perform, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_record.retrieve_by_id = mock.CoroutineMock() await test_module.actionmenu_perform(self.request) @@ -93,9 +93,12 @@ async def test_actionmenu_perform_no_conn_record(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object(test_module, "Perform", autospec=True): + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Perform", autospec=True), + ): # Emulate storage not found (bad connection id) mock_conn_record.retrieve_by_id = mock.CoroutineMock( side_effect=StorageNotFoundError @@ -108,9 +111,12 @@ async def test_actionmenu_perform_conn_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object(test_module, "Perform", autospec=True): + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Perform", autospec=True), + ): # Emulate connection not ready mock_conn_record.retrieve_by_id = mock.CoroutineMock() mock_conn_record.retrieve_by_id.return_value.is_ready = False @@ -122,13 +128,13 @@ async def test_actionmenu_request(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object( - test_module, "MenuRequest", autospec=True - ) as menu_request, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "MenuRequest", autospec=True) as menu_request, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_record.retrieve_by_id = mock.CoroutineMock() await test_module.actionmenu_request(self.request) @@ -142,9 +148,12 @@ async def test_actionmenu_request_no_conn_record(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object(test_module, "Perform", autospec=True): + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Perform", autospec=True), + ): # Emulate storage not found (bad connection id) mock_conn_record.retrieve_by_id = mock.CoroutineMock( side_effect=StorageNotFoundError @@ -157,9 +166,12 @@ async def test_actionmenu_request_conn_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object(test_module, "Perform", autospec=True): + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Perform", autospec=True), + ): # Emulate connection not ready mock_conn_record.retrieve_by_id = mock.CoroutineMock() mock_conn_record.retrieve_by_id.return_value.is_ready = False @@ -171,13 +183,13 @@ async def test_actionmenu_send(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object( - test_module, "Menu", autospec=True - ) as mock_menu, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Menu", autospec=True) as mock_menu, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_record.retrieve_by_id = mock.CoroutineMock() mock_menu.deserialize = mock.MagicMock() @@ -192,11 +204,12 @@ async def test_actionmenu_send_deserialize_x(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object( - test_module, "Menu", autospec=True - ) as mock_menu: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Menu", autospec=True) as mock_menu, + ): mock_conn_record.retrieve_by_id = mock.CoroutineMock() mock_menu.deserialize = mock.MagicMock( side_effect=test_module.BaseModelError("cannot deserialize") @@ -209,11 +222,12 @@ async def test_actionmenu_send_no_conn_record(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object( - test_module, "Menu", autospec=True - ) as mock_menu: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Menu", autospec=True) as mock_menu, + ): mock_menu.deserialize = mock.MagicMock() # Emulate storage not found (bad connection id) @@ -228,11 +242,12 @@ async def test_actionmenu_send_conn_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_record, mock.patch.object( - test_module, "Menu", autospec=True - ) as mock_menu: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_record, + mock.patch.object(test_module, "Menu", autospec=True) as mock_menu, + ): mock_menu.deserialize = mock.MagicMock() # Emulate connection not ready diff --git a/acapy_agent/protocols/basicmessage/v1_0/messages/basicmessage.py b/acapy_agent/protocols/basicmessage/v1_0/messages/basicmessage.py index 840be506b9..1a8940a904 100644 --- a/acapy_agent/protocols/basicmessage/v1_0/messages/basicmessage.py +++ b/acapy_agent/protocols/basicmessage/v1_0/messages/basicmessage.py @@ -8,8 +8,8 @@ from .....messaging.agent_message import AgentMessage, AgentMessageSchema from .....messaging.util import datetime_now, datetime_to_str from .....messaging.valid import ( - INDY_ISO8601_DATETIME_EXAMPLE, - INDY_ISO8601_DATETIME_VALIDATE, + ISO8601_DATETIME_EXAMPLE, + ISO8601_DATETIME_VALIDATE, ) from ..message_types import BASIC_MESSAGE, PROTOCOL_PACKAGE @@ -63,12 +63,12 @@ class Meta: sent_time = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": ( "Time message was sent, ISO8601 with space date/time separator" ), - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) content = fields.Str( diff --git a/acapy_agent/protocols/basicmessage/v1_0/tests/test_routes.py b/acapy_agent/protocols/basicmessage/v1_0/tests/test_routes.py index cd15506fd4..736ae633d7 100644 --- a/acapy_agent/protocols/basicmessage/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/basicmessage/v1_0/tests/test_routes.py @@ -33,13 +33,15 @@ async def test_connections_send_message(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": self.test_conn_id} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_connection_record, mock.patch.object( - test_module, "BasicMessage", autospec=True - ) as mock_basic_message, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_connection_record, + mock.patch.object( + test_module, "BasicMessage", autospec=True + ) as mock_basic_message, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_connection_record.retrieve_by_id = mock.CoroutineMock() await test_module.connections_send_message(self.request) @@ -50,10 +52,11 @@ async def test_connections_send_message_no_conn_record(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": self.test_conn_id} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_connection_record, mock.patch.object( - test_module, "BasicMessage", autospec=True + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_connection_record, + mock.patch.object(test_module, "BasicMessage", autospec=True), ): # Emulate storage not found (bad connection id) mock_connection_record.retrieve_by_id = mock.CoroutineMock( @@ -67,11 +70,14 @@ async def test_connections_send_message_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"conn_id": self.test_conn_id} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_connection_record, mock.patch.object( - test_module, "BasicMessage", autospec=True - ) as mock_basic_message: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_connection_record, + mock.patch.object( + test_module, "BasicMessage", autospec=True + ) as mock_basic_message, + ): # Emulate connection not ready mock_connection_record.retrieve_by_id = mock.CoroutineMock() mock_connection_record.retrieve_by_id.return_value.is_ready = False diff --git a/acapy_agent/protocols/connections/v1_0/messages/connection_invitation.py b/acapy_agent/protocols/connections/v1_0/messages/connection_invitation.py index d983eb0ede..51e9f5f3c2 100644 --- a/acapy_agent/protocols/connections/v1_0/messages/connection_invitation.py +++ b/acapy_agent/protocols/connections/v1_0/messages/connection_invitation.py @@ -10,8 +10,8 @@ from .....messaging.valid import ( GENERIC_DID_EXAMPLE, GENERIC_DID_VALIDATE, - INDY_RAW_PUBLIC_KEY_EXAMPLE, - INDY_RAW_PUBLIC_KEY_VALIDATE, + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, ) from .....wallet.util import b64_to_bytes, bytes_to_b64 from ..message_types import CONNECTION_INVITATION, PROTOCOL_PACKAGE @@ -131,10 +131,10 @@ class Meta: ) recipient_keys = fields.List( fields.Str( - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Recipient public key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ), data_key="recipientKeys", @@ -151,10 +151,10 @@ class Meta: ) routing_keys = fields.List( fields.Str( - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Routing key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ), data_key="routingKeys", diff --git a/acapy_agent/protocols/connections/v1_0/routes.py b/acapy_agent/protocols/connections/v1_0/routes.py index 8277484e40..0e415ceabc 100644 --- a/acapy_agent/protocols/connections/v1_0/routes.py +++ b/acapy_agent/protocols/connections/v1_0/routes.py @@ -29,8 +29,8 @@ GENERIC_DID_VALIDATE, INDY_DID_EXAMPLE, INDY_DID_VALIDATE, - INDY_RAW_PUBLIC_KEY_EXAMPLE, - INDY_RAW_PUBLIC_KEY_VALIDATE, + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, UUID4_EXAMPLE, UUID4_VALIDATE, ) @@ -94,10 +94,10 @@ class CreateInvitationRequestSchema(OpenAPISchema): recipient_keys = fields.List( fields.Str( - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Recipient public key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ), required=False, @@ -112,10 +112,10 @@ class CreateInvitationRequestSchema(OpenAPISchema): ) routing_keys = fields.List( fields.Str( - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Routing key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ), required=False, @@ -213,10 +213,10 @@ class ConnectionStaticResultSchema(OpenAPISchema): ) my_verkey = fields.Str( required=True, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "My verification key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) my_endpoint = fields.Str( @@ -231,10 +231,10 @@ class ConnectionStaticResultSchema(OpenAPISchema): ) their_verkey = fields.Str( required=True, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Remote verification key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) record = fields.Nested(ConnRecordSchema(), required=True) @@ -248,10 +248,10 @@ class ConnectionsListQueryStringSchema(PaginatedQuerySchema): ) invitation_key = fields.Str( required=False, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "invitation key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) my_did = fields.Str( diff --git a/acapy_agent/protocols/connections/v1_0/tests/test_manager.py b/acapy_agent/protocols/connections/v1_0/tests/test_manager.py index a96363dc00..eb2c5b7f6d 100644 --- a/acapy_agent/protocols/connections/v1_0/tests/test_manager.py +++ b/acapy_agent/protocols/connections/v1_0/tests/test_manager.py @@ -412,14 +412,18 @@ async def test_create_request_multitenant(self): endpoint=self.test_mediator_endpoint, ) - with mock.patch.object( - AskarWallet, "create_local_did", autospec=True - ) as mock_wallet_create_local_did, mock.patch.object( - ConnectionManager, "create_did_document", autospec=True - ) as create_did_document, mock.patch.object( - self.route_manager, - "mediation_records_for_connection", - mock.CoroutineMock(return_value=[mediation_record]), + with ( + mock.patch.object( + AskarWallet, "create_local_did", autospec=True + ) as mock_wallet_create_local_did, + mock.patch.object( + ConnectionManager, "create_did_document", autospec=True + ) as create_did_document, + mock.patch.object( + self.route_manager, + "mediation_records_for_connection", + mock.CoroutineMock(return_value=[mediation_record]), + ), ): mock_wallet_create_local_did.return_value = DIDInfo( self.test_did, @@ -465,14 +469,16 @@ async def test_create_request_mediation_id(self): # Ensure the path with new did creation is hit record.my_did = None - with mock.patch.object( - ConnectionManager, "create_did_document", autospec=True - ) as create_did_document, mock.patch.object( - AskarWallet, "create_local_did" - ) as create_local_did, mock.patch.object( - self.route_manager, - "mediation_records_for_connection", - mock.CoroutineMock(return_value=[mediation_record]), + with ( + mock.patch.object( + ConnectionManager, "create_did_document", autospec=True + ) as create_did_document, + mock.patch.object(AskarWallet, "create_local_did") as create_local_did, + mock.patch.object( + self.route_manager, + "mediation_records_for_connection", + mock.CoroutineMock(return_value=[mediation_record]), + ), ): did_info = DIDInfo( did=self.test_did, @@ -516,14 +522,16 @@ async def test_create_request_default_mediator(self): # Ensure the path with new did creation is hit record.my_did = None - with mock.patch.object( - ConnectionManager, "create_did_document", autospec=True - ) as create_did_document, mock.patch.object( - AskarWallet, "create_local_did" - ) as create_local_did, mock.patch.object( - self.route_manager, - "mediation_records_for_connection", - mock.CoroutineMock(return_value=[mediation_record]), + with ( + mock.patch.object( + ConnectionManager, "create_did_document", autospec=True + ) as create_did_document, + mock.patch.object(AskarWallet, "create_local_did") as create_local_did, + mock.patch.object( + self.route_manager, + "mediation_records_for_connection", + mock.CoroutineMock(return_value=[mediation_record]), + ), ): did_info = DIDInfo( did=self.test_did, @@ -565,18 +573,18 @@ async def test_receive_request_public_did_oob_invite(self): ) self.context.update_settings({"public_invites": True}) - with mock.patch.object( - ConnRecord, "connection_id", autospec=True - ), mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "attach_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_id", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_invitation_msg_id, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "connection_id", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnRecord, "attach_request", autospec=True), + mock.patch.object(ConnRecord, "retrieve_by_id", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_invitation_msg_id, + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_conn_retrieve_by_invitation_msg_id.return_value = ConnRecord() conn_rec = await self.manager.receive_request(mock_request, receipt) @@ -606,18 +614,19 @@ async def test_receive_request_public_did_unsolicited_fails(self): ) self.context.update_settings({"public_invites": True}) - with self.assertRaises(ConnectionManagerError), mock.patch.object( - ConnRecord, "connection_id", autospec=True - ), mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "attach_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_id", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_invitation_msg_id, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + self.assertRaises(ConnectionManagerError), + mock.patch.object(ConnRecord, "connection_id", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnRecord, "attach_request", autospec=True), + mock.patch.object(ConnRecord, "retrieve_by_id", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_invitation_msg_id, + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_conn_retrieve_by_invitation_msg_id.return_value = None await self.manager.receive_request(mock_request, receipt) @@ -646,20 +655,20 @@ async def test_receive_request_public_did_conn_invite(self): mock_connection_record.attach_request = mock.CoroutineMock() self.context.update_settings({"public_invites": True}) - with mock.patch.object( - ConnRecord, "connection_id", autospec=True - ), mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "attach_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_id", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object( - ConnRecord, - "retrieve_by_invitation_msg_id", - mock.CoroutineMock(return_value=mock_connection_record), - ), mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "connection_id", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnRecord, "attach_request", autospec=True), + mock.patch.object(ConnRecord, "retrieve_by_id", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object( + ConnRecord, + "retrieve_by_invitation_msg_id", + mock.CoroutineMock(return_value=mock_connection_record), + ), + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): conn_rec = await self.manager.receive_request(mock_request, receipt) assert conn_rec @@ -685,18 +694,18 @@ async def test_receive_request_public_did_unsolicited(self): self.context.update_settings({"public_invites": True}) self.context.update_settings({"requests_through_public_did": True}) - with mock.patch.object( - ConnRecord, "connection_id", autospec=True - ), mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "attach_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_id", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_invitation_msg_id, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "connection_id", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnRecord, "attach_request", autospec=True), + mock.patch.object(ConnRecord, "retrieve_by_id", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_invitation_msg_id, + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_conn_retrieve_by_invitation_msg_id.return_value = None conn_rec = await self.manager.receive_request(mock_request, receipt) @@ -721,11 +730,12 @@ async def test_receive_request_public_did_no_did_doc(self): ) self.context.update_settings({"public_invites": True}) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "attach_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_id", autospec=True - ), mock.patch.object(ConnRecord, "retrieve_request", autospec=True): + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnRecord, "attach_request", autospec=True), + mock.patch.object(ConnRecord, "retrieve_by_id", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + ): with self.assertRaises(ConnectionManagerError): await self.manager.receive_request(mock_request, receipt) @@ -749,11 +759,12 @@ async def test_receive_request_public_did_wrong_did(self): ) self.context.update_settings({"public_invites": True}) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "attach_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_id", autospec=True - ), mock.patch.object(ConnRecord, "retrieve_request", autospec=True): + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnRecord, "attach_request", autospec=True), + mock.patch.object(ConnRecord, "retrieve_by_id", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + ): with self.assertRaises(ConnectionManagerError): await self.manager.receive_request(mock_request, receipt) @@ -775,13 +786,13 @@ async def test_receive_request_public_did_no_public_invites(self): ) self.context.update_settings({"public_invites": False}) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "attach_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_id", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()): + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnRecord, "attach_request", autospec=True), + mock.patch.object(ConnRecord, "retrieve_by_id", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()), + ): with self.assertRaises(ConnectionManagerError): await self.manager.receive_request(mock_request, receipt) @@ -807,16 +818,17 @@ async def test_receive_request_public_did_no_auto_accept(self): self.context.update_settings( {"public_invites": True, "debug.auto_accept_requests": False} ) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "attach_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_id", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_invitation_msg_id, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnRecord, "attach_request", autospec=True), + mock.patch.object(ConnRecord, "retrieve_by_id", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_invitation_msg_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_invitation_msg_id, + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_conn_retrieve_by_invitation_msg_id.return_value = ConnRecord() conn_rec = await self.manager.receive_request(mock_request, receipt) @@ -828,11 +840,13 @@ async def test_receive_request_public_did_no_auto_accept(self): async def test_create_response(self): conn_rec = ConnRecord(state=ConnRecord.State.REQUEST.rfc160) - with mock.patch.object(ConnRecord, "log_state", autospec=True), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnectionResponse, "sign_field", autospec=True - ), mock.patch.object(conn_rec, "metadata_get", mock.CoroutineMock()): + with ( + mock.patch.object(ConnRecord, "log_state", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnectionResponse, "sign_field", autospec=True), + mock.patch.object(conn_rec, "metadata_get", mock.CoroutineMock()), + ): await self.manager.create_response(conn_rec, "http://10.20.30.40:5060/") async def test_create_response_multitenant(self): @@ -849,22 +863,25 @@ async def test_create_response_multitenant(self): endpoint=self.test_mediator_endpoint, ) - with mock.patch.object(ConnRecord, "log_state", autospec=True), mock.patch.object( - ConnRecord, "save", autospec=True - ), mock.patch.object( - ConnRecord, "metadata_get", mock.CoroutineMock(return_value=False) - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object( - ConnectionResponse, "sign_field", autospec=True - ), mock.patch.object( - AskarWallet, "create_local_did", autospec=True - ) as mock_wallet_create_local_did, mock.patch.object( - ConnectionManager, "create_did_document", autospec=True - ) as create_did_document, mock.patch.object( - self.route_manager, - "mediation_records_for_connection", - mock.CoroutineMock(return_value=[mediation_record]), + with ( + mock.patch.object(ConnRecord, "log_state", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "metadata_get", mock.CoroutineMock(return_value=False) + ), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object(ConnectionResponse, "sign_field", autospec=True), + mock.patch.object( + AskarWallet, "create_local_did", autospec=True + ) as mock_wallet_create_local_did, + mock.patch.object( + ConnectionManager, "create_did_document", autospec=True + ) as create_did_document, + mock.patch.object( + self.route_manager, + "mediation_records_for_connection", + mock.CoroutineMock(return_value=[mediation_record]), + ), ): mock_wallet_create_local_did.return_value = DIDInfo( self.test_did, @@ -921,21 +938,24 @@ async def test_create_response_mediation(self): # Ensure the path with new did creation is hit record.my_did = None - with mock.patch.object(ConnRecord, "log_state", autospec=True), mock.patch.object( - ConnRecord, "save", autospec=True - ), mock.patch.object( - record, "metadata_get", mock.CoroutineMock(return_value=False) - ), mock.patch.object( - ConnectionManager, "create_did_document", autospec=True - ) as create_did_document, mock.patch.object( - AskarWallet, "create_local_did" - ) as create_local_did, mock.patch.object( - self.route_manager, - "mediation_records_for_connection", - mock.CoroutineMock(return_value=[mediation_record]), - ), mock.patch.object( - record, "retrieve_request", autospec=True - ), mock.patch.object(ConnectionResponse, "sign_field", autospec=True): + with ( + mock.patch.object(ConnRecord, "log_state", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + record, "metadata_get", mock.CoroutineMock(return_value=False) + ), + mock.patch.object( + ConnectionManager, "create_did_document", autospec=True + ) as create_did_document, + mock.patch.object(AskarWallet, "create_local_did") as create_local_did, + mock.patch.object( + self.route_manager, + "mediation_records_for_connection", + mock.CoroutineMock(return_value=[mediation_record]), + ), + mock.patch.object(record, "retrieve_request", autospec=True), + mock.patch.object(ConnectionResponse, "sign_field", autospec=True), + ): did_info = DIDInfo( did=self.test_did, verkey=self.test_verkey, @@ -964,12 +984,14 @@ async def test_create_response_auto_send_mediation_request(self): ) conn_rec.my_did = None - with mock.patch.object(ConnRecord, "log_state", autospec=True), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnectionResponse, "sign_field", autospec=True - ), mock.patch.object( - conn_rec, "metadata_get", mock.CoroutineMock(return_value=True) + with ( + mock.patch.object(ConnRecord, "log_state", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object(ConnectionResponse, "sign_field", autospec=True), + mock.patch.object( + conn_rec, "metadata_get", mock.CoroutineMock(return_value=True) + ), ): await self.manager.create_response(conn_rec) @@ -988,11 +1010,16 @@ async def test_accept_response_find_by_thread_id(self): mock_response.verify_signed_field = mock.CoroutineMock(return_value="sig_verkey") receipt = MessageReceipt(recipient_did=self.test_did, recipient_did_public=True) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - MediationManager, "get_default_mediator", mock.CoroutineMock() - ), mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()): + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + MediationManager, "get_default_mediator", mock.CoroutineMock() + ), + mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()), + ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( did=self.test_target_did, did_doc=mock.MagicMock(did=self.test_target_did), @@ -1017,13 +1044,19 @@ async def test_accept_response_not_found_by_thread_id_receipt_has_sender_did(sel receipt = MessageReceipt(sender_did=self.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_did", mock.CoroutineMock() - ) as mock_conn_retrieve_by_did, mock.patch.object( - MediationManager, "get_default_mediator", mock.CoroutineMock() - ), mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()): + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_did", mock.CoroutineMock() + ) as mock_conn_retrieve_by_did, + mock.patch.object( + MediationManager, "get_default_mediator", mock.CoroutineMock() + ), + mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()), + ): mock_conn_retrieve_by_req_id.side_effect = StorageNotFoundError() mock_conn_retrieve_by_did.return_value = mock.MagicMock( did=self.test_target_did, @@ -1051,11 +1084,15 @@ async def test_accept_response_not_found_by_thread_id_nor_receipt_sender_did(sel receipt = MessageReceipt(sender_did=self.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_did", mock.CoroutineMock() - ) as mock_conn_retrieve_by_did: + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_did", mock.CoroutineMock() + ) as mock_conn_retrieve_by_did, + ): mock_conn_retrieve_by_req_id.side_effect = StorageNotFoundError() mock_conn_retrieve_by_did.side_effect = StorageNotFoundError() @@ -1072,9 +1109,12 @@ async def test_accept_response_find_by_thread_id_bad_state(self): receipt = MessageReceipt(sender_did=self.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id: + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( state=ConnRecord.State.ABANDONED.rfc23 ) @@ -1091,9 +1131,12 @@ async def test_accept_response_find_by_thread_id_no_connection_did_doc(self): receipt = MessageReceipt(sender_did=self.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id: + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( did=self.test_target_did, did_doc=mock.MagicMock(did=self.test_target_did), @@ -1113,9 +1156,12 @@ async def test_accept_response_find_by_thread_id_did_mismatch(self): receipt = MessageReceipt(sender_did=self.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id: + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( did=self.test_target_did, did_doc=mock.MagicMock(did=self.test_target_did), @@ -1135,10 +1181,14 @@ async def test_accept_response_verify_invitation_key_sign_failure(self): mock_response.verify_signed_field = mock.CoroutineMock(side_effect=ValueError) receipt = MessageReceipt(recipient_did=self.test_did, recipient_did_public=True) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - MediationManager, "get_default_mediator", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + MediationManager, "get_default_mediator", mock.CoroutineMock() + ), ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( did=self.test_target_did, @@ -1162,11 +1212,16 @@ async def test_accept_response_auto_send_mediation_request(self): mock_response.verify_signed_field = mock.CoroutineMock(return_value="sig_verkey") receipt = MessageReceipt(recipient_did=self.test_did, recipient_did_public=True) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - MediationManager, "get_default_mediator", mock.CoroutineMock() - ), mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()): + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + MediationManager, "get_default_mediator", mock.CoroutineMock() + ), + mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()), + ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( did=self.test_target_did, did_doc=mock.MagicMock(did=self.test_target_did), diff --git a/acapy_agent/protocols/connections/v1_0/tests/test_routes.py b/acapy_agent/protocols/connections/v1_0/tests/test_routes.py index 05e279e75b..002ad67263 100644 --- a/acapy_agent/protocols/connections/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/connections/v1_0/tests/test_routes.py @@ -148,11 +148,12 @@ async def test_connections_retrieve(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock(return_value={"hello": "world"}) - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec await test_module.connections_retrieve(self.request) @@ -161,11 +162,12 @@ async def test_connections_retrieve(self): async def test_connections_endpoints(self): self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_mgr_cls.return_value = mock.MagicMock( get_endpoints=mock.CoroutineMock( return_value=("localhost:8080", "1.2.3.4:8081") @@ -182,9 +184,12 @@ async def test_connections_endpoints(self): async def test_connections_endpoints_x(self): self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr_cls, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr_cls, + mock.patch.object(test_module.web, "json_response"), + ): mock_conn_mgr_cls.return_value = mock.MagicMock( get_endpoints=mock.CoroutineMock(side_effect=StorageNotFoundError()) ) @@ -203,13 +208,15 @@ async def test_connections_metadata(self): self.request.match_info = {"conn_id": "dummy"} mock_conn_rec = mock.MagicMock() - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - mock_conn_rec, "metadata_get_all", mock.CoroutineMock() - ) as mock_metadata_get_all, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object( + mock_conn_rec, "metadata_get_all", mock.CoroutineMock() + ) as mock_metadata_get_all, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec mock_metadata_get_all.return_value = {"hello": "world"} @@ -222,15 +229,16 @@ async def test_connections_metadata_get_single(self): mock_conn_rec = mock.MagicMock() self.request.query = {"key": "test"} - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - mock_conn_rec, "metadata_get_all", mock.CoroutineMock() - ), mock.patch.object( - mock_conn_rec, "metadata_get", mock.CoroutineMock() - ) as mock_metadata_get, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object(mock_conn_rec, "metadata_get_all", mock.CoroutineMock()), + mock.patch.object( + mock_conn_rec, "metadata_get", mock.CoroutineMock() + ) as mock_metadata_get, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec mock_metadata_get.return_value = {"test": "value"} @@ -242,11 +250,15 @@ async def test_connections_metadata_x(self): self.request.match_info = {"conn_id": "dummy"} mock_conn_rec = mock.MagicMock() - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - mock_conn_rec, "metadata_get_all", mock.CoroutineMock() - ) as mock_metadata_get_all, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object( + mock_conn_rec, "metadata_get_all", mock.CoroutineMock() + ) as mock_metadata_get_all, + mock.patch.object(test_module.web, "json_response"), + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec mock_metadata_get_all.side_effect = StorageNotFoundError() @@ -264,15 +276,18 @@ async def test_connections_metadata_set(self): return_value={"metadata": {"hello": "world"}} ) - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - mock_conn_rec, "metadata_get_all", mock.CoroutineMock() - ) as mock_metadata_get_all, mock.patch.object( - mock_conn_rec, "metadata_set", mock.CoroutineMock() - ) as mock_metadata_set, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object( + mock_conn_rec, "metadata_get_all", mock.CoroutineMock() + ) as mock_metadata_get_all, + mock.patch.object( + mock_conn_rec, "metadata_set", mock.CoroutineMock() + ) as mock_metadata_set, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec mock_metadata_get_all.return_value = {"hello": "world"} @@ -287,13 +302,16 @@ async def test_connections_metadata_set_x(self): return_value={"metadata": {"hello": "world"}} ) - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - mock_conn_rec, "metadata_get_all", mock.CoroutineMock() - ), mock.patch.object( - mock_conn_rec, "metadata_set", mock.CoroutineMock() - ) as mock_metadata_set, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object(mock_conn_rec, "metadata_get_all", mock.CoroutineMock()), + mock.patch.object( + mock_conn_rec, "metadata_set", mock.CoroutineMock() + ) as mock_metadata_set, + mock.patch.object(test_module.web, "json_response"), + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec mock_metadata_set.side_effect = StorageNotFoundError() @@ -345,11 +363,12 @@ async def test_connections_create_invitation(self): "multi_use": "true", } - with mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_mgr.return_value.create_invitation = mock.CoroutineMock( return_value=( mock.MagicMock( # connection record @@ -452,13 +471,15 @@ async def test_connections_receive_invitation(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - test_module.ConnectionInvitation, "deserialize", autospec=True - ), mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnectionInvitation, "deserialize", autospec=True + ), + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_mgr.return_value.receive_invitation = mock.CoroutineMock( return_value=mock_conn_rec ) @@ -476,10 +497,11 @@ async def test_connections_receive_invitation_bad(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - test_module.ConnectionInvitation, "deserialize", autospec=True - ) as mock_inv_deser, mock.patch.object( - test_module, "ConnectionManager", autospec=True + with ( + mock.patch.object( + test_module.ConnectionInvitation, "deserialize", autospec=True + ) as mock_inv_deser, + mock.patch.object(test_module, "ConnectionManager", autospec=True), ): mock_inv_deser.side_effect = test_module.BaseModelError() @@ -503,11 +525,14 @@ async def test_connections_receive_invitation_x_bad_mediation_id(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - test_module.ConnectionInvitation, "deserialize", autospec=True - ), mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr: + with ( + mock.patch.object( + test_module.ConnectionInvitation, "deserialize", autospec=True + ), + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + ): mock_conn_mgr.return_value.receive_invitation = mock.CoroutineMock( side_effect=StorageNotFoundError() ) @@ -525,13 +550,15 @@ async def test_connections_accept_invitation(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec mock_conn_mgr.return_value.create_request = mock.CoroutineMock() @@ -552,11 +579,14 @@ async def test_connections_accept_invitation_not_found(self): async def test_connections_accept_invitation_x(self): self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + ): mock_conn_mgr.return_value.create_request = mock.CoroutineMock( side_effect=test_module.ConnectionManagerError() ) @@ -568,11 +598,14 @@ async def test_connections_accept_invitation_x_bad_mediation_id(self): self.request.match_info = {"conn_id": "dummy"} self.request.query["mediation_id"] = "some-id" - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + ): mock_conn_mgr.return_value.create_request = mock.CoroutineMock( side_effect=StorageNotFoundError() ) @@ -589,13 +622,15 @@ async def test_connections_accept_request(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec mock_conn_mgr.return_value.create_response = mock.CoroutineMock() @@ -616,11 +651,15 @@ async def test_connections_accept_request_not_found(self): async def test_connections_accept_request_x(self): self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_conn_mgr.return_value.create_response = mock.CoroutineMock( side_effect=test_module.ConnectionManagerError() ) @@ -633,11 +672,12 @@ async def test_connections_remove(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.delete_record = mock.CoroutineMock() - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec await test_module.connections_remove(self.request) @@ -652,11 +692,12 @@ async def test_connections_remove_cache_key(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.delete_record = mock.CoroutineMock() assert (await cache.get("conn_rec_state::dummy")) == "active" - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec await test_module.connections_remove(self.request) @@ -716,11 +757,12 @@ async def test_connections_create_static(self): mock_their_info.did = "their_did" mock_their_info.verkey = "their_verkey" - with mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_conn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_conn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_mgr.return_value.create_static_connection = mock.CoroutineMock( return_value=(mock_my_info, mock_their_info, mock_conn_rec) ) diff --git a/acapy_agent/protocols/coordinate_mediation/v1_0/handlers/tests/test_keylist_update_response_handler.py b/acapy_agent/protocols/coordinate_mediation/v1_0/handlers/tests/test_keylist_update_response_handler.py index 8f7dbcc25d..4d32ebc819 100644 --- a/acapy_agent/protocols/coordinate_mediation/v1_0/handlers/tests/test_keylist_update_response_handler.py +++ b/acapy_agent/protocols/coordinate_mediation/v1_0/handlers/tests/test_keylist_update_response_handler.py @@ -57,11 +57,10 @@ async def test_handler_no_active_connection(self): async def test_handler(self): handler, responder = KeylistUpdateResponseHandler(), MockResponder() - with mock.patch.object( - MediationManager, "store_update_results" - ) as mock_store, mock.patch.object( - handler, "notify_keylist_updated" - ) as mock_notify: + with ( + mock.patch.object(MediationManager, "store_update_results") as mock_store, + mock.patch.object(handler, "notify_keylist_updated") as mock_notify, + ): await handler.handle(self.context, responder) mock_store.assert_called_once_with(TEST_CONN_ID, self.updated) mock_notify.assert_called_once_with( diff --git a/acapy_agent/protocols/coordinate_mediation/v1_0/handlers/tests/test_mediation_grant_handler.py b/acapy_agent/protocols/coordinate_mediation/v1_0/handlers/tests/test_mediation_grant_handler.py index 79b2ab6ae2..e494e4c83a 100644 --- a/acapy_agent/protocols/coordinate_mediation/v1_0/handlers/tests/test_mediation_grant_handler.py +++ b/acapy_agent/protocols/coordinate_mediation/v1_0/handlers/tests/test_mediation_grant_handler.py @@ -78,13 +78,16 @@ async def test_handler_connection_has_set_to_default_meta( handler, responder = MediationGrantHandler(), MockResponder() record = MediationRecord(connection_id=TEST_CONN_ID) await record.save(session) - with mock.patch.object( - context.connection_record, - "metadata_get", - mock.CoroutineMock(return_value=True), - ), mock.patch.object( - test_module, "MediationManager", autospec=True - ) as mock_mediation_manager: + with ( + mock.patch.object( + context.connection_record, + "metadata_get", + mock.CoroutineMock(return_value=True), + ), + mock.patch.object( + test_module, "MediationManager", autospec=True + ) as mock_mediation_manager, + ): await handler.handle(context, responder) mock_mediation_manager.return_value.set_default_mediator.assert_called_once_with( record @@ -127,12 +130,15 @@ async def test_handler_connection_no_set_to_default( handler, responder = MediationGrantHandler(), MockResponder() record = MediationRecord(connection_id=TEST_CONN_ID) await record.save(session) - with mock.patch.object( - context.connection_record, - "metadata_get", - mock.CoroutineMock(return_value=False), - ), mock.patch.object( - test_module, "MediationManager", autospec=True - ) as mock_mediation_manager: + with ( + mock.patch.object( + context.connection_record, + "metadata_get", + mock.CoroutineMock(return_value=False), + ), + mock.patch.object( + test_module, "MediationManager", autospec=True + ) as mock_mediation_manager, + ): await handler.handle(context, responder) mock_mediation_manager.return_value.set_default_mediator.assert_not_called() diff --git a/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_mediation_manager.py b/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_mediation_manager.py index 9bd237c9c0..c0ef5c6855 100644 --- a/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_mediation_manager.py +++ b/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_mediation_manager.py @@ -397,21 +397,27 @@ async def test_store_update_results( ), ] - with mock.patch.object( - RouteRecord, "query", mock.CoroutineMock() - ) as mock_route_rec_query, mock.patch.object( - test_module.LOGGER, "error", mock.MagicMock() - ) as mock_logger_error: + with ( + mock.patch.object( + RouteRecord, "query", mock.CoroutineMock() + ) as mock_route_rec_query, + mock.patch.object( + test_module.LOGGER, "error", mock.MagicMock() + ) as mock_logger_error, + ): mock_route_rec_query.side_effect = StorageNotFoundError("no record") await manager.store_update_results(TEST_CONN_ID, results) mock_logger_error.assert_called_once() - with mock.patch.object( - RouteRecord, "query", mock.CoroutineMock() - ) as mock_route_rec_query, mock.patch.object( - test_module.LOGGER, "error", mock.MagicMock() - ) as mock_logger_error: + with ( + mock.patch.object( + RouteRecord, "query", mock.CoroutineMock() + ) as mock_route_rec_query, + mock.patch.object( + test_module.LOGGER, "error", mock.MagicMock() + ) as mock_logger_error, + ): mock_route_rec_query.return_value = [ mock.MagicMock(delete_record=mock.CoroutineMock()) ] * 2 diff --git a/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_route_manager.py b/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_route_manager.py index 5ff5b4ac5b..86d9cc6bff 100644 --- a/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_route_manager.py +++ b/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_route_manager.py @@ -78,13 +78,14 @@ async def test_get_or_create_my_did_no_did( ): conn_record.my_did = None mock_did_info = mock.MagicMock() - with mock.patch.object( - AskarWallet, - "create_local_did", - mock.CoroutineMock(return_value=mock_did_info), - ) as mock_create_local_did, mock.patch.object( - conn_record, "save", mock.CoroutineMock() - ) as mock_save: + with ( + mock.patch.object( + AskarWallet, + "create_local_did", + mock.CoroutineMock(return_value=mock_did_info), + ) as mock_create_local_did, + mock.patch.object(conn_record, "save", mock.CoroutineMock()) as mock_save, + ): info = await route_manager.get_or_create_my_did(profile, conn_record) assert mock_did_info == info mock_create_local_did.assert_called_once() @@ -110,12 +111,15 @@ async def test_mediation_record_for_connection_mediation_id( profile: Profile, route_manager: RouteManager, conn_record: ConnRecord ): mediation_record = MediationRecord(mediation_id="test-mediation-id") - with mock.patch.object( - route_manager, - "mediation_record_if_id", - mock.CoroutineMock(return_value=mediation_record), - ) as mock_mediation_record_if_id, mock.patch.object( - route_manager, "save_mediator_for_connection", mock.CoroutineMock() + with ( + mock.patch.object( + route_manager, + "mediation_record_if_id", + mock.CoroutineMock(return_value=mediation_record), + ) as mock_mediation_record_if_id, + mock.patch.object( + route_manager, "save_mediator_for_connection", mock.CoroutineMock() + ), ): assert await route_manager.mediation_records_for_connection( profile, conn_record, mediation_record.mediation_id @@ -133,12 +137,15 @@ async def test_mediation_record_for_connection_mediation_metadata( conn_record.metadata_get.return_value = { MediationManager.METADATA_ID: mediation_record.mediation_id } - with mock.patch.object( - route_manager, - "mediation_record_if_id", - mock.CoroutineMock(return_value=mediation_record), - ) as mock_mediation_record_if_id, mock.patch.object( - route_manager, "save_mediator_for_connection", mock.CoroutineMock() + with ( + mock.patch.object( + route_manager, + "mediation_record_if_id", + mock.CoroutineMock(return_value=mediation_record), + ) as mock_mediation_record_if_id, + mock.patch.object( + route_manager, "save_mediator_for_connection", mock.CoroutineMock() + ), ): assert await route_manager.mediation_records_for_connection( profile, conn_record, "another-mediation-id" @@ -153,12 +160,15 @@ async def test_mediation_record_for_connection_default( profile: Profile, route_manager: RouteManager, conn_record: ConnRecord ): mediation_record = MediationRecord(mediation_id="test-mediation-id") - with mock.patch.object( - route_manager, - "mediation_record_if_id", - mock.CoroutineMock(return_value=mediation_record), - ) as mock_mediation_record_if_id, mock.patch.object( - route_manager, "save_mediator_for_connection", mock.CoroutineMock() + with ( + mock.patch.object( + route_manager, + "mediation_record_if_id", + mock.CoroutineMock(return_value=mediation_record), + ) as mock_mediation_record_if_id, + mock.patch.object( + route_manager, "save_mediator_for_connection", mock.CoroutineMock() + ), ): assert await route_manager.mediation_records_for_connection( profile, conn_record, None, or_default=True @@ -210,13 +220,16 @@ async def test_mediation_record_if_id_with_id_and_default( mediation_record = MediationRecord( mediation_id="test-mediation-id", state=MediationRecord.STATE_GRANTED ) - with mock.patch.object( - MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mediation_record), - ) as mock_retrieve_by_id, mock.patch.object( - MediationManager, "get_default_mediator", mock.CoroutineMock() - ) as mock_get_default_mediator: + with ( + mock.patch.object( + MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mediation_record), + ) as mock_retrieve_by_id, + mock.patch.object( + MediationManager, "get_default_mediator", mock.CoroutineMock() + ) as mock_get_default_mediator, + ): actual = await route_manager.mediation_record_if_id( profile, mediation_id=mediation_record.mediation_id, or_default=True ) @@ -233,13 +246,16 @@ async def test_mediation_record_if_id_without_id_and_default( mediation_record = MediationRecord( mediation_id="test-mediation-id", state=MediationRecord.STATE_GRANTED ) - with mock.patch.object( - MediationRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve_by_id, mock.patch.object( - MediationManager, - "get_default_mediator", - mock.CoroutineMock(return_value=mediation_record), - ) as mock_get_default_mediator: + with ( + mock.patch.object( + MediationRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve_by_id, + mock.patch.object( + MediationManager, + "get_default_mediator", + mock.CoroutineMock(return_value=mediation_record), + ) as mock_get_default_mediator, + ): actual = await route_manager.mediation_record_if_id( profile, mediation_id=None, or_default=True ) @@ -253,11 +269,16 @@ async def test_mediation_record_if_id_without_id_and_no_default( profile: Profile, route_manager: RouteManager, ): - with mock.patch.object( - MediationRecord, "retrieve_by_id", mock.CoroutineMock(return_value=None) - ) as mock_retrieve_by_id, mock.patch.object( - MediationManager, "get_default_mediator", mock.CoroutineMock(return_value=None) - ) as mock_get_default_mediator: + with ( + mock.patch.object( + MediationRecord, "retrieve_by_id", mock.CoroutineMock(return_value=None) + ) as mock_retrieve_by_id, + mock.patch.object( + MediationManager, + "get_default_mediator", + mock.CoroutineMock(return_value=None), + ) as mock_get_default_mediator, + ): assert ( await route_manager.mediation_record_if_id( profile, mediation_id=None, or_default=True @@ -319,21 +340,24 @@ async def test_route_connection_state_inviter_replace_key_none( mock_did_info = mock.MagicMock(DIDInfo) conn_record.invitation_key = TEST_RECORD_VERKEY - with mock.patch.object( - route_manager, - "get_or_create_my_did", - mock.CoroutineMock(return_value=mock_did_info), - ), mock.patch.object( - AskarWallet, - "get_public_did", - mock.CoroutineMock( - return_value=DIDInfo( - TEST_RECORD_DID, - TEST_RECORD_VERKEY, - None, - method=SOV, - key_type=ED25519, - ) + with ( + mock.patch.object( + route_manager, + "get_or_create_my_did", + mock.CoroutineMock(return_value=mock_did_info), + ), + mock.patch.object( + AskarWallet, + "get_public_did", + mock.CoroutineMock( + return_value=DIDInfo( + TEST_RECORD_DID, + TEST_RECORD_VERKEY, + None, + method=SOV, + key_type=ED25519, + ) + ), ), ): await route_manager.route_connection_as_inviter( @@ -355,11 +379,14 @@ async def test_route_connection_state_invitee( mediation_record = MediationRecord(mediation_id="test-mediation-id") conn_record.state = "invitation" conn_record.their_role = "responder" - with mock.patch.object( - route_manager, "route_connection_as_invitee", mock.CoroutineMock() - ) as mock_route_connection_as_invitee, mock.patch.object( - route_manager, "route_connection_as_inviter", mock.CoroutineMock() - ) as mock_route_connection_as_inviter: + with ( + mock.patch.object( + route_manager, "route_connection_as_invitee", mock.CoroutineMock() + ) as mock_route_connection_as_invitee, + mock.patch.object( + route_manager, "route_connection_as_inviter", mock.CoroutineMock() + ) as mock_route_connection_as_inviter, + ): await route_manager.route_connection(profile, conn_record, [mediation_record]) mock_route_connection_as_invitee.assert_called_once() mock_route_connection_as_inviter.assert_not_called() @@ -372,11 +399,14 @@ async def test_route_connection_state_inviter( mediation_record = MediationRecord(mediation_id="test-mediation-id") conn_record.state = "request" conn_record.their_role = "requester" - with mock.patch.object( - route_manager, "route_connection_as_invitee", mock.CoroutineMock() - ) as mock_route_connection_as_invitee, mock.patch.object( - route_manager, "route_connection_as_inviter", mock.CoroutineMock() - ) as mock_route_connection_as_inviter: + with ( + mock.patch.object( + route_manager, "route_connection_as_invitee", mock.CoroutineMock() + ) as mock_route_connection_as_invitee, + mock.patch.object( + route_manager, "route_connection_as_inviter", mock.CoroutineMock() + ) as mock_route_connection_as_inviter, + ): await route_manager.route_connection(profile, conn_record, [mediation_record]) mock_route_connection_as_inviter.assert_called_once() mock_route_connection_as_invitee.assert_not_called() diff --git a/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_routes.py b/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_routes.py index 773f31fbc6..cf0eda45ab 100644 --- a/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/coordinate_mediation/v1_0/tests/test_routes.py @@ -71,13 +71,14 @@ def test_mediation_sort_key(self): async def test_list_mediation_requests(self): self.request.query = {} - with mock.patch.object( - test_module.MediationRecord, - "query", - mock.CoroutineMock(return_value=[self.mock_record]), - ) as mock_query, mock.patch.object( - test_module.web, "json_response" - ) as json_response: + with ( + mock.patch.object( + test_module.MediationRecord, + "query", + mock.CoroutineMock(return_value=[self.mock_record]), + ) as mock_query, + mock.patch.object(test_module.web, "json_response") as json_response, + ): await test_module.list_mediation_requests(self.request) json_response.assert_called_once_with( {"results": [self.mock_record.serialize.return_value]} @@ -89,13 +90,14 @@ async def test_list_mediation_requests_filters(self): "state": MediationRecord.STATE_GRANTED, "conn_id": "test-conn-id", } - with mock.patch.object( - test_module.MediationRecord, - "query", - mock.CoroutineMock(return_value=[self.mock_record]), - ) as mock_query, mock.patch.object( - test_module.web, "json_response" - ) as json_response: + with ( + mock.patch.object( + test_module.MediationRecord, + "query", + mock.CoroutineMock(return_value=[self.mock_record]), + ) as mock_query, + mock.patch.object(test_module.web, "json_response") as json_response, + ): await test_module.list_mediation_requests(self.request) json_response.assert_called_once_with( {"results": [self.mock_record.serialize.return_value]} @@ -114,53 +116,63 @@ async def test_list_mediation_requests_x(self): await test_module.list_mediation_requests(self.request) async def test_list_mediation_requests_no_records(self): - with mock.patch.object( - test_module, - "MediationRecord", - mock.MagicMock(query=mock.CoroutineMock(return_value=[])), - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object( + test_module, + "MediationRecord", + mock.MagicMock(query=mock.CoroutineMock(return_value=[])), + ), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): await test_module.list_mediation_requests(self.request) mock_response.assert_called_once_with({"results": []}) async def test_retrieve_mediation_request(self): - with mock.patch.object( - test_module.MediationRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_mediation_record_retrieve, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.MediationRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_mediation_record_retrieve, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_mediation_record_retrieve.return_value = self.mock_record await test_module.retrieve_mediation_request(self.request) mock_response.assert_called_once_with(self.mock_record.serialize.return_value) mock_mediation_record_retrieve.assert_called() async def test_retrieve_mediation_request_x_not_found(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), - ), mock.patch.object(test_module.web, "json_response"), self.assertRaises( - test_module.web.HTTPNotFound + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + ), + mock.patch.object(test_module.web, "json_response"), + self.assertRaises(test_module.web.HTTPNotFound), ): await test_module.retrieve_mediation_request(self.request) async def test_retrieve_mediation_request_x_storage_error(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), mock.patch.object(test_module.web, "json_response"), self.assertRaises( - test_module.web.HTTPBadRequest + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + mock.patch.object(test_module.web, "json_response"), + self.assertRaises(test_module.web.HTTPBadRequest), ): await test_module.retrieve_mediation_request(self.request) async def test_delete_mediation_request(self): - with mock.patch.object( - test_module.MediationRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_mediation_record_retrieve, mock.patch.object( - self.mock_record, "delete_record", mock.CoroutineMock() - ) as mock_delete_record, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.MediationRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_mediation_record_retrieve, + mock.patch.object( + self.mock_record, "delete_record", mock.CoroutineMock() + ) as mock_delete_record, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_mediation_record_retrieve.return_value = self.mock_record await test_module.delete_mediation_request(self.request) mock_response.assert_called_once_with(self.mock_record.serialize.return_value) @@ -168,38 +180,45 @@ async def test_delete_mediation_request(self): mock_delete_record.assert_called() async def test_delete_mediation_request_x_not_found(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), - ), mock.patch.object(test_module.web, "json_response"), self.assertRaises( - test_module.web.HTTPNotFound + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + ), + mock.patch.object(test_module.web, "json_response"), + self.assertRaises(test_module.web.HTTPNotFound), ): await test_module.delete_mediation_request(self.request) async def test_delete_mediation_request_x_storage_error(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), mock.patch.object(test_module.web, "json_response"), self.assertRaises( - test_module.web.HTTPBadRequest + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + mock.patch.object(test_module.web, "json_response"), + self.assertRaises(test_module.web.HTTPBadRequest), ): await test_module.delete_mediation_request(self.request) async def test_request_mediation(self): body = {} self.request.json.return_value = body - with mock.patch.object( - test_module, "MediationManager", autospec=True - ) as mock_med_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - test_module.MediationRecord, - "exists_for_connection_id", - mock.CoroutineMock(return_value=False), - ), mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "MediationManager", autospec=True + ) as mock_med_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + test_module.MediationRecord, + "exists_for_connection_id", + mock.CoroutineMock(return_value=False), + ), + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), ): mock_med_mgr.return_value.prepare_request = mock.CoroutineMock( return_value=( @@ -218,52 +237,68 @@ async def test_request_mediation(self): async def test_request_mediation_x_conn_not_ready(self): body = {} self.request.json.return_value = body - with mock.patch.object( - test_module.ConnRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock.MagicMock(is_ready=False)), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.ConnRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock.MagicMock(is_ready=False)), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.request_mediation(self.request) async def test_request_mediation_x_already_exists(self): body = {} self.request.json.return_value = body - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object( - test_module.MediationRecord, - "exists_for_connection_id", - mock.CoroutineMock(return_value=True), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object( + test_module.MediationRecord, + "exists_for_connection_id", + mock.CoroutineMock(return_value=True), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.request_mediation(self.request) async def test_request_mediation_x_conn_not_found(self): body = {} self.request.json.return_value = body - with mock.patch.object( - test_module.ConnRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), - ), self.assertRaises(test_module.web.HTTPNotFound): + with ( + mock.patch.object( + test_module.ConnRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + ), + self.assertRaises(test_module.web.HTTPNotFound), + ): await test_module.request_mediation(self.request) async def test_request_mediation_x_storage_error(self): body = {} self.request.json.return_value = body - with mock.patch.object( - test_module.ConnRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.ConnRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.request_mediation(self.request) async def test_mediation_request_grant_role_server(self): self.mock_record.role = MediationRecord.ROLE_SERVER - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=self.mock_record), - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=self.mock_record), + ), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): await test_module.mediation_request_grant(self.request) mock_response.assert_called_once_with( self.mock_record.serialize.return_value, status=201 @@ -272,36 +307,48 @@ async def test_mediation_request_grant_role_server(self): async def test_mediation_request_grant_role_client_x(self): self.mock_record.role = MediationRecord.ROLE_CLIENT - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=self.mock_record), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=self.mock_record), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.mediation_request_grant(self.request) async def test_mediation_request_grant_x_rec_not_found(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), - ), self.assertRaises(test_module.web.HTTPNotFound): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + ), + self.assertRaises(test_module.web.HTTPNotFound), + ): await test_module.mediation_request_grant(self.request) async def test_mediation_request_grant_x_storage_error(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.mediation_request_grant(self.request) async def test_mediation_request_deny_role_server(self): self.mock_record.role = MediationRecord.ROLE_SERVER - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=self.mock_record), - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=self.mock_record), + ), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): await test_module.mediation_request_deny(self.request) mock_response.assert_called_once_with( self.mock_record.serialize.return_value, status=201 @@ -310,10 +357,11 @@ async def test_mediation_request_deny_role_server(self): async def test_mediation_request_deny_role_client_x(self): self.mock_record.role = MediationRecord.ROLE_CLIENT - with mock.patch.object( - test_module.MediationRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_mediation_record_retrieve, mock.patch.object( - test_module.web, "json_response" + with ( + mock.patch.object( + test_module.MediationRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_mediation_record_retrieve, + mock.patch.object(test_module.web, "json_response"), ): mock_mediation_record_retrieve.return_value = mock.MagicMock( role=MediationRecord.ROLE_CLIENT @@ -322,19 +370,25 @@ async def test_mediation_request_deny_role_client_x(self): await test_module.mediation_request_deny(self.request) async def test_mediation_request_deny_x_rec_not_found(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), - ), self.assertRaises(test_module.web.HTTPNotFound): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + ), + self.assertRaises(test_module.web.HTTPNotFound), + ): await test_module.mediation_request_deny(self.request) async def test_mediation_request_deny_x_storage_error(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.mediation_request_deny(self.request) async def test_get_keylist(self): @@ -348,17 +402,19 @@ async def test_get_keylist(self): ) ] - with mock.patch.object( - test_module.RouteRecord, - "query", - mock.CoroutineMock(return_value=query_results), - ) as mock_query, mock.patch.object( - self.profile, - "session", - mock.MagicMock(return_value=session), - ) as mock_session, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.RouteRecord, + "query", + mock.CoroutineMock(return_value=query_results), + ) as mock_query, + mock.patch.object( + self.profile, + "session", + mock.MagicMock(return_value=session), + ) as mock_session, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): await test_module.get_keylist(self.request) mock_response.assert_called_once_with( {"results": [{"serialized": "route record"}]}, status=200 @@ -370,27 +426,32 @@ async def test_get_keylist(self): async def test_get_keylist_no_matching_records(self): session = await self.profile.session() - with mock.patch.object( - test_module.RouteRecord, - "query", - mock.CoroutineMock(return_value=[]), - ) as mock_query, mock.patch.object( - self.profile, - "session", - mock.MagicMock(return_value=session), - ) as mock_session, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.RouteRecord, + "query", + mock.CoroutineMock(return_value=[]), + ) as mock_query, + mock.patch.object( + self.profile, + "session", + mock.MagicMock(return_value=session), + ) as mock_session, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): await test_module.get_keylist(self.request) mock_query.assert_called_once_with(mock_session.return_value, {}) mock_response.assert_called_once_with({"results": []}, status=200) async def test_get_keylist_storage_error(self): - with mock.patch.object( - test_module.RouteRecord, - "query", - mock.CoroutineMock(side_effect=test_module.StorageError), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.RouteRecord, + "query", + mock.CoroutineMock(side_effect=test_module.StorageError), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.get_keylist(self.request) async def test_send_keylist_update(self): @@ -421,18 +482,23 @@ async def test_send_keylist_update(self): self.request.json.return_value = body - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock( - return_value=mock.MagicMock( - state=MediationRecord.STATE_GRANTED, connection_id="test-conn-id" - ) + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock( + return_value=mock.MagicMock( + state=MediationRecord.STATE_GRANTED, connection_id="test-conn-id" + ) + ), + ), + mock.patch.object( + test_module.web, + "json_response", + mock.MagicMock( + side_effect=lambda *args, **kwargs: [*args, *kwargs.values()] + ), ), - ), mock.patch.object( - test_module.web, - "json_response", - mock.MagicMock(side_effect=lambda *args, **kwargs: [*args, *kwargs.values()]), ): results, status = await test_module.send_keylist_update(self.request) assert results["updates"] == body_with_didkey["updates"] @@ -461,15 +527,18 @@ async def test_send_keylist_update_bad_mediation_state(self): ] } - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock( - return_value=mock.MagicMock( - state=MediationRecord.STATE_DENIED, connection_id="test-conn-id" - ) + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock( + return_value=mock.MagicMock( + state=MediationRecord.STATE_DENIED, connection_id="test-conn-id" + ) + ), ), - ), self.assertRaises(test_module.web.HTTPBadRequest): + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.send_keylist_update(self.request) async def test_send_keylist_update_bad_updates(self): @@ -486,11 +555,14 @@ async def test_send_keylist_update_x_no_mediation_rec(self): }, ] } - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), - ), self.assertRaises(test_module.web.HTTPNotFound): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + ), + self.assertRaises(test_module.web.HTTPNotFound), + ): await test_module.send_keylist_update(self.request) async def test_send_keylist_update_x_storage_error(self): @@ -503,28 +575,33 @@ async def test_send_keylist_update_x_storage_error(self): ] } - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.send_keylist_update(self.request) @mock.patch.object(test_module, "MediationManager", autospec=True) async def test_send_keylist_query(self, mock_manager): self.request.json.return_value = {"filter": {"test": "filter"}} self.request.query = {"paginate_limit": 10, "paginate_offset": 20} - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=self.mock_record), - ), mock.patch.object( - mock_manager.return_value, - "prepare_keylist_query", - mock.CoroutineMock(), - ) as mock_prepare_keylist_query, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=self.mock_record), + ), + mock.patch.object( + mock_manager.return_value, + "prepare_keylist_query", + mock.CoroutineMock(), + ) as mock_prepare_keylist_query, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): await test_module.send_keylist_query(self.request) mock_prepare_keylist_query.assert_called_once_with( filter_={"test": "filter"}, paginate_limit=10, paginate_offset=20 @@ -536,29 +613,36 @@ async def test_send_keylist_query(self, mock_manager): ) async def test_send_keylist_query_x_no_mediation_record(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), - ), self.assertRaises(test_module.web.HTTPNotFound): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + ), + self.assertRaises(test_module.web.HTTPNotFound), + ): await test_module.send_keylist_query(self.request) async def test_send_keylist_query_x_storage_error(self): - with mock.patch.object( - test_module.MediationRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), self.assertRaises(test_module.web.HTTPBadRequest): + with ( + mock.patch.object( + test_module.MediationRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + self.assertRaises(test_module.web.HTTPBadRequest), + ): await test_module.send_keylist_query(self.request) async def test_get_default_mediator(self): self.request.query = {} - with mock.patch.object( - test_module.web, "json_response" - ) as json_response, mock.patch.object( - test_module.MediationManager, - "get_default_mediator", - mock.CoroutineMock(return_value=self.mock_record), + with ( + mock.patch.object(test_module.web, "json_response") as json_response, + mock.patch.object( + test_module.MediationManager, + "get_default_mediator", + mock.CoroutineMock(return_value=self.mock_record), + ), ): await test_module.get_default_mediator(self.request) json_response.assert_called_once_with( @@ -568,12 +652,13 @@ async def test_get_default_mediator(self): async def test_get_empty_default_mediator(self): self.request.query = {} - with mock.patch.object( - test_module.web, "json_response" - ) as json_response, mock.patch.object( - test_module.MediationManager, - "get_default_mediator", - mock.CoroutineMock(return_value=None), + with ( + mock.patch.object(test_module.web, "json_response") as json_response, + mock.patch.object( + test_module.MediationManager, + "get_default_mediator", + mock.CoroutineMock(return_value=None), + ), ): await test_module.get_default_mediator(self.request) json_response.assert_called_once_with( @@ -583,10 +668,13 @@ async def test_get_empty_default_mediator(self): async def test_get_default_mediator_storage_error(self): self.request.query = {} - with mock.patch.object(test_module.web, "json_response"), mock.patch.object( - test_module.MediationManager, - "get_default_mediator", - mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + with ( + mock.patch.object(test_module.web, "json_response"), + mock.patch.object( + test_module.MediationManager, + "get_default_mediator", + mock.CoroutineMock(side_effect=test_module.StorageNotFoundError()), + ), ): with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.get_default_mediator(self.request) @@ -596,15 +684,19 @@ async def test_set_default_mediator(self): "mediation_id": "fake_id", } self.request.query = {} - with mock.patch.object( - test_module.MediationManager, - "get_default_mediator", - mock.CoroutineMock(return_value=self.mock_record), - ), mock.patch.object( - test_module.MediationManager, - "set_default_mediator_by_id", - mock.CoroutineMock(), - ), mock.patch.object(test_module.web, "json_response") as json_response: + with ( + mock.patch.object( + test_module.MediationManager, + "get_default_mediator", + mock.CoroutineMock(return_value=self.mock_record), + ), + mock.patch.object( + test_module.MediationManager, + "set_default_mediator_by_id", + mock.CoroutineMock(), + ), + mock.patch.object(test_module.web, "json_response") as json_response, + ): await test_module.set_default_mediator(self.request) json_response.assert_called_once_with( self.mock_record.serialize.return_value, @@ -616,29 +708,37 @@ async def test_set_default_mediator_storage_error(self): "mediation_id": "bad_id", } self.request.query = {} - with mock.patch.object( - test_module.MediationManager, - "get_default_mediator", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), mock.patch.object( - test_module.MediationManager, - "set_default_mediator_by_id", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.MediationManager, + "get_default_mediator", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + mock.patch.object( + test_module.MediationManager, + "set_default_mediator_by_id", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + mock.patch.object(test_module.web, "json_response"), + ): with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.set_default_mediator(self.request) async def test_clear_default_mediator(self): self.request.query = {} - with mock.patch.object( - test_module.MediationManager, - "get_default_mediator", - mock.CoroutineMock(return_value=self.mock_record), - ), mock.patch.object( - test_module.MediationManager, - "clear_default_mediator", - mock.CoroutineMock(), - ), mock.patch.object(test_module.web, "json_response") as json_response: + with ( + mock.patch.object( + test_module.MediationManager, + "get_default_mediator", + mock.CoroutineMock(return_value=self.mock_record), + ), + mock.patch.object( + test_module.MediationManager, + "clear_default_mediator", + mock.CoroutineMock(), + ), + mock.patch.object(test_module.web, "json_response") as json_response, + ): await test_module.clear_default_mediator(self.request) json_response.assert_called_once_with( self.mock_record.serialize.return_value, @@ -647,15 +747,19 @@ async def test_clear_default_mediator(self): async def test_clear_default_mediator_storage_error(self): self.request.query = {} - with mock.patch.object( - test_module.MediationManager, - "get_default_mediator", - mock.CoroutineMock(side_effect=test_module.StorageError()), - ), mock.patch.object( - test_module.MediationManager, - "clear_default_mediator", - mock.CoroutineMock(), - ), mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.MediationManager, + "get_default_mediator", + mock.CoroutineMock(side_effect=test_module.StorageError()), + ), + mock.patch.object( + test_module.MediationManager, + "clear_default_mediator", + mock.CoroutineMock(), + ), + mock.patch.object(test_module.web, "json_response"), + ): with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.clear_default_mediator(self.request) @@ -673,9 +777,12 @@ async def test_update_keylist_for_connection(self): ) mock_route_manager.mediation_record_for_connection = mock.CoroutineMock() self.context.injector.bind_instance(RouteManager, mock_route_manager) - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object(test_module.web, "json_response") as json_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object(test_module.web, "json_response") as json_response, + ): await test_module.update_keylist_for_connection(self.request) json_response.assert_called_once_with({"mock": "serialized"}, status=200) diff --git a/acapy_agent/protocols/did_rotate/v1_0/manager.py b/acapy_agent/protocols/did_rotate/v1_0/manager.py index 8c5e508e06..684bb20dc6 100644 --- a/acapy_agent/protocols/did_rotate/v1_0/manager.py +++ b/acapy_agent/protocols/did_rotate/v1_0/manager.py @@ -128,7 +128,7 @@ async def receive_rotate(self, conn: ConnRecord, rotate: Rotate) -> RotateRecord ) try: - await self._ensure_supported_did(rotate.to_did) + await self.ensure_supported_did(rotate.to_did) except ReportableDIDRotateError as err: responder = self.profile.inject(BaseResponder) err.message.assign_thread_from(rotate) @@ -234,7 +234,7 @@ async def receive_hangup(self, conn: ConnRecord): async with self.profile.session() as session: await conn.delete_record(session) - async def _ensure_supported_did(self, did: str): + async def ensure_supported_did(self, did: str): """Check if the DID is supported.""" resolver = self.profile.inject(DIDResolver) conn_mgr = BaseConnectionManager(self.profile) diff --git a/acapy_agent/protocols/did_rotate/v1_0/message_types.py b/acapy_agent/protocols/did_rotate/v1_0/message_types.py index 2d0c0bfb6e..7cb418fc91 100644 --- a/acapy_agent/protocols/did_rotate/v1_0/message_types.py +++ b/acapy_agent/protocols/did_rotate/v1_0/message_types.py @@ -15,8 +15,8 @@ MESSAGE_TYPES = DIDCommPrefix.qualify_all( { ROTATE: f"{PROTOCOL_PACKAGE}.messages.rotate.Rotate", - ACK: f"{PROTOCOL_PACKAGE}.messages.ack.Ack", + ACK: f"{PROTOCOL_PACKAGE}.messages.ack.RotateAck", HANGUP: f"{PROTOCOL_PACKAGE}.messages.hangup.Hangup", - PROBLEM_REPORT: f"{PROTOCOL_PACKAGE}.messages.problem_report.ProblemReport", + PROBLEM_REPORT: f"{PROTOCOL_PACKAGE}.messages.problem_report.RotateProblemReport", } ) diff --git a/acapy_agent/protocols/did_rotate/v1_0/routes.py b/acapy_agent/protocols/did_rotate/v1_0/routes.py index f441ded27b..15c485371f 100644 --- a/acapy_agent/protocols/did_rotate/v1_0/routes.py +++ b/acapy_agent/protocols/did_rotate/v1_0/routes.py @@ -12,7 +12,12 @@ from ....messaging.models.openapi import OpenAPISchema from ....messaging.valid import DID_WEB_EXAMPLE, UUID4_EXAMPLE from ....storage.error import StorageNotFoundError -from .manager import DIDRotateManager +from .manager import ( + DIDRotateManager, + UnresolvableDIDCommServicesError, + UnresolvableDIDError, + UnsupportedDIDMethodError, +) from .message_types import SPEC_URI from .messages.hangup import HangupSchema as HangupMessageSchema from .messages.rotate import RotateSchema as RotateMessageSchema @@ -63,6 +68,16 @@ async def rotate(request: web.BaseRequest): body = await request.json() to_did = body["to_did"] + # Validate DID before proceeding + try: + await did_rotate_mgr.ensure_supported_did(to_did) + except ( + UnsupportedDIDMethodError, + UnresolvableDIDError, + UnresolvableDIDCommServicesError, + ) as err: + raise web.HTTPBadRequest(reason=str(err)) from err + async with context.session() as session: try: conn = await ConnRecord.retrieve_by_id(session, connection_id) diff --git a/acapy_agent/protocols/did_rotate/v1_0/tests/test_manager.py b/acapy_agent/protocols/did_rotate/v1_0/tests/test_manager.py index b4bc7cd6d5..2383bfdc17 100644 --- a/acapy_agent/protocols/did_rotate/v1_0/tests/test_manager.py +++ b/acapy_agent/protocols/did_rotate/v1_0/tests/test_manager.py @@ -92,9 +92,12 @@ async def test_receive_rotate_x(self): RotateProblemReport(problem_items=[{"did": test_to_did}]) ) - with mock.patch.object( - self.manager, "_ensure_supported_did", side_effect=test_problem_report - ), mock.patch.object(self.responder, "send", mock.CoroutineMock()) as mock_send: + with ( + mock.patch.object( + self.manager, "ensure_supported_did", side_effect=test_problem_report + ), + mock.patch.object(self.responder, "send", mock.CoroutineMock()) as mock_send, + ): await self.manager.receive_rotate( mock_conn_record, Rotate(to_did=test_to_did) ) diff --git a/acapy_agent/protocols/did_rotate/v1_0/tests/test_routes.py b/acapy_agent/protocols/did_rotate/v1_0/tests/test_routes.py index 932d413ed9..22ec03fed2 100644 --- a/acapy_agent/protocols/did_rotate/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/did_rotate/v1_0/tests/test_routes.py @@ -57,7 +57,8 @@ async def asyncSetUp(self): "DIDRotateManager", autospec=True, return_value=mock.MagicMock( - rotate_my_did=mock.CoroutineMock(return_value=generate_mock_rotate_message()) + rotate_my_did=mock.CoroutineMock(return_value=generate_mock_rotate_message()), + ensure_supported_did=mock.CoroutineMock(), ), ) async def test_rotate(self, *_): @@ -102,7 +103,15 @@ async def test_hangup(self, *_): } ) - async def test_rotate_conn_not_found(self): + @mock.patch.object( + test_module, + "DIDRotateManager", + autospec=True, + return_value=mock.MagicMock( + ensure_supported_did=mock.CoroutineMock(), + ), + ) + async def test_rotate_conn_not_found(self, *_): self.request.match_info = {"conn_id": test_conn_id} self.request.json = mock.CoroutineMock(return_value=test_valid_rotate_request) @@ -114,6 +123,28 @@ async def test_rotate_conn_not_found(self): with self.assertRaises(test_module.web.HTTPNotFound): await test_module.rotate(self.request) + async def test_rotate_did_validation_errors(self): + self.request.match_info = {"conn_id": test_conn_id} + self.request.json = mock.CoroutineMock(return_value=test_valid_rotate_request) + + for error_class in [ + test_module.UnsupportedDIDMethodError, + test_module.UnresolvableDIDError, + test_module.UnresolvableDIDCommServicesError, + ]: + with mock.patch.object( + test_module, + "DIDRotateManager", + autospec=True, + return_value=mock.MagicMock( + ensure_supported_did=mock.CoroutineMock( + side_effect=error_class("test error") + ), + ), + ): + with self.assertRaises(test_module.web.HTTPBadRequest): + await test_module.rotate(self.request) + if __name__ == "__main__": unittest.main() diff --git a/acapy_agent/protocols/didexchange/v1_0/tests/test_manager.py b/acapy_agent/protocols/didexchange/v1_0/tests/test_manager.py index 57c8752e23..5dae863727 100644 --- a/acapy_agent/protocols/didexchange/v1_0/tests/test_manager.py +++ b/acapy_agent/protocols/didexchange/v1_0/tests/test_manager.py @@ -174,13 +174,15 @@ async def test_receive_invitation(self): ) await mediation_record.save(session) - with mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - self.multitenant_mgr, "get_default_mediator" - ) as mock_get_default_mediator, mock.patch.object( - AdminResponder, "send_reply" - ) as mock_send_reply: + with ( + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object( + self.multitenant_mgr, "get_default_mediator" + ) as mock_get_default_mediator, + mock.patch.object(AdminResponder, "send_reply") as mock_send_reply, + ): mock_get_default_mediator.return_value = mediation_record invi_rec = await self.oob_manager.create_invitation( my_endpoint="testendpoint", @@ -206,15 +208,18 @@ async def test_receive_invitation_oob_public_did(self): ED25519, ) public_did_info = await wallet.get_public_did() - with mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - self.multitenant_mgr, "get_default_mediator" - ) as mock_get_default_mediator, mock.patch.object( - self.manager, "resolve_connection_targets", mock.CoroutineMock() - ) as mock_resolve_targets, mock.patch.object( - AdminResponder, "send_reply" - ) as mock_send_reply: + with ( + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object( + self.multitenant_mgr, "get_default_mediator" + ) as mock_get_default_mediator, + mock.patch.object( + self.manager, "resolve_connection_targets", mock.CoroutineMock() + ) as mock_resolve_targets, + mock.patch.object(AdminResponder, "send_reply") as mock_send_reply, + ): mock_resolve_targets.return_value = [ mock.MagicMock(recipient_keys=["test"]) ] @@ -289,11 +294,14 @@ async def test_create_request_implicit(self): ) await mediation_record.save(session) - with mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc, mock.patch.object( - self.multitenant_mgr, "get_default_mediator" - ) as mock_get_default_mediator: + with ( + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + mock.patch.object( + self.multitenant_mgr, "get_default_mediator" + ) as mock_get_default_mediator, + ): mock_get_default_mediator.return_value = mediation_record mock_create_did_doc.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={}) @@ -370,8 +378,11 @@ async def test_create_request_implicit_x_public_already_connected(self): SOV, ED25519, ) - with self.assertRaises(DIDXManagerError) as context, mock.patch.object( - test_module.ConnRecord, "retrieve_by_did", mock.CoroutineMock() + with ( + self.assertRaises(DIDXManagerError) as context, + mock.patch.object( + test_module.ConnRecord, "retrieve_by_did", mock.CoroutineMock() + ), ): await self.manager.create_request_implicit( their_public_did=TestConfig.test_target_did, @@ -414,13 +425,17 @@ async def test_create_request_multitenant(self): {"multitenant.enabled": True, "wallet.id": "test_wallet"} ) - with mock.patch.object( - AskarWallet, "create_local_did", autospec=True - ) as mock_wallet_create_local_did, mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco: + with ( + mock.patch.object( + AskarWallet, "create_local_did", autospec=True + ) as mock_wallet_create_local_did, + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + ): mock_create_did_doc.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={}) ) @@ -625,24 +640,35 @@ async def test_receive_request_explicit_public_did(self): STATE_REQUEST = ConnRecord.State.REQUEST self.profile.context.update_settings({"public_invites": True}) ACCEPT_AUTO = ConnRecord.ACCEPT_AUTO - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "DIDPosture", autospec=True - ) as mock_did_posture, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - test_module, "DIDXResponse", autospec=True - ) as mock_response, mock.patch.object( - self.manager, - "verify_diddoc", - mock.CoroutineMock(return_value={"id": "did:sov:" + TestConfig.test_did}), - ), mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc, mock.patch.object( - MediationManager, "prepare_request", autospec=True - ) as mock_mediation_mgr_prep_req, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "DIDPosture", autospec=True + ) as mock_did_posture, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object( + test_module, "DIDXResponse", autospec=True + ) as mock_response, + mock.patch.object( + self.manager, + "verify_diddoc", + mock.CoroutineMock( + return_value={"id": "did:sov:" + TestConfig.test_did} + ), + ), + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + mock.patch.object( + MediationManager, "prepare_request", autospec=True + ) as mock_mediation_mgr_prep_req, + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_create_did_doc.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={}) @@ -760,27 +786,36 @@ async def test_receive_request_public_did_no_did_doc_attachment(self): STATE_REQUEST = ConnRecord.State.REQUEST self.profile.context.update_settings({"public_invites": True}) ACCEPT_AUTO = ConnRecord.ACCEPT_AUTO - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "DIDPosture", autospec=True - ) as mock_did_posture, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - test_module, "DIDXResponse", autospec=True - ) as mock_response, mock.patch.object( - self.manager, - "verify_diddoc", - mock.CoroutineMock(return_value=DIDDoc(TestConfig.test_did)), - ), mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc, mock.patch.object( - self.manager, - "record_keys_for_resolvable_did", - mock.CoroutineMock(), - ), mock.patch.object( - MediationManager, "prepare_request", autospec=True - ) as mock_mediation_mgr_prep_req: + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "DIDPosture", autospec=True + ) as mock_did_posture, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object( + test_module, "DIDXResponse", autospec=True + ) as mock_response, + mock.patch.object( + self.manager, + "verify_diddoc", + mock.CoroutineMock(return_value=DIDDoc(TestConfig.test_did)), + ), + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + mock.patch.object( + self.manager, + "record_keys_for_resolvable_did", + mock.CoroutineMock(), + ), + mock.patch.object( + MediationManager, "prepare_request", autospec=True + ) as mock_mediation_mgr_prep_req, + ): mock_create_did_doc.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={}) ) @@ -856,11 +891,14 @@ async def test_receive_request_public_did_no_did_doc_attachment_no_did(self): STATE_REQUEST = ConnRecord.State.REQUEST self.profile.context.update_settings({"public_invites": True}) ACCEPT_AUTO = ConnRecord.ACCEPT_AUTO - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "DIDPosture", autospec=True - ) as mock_did_posture: + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "DIDPosture", autospec=True + ) as mock_did_posture, + ): mock_conn_record = mock.MagicMock( accept=ACCEPT_AUTO, my_did=None, @@ -964,16 +1002,21 @@ async def test_receive_request_public_did_x_wrong_did(self): self.profile.context.update_settings({"public_invites": True}) mock_conn_rec_state_request = ConnRecord.State.REQUEST - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "DIDPosture", autospec=True - ) as mock_did_posture, mock.patch.object( - self.manager, - "verify_diddoc", - mock.CoroutineMock(return_value={"id": "LjgpST2rjsoxYegQDRm7EL"}), - ), mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "DIDPosture", autospec=True + ) as mock_did_posture, + mock.patch.object( + self.manager, + "verify_diddoc", + mock.CoroutineMock(return_value={"id": "LjgpST2rjsoxYegQDRm7EL"}), + ), + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_conn_record = mock.MagicMock( accept=ConnRecord.ACCEPT_MANUAL, @@ -1028,14 +1071,18 @@ async def test_receive_request_public_did_x_did_doc_attach_bad_sig(self): self.profile.context.update_settings({"public_invites": True}) mock_conn_rec_state_request = ConnRecord.State.REQUEST - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "DIDPosture", autospec=True - ) as mock_did_posture, mock.patch.object( - self.manager, - "verify_diddoc", - mock.CoroutineMock(side_effect=DIDXManagerError), + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "DIDPosture", autospec=True + ) as mock_did_posture, + mock.patch.object( + self.manager, + "verify_diddoc", + mock.CoroutineMock(side_effect=DIDXManagerError), + ), ): mock_conn_record = mock.MagicMock( accept=ConnRecord.ACCEPT_MANUAL, @@ -1088,14 +1135,13 @@ async def test_receive_request_public_did_no_public_invites(self): ) self.profile.context.update_settings({"public_invites": False}) - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ), mock.patch.object( - test_module, "AttachDecorator", autospec=True - ), mock.patch.object( - test_module, "DIDXResponse", autospec=True - ), mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() + with ( + mock.patch.object(test_module, "ConnRecord", mock.MagicMock()), + mock.patch.object(test_module, "AttachDecorator", autospec=True), + mock.patch.object(test_module, "DIDXResponse", autospec=True), + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ), ): with self.assertRaises(DIDXManagerError) as context: await self.manager.receive_request( @@ -1133,22 +1179,28 @@ async def test_receive_request_public_did_no_auto_accept(self): {"public_invites": True, "debug.auto_accept_requests": False} ) mock_conn_rec_state_request = ConnRecord.State.REQUEST - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "DIDPosture", autospec=True - ) as mock_did_posture, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ), mock.patch.object( - test_module, "DIDXResponse", autospec=True - ), mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ), mock.patch.object( - self.manager, - "verify_diddoc", - mock.CoroutineMock(return_value={"id": "did:sov:" + TestConfig.test_did}), - ), mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "DIDPosture", autospec=True + ) as mock_did_posture, + mock.patch.object(test_module, "AttachDecorator", autospec=True), + mock.patch.object(test_module, "DIDXResponse", autospec=True), + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ), + mock.patch.object( + self.manager, + "verify_diddoc", + mock.CoroutineMock( + return_value={"id": "did:sov:" + TestConfig.test_did} + ), + ), + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_conn_record = mock.MagicMock( accept=ConnRecord.ACCEPT_MANUAL, @@ -1213,16 +1265,23 @@ async def test_receive_request_implicit_public_did_not_enabled(self): self.profile.context.update_settings({"public_invites": True}) - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "DIDPosture", autospec=True - ) as mock_did_posture, mock.patch.object( - self.manager, - "verify_diddoc", - mock.CoroutineMock(return_value={"id": "did:sov:" + TestConfig.test_did}), - ), mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "DIDPosture", autospec=True + ) as mock_did_posture, + mock.patch.object( + self.manager, + "verify_diddoc", + mock.CoroutineMock( + return_value={"id": "did:sov:" + TestConfig.test_did} + ), + ), + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_did_posture.get = mock.MagicMock( return_value=test_module.DIDPosture.PUBLIC @@ -1279,16 +1338,23 @@ async def test_receive_request_implicit_public_did(self): ACCEPT_AUTO = ConnRecord.ACCEPT_AUTO STATE_REQUEST = ConnRecord.State.REQUEST - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "DIDPosture", autospec=True - ) as mock_did_posture, mock.patch.object( - self.manager, - "verify_diddoc", - mock.CoroutineMock(return_value={"id": "did:sov:" + TestConfig.test_did}), - ), mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "DIDPosture", autospec=True + ) as mock_did_posture, + mock.patch.object( + self.manager, + "verify_diddoc", + mock.CoroutineMock( + return_value={"id": "did:sov:" + TestConfig.test_did} + ), + ), + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_did_posture.get = mock.MagicMock( return_value=test_module.DIDPosture.PUBLIC @@ -1363,18 +1429,26 @@ async def test_receive_request_peer_did(self): ) self.profile.context.update_settings({"public_invites": True}) - with mock.patch.object( - test_module, "ConnRecord", mock.MagicMock() - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - test_module, "DIDXResponse", autospec=True - ) as mock_response, mock.patch.object( - self.manager, - "verify_diddoc", - mock.CoroutineMock(return_value={"id": "did:sov:" + TestConfig.test_did}), - ), mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "ConnRecord", mock.MagicMock() + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object( + test_module, "DIDXResponse", autospec=True + ) as mock_response, + mock.patch.object( + self.manager, + "verify_diddoc", + mock.CoroutineMock( + return_value={"id": "did:sov:" + TestConfig.test_did} + ), + ), + mock.patch.object( + self.manager, "store_did_document", mock.CoroutineMock() + ), ): mock_conn_rec_cls.retrieve_by_invitation_msg_id = mock.CoroutineMock( return_value=mock_conn @@ -1451,15 +1525,19 @@ async def test_receive_request_peer_did_not_found_x(self): async def test_create_response(self): conn_rec = ConnRecord(connection_id="dummy", state=ConnRecord.State.REQUEST.rfc23) - with mock.patch.object( - test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() - ), mock.patch.object(conn_rec, "save", mock.CoroutineMock()), mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - test_module, "DIDXResponse", autospec=True - ), mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() + ), + mock.patch.object(conn_rec, "save", mock.CoroutineMock()), + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object(test_module, "DIDXResponse", autospec=True), + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + ): mock_create_did_doc.return_value = mock.MagicMock(serialize=mock.MagicMock()) mock_attach_deco.data_base64 = mock.MagicMock( return_value=mock.MagicMock( @@ -1499,15 +1577,17 @@ async def test_create_response_mediation_id(self): await record.save(session) await record.attach_invitation(session, invi) - with mock.patch.object( - ConnRecord, "log_state", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - record, "metadata_get", mock.CoroutineMock(return_value=False) - ), mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco: + with ( + mock.patch.object(ConnRecord, "log_state", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + record, "metadata_get", mock.CoroutineMock(return_value=False) + ), + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + ): mock_attach_deco.data_base64 = mock.MagicMock( return_value=mock.MagicMock( data=mock.MagicMock(sign=mock.CoroutineMock()) @@ -1548,12 +1628,13 @@ async def test_create_response_mediation_id_invalid_conn_state(self): await record.save(session) await record.attach_invitation(session, invi) - with mock.patch.object( - ConnRecord, "log_state", autospec=True - ), mock.patch.object( - ConnRecord, "retrieve_request", autospec=True - ), mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - record, "metadata_get", mock.CoroutineMock(return_value=False) + with ( + mock.patch.object(ConnRecord, "log_state", autospec=True), + mock.patch.object(ConnRecord, "retrieve_request", autospec=True), + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + record, "metadata_get", mock.CoroutineMock(return_value=False) + ), ): with self.assertRaises(DIDXManagerError) as context: await self.manager.create_response( @@ -1571,15 +1652,19 @@ async def test_create_response_multitenant(self): } ) - with mock.patch.object( - test_module.ConnRecord, "retrieve_request" - ), mock.patch.object(conn_rec, "save", mock.CoroutineMock()), mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc, mock.patch.object( - AskarWallet, "create_local_did", autospec=True - ) as mock_wallet_create_local_did: + with ( + mock.patch.object(test_module.ConnRecord, "retrieve_request"), + mock.patch.object(conn_rec, "save", mock.CoroutineMock()), + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + mock.patch.object( + AskarWallet, "create_local_did", autospec=True + ) as mock_wallet_create_local_did, + ): mock_wallet_create_local_did.return_value = DIDInfo( TestConfig.test_did, TestConfig.test_verkey, @@ -1604,17 +1689,22 @@ async def test_create_response_conn_rec_my_did(self): state=ConnRecord.State.REQUEST.rfc23, ) - with mock.patch.object( - test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() - ), mock.patch.object(conn_rec, "save", mock.CoroutineMock()), mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - test_module, "DIDXResponse", autospec=True - ), mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc, mock.patch.object( - AskarWallet, "get_local_did", mock.CoroutineMock() - ) as mock_get_loc_did: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() + ), + mock.patch.object(conn_rec, "save", mock.CoroutineMock()), + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object(test_module, "DIDXResponse", autospec=True), + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + mock.patch.object( + AskarWallet, "get_local_did", mock.CoroutineMock() + ) as mock_get_loc_did, + ): mock_get_loc_did.return_value = self.did_info mock_create_did_doc.return_value = mock.MagicMock(serialize=mock.MagicMock()) mock_attach_deco.data_base64 = mock.MagicMock( @@ -1635,11 +1725,15 @@ async def test_create_response_inkind_peer_did_2(self): self.profile.context.update_settings({"emit_did_peer_2": False}) - with mock.patch.object( - self.manager, "create_did_peer_2", mock.CoroutineMock() - ) as mock_create_did_peer_2, mock.patch.object( - test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() - ), mock.patch.object(conn_rec, "save", mock.CoroutineMock()): + with ( + mock.patch.object( + self.manager, "create_did_peer_2", mock.CoroutineMock() + ) as mock_create_did_peer_2, + mock.patch.object( + test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() + ), + mock.patch.object(conn_rec, "save", mock.CoroutineMock()), + ): mock_create_did_peer_2.return_value = DIDInfo( TestConfig.test_did_peer_2, TestConfig.test_verkey, @@ -1663,11 +1757,15 @@ async def test_create_response_inkind_peer_did_4(self): self.profile.context.update_settings({"emit_did_peer_4": False}) - with mock.patch.object( - self.manager, "create_did_peer_4", mock.CoroutineMock() - ) as mock_create_did_peer_4, mock.patch.object( - test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() - ), mock.patch.object(conn_rec, "save", mock.CoroutineMock()): + with ( + mock.patch.object( + self.manager, "create_did_peer_4", mock.CoroutineMock() + ) as mock_create_did_peer_4, + mock.patch.object( + test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() + ), + mock.patch.object(conn_rec, "save", mock.CoroutineMock()), + ): mock_create_did_peer_4.return_value = DIDInfo( TestConfig.test_did_peer_4, TestConfig.test_verkey, @@ -1691,11 +1789,15 @@ async def test_create_response_peer_1_gets_peer_4(self): self.profile.context.update_settings({"emit_did_peer_4": False}) - with mock.patch.object( - self.manager, "create_did_peer_4", mock.CoroutineMock() - ) as mock_create_did_peer_4, mock.patch.object( - test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() - ), mock.patch.object(conn_rec, "save", mock.CoroutineMock()): + with ( + mock.patch.object( + self.manager, "create_did_peer_4", mock.CoroutineMock() + ) as mock_create_did_peer_4, + mock.patch.object( + test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() + ), + mock.patch.object(conn_rec, "save", mock.CoroutineMock()), + ): mock_create_did_peer_4.return_value = DIDInfo( TestConfig.test_did_peer_4, TestConfig.test_verkey, @@ -1731,15 +1833,19 @@ async def test_create_response_use_public_did(self): conn_rec = ConnRecord(connection_id="dummy", state=ConnRecord.State.REQUEST.rfc23) - with mock.patch.object( - test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() - ), mock.patch.object(conn_rec, "save", mock.CoroutineMock()), mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - test_module, "DIDXResponse", autospec=True - ), mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() + ), + mock.patch.object(conn_rec, "save", mock.CoroutineMock()), + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object(test_module, "DIDXResponse", autospec=True), + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + ): mock_create_did_doc.return_value = mock.MagicMock(serialize=mock.MagicMock()) mock_attach_deco.data_base64 = mock.MagicMock( return_value=mock.MagicMock( @@ -1754,15 +1860,19 @@ async def test_create_response_use_public_did(self): async def test_create_response_use_public_did_x_no_public_did(self): conn_rec = ConnRecord(connection_id="dummy", state=ConnRecord.State.REQUEST.rfc23) - with mock.patch.object( - test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() - ), mock.patch.object(conn_rec, "save", mock.CoroutineMock()), mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_deco, mock.patch.object( - test_module, "DIDXResponse", autospec=True - ), mock.patch.object( - self.manager, "create_did_document", mock.CoroutineMock() - ) as mock_create_did_doc: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_request", mock.CoroutineMock() + ), + mock.patch.object(conn_rec, "save", mock.CoroutineMock()), + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_deco, + mock.patch.object(test_module, "DIDXResponse", autospec=True), + mock.patch.object( + self.manager, "create_did_document", mock.CoroutineMock() + ) as mock_create_did_doc, + ): mock_create_did_doc.return_value = mock.MagicMock(serialize=mock.MagicMock()) mock_attach_deco.data_base64 = mock.MagicMock( return_value=mock.MagicMock( @@ -1798,12 +1908,15 @@ async def test_accept_response_find_by_thread_id(self): recipient_did_public=True, ) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_id, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_id, + mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()), ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( did=TestConfig.test_target_did, @@ -1856,14 +1969,18 @@ async def test_accept_response_find_by_thread_id_auto_disclose_features(self): ) self.context.update_settings({"auto_disclose_features": True}) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_id, mock.patch.object( - V20DiscoveryMgr, "proactive_disclose_features", mock.CoroutineMock() - ) as mock_proactive_disclose_features, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_id, + mock.patch.object( + V20DiscoveryMgr, "proactive_disclose_features", mock.CoroutineMock() + ) as mock_proactive_disclose_features, + mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()), ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( did=TestConfig.test_target_did, @@ -1912,12 +2029,15 @@ async def test_accept_response_not_found_by_thread_id_receipt_has_sender_did(sel receipt = MessageReceipt(sender_did=TestConfig.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_did", mock.CoroutineMock() - ) as mock_conn_retrieve_by_did, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_did", mock.CoroutineMock() + ) as mock_conn_retrieve_by_did, + mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()), ): mock_conn_retrieve_by_req_id.side_effect = StorageNotFoundError() mock_conn_retrieve_by_did.return_value = mock.MagicMock( @@ -1958,11 +2078,15 @@ async def test_accept_response_not_found_by_thread_id_nor_receipt_sender_did(sel receipt = MessageReceipt(sender_did=TestConfig.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_did", mock.CoroutineMock() - ) as mock_conn_retrieve_by_did: + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_did", mock.CoroutineMock() + ) as mock_conn_retrieve_by_did, + ): mock_conn_retrieve_by_req_id.side_effect = StorageNotFoundError() mock_conn_retrieve_by_did.side_effect = StorageNotFoundError() @@ -1984,9 +2108,12 @@ async def test_accept_response_find_by_thread_id_bad_state(self): receipt = MessageReceipt(sender_did=TestConfig.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id: + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( state=ConnRecord.State.ABANDONED.rfc23 ) @@ -2007,14 +2134,20 @@ async def test_accept_response_find_by_thread_id_no_did_doc_attached(self): recipient_did_public=True, ) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_id, mock.patch.object( - DIDDoc, "deserialize", mock.MagicMock() - ) as mock_did_doc_deser, mock.patch.object( - self.manager, "record_keys_for_resolvable_did", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_id, + mock.patch.object( + DIDDoc, "deserialize", mock.MagicMock() + ) as mock_did_doc_deser, + mock.patch.object( + self.manager, "record_keys_for_resolvable_did", mock.CoroutineMock() + ), ): mock_did_doc_deser.return_value = mock.MagicMock( did=TestConfig.test_target_did @@ -2047,14 +2180,20 @@ async def test_accept_response_find_by_thread_id_no_did_doc_attached_no_did(self recipient_did_public=True, ) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_id, mock.patch.object( - DIDDoc, "deserialize", mock.MagicMock() - ) as mock_did_doc_deser, mock.patch.object( - self.manager, "record_keys_for_resolvable_did", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_id, + mock.patch.object( + DIDDoc, "deserialize", mock.MagicMock() + ) as mock_did_doc_deser, + mock.patch.object( + self.manager, "record_keys_for_resolvable_did", mock.CoroutineMock() + ), ): mock_did_doc_deser.return_value = mock.MagicMock( did=TestConfig.test_target_did @@ -2092,12 +2231,15 @@ async def test_accept_response_find_by_thread_id_did_mismatch(self): receipt = MessageReceipt(sender_did=TestConfig.test_target_did) - with mock.patch.object(ConnRecord, "save", autospec=True), mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_id, mock.patch.object( - self.manager, "store_did_document", mock.CoroutineMock() + with ( + mock.patch.object(ConnRecord, "save", autospec=True), + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_id, + mock.patch.object(self.manager, "store_did_document", mock.CoroutineMock()), ): mock_conn_retrieve_by_req_id.return_value = mock.MagicMock( did=TestConfig.test_target_did, @@ -2139,11 +2281,14 @@ async def test_accept_complete_with_disclose(self): mock_complete = mock.MagicMock() receipt = MessageReceipt(sender_did=TestConfig.test_target_did) self.context.update_settings({"auto_disclose_features": True}) - with mock.patch.object( - ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_req_id, mock.patch.object( - V20DiscoveryMgr, "proactive_disclose_features", mock.CoroutineMock() - ) as mock_proactive_disclose_features: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_request_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_req_id, + mock.patch.object( + V20DiscoveryMgr, "proactive_disclose_features", mock.CoroutineMock() + ) as mock_proactive_disclose_features, + ): mock_conn_retrieve_by_req_id.return_value.save = mock.CoroutineMock() mock_conn_retrieve_by_req_id.return_value.my_did = None mock_conn_retrieve_by_req_id.return_value.their_did = None diff --git a/acapy_agent/protocols/didexchange/v1_0/tests/test_routes.py b/acapy_agent/protocols/didexchange/v1_0/tests/test_routes.py index 20b0eace36..81be5fda3d 100644 --- a/acapy_agent/protocols/didexchange/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/didexchange/v1_0/tests/test_routes.py @@ -43,13 +43,13 @@ async def test_didx_accept_invitation(self): mock_conn_rec = mock.MagicMock(save=mock.CoroutineMock()) mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_class, mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_class, + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_class.retrieve_by_id.return_value = mock_conn_rec mock_didx_mgr.return_value.create_request = mock.CoroutineMock() @@ -70,9 +70,12 @@ async def test_didx_accept_invitation_not_found(self): async def test_didx_accept_invitation_x(self): self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + ): mock_didx_mgr.return_value.create_request = mock.CoroutineMock( side_effect=test_module.DIDXManagerError() ) @@ -88,11 +91,10 @@ async def test_didx_create_request_implicit(self): "mediator_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", } - with mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_didx_mgr.return_value.create_request_implicit = mock.CoroutineMock( return_value=mock.MagicMock( serialize=mock.MagicMock(return_value="mock serialization") @@ -111,9 +113,10 @@ async def test_didx_create_request_implicit_not_found_x(self): "auto_accept": "true", } - with mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_didx_mgr.return_value.create_request_implicit = mock.CoroutineMock( side_effect=StorageNotFoundError("not found") ) @@ -130,9 +133,10 @@ async def test_didx_create_request_implicit_wallet_x(self): "auto_accept": "true", } - with mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_didx_mgr.return_value.create_request_implicit = mock.CoroutineMock( side_effect=test_module.WalletError("wallet error") ) @@ -152,13 +156,11 @@ async def test_didx_receive_request_implicit(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - test_module.DIDXRequest, "deserialize", mock.MagicMock() - ), mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module.DIDXRequest, "deserialize", mock.MagicMock()), + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_didx_mgr.return_value.receive_request = mock.CoroutineMock( return_value=mock_conn_rec ) @@ -174,11 +176,11 @@ async def test_didx_receive_request_implicit_not_found_x(self): self.request._thread.pthid = "did:sov:0000000000000000000000" self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module.DIDXRequest, "deserialize", mock.MagicMock() - ), mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module.DIDXRequest, "deserialize", mock.MagicMock()), + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_didx_mgr.return_value.receive_request = mock.CoroutineMock( side_effect=StorageNotFoundError("tricorder must be broken") ) @@ -195,11 +197,13 @@ async def test_didx_receive_request_implicit_bad_request_x(self): self.request._thread.pthid = "did:sov:0000000000000000000000" self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module.DIDXRequest, "deserialize", mock.MagicMock() - ) as mock_didx_req_deser, mock.patch.object( - test_module, "DIDXManager", autospec=True - ), mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.DIDXRequest, "deserialize", mock.MagicMock() + ) as mock_didx_req_deser, + mock.patch.object(test_module, "DIDXManager", autospec=True), + mock.patch.object(test_module.web, "json_response"), + ): mock_didx_req_deser.side_effect = test_module.BaseModelError("bad bits") with self.assertRaises(test_module.web.HTTPBadRequest) as context: await test_module.didx_receive_request_implicit(self.request) @@ -214,13 +218,13 @@ async def test_didx_accept_request(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve_by_id, mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve_by_id, + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve_by_id.return_value = mock_conn_rec mock_didx_mgr.return_value.create_response = mock.CoroutineMock() @@ -241,11 +245,13 @@ async def test_didx_accept_request_not_found(self): async def test_didx_accept_request_x(self): self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_didx_mgr.return_value.create_response = mock.CoroutineMock( side_effect=test_module.DIDXManagerError() ) @@ -257,11 +263,13 @@ async def test_didx_reject(self): self.request.match_info = {"conn_id": "dummy"} self.request.json = mock.CoroutineMock(return_value={"reason": "asdf"}) - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_didx_mgr.return_value.reject = mock.CoroutineMock() await test_module.didx_reject(self.request) @@ -282,11 +290,13 @@ async def test_didx_reject_x_bad_conn_state(self): self.request.match_info = {"conn_id": "dummy"} self.request.json = mock.CoroutineMock(return_value={"reason": "asdf"}) - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ), mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as mock_didx_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ), + mock.patch.object(test_module, "DIDXManager", autospec=True) as mock_didx_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_didx_mgr.return_value.reject = mock.CoroutineMock( side_effect=test_module.DIDXManagerError() ) diff --git a/acapy_agent/protocols/discovery/v1_0/handlers/tests/test_query_handler.py b/acapy_agent/protocols/discovery/v1_0/handlers/tests/test_query_handler.py index efb99110cb..9e428c958a 100644 --- a/acapy_agent/protocols/discovery/v1_0/handlers/tests/test_query_handler.py +++ b/acapy_agent/protocols/discovery/v1_0/handlers/tests/test_query_handler.py @@ -69,11 +69,14 @@ async def test_receive_query_process_disclosed(self, request_context): request_context.connection_ready = True handler = QueryHandler() responder = MockResponder() - with mock.patch.object( - ProtocolRegistry, "protocols_matching_query", mock.MagicMock() - ), mock.patch.object( - ProtocolRegistry, "prepare_disclosed", mock.CoroutineMock() - ) as mock_prepare_disclosed: + with ( + mock.patch.object( + ProtocolRegistry, "protocols_matching_query", mock.MagicMock() + ), + mock.patch.object( + ProtocolRegistry, "prepare_disclosed", mock.CoroutineMock() + ) as mock_prepare_disclosed, + ): mock_prepare_disclosed.return_value = [ {"test": "test"}, { diff --git a/acapy_agent/protocols/discovery/v1_0/tests/test_manager.py b/acapy_agent/protocols/discovery/v1_0/tests/test_manager.py index 88ccfcecde..134b7a736b 100644 --- a/acapy_agent/protocols/discovery/v1_0/tests/test_manager.py +++ b/acapy_agent/protocols/discovery/v1_0/tests/test_manager.py @@ -43,11 +43,14 @@ async def asyncSetUp(self): async def test_receive_disclosure(self): test_conn_id = "test123" self.disclose.assign_thread_id("test123") - with mock.patch.object( - V10DiscoveryExchangeRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V10DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve: + with ( + mock.patch.object( + V10DiscoveryExchangeRecord, "save", autospec=True + ) as save_ex, + mock.patch.object( + V10DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve, + ): mock_retrieve.return_value = TEST_DISCOVERY_EX_REC ex_rec = await self.manager.receive_disclose( disclose_msg=self.disclose, connection_id=test_conn_id @@ -62,19 +65,24 @@ async def test_receive_disclosure(self): async def test_receive_disclosure_retrieve_by_conn(self): test_conn_id = "test123" self.disclose.assign_thread_id("test123") - with mock.patch.object( - V10DiscoveryExchangeRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V10DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V10DiscoveryExchangeRecord, - "retrieve_by_connection_id", - mock.CoroutineMock(), - ) as mock_retrieve_by_connection_id, mock.patch.object( - V10DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve_by_id: + with ( + mock.patch.object( + V10DiscoveryExchangeRecord, "save", autospec=True + ) as save_ex, + mock.patch.object( + V10DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V10DiscoveryExchangeRecord, + "retrieve_by_connection_id", + mock.CoroutineMock(), + ) as mock_retrieve_by_connection_id, + mock.patch.object( + V10DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve_by_id, + ): mock_retrieve_by_id.side_effect = StorageNotFoundError mock_exists_for_connection_id.return_value = True mock_retrieve_by_connection_id.return_value = TEST_DISCOVERY_EX_REC @@ -91,15 +99,19 @@ async def test_receive_disclosure_retrieve_by_conn(self): async def test_receive_disclosure_retrieve_by_conn_not_found(self): test_conn_id = "test123" self.disclose.assign_thread_id("test123") - with mock.patch.object( - V10DiscoveryExchangeRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V10DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V10DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve_by_id: + with ( + mock.patch.object( + V10DiscoveryExchangeRecord, "save", autospec=True + ) as save_ex, + mock.patch.object( + V10DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V10DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve_by_id, + ): mock_retrieve_by_id.side_effect = StorageNotFoundError mock_exists_for_connection_id.return_value = False ex_rec = await self.manager.receive_disclose( @@ -114,15 +126,19 @@ async def test_receive_disclosure_retrieve_by_conn_not_found(self): async def test_receive_disclosure_retrieve_new_ex_rec(self): test_conn_id = "test123" - with mock.patch.object( - V10DiscoveryExchangeRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V10DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V10DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve_by_id: + with ( + mock.patch.object( + V10DiscoveryExchangeRecord, "save", autospec=True + ) as save_ex, + mock.patch.object( + V10DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V10DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve_by_id, + ): mock_retrieve_by_id.side_effect = StorageNotFoundError mock_exists_for_connection_id.return_value = False ex_rec = await self.manager.receive_disclose( @@ -148,23 +164,27 @@ async def test_check_if_disclosure_received(self): async def test_create_and_send_query_with_connection(self): return_ex_rec = V10DiscoveryExchangeRecord(query_msg=Query(query="*")) - with mock.patch.object( - V10DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V10DiscoveryExchangeRecord, - "retrieve_by_connection_id", - mock.CoroutineMock(), - ) as mock_retrieve_by_connection_id, mock.patch.object( - V10DiscoveryExchangeRecord, - "save", - mock.CoroutineMock(), - ), mock.patch.object( - V10DiscoveryMgr, "check_if_disclosure_received", mock.CoroutineMock() - ) as mock_disclosure_received, mock.patch.object( - self.responder, "send", mock.CoroutineMock() - ) as mock_send: + with ( + mock.patch.object( + V10DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V10DiscoveryExchangeRecord, + "retrieve_by_connection_id", + mock.CoroutineMock(), + ) as mock_retrieve_by_connection_id, + mock.patch.object( + V10DiscoveryExchangeRecord, + "save", + mock.CoroutineMock(), + ), + mock.patch.object( + V10DiscoveryMgr, "check_if_disclosure_received", mock.CoroutineMock() + ) as mock_disclosure_received, + mock.patch.object(self.responder, "send", mock.CoroutineMock()) as mock_send, + ): mock_exists_for_connection_id.return_value = True mock_retrieve_by_connection_id.return_value = V10DiscoveryExchangeRecord() mock_disclosure_received.return_value = return_ex_rec diff --git a/acapy_agent/protocols/discovery/v1_0/tests/test_routes.py b/acapy_agent/protocols/discovery/v1_0/tests/test_routes.py index d644c0bfce..3269bbafe2 100644 --- a/acapy_agent/protocols/discovery/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/discovery/v1_0/tests/test_routes.py @@ -40,11 +40,12 @@ async def test_query_features(self): discovery_exchange_id="3fa85f64-5717-4562-b3fc-2c963f66afa6", query_msg=Query(query="*"), ) - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - V10DiscoveryMgr, "create_and_send_query", autospec=True - ) as mock_create_query: + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + V10DiscoveryMgr, "create_and_send_query", autospec=True + ) as mock_create_query, + ): mock_create_query.return_value = test_rec await test_module.query_features(self.request) mock_response.assert_called_once_with(test_rec.serialize()) @@ -59,11 +60,12 @@ async def test_query_features_with_connection(self): query_msg=Query(query="*"), ) - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - V10DiscoveryMgr, "create_and_send_query", autospec=True - ) as mock_create_query: + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + V10DiscoveryMgr, "create_and_send_query", autospec=True + ) as mock_create_query, + ): mock_create_query.return_value = test_rec await test_module.query_features(self.request) mock_response.assert_called_once_with(test_rec.serialize()) @@ -78,11 +80,12 @@ async def test_query_records(self): query_msg=Query(query="*"), ) - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - test_module, "V10DiscoveryExchangeRecord", autospec=True - ) as mock_ex_rec: + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + test_module, "V10DiscoveryExchangeRecord", autospec=True + ) as mock_ex_rec, + ): mock_ex_rec.retrieve_by_connection_id.return_value = test_rec await test_module.query_records(self.request) mock_response.assert_called_once_with({"results": [test_rec.serialize()]}) @@ -92,9 +95,12 @@ async def test_query_records_x(self): self.request.query = {"connection_id": "test"} - with mock.patch.object(test_module.web, "json_response"), mock.patch.object( - test_module, "V10DiscoveryExchangeRecord", autospec=True - ) as mock_ex_rec: + with ( + mock.patch.object(test_module.web, "json_response"), + mock.patch.object( + test_module, "V10DiscoveryExchangeRecord", autospec=True + ) as mock_ex_rec, + ): mock_ex_rec.retrieve_by_connection_id.side_effect = StorageError with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.query_records(self.request) @@ -113,11 +119,12 @@ async def test_query_records_all(self): ), ] - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - test_module, "V10DiscoveryExchangeRecord", autospec=True - ) as mock_ex_rec: + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + test_module, "V10DiscoveryExchangeRecord", autospec=True + ) as mock_ex_rec, + ): mock_ex_rec.query.return_value = test_recs await test_module.query_records(self.request) mock_response.assert_called_once_with( @@ -127,9 +134,12 @@ async def test_query_records_all(self): async def test_query_records_connection_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object(test_module.web, "json_response"), mock.patch.object( - test_module, "V10DiscoveryExchangeRecord", autospec=True - ) as mock_ex_rec: + with ( + mock.patch.object(test_module.web, "json_response"), + mock.patch.object( + test_module, "V10DiscoveryExchangeRecord", autospec=True + ) as mock_ex_rec, + ): mock_ex_rec.query.side_effect = StorageError with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.query_records(self.request) diff --git a/acapy_agent/protocols/discovery/v2_0/handlers/tests/test_disclosures_handler.py b/acapy_agent/protocols/discovery/v2_0/handlers/tests/test_disclosures_handler.py index 0405014557..11bf227dae 100644 --- a/acapy_agent/protocols/discovery/v2_0/handlers/tests/test_disclosures_handler.py +++ b/acapy_agent/protocols/discovery/v2_0/handlers/tests/test_disclosures_handler.py @@ -94,14 +94,17 @@ async def test_disclosures_connection_id_no_thid(self, request_context): handler = DisclosuresHandler() mock_responder = MockResponder() - with mock.patch.object( - V20DiscoveryExchangeRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=StorageNotFoundError), - ), mock.patch.object( - V20DiscoveryExchangeRecord, - "retrieve_by_connection_id", - mock.CoroutineMock(return_value=discovery_record), + with ( + mock.patch.object( + V20DiscoveryExchangeRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=StorageNotFoundError), + ), + mock.patch.object( + V20DiscoveryExchangeRecord, + "retrieve_by_connection_id", + mock.CoroutineMock(return_value=discovery_record), + ), ): await handler.handle(request_context, mock_responder) assert not mock_responder.messages @@ -127,14 +130,17 @@ async def test_disclosures_no_conn_id_no_thid(self, request_context): handler = DisclosuresHandler() mock_responder = MockResponder() - with mock.patch.object( - V20DiscoveryExchangeRecord, - "retrieve_by_id", - mock.CoroutineMock(side_effect=StorageNotFoundError), - ), mock.patch.object( - V20DiscoveryExchangeRecord, - "retrieve_by_connection_id", - mock.CoroutineMock(side_effect=StorageNotFoundError), + with ( + mock.patch.object( + V20DiscoveryExchangeRecord, + "retrieve_by_id", + mock.CoroutineMock(side_effect=StorageNotFoundError), + ), + mock.patch.object( + V20DiscoveryExchangeRecord, + "retrieve_by_connection_id", + mock.CoroutineMock(side_effect=StorageNotFoundError), + ), ): await handler.handle(request_context, mock_responder) assert not mock_responder.messages diff --git a/acapy_agent/protocols/discovery/v2_0/handlers/tests/test_queries_handler.py b/acapy_agent/protocols/discovery/v2_0/handlers/tests/test_queries_handler.py index adf63001da..b988702070 100644 --- a/acapy_agent/protocols/discovery/v2_0/handlers/tests/test_queries_handler.py +++ b/acapy_agent/protocols/discovery/v2_0/handlers/tests/test_queries_handler.py @@ -134,11 +134,14 @@ async def test_receive_query_process_disclosed(self, request_context): request_context.connection_ready = True handler = QueriesHandler() responder = MockResponder() - with mock.patch.object( - V20DiscoveryMgr, "execute_protocol_query", mock.CoroutineMock() - ) as mock_exec_protocol_query, mock.patch.object( - V20DiscoveryMgr, "execute_goal_code_query", mock.CoroutineMock() - ) as mock_goal_code_protocol_query: + with ( + mock.patch.object( + V20DiscoveryMgr, "execute_protocol_query", mock.CoroutineMock() + ) as mock_exec_protocol_query, + mock.patch.object( + V20DiscoveryMgr, "execute_goal_code_query", mock.CoroutineMock() + ) as mock_goal_code_protocol_query, + ): mock_exec_protocol_query.return_value = [ {"test": "test"}, { diff --git a/acapy_agent/protocols/discovery/v2_0/tests/test_manager.py b/acapy_agent/protocols/discovery/v2_0/tests/test_manager.py index 3778d0784e..0473161c73 100644 --- a/acapy_agent/protocols/discovery/v2_0/tests/test_manager.py +++ b/acapy_agent/protocols/discovery/v2_0/tests/test_manager.py @@ -52,11 +52,14 @@ async def asyncSetUp(self): async def test_receive_disclosure(self): test_conn_id = "test123" self.queries.assign_thread_id("test123") - with mock.patch.object( - V20DiscoveryExchangeRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve: + with ( + mock.patch.object( + V20DiscoveryExchangeRecord, "save", autospec=True + ) as save_ex, + mock.patch.object( + V20DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve, + ): mock_retrieve.return_value = TEST_DISCOVERY_EX_REC ex_rec = await self.manager.receive_disclose( disclose_msg=self.disclosures, connection_id=test_conn_id @@ -71,19 +74,24 @@ async def test_receive_disclosure(self): async def test_receive_disclosure_retrieve_by_conn(self): test_conn_id = "test123" self.queries.assign_thread_id("test123") - with mock.patch.object( - V20DiscoveryExchangeRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V20DiscoveryExchangeRecord, - "retrieve_by_connection_id", - mock.CoroutineMock(), - ) as mock_retrieve_by_connection_id, mock.patch.object( - V20DiscoveryExchangeRecord, "retrieve_by_id", autospec=True - ) as mock_retrieve_by_id: + with ( + mock.patch.object( + V20DiscoveryExchangeRecord, "save", autospec=True + ) as save_ex, + mock.patch.object( + V20DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V20DiscoveryExchangeRecord, + "retrieve_by_connection_id", + mock.CoroutineMock(), + ) as mock_retrieve_by_connection_id, + mock.patch.object( + V20DiscoveryExchangeRecord, "retrieve_by_id", autospec=True + ) as mock_retrieve_by_id, + ): mock_retrieve_by_id.side_effect = StorageNotFoundError mock_exists_for_connection_id.return_value = True mock_retrieve_by_connection_id.return_value = TEST_DISCOVERY_EX_REC @@ -100,15 +108,19 @@ async def test_receive_disclosure_retrieve_by_conn(self): async def test_receive_disclosure_retrieve_by_conn_not_found(self): test_conn_id = "test123" self.queries.assign_thread_id("test123") - with mock.patch.object( - V20DiscoveryExchangeRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V20DiscoveryExchangeRecord, "retrieve_by_id", autospec=True - ) as mock_retrieve_by_id: + with ( + mock.patch.object( + V20DiscoveryExchangeRecord, "save", autospec=True + ) as save_ex, + mock.patch.object( + V20DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V20DiscoveryExchangeRecord, "retrieve_by_id", autospec=True + ) as mock_retrieve_by_id, + ): mock_retrieve_by_id.side_effect = StorageNotFoundError mock_exists_for_connection_id.return_value = False ex_rec = await self.manager.receive_disclose( @@ -123,15 +135,19 @@ async def test_receive_disclosure_retrieve_by_conn_not_found(self): async def test_receive_disclosure_retrieve_new_ex_rec(self): test_conn_id = "test123" - with mock.patch.object( - V20DiscoveryExchangeRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V20DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve_by_id: + with ( + mock.patch.object( + V20DiscoveryExchangeRecord, "save", autospec=True + ) as save_ex, + mock.patch.object( + V20DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V20DiscoveryExchangeRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve_by_id, + ): mock_retrieve_by_id.side_effect = StorageNotFoundError mock_exists_for_connection_id.return_value = False ex_rec = await self.manager.receive_disclose( @@ -144,25 +160,27 @@ async def test_receive_disclosure_retrieve_new_ex_rec(self): ) async def test_proactive_disclosure(self): - with mock.patch.object( - V20DiscoveryMgr, - "receive_query", - mock.CoroutineMock(), - ) as mock_receive_query, mock.patch.object( - self.responder, "send", mock.CoroutineMock() - ) as mock_send: + with ( + mock.patch.object( + V20DiscoveryMgr, + "receive_query", + mock.CoroutineMock(), + ) as mock_receive_query, + mock.patch.object(self.responder, "send", mock.CoroutineMock()) as mock_send, + ): mock_receive_query.return_value = Disclosures() await self.manager.proactive_disclose_features("test123") mock_send.assert_called_once() async def test_proactive_disclosure_no_responder(self): self.profile.context.injector.clear_binding(BaseResponder) - with mock.patch.object( - V20DiscoveryMgr, - "receive_query", - mock.CoroutineMock(), - ) as mock_receive_query, mock.patch.object( - self.responder, "send", mock.CoroutineMock() + with ( + mock.patch.object( + V20DiscoveryMgr, + "receive_query", + mock.CoroutineMock(), + ) as mock_receive_query, + mock.patch.object(self.responder, "send", mock.CoroutineMock()), ): self._caplog.set_level(logging.WARNING) mock_receive_query.return_value = Disclosures() @@ -195,23 +213,27 @@ async def test_create_and_send_query_with_connection(self): ] ) ) - with mock.patch.object( - V20DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V20DiscoveryExchangeRecord, - "retrieve_by_connection_id", - mock.CoroutineMock(), - ) as mock_retrieve_by_connection_id, mock.patch.object( - V20DiscoveryExchangeRecord, - "save", - mock.CoroutineMock(), - ), mock.patch.object( - V20DiscoveryMgr, "check_if_disclosure_received", mock.CoroutineMock() - ) as mock_disclosure_received, mock.patch.object( - self.responder, "send", mock.CoroutineMock() - ) as mock_send: + with ( + mock.patch.object( + V20DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V20DiscoveryExchangeRecord, + "retrieve_by_connection_id", + mock.CoroutineMock(), + ) as mock_retrieve_by_connection_id, + mock.patch.object( + V20DiscoveryExchangeRecord, + "save", + mock.CoroutineMock(), + ), + mock.patch.object( + V20DiscoveryMgr, "check_if_disclosure_received", mock.CoroutineMock() + ) as mock_disclosure_received, + mock.patch.object(self.responder, "send", mock.CoroutineMock()) as mock_send, + ): mock_exists_for_connection_id.return_value = True mock_retrieve_by_connection_id.return_value = V20DiscoveryExchangeRecord() mock_disclosure_received.return_value = return_ex_rec @@ -223,17 +245,21 @@ async def test_create_and_send_query_with_connection(self): async def test_create_and_send_query_with_connection_no_responder(self): self.profile.context.injector.clear_binding(BaseResponder) - with mock.patch.object( - V20DiscoveryExchangeRecord, - "exists_for_connection_id", - mock.CoroutineMock(), - ) as mock_exists_for_connection_id, mock.patch.object( - V20DiscoveryExchangeRecord, - "save", - mock.CoroutineMock(), - ), mock.patch.object( - V20DiscoveryMgr, "check_if_disclosure_received", mock.CoroutineMock() - ) as mock_disclosure_received: + with ( + mock.patch.object( + V20DiscoveryExchangeRecord, + "exists_for_connection_id", + mock.CoroutineMock(), + ) as mock_exists_for_connection_id, + mock.patch.object( + V20DiscoveryExchangeRecord, + "save", + mock.CoroutineMock(), + ), + mock.patch.object( + V20DiscoveryMgr, "check_if_disclosure_received", mock.CoroutineMock() + ) as mock_disclosure_received, + ): self._caplog.set_level(logging.WARNING) mock_exists_for_connection_id.return_value = False mock_disclosure_received.side_effect = asyncio.TimeoutError diff --git a/acapy_agent/protocols/discovery/v2_0/tests/test_routes.py b/acapy_agent/protocols/discovery/v2_0/tests/test_routes.py index 464916b963..dc06abcb00 100644 --- a/acapy_agent/protocols/discovery/v2_0/tests/test_routes.py +++ b/acapy_agent/protocols/discovery/v2_0/tests/test_routes.py @@ -46,11 +46,12 @@ async def test_query_features(self): ), ) - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - V20DiscoveryMgr, "create_and_send_query", autospec=True - ) as mock_create_query: + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + V20DiscoveryMgr, "create_and_send_query", autospec=True + ) as mock_create_query, + ): mock_create_query.return_value = test_rec await test_module.query_features(self.request) mock_response.assert_called_once_with(test_rec.serialize()) @@ -74,11 +75,12 @@ async def test_query_features_with_connection(self): ), ) - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - V20DiscoveryMgr, "create_and_send_query", autospec=True - ) as mock_create_query: + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + V20DiscoveryMgr, "create_and_send_query", autospec=True + ) as mock_create_query, + ): mock_create_query.return_value = test_rec await test_module.query_features(self.request) mock_response.assert_called_once_with(test_rec.serialize()) @@ -98,11 +100,12 @@ async def test_query_records(self): ), ) - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - test_module, "V20DiscoveryExchangeRecord", autospec=True - ) as mock_ex_rec: + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + test_module, "V20DiscoveryExchangeRecord", autospec=True + ) as mock_ex_rec, + ): mock_ex_rec.retrieve_by_connection_id.return_value = test_rec await test_module.query_records(self.request) mock_response.assert_called_once_with({"results": [test_rec.serialize()]}) @@ -112,9 +115,12 @@ async def test_query_records_x(self): self.request.query = {"connection_id": "test"} - with mock.patch.object(test_module.web, "json_response"), mock.patch.object( - test_module, "V20DiscoveryExchangeRecord", autospec=True - ) as mock_ex_rec: + with ( + mock.patch.object(test_module.web, "json_response"), + mock.patch.object( + test_module, "V20DiscoveryExchangeRecord", autospec=True + ) as mock_ex_rec, + ): mock_ex_rec.retrieve_by_connection_id.side_effect = StorageError with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.query_records(self.request) @@ -143,11 +149,12 @@ async def test_query_records_all(self): ), ] - with mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - test_module, "V20DiscoveryExchangeRecord", autospec=True - ) as mock_ex_rec: + with ( + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + test_module, "V20DiscoveryExchangeRecord", autospec=True + ) as mock_ex_rec, + ): mock_ex_rec.query.return_value = test_recs await test_module.query_records(self.request) mock_response.assert_called_once_with( @@ -157,9 +164,12 @@ async def test_query_records_all(self): async def test_query_records_connection_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object(test_module.web, "json_response"), mock.patch.object( - test_module, "V20DiscoveryExchangeRecord", autospec=True - ) as mock_ex_rec: + with ( + mock.patch.object(test_module.web, "json_response"), + mock.patch.object( + test_module, "V20DiscoveryExchangeRecord", autospec=True + ) as mock_ex_rec, + ): mock_ex_rec.query.side_effect = StorageError with self.assertRaises(test_module.web.HTTPBadRequest): await test_module.query_records(self.request) diff --git a/acapy_agent/protocols/endorse_transaction/v1_0/tests/test_manager.py b/acapy_agent/protocols/endorse_transaction/v1_0/tests/test_manager.py index 6519e9b27e..d333948eda 100644 --- a/acapy_agent/protocols/endorse_transaction/v1_0/tests/test_manager.py +++ b/acapy_agent/protocols/endorse_transaction/v1_0/tests/test_manager.py @@ -476,11 +476,10 @@ async def test_complete_transaction(self): ) ) - with mock.patch.object( - TransactionRecord, "save", autospec=True - ) as save_record, mock.patch.object( - ConnRecord, "retrieve_by_id" - ) as mock_conn_rec_retrieve: + with ( + mock.patch.object(TransactionRecord, "save", autospec=True) as save_record, + mock.patch.object(ConnRecord, "retrieve_by_id") as mock_conn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -534,11 +533,10 @@ async def test_complete_transaction_anoncreds( ) self.ledger.get_indy_storage = future - with mock.patch.object( - TransactionRecord, "save", autospec=True - ) as save_record, mock.patch.object( - ConnRecord, "retrieve_by_id" - ) as mock_conn_rec_retrieve: + with ( + mock.patch.object(TransactionRecord, "save", autospec=True) as save_record, + mock.patch.object(ConnRecord, "retrieve_by_id") as mock_conn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ diff --git a/acapy_agent/protocols/endorse_transaction/v1_0/tests/test_routes.py b/acapy_agent/protocols/endorse_transaction/v1_0/tests/test_routes.py index 66bf109838..65dd81e8c7 100644 --- a/acapy_agent/protocols/endorse_transaction/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/endorse_transaction/v1_0/tests/test_routes.py @@ -62,11 +62,12 @@ async def asyncSetUp(self): self.test_did = "sample-did" async def test_transactions_list(self): - with mock.patch.object( - TransactionRecord, "query", mock.CoroutineMock() - ) as mock_query, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + TransactionRecord, "query", mock.CoroutineMock() + ) as mock_query, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_query.return_value = [ mock.MagicMock(serialize=mock.MagicMock(return_value={"...": "..."})) ] @@ -75,9 +76,12 @@ async def test_transactions_list(self): mock_response.assert_called_once_with({"results": [{"...": "..."}]}) async def test_transactions_list_x(self): - with mock.patch.object( - TransactionRecord, "query", mock.CoroutineMock() - ) as mock_query, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + TransactionRecord, "query", mock.CoroutineMock() + ) as mock_query, + mock.patch.object(test_module.web, "json_response"), + ): mock_query.side_effect = test_module.StorageError() with self.assertRaises(test_module.web.HTTPBadRequest): @@ -86,11 +90,12 @@ async def test_transactions_list_x(self): async def test_transactions_retrieve(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={"...": "..."}) ) @@ -129,15 +134,18 @@ async def test_transaction_create_request(self): "expires_time": "2021-03-29T05:22:19Z", } ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( create_request=mock.CoroutineMock( return_value=( @@ -193,11 +201,14 @@ async def test_transaction_create_request_base_model_x(self): "expires_time": "2021-03-29T05:22:19Z", } ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -224,13 +235,17 @@ async def test_transaction_create_request_no_jobs_x(self): "expires_time": "2021-03-29T05:22:19Z", } ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( create_request=mock.CoroutineMock( return_value=( @@ -260,13 +275,17 @@ async def test_transaction_create_request_no_my_job_x(self): "expires_time": "2021-03-29T05:22:19Z", } ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( create_request=mock.CoroutineMock( return_value=( @@ -302,13 +321,17 @@ async def test_transaction_create_request_no_their_job_x(self): "expires_time": "2021-03-29T05:22:19Z", } ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( create_request=mock.CoroutineMock( return_value=( @@ -344,11 +367,14 @@ async def test_transaction_create_request_my_wrong_job_x(self): "expires_time": "2021-03-29T05:22:19Z", } ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -375,13 +401,17 @@ async def test_transaction_create_request_mgr_create_request_x(self): "expires_time": "2021-03-29T05:22:19Z", } ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( create_request=mock.CoroutineMock( side_effect=test_module.TransactionManagerError() @@ -423,15 +453,18 @@ async def test_endorse_transaction_response(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( create_endorse_response=mock.CoroutineMock( return_value=( @@ -523,11 +556,14 @@ async def test_endorse_transaction_response_base_model_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.side_effect = test_module.BaseModelError() mock_txn_rec_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={"...": "..."}) @@ -554,11 +590,14 @@ async def test_endorse_transaction_response_no_jobs_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock(return_value=None) ) @@ -588,13 +627,17 @@ async def test_endorse_transaction_response_no_ledger_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( create_endorse_response=mock.CoroutineMock( return_value=( @@ -639,11 +682,14 @@ async def test_endorse_transaction_response_wrong_my_job_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -682,13 +728,17 @@ async def test_endorse_transaction_response_ledger_x(self): side_effect=test_module.LedgerError() ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( create_endorse_response=mock.CoroutineMock( return_value=( @@ -733,13 +783,18 @@ async def test_endorse_transaction_response_txn_mgr_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_txn_mgr.return_value = mock.MagicMock( create_endorse_response=mock.CoroutineMock( side_effect=test_module.TransactionManagerError() @@ -779,15 +834,18 @@ async def test_refuse_transaction_response(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( create_refuse_response=mock.CoroutineMock( return_value=( @@ -859,11 +917,14 @@ async def test_refuse_transaction_response_conn_base_model_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.side_effect = test_module.BaseModelError() mock_txn_rec_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={"...": "..."}) @@ -890,11 +951,14 @@ async def test_refuse_transaction_response_no_jobs_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock(return_value=None) ) @@ -923,11 +987,14 @@ async def test_refuse_transaction_response_wrong_my_job_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -962,13 +1029,18 @@ async def test_refuse_transaction_response_txn_mgr_x(self): ), ) - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_txn_mgr.return_value = mock.MagicMock( create_refuse_response=mock.CoroutineMock( side_effect=test_module.TransactionManagerError() @@ -993,15 +1065,18 @@ async def test_refuse_transaction_response_txn_mgr_x(self): async def test_cancel_transaction(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( cancel_transaction=mock.CoroutineMock( return_value=( @@ -1043,11 +1118,14 @@ async def test_cancel_transaction_not_found_x(self): async def test_cancel_transaction_conn_rec_base_model_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.side_effect = test_module.BaseModelError() mock_txn_rec_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={"...": "..."}) @@ -1059,11 +1137,14 @@ async def test_cancel_transaction_conn_rec_base_model_x(self): async def test_cancel_transaction_no_jobs_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock(return_value=None) ) @@ -1077,11 +1158,14 @@ async def test_cancel_transaction_no_jobs_x(self): async def test_cancel_transaction_wrong_my_job_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -1101,13 +1185,18 @@ async def test_cancel_transaction_wrong_my_job_x(self): async def test_cancel_transaction_txn_mgr_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_txn_mgr.return_value = mock.MagicMock( cancel_transaction=mock.CoroutineMock( side_effect=test_module.TransactionManagerError() @@ -1132,15 +1221,18 @@ async def test_cancel_transaction_txn_mgr_x(self): async def test_transaction_resend(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( transaction_resend=mock.CoroutineMock( return_value=( @@ -1182,11 +1274,14 @@ async def test_transaction_resend_not_found_x(self): async def test_transaction_resend_conn_rec_base_model_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.side_effect = test_module.BaseModelError() mock_txn_rec_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value={"...": "..."}) @@ -1198,11 +1293,14 @@ async def test_transaction_resend_conn_rec_base_model_x(self): async def test_transaction_resend_no_jobs_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock(return_value=None) ) @@ -1216,11 +1314,14 @@ async def test_transaction_resend_no_jobs_x(self): async def test_transaction_resend_my_wrong_job_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -1241,13 +1342,18 @@ async def test_transaction_resend_my_wrong_job_x(self): async def test_transaction_resend_txn_mgr_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_txn_mgr.return_value = mock.MagicMock( transaction_resend=mock.CoroutineMock( side_effect=test_module.TransactionManagerError() @@ -1272,13 +1378,15 @@ async def test_transaction_resend_txn_mgr_x(self): async def test_set_endorser_role(self): self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_txn_mgr.return_value = mock.MagicMock( set_transaction_my_job=mock.CoroutineMock() ) @@ -1322,11 +1430,12 @@ async def test_set_endorser_role_base_model_x(self): async def test_set_endorser_info(self): self.request.match_info = {"conn_id": "dummy"} self.request.query = {"endorser_did": "did", "endorser_name": "name"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( return_value={ @@ -1354,11 +1463,12 @@ async def test_set_endorser_info(self): async def test_set_endorser_info_no_prior_value(self): self.request.match_info = {"conn_id": "dummy"} self.request.query = {"endorser_did": "did", "endorser_name": "name"} - with mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_rec_retrieve, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_rec_retrieve, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_conn_rec_retrieve.return_value = mock.MagicMock( metadata_get=mock.CoroutineMock( side_effect=[ @@ -1466,13 +1576,15 @@ async def test_set_endorser_info_my_wrong_job_x(self): async def test_transaction_write_schema_txn(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_txn_mgr.return_value.complete_transaction = mock.CoroutineMock() mock_txn_mgr.return_value.complete_transaction.return_value = ( @@ -1526,11 +1638,14 @@ async def test_transaction_write_wrong_state_x(self): async def test_transaction_write_schema_txn_complete_x(self): self.request.match_info = {"tran_id": "dummy"} - with mock.patch.object( - TransactionRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_txn_rec_retrieve, mock.patch.object( - test_module, "TransactionManager", mock.MagicMock() - ) as mock_txn_mgr: + with ( + mock.patch.object( + TransactionRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_txn_rec_retrieve, + mock.patch.object( + test_module, "TransactionManager", mock.MagicMock() + ) as mock_txn_mgr, + ): mock_txn_mgr.return_value = mock.MagicMock( complete_transaction=mock.CoroutineMock( side_effect=test_module.StorageError() diff --git a/acapy_agent/protocols/introduction/v0_1/tests/test_routes.py b/acapy_agent/protocols/introduction/v0_1/tests/test_routes.py index 656b3db249..c8a0e94d52 100644 --- a/acapy_agent/protocols/introduction/v0_1/tests/test_routes.py +++ b/acapy_agent/protocols/introduction/v0_1/tests/test_routes.py @@ -70,11 +70,12 @@ async def test_introduction_start(self): mock_conn_rec = mock.MagicMock() mock_conn_rec.serialize = mock.MagicMock() - with mock.patch.object( - self.context, "inject_or", mock.MagicMock() - ) as mock_ctx_inject, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + self.context, "inject_or", mock.MagicMock() + ) as mock_ctx_inject, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_ctx_inject.return_value = mock.MagicMock( start_introduction=mock.CoroutineMock() ) diff --git a/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_issue_handler.py b/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_issue_handler.py index 32aa553b2e..43eeb5e1ff 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_issue_handler.py +++ b/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_issue_handler.py @@ -117,11 +117,12 @@ async def test_called_auto_store_x(self): handler = test_module.CredentialIssueHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ), mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object(responder, "send_reply", mock.CoroutineMock()), + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_offer_handler.py b/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_offer_handler.py index 4b3982431d..c6fe03eafc 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_offer_handler.py +++ b/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_offer_handler.py @@ -109,11 +109,12 @@ async def test_called_auto_request_x(self): handler = test_module.CredentialOfferHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ), mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object(responder, "send_reply", mock.CoroutineMock()), + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_proposal_handler.py b/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_proposal_handler.py index 94b0ee83e3..905b7c2e46 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_proposal_handler.py +++ b/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_proposal_handler.py @@ -86,11 +86,12 @@ async def test_called_auto_offer_x(self): handler = test_module.CredentialProposalHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ), mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object(responder, "send_reply", mock.CoroutineMock()), + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_request_handler.py b/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_request_handler.py index 7050d754e6..740a3f759c 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_request_handler.py +++ b/acapy_agent/protocols/issue_credential/v1_0/handlers/tests/test_credential_request_handler.py @@ -128,10 +128,11 @@ async def test_called_auto_issue_x(self): }, ) - with mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - cred_ex_rec, "save_error_state", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(cred_ex_rec, "save_error_state", mock.CoroutineMock()), ): mock_cred_mgr.return_value.receive_request = mock.CoroutineMock( return_value=cred_ex_rec @@ -146,11 +147,12 @@ async def test_called_auto_issue_x(self): handler = test_module.CredentialRequestHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ), mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object(responder, "send_reply", mock.CoroutineMock()), + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v1_0/messages/credential_proposal.py b/acapy_agent/protocols/issue_credential/v1_0/messages/credential_proposal.py index 05416c54b1..d53ce0e549 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/messages/credential_proposal.py +++ b/acapy_agent/protocols/issue_credential/v1_0/messages/credential_proposal.py @@ -12,8 +12,8 @@ INDY_DID_VALIDATE, INDY_SCHEMA_ID_EXAMPLE, INDY_SCHEMA_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, ) from ..message_types import CREDENTIAL_PROPOSAL, PROTOCOL_PACKAGE from .inner.credential_preview import CredentialPreview, CredentialPreviewSchema @@ -104,8 +104,8 @@ class Meta: schema_version = fields.Str( required=False, allow_none=False, - validate=INDY_VERSION_VALIDATE, - metadata={"example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={"example": MAJOR_MINOR_VERSION_EXAMPLE}, ) cred_def_id = fields.Str( required=False, diff --git a/acapy_agent/protocols/issue_credential/v1_0/models/tests/test_credential_exchange.py b/acapy_agent/protocols/issue_credential/v1_0/models/tests/test_credential_exchange.py index dabca65888..661504d4c2 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/models/tests/test_credential_exchange.py +++ b/acapy_agent/protocols/issue_credential/v1_0/models/tests/test_credential_exchange.py @@ -77,11 +77,12 @@ async def test_save_error_state(self): record.state = V10CredentialExchange.STATE_PROPOSAL_RECEIVED await record.save(session) - with mock.patch.object( - record, "save", mock.CoroutineMock() - ) as mock_save, mock.patch.object( - test_module.LOGGER, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object(record, "save", mock.CoroutineMock()) as mock_save, + mock.patch.object( + test_module.LOGGER, "exception", mock.MagicMock() + ) as mock_log_exc, + ): mock_save.side_effect = test_module.StorageError() await record.save_error_state(session, reason="test") mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v1_0/routes.py b/acapy_agent/protocols/issue_credential/v1_0/routes.py index 898f335b01..95bb4eeedc 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/routes.py +++ b/acapy_agent/protocols/issue_credential/v1_0/routes.py @@ -34,8 +34,8 @@ INDY_DID_VALIDATE, INDY_SCHEMA_ID_EXAMPLE, INDY_SCHEMA_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, UUID4_EXAMPLE, UUID4_VALIDATE, ) @@ -142,8 +142,11 @@ class V10CredentialCreateSchema(AdminAPIMessageTracingSchema): ) schema_version = fields.Str( required=False, - validate=INDY_VERSION_VALIDATE, - metadata={"description": "Schema version", "example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, ) issuer_did = fields.Str( required=False, @@ -201,8 +204,11 @@ class V10CredentialProposalRequestSchemaBase(AdminAPIMessageTracingSchema): ) schema_version = fields.Str( required=False, - validate=INDY_VERSION_VALIDATE, - metadata={"description": "Schema version", "example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, ) issuer_did = fields.Str( required=False, diff --git a/acapy_agent/protocols/issue_credential/v1_0/tests/test_manager.py b/acapy_agent/protocols/issue_credential/v1_0/tests/test_manager.py index a8bed3b72b..af7a358fec 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/tests/test_manager.py +++ b/acapy_agent/protocols/issue_credential/v1_0/tests/test_manager.py @@ -402,12 +402,12 @@ async def test_create_bound_offer(self): async with self.profile.session() as session: await stored_exchange.save(session) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10CredentialExchange, "get_cached_key", autospec=True - ) as get_cached_key, mock.patch.object( - V10CredentialExchange, "set_cached_key", autospec=True + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + mock.patch.object( + V10CredentialExchange, "get_cached_key", autospec=True + ) as get_cached_key, + mock.patch.object(V10CredentialExchange, "set_cached_key", autospec=True), ): get_cached_key.return_value = None issuer = mock.MagicMock(IndyIssuer, autospec=True) @@ -473,12 +473,12 @@ async def test_create_bound_offer_no_cred_def(self): async with self.profile.session() as session: await stored_exchange.save(session) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ), mock.patch.object( - V10CredentialExchange, "get_cached_key", autospec=True - ) as get_cached_key, mock.patch.object( - V10CredentialExchange, "set_cached_key", autospec=True + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True), + mock.patch.object( + V10CredentialExchange, "get_cached_key", autospec=True + ) as get_cached_key, + mock.patch.object(V10CredentialExchange, "set_cached_key", autospec=True), ): get_cached_key.return_value = None issuer = mock.MagicMock() @@ -526,12 +526,13 @@ async def test_receive_offer_proposed(self): async with self.profile.session() as session: await stored_exchange.save(session) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ), mock.patch.object( - V10CredentialExchange, - "retrieve_by_connection_and_thread", - mock.CoroutineMock(return_value=stored_exchange), + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True), + mock.patch.object( + V10CredentialExchange, + "retrieve_by_connection_and_thread", + mock.CoroutineMock(return_value=stored_exchange), + ), ): exchange = await self.manager.receive_offer(offer, connection_id) @@ -565,12 +566,13 @@ async def test_receive_free_offer(self): self.profile.context.connection_record = mock.MagicMock() self.profile.context.connection_record.connection_id = connection_id - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ), mock.patch.object( - V10CredentialExchange, - "retrieve_by_connection_and_thread", - mock.CoroutineMock(side_effect=StorageNotFoundError), + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True), + mock.patch.object( + V10CredentialExchange, + "retrieve_by_connection_and_thread", + mock.CoroutineMock(side_effect=StorageNotFoundError), + ), ): exchange = await self.manager.receive_offer(offer, connection_id) @@ -752,13 +754,16 @@ async def test_receive_request(self): requests_attach=[CredentialRequest.wrap_indy_cred_req(INDY_CRED_REQ)] ) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10CredentialExchange, - "retrieve_by_connection_and_thread", - mock.CoroutineMock(return_value=stored_exchange), - ) as retrieve_ex: + with ( + mock.patch.object( + V10CredentialExchange, "save", autospec=True + ) as save_ex, + mock.patch.object( + V10CredentialExchange, + "retrieve_by_connection_and_thread", + mock.CoroutineMock(return_value=stored_exchange), + ) as retrieve_ex, + ): exchange = await self.manager.receive_request(request, mock_conn, None) retrieve_ex.assert_called() @@ -787,13 +792,14 @@ async def test_receive_request_no_connection_cred_request(self): ) mock_oob = mock.MagicMock() - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as mock_save, mock.patch.object( - V10CredentialExchange, - "retrieve_by_connection_and_thread", - mock.CoroutineMock(), - ) as mock_retrieve: + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True) as mock_save, + mock.patch.object( + V10CredentialExchange, + "retrieve_by_connection_and_thread", + mock.CoroutineMock(), + ) as mock_retrieve, + ): mock_retrieve.return_value = stored_exchange cx_rec = await self.manager.receive_request(request, mock_conn, mock_oob) @@ -822,13 +828,14 @@ async def test_receive_request_no_cred_ex_with_offer_found(self): connection_id="test_conn_id", ) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ), mock.patch.object( - V10CredentialExchange, - "retrieve_by_connection_and_thread", - mock.CoroutineMock(), - ) as mock_retrieve: + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True), + mock.patch.object( + V10CredentialExchange, + "retrieve_by_connection_and_thread", + mock.CoroutineMock(), + ) as mock_retrieve, + ): mock_retrieve.side_effect = (StorageNotFoundError(),) with self.assertRaises(StorageNotFoundError): await self.manager.receive_request(request, mock_conn, None) @@ -870,11 +877,10 @@ async def test_issue_credential_revocable(self): ) self.profile.context.injector.bind_instance(IndyIssuer, issuer) - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex: + with ( + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + ): revoc.return_value.get_or_create_active_registry = mock.CoroutineMock( return_value=( mock.MagicMock( # active_rev_reg_rec @@ -959,12 +965,13 @@ async def test_issue_credential_non_revocable(self): self.ledger.__aenter__ = mock.CoroutineMock(return_value=self.ledger) self.profile.context.injector.clear_binding(BaseLedger) self.profile.context.injector.bind_instance(BaseLedger, self.ledger) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), ): (ret_exchange, ret_cred_issue) = await self.manager.issue_credential( stored_exchange, comment=comment, retries=0 @@ -1022,11 +1029,10 @@ async def test_issue_credential_fills_rr(self): ) self.profile.context.injector.bind_instance(IndyIssuer, issuer) - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex: + with ( + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + ): revoc.return_value = mock.MagicMock( get_or_create_active_registry=( mock.CoroutineMock( @@ -1216,13 +1222,14 @@ async def test_receive_credential(self): credentials_attach=[CredentialIssue.wrap_indy_credential(INDY_CRED)] ) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10CredentialExchange, - "retrieve_by_connection_and_thread", - mock.CoroutineMock(return_value=stored_exchange), - ) as retrieve_ex: + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + mock.patch.object( + V10CredentialExchange, + "retrieve_by_connection_and_thread", + mock.CoroutineMock(return_value=stored_exchange), + ) as retrieve_ex, + ): exchange = await self.manager.receive_credential(issue, connection_id) assert retrieve_ex.call_args.args[1] == connection_id @@ -1283,12 +1290,12 @@ async def test_store_credential(self): return_value=("test_ledger_id", self.ledger) ) self.profile.context.injector.bind_instance(IndyLedgerRequestsExecutor, executor) - with mock.patch.object( - test_module, "RevocationRegistry", autospec=True - ) as mock_rev_reg, mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10CredentialExchange, "delete_record", autospec=True + with ( + mock.patch.object( + test_module, "RevocationRegistry", autospec=True + ) as mock_rev_reg, + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + mock.patch.object(V10CredentialExchange, "delete_record", autospec=True), ): mock_rev_reg.from_definition = mock.MagicMock( return_value=mock.MagicMock( @@ -1389,10 +1396,9 @@ async def test_store_credential_no_preview(self): return_value=("test_ledger_id", self.ledger) ) self.profile.context.injector.bind_instance(IndyLedgerRequestsExecutor, executor) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10CredentialExchange, "delete_record", autospec=True + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + mock.patch.object(V10CredentialExchange, "delete_record", autospec=True), ): ret_exchange = await self.manager.store_credential(stored_exchange) @@ -1480,15 +1486,18 @@ async def test_send_credential_ack(self): async with self.profile.session() as session: await stored_exchange.save(session) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ), mock.patch.object( - V10CredentialExchange, "delete_record", autospec=True - ) as mock_delete_ex, mock.patch.object( - test_module.LOGGER, "exception", mock.MagicMock() - ) as mock_log_exception, mock.patch.object( - test_module.LOGGER, "warning", mock.MagicMock() - ) as mock_log_warning: + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True), + mock.patch.object( + V10CredentialExchange, "delete_record", autospec=True + ) as mock_delete_ex, + mock.patch.object( + test_module.LOGGER, "exception", mock.MagicMock() + ) as mock_log_exception, + mock.patch.object( + test_module.LOGGER, "warning", mock.MagicMock() + ) as mock_log_warning, + ): mock_delete_ex.side_effect = test_module.StorageError() (exch, ack) = await self.manager.send_credential_ack(stored_exchange) assert ack._thread @@ -1516,15 +1525,17 @@ async def test_receive_credential_ack(self): ack = CredentialAck() - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10CredentialExchange, "delete_record", autospec=True - ) as delete_ex, mock.patch.object( - V10CredentialExchange, - "retrieve_by_connection_and_thread", - mock.CoroutineMock(), - ) as retrieve_ex: + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + mock.patch.object( + V10CredentialExchange, "delete_record", autospec=True + ) as delete_ex, + mock.patch.object( + V10CredentialExchange, + "retrieve_by_connection_and_thread", + mock.CoroutineMock(), + ) as retrieve_ex, + ): retrieve_ex.return_value = stored_exchange ret_exchange = await self.manager.receive_credential_ack(ack, connection_id) @@ -1557,13 +1568,14 @@ async def test_receive_problem_report(self): } ) - with mock.patch.object( - V10CredentialExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10CredentialExchange, - "retrieve_by_connection_and_thread", - mock.CoroutineMock(), - ) as retrieve_ex: + with ( + mock.patch.object(V10CredentialExchange, "save", autospec=True) as save_ex, + mock.patch.object( + V10CredentialExchange, + "retrieve_by_connection_and_thread", + mock.CoroutineMock(), + ) as retrieve_ex, + ): retrieve_ex.return_value = stored_exchange ret_exchange = await self.manager.receive_problem_report( diff --git a/acapy_agent/protocols/issue_credential/v1_0/tests/test_routes.py b/acapy_agent/protocols/issue_credential/v1_0/tests/test_routes.py index a5fe618496..dddac2e214 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/issue_credential/v1_0/tests/test_routes.py @@ -120,13 +120,16 @@ async def test_credential_exchange_retrieve_x(self): async def test_credential_exchange_create(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.CredentialPreview, "deserialize", autospec=True - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module.CredentialPreview, "deserialize", autospec=True + ), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_credential_manager.return_value.create_offer = mock.CoroutineMock() mock_credential_manager.return_value.create_offer.return_value = ( @@ -151,13 +154,16 @@ async def test_credential_exchange_create(self): async def test_credential_exchange_create_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.CredentialPreview, "deserialize", autospec=True - ), mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module.CredentialPreview, "deserialize", autospec=True + ), + mock.patch.object(test_module.web, "json_response"), + ): mock_credential_manager.return_value.create_offer = mock.CoroutineMock() mock_credential_manager.return_value.create_offer.return_value = ( @@ -184,13 +190,16 @@ async def test_credential_exchange_create_no_proposal(self): async def test_credential_exchange_send(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.CredentialPreview, "deserialize", autospec=True - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module.CredentialPreview, "deserialize", autospec=True + ), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_credential_manager.return_value.create_offer = mock.CoroutineMock() mock_credential_manager.return_value.create_offer.return_value = ( @@ -229,11 +238,12 @@ async def test_credential_exchange_send_no_conn_record(self): return_value={"connection_id": conn_id, "credential_proposal": preview_spec} ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + ): # Emulate storage not found (bad connection id) mock_conn_rec.retrieve_by_id = mock.CoroutineMock( side_effect=test_module.StorageNotFoundError() @@ -255,11 +265,12 @@ async def test_credential_exchange_send_not_ready(self): return_value={"connection_id": conn_id, "credential_proposal": preview_spec} ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + ): # Emulate connection not ready mock_conn_rec.retrieve_by_id.return_value.is_ready = False @@ -274,12 +285,14 @@ async def test_credential_exchange_send_not_ready(self): async def test_credential_exchange_send_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.CredentialPreview, "deserialize", autospec=True + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module.CredentialPreview, "deserialize", autospec=True + ), ): mock_cred_ex_record = mock.MagicMock( serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), @@ -313,13 +326,13 @@ async def test_credential_exchange_send_proposal(self): return_value={"connection_id": conn_id, "credential_proposal": preview_spec} ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex_record = mock.MagicMock() mock_credential_manager.return_value.create_proposal.return_value = ( mock_cred_ex_record @@ -336,12 +349,14 @@ async def test_credential_exchange_send_proposal(self): async def test_credential_exchange_send_proposal_no_conn_record(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.CredentialPreview, "deserialize", autospec=True + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module.CredentialPreview, "deserialize", autospec=True + ), ): # Emulate storage not found (bad connection id) mock_conn_rec.retrieve_by_id = mock.CoroutineMock( @@ -373,12 +388,14 @@ async def test_credential_exchange_send_proposal_deser_x(self): async def test_credential_exchange_send_proposal_not_ready(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.CredentialPreview, "deserialize", autospec=True + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module.CredentialPreview, "deserialize", autospec=True + ), ): # Emulate connection not ready mock_conn_rec.retrieve_by_id = mock.CoroutineMock() @@ -399,11 +416,12 @@ async def test_credential_exchange_send_proposal_x(self): return_value={"connection_id": conn_id, "credential_proposal": preview_spec} ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + ): mock_cred_ex_record = mock.MagicMock( serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), save_error_state=mock.CoroutineMock(), @@ -428,13 +446,13 @@ async def test_credential_exchange_create_free_offer(self): self.context.update_settings({"debug.auto_respond_credential_offer": True}) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_credential_manager.return_value.create_offer = mock.CoroutineMock() mock_cred_ex_record = mock.MagicMock() mock_credential_manager.return_value.create_offer.return_value = ( @@ -498,11 +516,12 @@ async def test_credential_exchange_create_free_offer_deser_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + ): mock_credential_manager.return_value.create_offer = mock.CoroutineMock() mock_credential_manager.return_value.create_offer.side_effect = ( test_module.BaseModelError() @@ -522,11 +541,12 @@ async def test_credential_exchange_create_free_offer_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + ): mock_cred_ex_record = mock.MagicMock( serialize=mock.MagicMock( side_effect=test_module.BaseModelError(), @@ -555,13 +575,13 @@ async def test_credential_exchange_send_free_offer(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_credential_manager.return_value.create_offer = mock.CoroutineMock() mock_cred_ex_record = mock.MagicMock() @@ -606,11 +626,12 @@ async def test_credential_exchange_send_free_offer_no_conn_record(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + ): # Emulate storage not found (bad connection id) mock_conn_rec.retrieve_by_id = mock.CoroutineMock( side_effect=test_module.StorageNotFoundError() @@ -629,11 +650,12 @@ async def test_credential_exchange_send_free_offer_not_ready(self): self.request.json = mock.CoroutineMock() self.request.json.return_value["auto_issue"] = True - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + ): # Emulate connection not ready mock_conn_rec.retrieve_by_id = mock.CoroutineMock() mock_conn_rec.retrieve_by_id.return_value.is_ready = False @@ -658,11 +680,13 @@ async def test_credential_exchange_send_free_offer_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object(test_module.web, "json_response"), + ): mock_cred_ex_record = mock.MagicMock( serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), save_error_state=mock.CoroutineMock(), @@ -684,15 +708,16 @@ async def test_credential_exchange_send_bound_offer(self): self.request.json = mock.CoroutineMock(return_value={}) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( mock_cred_ex.STATE_PROPOSAL_RECEIVED @@ -732,13 +757,15 @@ async def test_credential_exchange_send_bound_offer_no_conn_record(self): self.request.json = mock.CoroutineMock(return_value={}) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.connection_id = "conn-123" mock_cred_ex.thread_id = "conn-123" mock_cred_ex.retrieve_by_id = mock.CoroutineMock( @@ -785,13 +812,15 @@ async def test_credential_exchange_send_bound_offer_not_ready(self): self.request.json = mock.CoroutineMock(return_value={}) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.connection_id = "conn-123" mock_cred_ex.thread_id = "conn-123" mock_cred_ex.retrieve_by_id = mock.CoroutineMock() @@ -816,15 +845,16 @@ async def test_credential_exchange_send_request(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( mock_cred_ex.STATE_OFFER_RECEIVED @@ -847,17 +877,19 @@ async def test_credential_exchange_send_request_no_conn(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "OobRecord", autospec=True - ) as mock_oob_rec, mock.patch.object( - test_module, "default_did_from_verkey", autospec=True - ) as mock_default_did_from_verkey, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "OobRecord", autospec=True) as mock_oob_rec, + mock.patch.object( + test_module, "default_did_from_verkey", autospec=True + ) as mock_default_did_from_verkey, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_oob_rec.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock.MagicMock(our_recipient_key="our-recipient_key") ) @@ -905,13 +937,15 @@ async def test_credential_exchange_send_request_no_conn_record(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.connection_id = "conn-123" mock_cred_ex.thread_id = "conn-123" mock_cred_ex.retrieve_by_id = mock.CoroutineMock() @@ -938,13 +972,15 @@ async def test_credential_exchange_send_request_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.connection_id = "conn-123" mock_cred_ex.thread_id = "conn-123" mock_cred_ex.retrieve_by_id = mock.CoroutineMock() @@ -969,15 +1005,16 @@ async def test_credential_exchange_issue(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( mock_cred_ex.STATE_REQUEST_RECEIVED @@ -1020,13 +1057,15 @@ async def test_credential_exchange_issue_no_conn_record(self): serialize=mock.MagicMock(), save_error_state=mock.CoroutineMock(), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex_cls: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex_cls, + ): mock_cred_ex_rec.state = mock_cred_ex_cls.STATE_REQUEST_RECEIVED mock_cred_ex_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock_cred_ex_rec @@ -1050,13 +1089,15 @@ async def test_credential_exchange_issue_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( mock_cred_ex.STATE_REQUEST_RECEIVED @@ -1084,13 +1125,15 @@ async def test_credential_exchange_issue_rev_reg_full(self): serialize=mock.MagicMock(), save_error_state=mock.CoroutineMock(), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex_cls: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex_cls, + ): mock_cred_ex_cls.state = mock_cred_ex_cls.STATE_REQUEST_RECEIVED mock_cred_ex_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock_cred_ex_rec @@ -1116,13 +1159,15 @@ async def test_credential_exchange_issue_deser_x(self): serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), save_error_state=mock.CoroutineMock(), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex_cls: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex_cls, + ): mock_cred_ex_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock_cred_ex_rec ) @@ -1141,15 +1186,16 @@ async def test_credential_exchange_store(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( mock_cred_ex.STATE_CREDENTIAL_RECEIVED @@ -1177,15 +1223,16 @@ async def test_credential_exchange_store_bad_cred_id_json(self): ) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value.state = ( mock_cred_ex.STATE_CREDENTIAL_RECEIVED @@ -1226,13 +1273,15 @@ async def test_credential_exchange_store_no_conn_record(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.connection_id = "conn-123" mock_cred_ex.thread_id = "conn-123" mock_cred_ex.retrieve_by_id = mock.CoroutineMock( @@ -1262,13 +1311,13 @@ async def test_credential_exchange_store_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "CredentialManager", autospec=True - ), mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object(test_module, "CredentialManager", autospec=True), + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.connection_id = "conn-123" mock_cred_ex.thread_id = "conn-123" mock_cred_ex.retrieve_by_id = mock.CoroutineMock() @@ -1287,13 +1336,16 @@ async def test_credential_exchange_store_x(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "CredentialManager", autospec=True - ) as mock_credential_manager, mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex_cls, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "CredentialManager", autospec=True + ) as mock_credential_manager, + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex_cls, + mock.patch.object(test_module.web, "json_response"), + ): mock_cred_ex_record = mock.MagicMock( state=mock_cred_ex_cls.STATE_CREDENTIAL_RECEIVED, serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), @@ -1316,11 +1368,12 @@ async def test_credential_exchange_store_x(self): async def test_credential_exchange_remove(self): self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock() mock_cred_ex.retrieve_by_id.return_value = mock_cred_ex @@ -1366,15 +1419,17 @@ async def test_credential_exchange_problem_report(self): self.request.match_info = {"cred_ex_id": "dummy"} magic_report = mock.MagicMock() - with mock.patch.object( - test_module, "CredentialManager", autospec=True - ), mock.patch.object(test_module, "ConnRecord", autospec=True), mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ) as mock_problem_report, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "CredentialManager", autospec=True), + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + mock.patch.object( + test_module, "problem_report_for_record", mock.MagicMock() + ) as mock_problem_report, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock(save_error_state=mock.CoroutineMock()) ) @@ -1410,13 +1465,13 @@ async def test_credential_exchange_problem_report_x(self): ) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "CredentialManager", autospec=True - ), mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ), mock.patch.object( - test_module, "V10CredentialExchange", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "CredentialManager", autospec=True), + mock.patch.object(test_module, "problem_report_for_record", mock.MagicMock()), + mock.patch.object( + test_module, "V10CredentialExchange", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock( save_error_state=mock.CoroutineMock( diff --git a/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/handler.py b/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/handler.py index e72614437a..a25e4bb62c 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/handler.py @@ -1,30 +1,28 @@ -"""V2.0 issue-credential indy credential format handler.""" +"""V2.0 issue-credential anoncreds credential format handler.""" import json import logging from typing import Mapping, Optional, Tuple +from anoncreds import CredentialDefinition, Schema from marshmallow import RAISE +from ......anoncreds.base import AnonCredsResolutionError from ......anoncreds.holder import AnonCredsHolder, AnonCredsHolderError -from ......anoncreds.issuer import AnonCredsIssuer +from ......anoncreds.issuer import CATEGORY_CRED_DEF, CATEGORY_SCHEMA, AnonCredsIssuer +from ......anoncreds.models.credential import AnoncredsCredentialSchema +from ......anoncreds.models.credential_offer import AnoncredsCredentialOfferSchema +from ......anoncreds.models.credential_proposal import ( + AnoncredsCredentialDefinitionProposal, +) +from ......anoncreds.models.credential_request import AnoncredsCredRequestSchema from ......anoncreds.registry import AnonCredsRegistry from ......anoncreds.revocation import AnonCredsRevocation from ......cache.base import BaseCache -from ......indy.models.cred import IndyCredentialSchema -from ......indy.models.cred_abstract import IndyCredAbstractSchema -from ......indy.models.cred_request import IndyCredRequestSchema -from ......ledger.base import BaseLedger -from ......ledger.multiple_ledger.ledger_requests_executor import ( - GET_CRED_DEF, - IndyLedgerRequestsExecutor, -) from ......messaging.credential_definitions.util import ( CRED_DEF_SENT_RECORD_TYPE, - CredDefQueryStringSchema, ) from ......messaging.decorators.attach_decorator import AttachDecorator -from ......multitenant.base import BaseMultitenantManager from ......revocation_anoncreds.models.issuer_cred_rev_record import IssuerCredRevRecord from ......storage.base import BaseStorage from ...message_types import ( @@ -40,16 +38,16 @@ from ...messages.cred_proposal import V20CredProposal from ...messages.cred_request import V20CredRequest from ...models.cred_ex_record import V20CredExRecord -from ...models.detail.indy import V20CredExRecordIndy +from ...models.detail.anoncreds import V20CredExRecordAnoncreds from ..handler import CredFormatAttachment, V20CredFormatError, V20CredFormatHandler LOGGER = logging.getLogger(__name__) class AnonCredsCredFormatHandler(V20CredFormatHandler): - """Indy credential format handler.""" + """Anoncreds credential format handler.""" - format = V20CredFormat.Format.INDY + format = V20CredFormat.Format.ANONCREDS @classmethod def validate_fields(cls, message_type: str, attachment_data: Mapping): @@ -71,10 +69,10 @@ def validate_fields(cls, message_type: str, attachment_data: Mapping): """ mapping = { - CRED_20_PROPOSAL: CredDefQueryStringSchema, - CRED_20_OFFER: IndyCredAbstractSchema, - CRED_20_REQUEST: IndyCredRequestSchema, - CRED_20_ISSUE: IndyCredentialSchema, + CRED_20_PROPOSAL: AnoncredsCredentialDefinitionProposal, + CRED_20_OFFER: AnoncredsCredentialOfferSchema, + CRED_20_REQUEST: AnoncredsCredRequestSchema, + CRED_20_ISSUE: AnoncredsCredentialSchema, } # Get schema class @@ -83,7 +81,7 @@ def validate_fields(cls, message_type: str, attachment_data: Mapping): # Validate, throw if not valid Schema(unknown=RAISE).load(attachment_data) - async def get_detail_record(self, cred_ex_id: str) -> V20CredExRecordIndy: + async def get_detail_record(self, cred_ex_id: str) -> V20CredExRecordAnoncreds: """Retrieve credential exchange detail record by cred_ex_id.""" async with self.profile.session() as session: @@ -167,7 +165,7 @@ async def _match_sent_cred_def_id(self, tag_query: Mapping[str, str]) -> str: async def create_proposal( self, cred_ex_record: V20CredExRecord, proposal_data: Mapping[str, str] ) -> Tuple[V20CredFormat, AttachDecorator]: - """Create indy credential proposal.""" + """Create anoncreds credential proposal.""" if proposal_data is None: proposal_data = {} @@ -176,7 +174,7 @@ async def create_proposal( async def receive_proposal( self, cred_ex_record: V20CredExRecord, cred_proposal_message: V20CredProposal ) -> None: - """Receive indy credential proposal. + """Receive anoncreds credential proposal. No custom handling is required for this step. """ @@ -184,35 +182,37 @@ async def receive_proposal( async def create_offer( self, cred_proposal_message: V20CredProposal ) -> CredFormatAttachment: - """Create indy credential offer.""" + """Create anoncreds credential offer.""" issuer = AnonCredsIssuer(self.profile) - ledger = self.profile.inject(BaseLedger) cache = self.profile.inject_or(BaseCache) + anoncreds_attachment = cred_proposal_message.attachment( + AnonCredsCredFormatHandler.format + ) + + if not anoncreds_attachment: + anoncreds_attachment = cred_proposal_message.attachment( + V20CredFormat.Format.INDY.api + ) + cred_def_id = await issuer.match_created_credential_definitions( - **cred_proposal_message.attachment(AnonCredsCredFormatHandler.format) + **anoncreds_attachment ) async def _create(): offer_json = await issuer.create_credential_offer(cred_def_id) return json.loads(offer_json) - multitenant_mgr = self.profile.inject_or(BaseMultitenantManager) - if multitenant_mgr: - ledger_exec_inst = IndyLedgerRequestsExecutor(self.profile) - else: - ledger_exec_inst = self.profile.inject(IndyLedgerRequestsExecutor) - ledger = ( - await ledger_exec_inst.get_ledger_for_identifier( - cred_def_id, - txn_record_type=GET_CRED_DEF, + async with self.profile.session() as session: + cred_def_entry = await session.handle.fetch(CATEGORY_CRED_DEF, cred_def_id) + cred_def_dict = CredentialDefinition.load(cred_def_entry.value).to_dict() + schema_entry = await session.handle.fetch( + CATEGORY_SCHEMA, cred_def_dict["schemaId"] ) - )[1] - async with ledger: - schema_id = await ledger.credential_definition_id2schema_id(cred_def_id) - schema = await ledger.get_schema(schema_id) - schema_attrs = set(schema["attrNames"]) + schema_dict = Schema.load(schema_entry.value).to_dict() + + schema_attrs = set(schema_dict["attrNames"]) preview_attrs = set(cred_proposal_message.credential_preview.attr_dict()) if preview_attrs != schema_attrs: raise V20CredFormatError( @@ -238,23 +238,26 @@ async def _create(): async def receive_offer( self, cred_ex_record: V20CredExRecord, cred_offer_message: V20CredOffer ) -> None: - """Receive indy credential offer.""" + """Receive anoncreds credential offer.""" async def create_request( self, cred_ex_record: V20CredExRecord, request_data: Optional[Mapping] = None ) -> CredFormatAttachment: - """Create indy credential request.""" + """Create anoncreds credential request.""" if cred_ex_record.state != V20CredExRecord.STATE_OFFER_RECEIVED: raise V20CredFormatError( - "Indy issue credential format cannot start from credential request" + "Anoncreds issue credential format cannot start from credential request" ) await self._check_uniqueness(cred_ex_record.cred_ex_id) - holder_did = request_data.get("holder_did") if request_data else None + + # For backwards compatibility, remove indy backup when indy format is retired + from ..indy.handler import IndyCredFormatHandler + cred_offer = cred_ex_record.cred_offer.attachment( AnonCredsCredFormatHandler.format - ) + ) or cred_ex_record.cred_offer.attachment(IndyCredFormatHandler.format) if "nonce" not in cred_offer: raise V20CredFormatError("Missing nonce in credential offer") @@ -265,19 +268,24 @@ async def create_request( async def _create(): anoncreds_registry = self.profile.inject(AnonCredsRegistry) - cred_def_result = await anoncreds_registry.get_credential_definition( - self.profile, cred_def_id - ) - - holder = AnonCredsHolder(self.profile) - request_json, metadata_json = await holder.create_credential_request( - cred_offer, cred_def_result.credential_definition, holder_did - ) + try: + cred_def_result = await anoncreds_registry.get_credential_definition( + self.profile, cred_def_id + ) + holder = AnonCredsHolder(self.profile) + request_json, metadata_json = await holder.create_credential_request( + cred_offer, cred_def_result.credential_definition, holder_did + ) - return { - "request": json.loads(request_json), - "metadata": json.loads(metadata_json), - } + return { + "request": json.loads(request_json), + "metadata": json.loads(metadata_json), + } + # This is for compatability with a holder that isn't anoncreds capable + except AnonCredsResolutionError: + return await IndyCredFormatHandler.create_cred_request_result( + self, cred_offer, holder_did, cred_def_id + ) cache_key = f"credential_request::{cred_def_id}::{holder_did}::{nonce}" cred_req_result = None @@ -292,7 +300,7 @@ async def _create(): if not cred_req_result: cred_req_result = await _create() - detail_record = V20CredExRecordIndy( + detail_record = V20CredExRecordAnoncreds( cred_ex_id=cred_ex_record.cred_ex_id, cred_request_metadata=cred_req_result["metadata"], ) @@ -305,18 +313,25 @@ async def _create(): async def receive_request( self, cred_ex_record: V20CredExRecord, cred_request_message: V20CredRequest ) -> None: - """Receive indy credential request.""" + """Receive anoncreds credential request.""" if not cred_ex_record.cred_offer: raise V20CredFormatError( - "Indy issue credential format cannot start from credential request" + "Anoncreds issue credential format cannot start from credential request" ) async def issue_credential( self, cred_ex_record: V20CredExRecord, retries: int = 5 ) -> CredFormatAttachment: - """Issue indy credential.""" + """Issue anoncreds credential.""" await self._check_uniqueness(cred_ex_record.cred_ex_id) + # For backwards compatibility, remove indy backup when indy format is retired + from ..indy.handler import IndyCredFormatHandler + + if cred_ex_record.cred_offer.attachment(IndyCredFormatHandler.format): + indy_handler = IndyCredFormatHandler(self.profile) + return await indy_handler.issue_credential(cred_ex_record, retries) + cred_offer = cred_ex_record.cred_offer.attachment( AnonCredsCredFormatHandler.format ) @@ -342,7 +357,7 @@ async def issue_credential( result = self.get_format_data(CRED_20_ISSUE, json.loads(cred_json)) async with self._profile.transaction() as txn: - detail_record = V20CredExRecordIndy( + detail_record = V20CredExRecordAnoncreds( cred_ex_id=cred_ex_record.cred_ex_id, rev_reg_id=rev_reg_def_id, cred_rev_id=cred_rev_id, @@ -371,7 +386,7 @@ async def issue_credential( async def receive_credential( self, cred_ex_record: V20CredExRecord, cred_issue_message: V20CredIssue ) -> None: - """Receive indy credential. + """Receive anoncreds credential. Validation is done in the store credential step. """ @@ -379,21 +394,33 @@ async def receive_credential( async def store_credential( self, cred_ex_record: V20CredExRecord, cred_id: Optional[str] = None ) -> None: - """Store indy credential.""" - cred = cred_ex_record.cred_issue.attachment(AnonCredsCredFormatHandler.format) + """Store anoncreds credential.""" + + # For backwards compatibility, remove indy backup when indy format is retired + from ..indy.handler import IndyCredFormatHandler + + cred = cred_ex_record.cred_issue.attachment( + AnonCredsCredFormatHandler.format + ) or cred_ex_record.cred_issue.attachment(IndyCredFormatHandler.format) rev_reg_def = None anoncreds_registry = self.profile.inject(AnonCredsRegistry) - cred_def_result = await anoncreds_registry.get_credential_definition( - self.profile, cred["cred_def_id"] - ) - if cred.get("rev_reg_id"): - rev_reg_def_result = ( - await anoncreds_registry.get_revocation_registry_definition( - self.profile, cred["rev_reg_id"] + try: + cred_def_result = await anoncreds_registry.get_credential_definition( + self.profile, cred["cred_def_id"] + ) + if cred.get("rev_reg_id"): + rev_reg_def_result = ( + await anoncreds_registry.get_revocation_registry_definition( + self.profile, cred["rev_reg_id"] + ) ) + rev_reg_def = rev_reg_def_result.revocation_registry + + except AnonCredsResolutionError: + return await IndyCredFormatHandler.store_credential( + self, cred_ex_record, cred_id ) - rev_reg_def = rev_reg_def_result.revocation_registry holder = AnonCredsHolder(self.profile) cred_offer_message = cred_ex_record.cred_offer diff --git a/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/tests/test_handler.py b/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/tests/test_handler.py index 46606417fb..f795929e8b 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/tests/test_handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/formats/anoncreds/tests/test_handler.py @@ -36,10 +36,10 @@ from ....messages.cred_request import V20CredRequest from ....messages.inner.cred_preview import V20CredAttrSpec, V20CredPreview from ....models.cred_ex_record import V20CredExRecord -from ....models.detail.indy import V20CredExRecordIndy +from ....models.detail.anoncreds import V20CredExRecordAnoncreds from ...handler import V20CredFormatError from .. import handler as test_module -from ..handler import LOGGER as INDY_LOGGER +from ..handler import LOGGER as ANONCREDS_LOGGER from ..handler import AnonCredsCredFormatHandler TEST_DID = "LjgpST2rjsoxYegQDRm7EL" @@ -108,7 +108,7 @@ "tailsLocation": TAILS_LOCAL, }, } -INDY_OFFER = { +ANONCREDS_OFFER = { "schema_id": SCHEMA_ID, "cred_def_id": CRED_DEF_ID, "key_correctness_proof": { @@ -131,7 +131,7 @@ }, "nonce": "1234567890", } -INDY_CRED_REQ = { +ANONCREDS_CRED_REQ = { "prover_did": TEST_DID, "cred_def_id": CRED_DEF_ID, "blinded_ms": { @@ -148,7 +148,7 @@ }, "nonce": "9876543210", } -INDY_CRED = { +ANONCREDS_CRED = { "schema_id": SCHEMA_ID, "cred_def_id": CRED_DEF_ID, "rev_reg_id": REV_REG_ID, @@ -232,9 +232,9 @@ async def asyncSetUp(self): async def test_validate_fields(self): # Test correct data self.handler.validate_fields(CRED_20_PROPOSAL, {"cred_def_id": CRED_DEF_ID}) - self.handler.validate_fields(CRED_20_OFFER, INDY_OFFER) - self.handler.validate_fields(CRED_20_REQUEST, INDY_CRED_REQ) - self.handler.validate_fields(CRED_20_ISSUE, INDY_CRED) + self.handler.validate_fields(CRED_20_OFFER, ANONCREDS_OFFER) + self.handler.validate_fields(CRED_20_REQUEST, ANONCREDS_CRED_REQ) + self.handler.validate_fields(CRED_20_ISSUE, ANONCREDS_CRED) # test incorrect proposal with self.assertRaises(ValidationError): @@ -244,31 +244,31 @@ async def test_validate_fields(self): # test incorrect offer with self.assertRaises(ValidationError): - offer = INDY_OFFER.copy() + offer = ANONCREDS_OFFER.copy() offer.pop("nonce") self.handler.validate_fields(CRED_20_OFFER, offer) # test incorrect request with self.assertRaises(ValidationError): - req = INDY_CRED_REQ.copy() + req = ANONCREDS_CRED_REQ.copy() req.pop("nonce") self.handler.validate_fields(CRED_20_REQUEST, req) # test incorrect cred with self.assertRaises(ValidationError): - cred = INDY_CRED.copy() + cred = ANONCREDS_CRED.copy() cred.pop("schema_id") self.handler.validate_fields(CRED_20_ISSUE, cred) async def test_get_indy_detail_record(self): cred_ex_id = "dummy" details_indy = [ - V20CredExRecordIndy( + V20CredExRecordAnoncreds( cred_ex_id=cred_ex_id, rev_reg_id="rr-id", cred_rev_id="0", ), - V20CredExRecordIndy( + V20CredExRecordAnoncreds( cred_ex_id=cred_ex_id, rev_reg_id="rr-id", cred_rev_id="1", @@ -278,7 +278,9 @@ async def test_get_indy_detail_record(self): await details_indy[0].save(session) await details_indy[1].save(session) # exercise logger warning on get() - with mock.patch.object(INDY_LOGGER, "warning", mock.MagicMock()) as mock_warning: + with mock.patch.object( + ANONCREDS_LOGGER, "warning", mock.MagicMock() + ) as mock_warning: assert await self.handler.get_detail_record(cred_ex_id) in details_indy mock_warning.assert_called_once() @@ -354,7 +356,7 @@ async def test_create_offer(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_PROPOSAL][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], @@ -379,7 +381,7 @@ async def test_create_offer(self): await self.session.storage.add_record(cred_def_record) self.issuer.create_credential_offer = mock.CoroutineMock( - return_value=json.dumps(INDY_OFFER) + return_value=json.dumps(ANONCREDS_OFFER) ) (cred_format, attachment) = await self.handler.create_offer(cred_proposal) @@ -390,7 +392,7 @@ async def test_create_offer(self): assert cred_format.attach_id == self.handler.format.api == attachment.ident # assert content of attachment is proposal data - assert attachment.content == INDY_OFFER + assert attachment.content == ANONCREDS_OFFER # assert data is encoded as base64 assert attachment.data.base64 @@ -417,7 +419,7 @@ async def test_create_offer_no_cache(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_PROPOSAL][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], @@ -446,7 +448,7 @@ async def test_create_offer_no_cache(self): await self.session.storage.add_record(cred_def_record) self.issuer.create_credential_offer = mock.CoroutineMock( - return_value=json.dumps(INDY_OFFER) + return_value=json.dumps(ANONCREDS_OFFER) ) (cred_format, attachment) = await self.handler.create_offer(cred_proposal) @@ -457,7 +459,7 @@ async def test_create_offer_no_cache(self): assert cred_format.attach_id == self.handler.format.api == attachment.ident # assert content of attachment is proposal data - assert attachment.content == INDY_OFFER + assert attachment.content == ANONCREDS_OFFER # assert data is encoded as base64 assert attachment.data.base64 @@ -480,7 +482,7 @@ async def test_create_offer_attr_mismatch(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_PROPOSAL][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], @@ -509,7 +511,7 @@ async def test_create_offer_attr_mismatch(self): await self.session.storage.add_record(cred_def_record) self.issuer.create_credential_offer = mock.CoroutineMock( - return_value=json.dumps(INDY_OFFER) + return_value=json.dumps(ANONCREDS_OFFER) ) with mock.patch.object( IndyLedgerRequestsExecutor, @@ -526,7 +528,7 @@ async def test_create_offer_no_matching_sent_cred_def(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_PROPOSAL][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], @@ -534,7 +536,7 @@ async def test_create_offer_no_matching_sent_cred_def(self): ) self.issuer.create_credential_offer = mock.CoroutineMock( - return_value=json.dumps(INDY_OFFER) + return_value=json.dumps(ANONCREDS_OFFER) ) with self.assertRaises(V20CredFormatError) as context: @@ -557,11 +559,11 @@ async def test_create_request(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_OFFER][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - offers_attach=[AttachDecorator.data_base64(INDY_OFFER, ident="0")], + offers_attach=[AttachDecorator.data_base64(ANONCREDS_OFFER, ident="0")], ) cred_ex_record = V20CredExRecord( cred_ex_id="dummy-id", @@ -574,7 +576,7 @@ async def test_create_request(self): cred_req_meta = {} self.holder.create_credential_request = mock.CoroutineMock( - return_value=(json.dumps(INDY_CRED_REQ), json.dumps(cred_req_meta)) + return_value=(json.dumps(ANONCREDS_CRED_REQ), json.dumps(cred_req_meta)) ) (cred_format, attachment) = await self.handler.create_request( @@ -582,14 +584,14 @@ async def test_create_request(self): ) self.holder.create_credential_request.assert_called_once_with( - INDY_OFFER, cred_def, holder_did + ANONCREDS_OFFER, cred_def, holder_did ) # assert identifier match assert cred_format.attach_id == self.handler.format.api == attachment.ident # assert content of attachment is proposal data - assert attachment.content == INDY_CRED_REQ + assert attachment.content == ANONCREDS_CRED_REQ # assert data is encoded as base64 assert attachment.data.base64 @@ -617,16 +619,18 @@ async def test_create_request_bad_state(self): with self.assertRaises(V20CredFormatError) as context: await self.handler.create_request(cred_ex_record) - assert "Indy issue credential format cannot start from credential request" in str( - context.exception + assert ( + "Anoncreds issue credential format cannot start from credential request" + in str(context.exception) ) cred_ex_record.state = None with self.assertRaises(V20CredFormatError) as context: await self.handler.create_request(cred_ex_record) - assert "Indy issue credential format cannot start from credential request" in str( - context.exception + assert ( + "Anoncreds issue credential format cannot start from credential request" + in str(context.exception) ) async def test_create_request_not_unique_x(self): @@ -658,8 +662,9 @@ async def test_receive_request_no_offer(self): with self.assertRaises(V20CredFormatError) as context: await self.handler.receive_request(cred_ex_record, cred_request_message) - assert "Indy issue credential format cannot start from credential request" in str( - context.exception + assert ( + "Anoncreds issue credential format cannot start from credential request" + in str(context.exception) ) @pytest.mark.skip(reason="Anoncreds-break") @@ -680,22 +685,22 @@ async def test_issue_credential_revocable(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_OFFER][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - offers_attach=[AttachDecorator.data_base64(INDY_OFFER, ident="0")], + offers_attach=[AttachDecorator.data_base64(ANONCREDS_OFFER, ident="0")], ) cred_request = V20CredRequest( formats=[ V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_REQUEST][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], + requests_attach=[AttachDecorator.data_base64(ANONCREDS_CRED_REQ, ident="0")], ) cred_ex_record = V20CredExRecord( @@ -709,7 +714,7 @@ async def test_issue_credential_revocable(self): cred_rev_id = "1000" self.issuer.create_credential = mock.CoroutineMock( - return_value=(json.dumps(INDY_CRED), cred_rev_id) + return_value=(json.dumps(ANONCREDS_CRED), cred_rev_id) ) with mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc: @@ -732,8 +737,8 @@ async def test_issue_credential_revocable(self): self.issuer.create_credential.assert_called_once_with( SCHEMA, - INDY_OFFER, - INDY_CRED_REQ, + ANONCREDS_OFFER, + ANONCREDS_CRED_REQ, attr_values, REV_REG_ID, "dummy-path", @@ -743,7 +748,7 @@ async def test_issue_credential_revocable(self): assert cred_format.attach_id == self.handler.format.api == attachment.ident # assert content of attachment is proposal data - assert attachment.content == INDY_CRED + assert attachment.content == ANONCREDS_CRED # assert data is encoded as base64 assert attachment.data.base64 @@ -768,22 +773,22 @@ async def test_issue_credential_non_revocable(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_OFFER][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - offers_attach=[AttachDecorator.data_base64(INDY_OFFER, ident="0")], + offers_attach=[AttachDecorator.data_base64(ANONCREDS_OFFER, ident="0")], ) cred_request = V20CredRequest( formats=[ V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_REQUEST][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], + requests_attach=[AttachDecorator.data_base64(ANONCREDS_CRED_REQ, ident="0")], ) cred_ex_record = V20CredExRecord( @@ -796,7 +801,7 @@ async def test_issue_credential_non_revocable(self): ) self.issuer.create_credential = mock.CoroutineMock( - return_value=(json.dumps(INDY_CRED), None) + return_value=(json.dumps(ANONCREDS_CRED), None) ) self.ledger.get_credential_definition = mock.CoroutineMock( return_value=CRED_DEF_NR @@ -816,8 +821,8 @@ async def test_issue_credential_non_revocable(self): self.issuer.create_credential.assert_called_once_with( SCHEMA, - INDY_OFFER, - INDY_CRED_REQ, + ANONCREDS_OFFER, + ANONCREDS_CRED_REQ, attr_values, None, None, @@ -827,7 +832,7 @@ async def test_issue_credential_non_revocable(self): assert cred_format.attach_id == self.handler.format.api == attachment.ident # assert content of attachment is proposal data - assert attachment.content == INDY_CRED + assert attachment.content == ANONCREDS_CRED # assert data is encoded as base64 assert attachment.data.base64 @@ -867,22 +872,22 @@ async def test_issue_credential_no_active_rr_no_retries(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_OFFER][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - offers_attach=[AttachDecorator.data_base64(INDY_OFFER, ident="0")], + offers_attach=[AttachDecorator.data_base64(ANONCREDS_OFFER, ident="0")], ) cred_request = V20CredRequest( formats=[ V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_REQUEST][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], + requests_attach=[AttachDecorator.data_base64(ANONCREDS_CRED_REQ, ident="0")], ) cred_ex_record = V20CredExRecord( @@ -895,7 +900,7 @@ async def test_issue_credential_no_active_rr_no_retries(self): ) self.issuer.create_credential = mock.CoroutineMock( - return_value=(json.dumps(INDY_CRED), cred_rev_id) + return_value=(json.dumps(ANONCREDS_CRED), cred_rev_id) ) with mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc: @@ -926,22 +931,22 @@ async def test_issue_credential_no_active_rr_retry(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_OFFER][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - offers_attach=[AttachDecorator.data_base64(INDY_OFFER, ident="0")], + offers_attach=[AttachDecorator.data_base64(ANONCREDS_OFFER, ident="0")], ) cred_request = V20CredRequest( formats=[ V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_REQUEST][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], + requests_attach=[AttachDecorator.data_base64(ANONCREDS_CRED_REQ, ident="0")], ) cred_ex_record = V20CredExRecord( @@ -954,7 +959,7 @@ async def test_issue_credential_no_active_rr_retry(self): ) self.issuer.create_credential = mock.CoroutineMock( - return_value=(json.dumps(INDY_CRED), cred_rev_id) + return_value=(json.dumps(ANONCREDS_CRED), cred_rev_id) ) with mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc: @@ -996,22 +1001,22 @@ async def test_issue_credential_rr_full(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_OFFER][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - offers_attach=[AttachDecorator.data_base64(INDY_OFFER, ident="0")], + offers_attach=[AttachDecorator.data_base64(ANONCREDS_OFFER, ident="0")], ) cred_request = V20CredRequest( formats=[ V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_REQUEST][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], + requests_attach=[AttachDecorator.data_base64(ANONCREDS_CRED_REQ, ident="0")], ) cred_ex_record = V20CredExRecord( @@ -1075,11 +1080,11 @@ async def test_store_credential(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_OFFER][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - offers_attach=[AttachDecorator.data_base64(INDY_OFFER, ident="0")], + offers_attach=[AttachDecorator.data_base64(ANONCREDS_OFFER, ident="0")], ) cred_offer.assign_thread_id(thread_id) cred_request = V20CredRequest( @@ -1087,22 +1092,22 @@ async def test_store_credential(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_REQUEST][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], + requests_attach=[AttachDecorator.data_base64(ANONCREDS_CRED_REQ, ident="0")], ) cred_issue = V20CredIssue( formats=[ V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_ISSUE][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - credentials_attach=[AttachDecorator.data_base64(INDY_CRED, ident="0")], + credentials_attach=[AttachDecorator.data_base64(ANONCREDS_CRED, ident="0")], ) stored_cx_rec = V20CredExRecord( @@ -1141,15 +1146,19 @@ async def test_store_credential(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object( - test_module, "RevocationRegistry", autospec=True - ) as mock_rev_reg, mock.patch.object( - test_module.AnonCredsCredFormatHandler, "get_detail_record", autospec=True - ) as mock_get_detail_record: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object( + test_module, "RevocationRegistry", autospec=True + ) as mock_rev_reg, + mock.patch.object( + test_module.AnonCredsCredFormatHandler, "get_detail_record", autospec=True + ) as mock_get_detail_record, + ): mock_rev_reg.from_definition = mock.MagicMock( return_value=mock.MagicMock( get_or_fetch_local_tails_path=mock.CoroutineMock() @@ -1167,7 +1176,7 @@ async def test_store_credential(self): self.holder.store_credential.assert_called_once_with( CRED_DEF, - INDY_CRED, + ANONCREDS_CRED, cred_req_meta, {"pic": "image/jpeg"}, credential_id=cred_id, @@ -1198,11 +1207,11 @@ async def test_store_credential_holder_store_indy_error(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_OFFER][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - offers_attach=[AttachDecorator.data_base64(INDY_OFFER, ident="0")], + offers_attach=[AttachDecorator.data_base64(ANONCREDS_OFFER, ident="0")], ) cred_offer.assign_thread_id(thread_id) cred_request = V20CredRequest( @@ -1210,22 +1219,22 @@ async def test_store_credential_holder_store_indy_error(self): V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_REQUEST][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], + requests_attach=[AttachDecorator.data_base64(ANONCREDS_CRED_REQ, ident="0")], ) cred_issue = V20CredIssue( formats=[ V20CredFormat( attach_id="0", format_=ATTACHMENT_FORMAT[CRED_20_ISSUE][ - V20CredFormat.Format.INDY.api + V20CredFormat.Format.ANONCREDS.api ], ) ], - credentials_attach=[AttachDecorator.data_base64(INDY_CRED, ident="0")], + credentials_attach=[AttachDecorator.data_base64(ANONCREDS_CRED, ident="0")], ) stored_cx_rec = V20CredExRecord( @@ -1246,11 +1255,14 @@ async def test_store_credential_holder_store_indy_error(self): side_effect=test_module.AnonCredsHolderError("Problem", {"message": "Nope"}) ) - with mock.patch.object( - test_module.AnonCredsCredFormatHandler, "get_detail_record", autospec=True - ) as mock_get_detail_record, mock.patch.object( - test_module.RevocationRegistry, "from_definition", mock.MagicMock() - ) as mock_rev_reg: + with ( + mock.patch.object( + test_module.AnonCredsCredFormatHandler, "get_detail_record", autospec=True + ) as mock_get_detail_record, + mock.patch.object( + test_module.RevocationRegistry, "from_definition", mock.MagicMock() + ) as mock_rev_reg, + ): mock_get_detail_record.return_value = mock.MagicMock( cred_request_metadata=cred_req_meta, save=mock.CoroutineMock(), diff --git a/acapy_agent/protocols/issue_credential/v2_0/formats/handler.py b/acapy_agent/protocols/issue_credential/v2_0/formats/handler.py index cc5cc15f7e..a001b11d86 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/formats/handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/formats/handler.py @@ -1,7 +1,7 @@ """V2.0 issue-credential base credential format handler.""" import logging -from abc import ABC, abstractclassmethod, abstractmethod +from abc import ABC, abstractmethod from typing import Mapping, Optional, Tuple from .....core.error import BaseError @@ -60,7 +60,8 @@ def get_format_identifier(self, message_type: str) -> str: def get_format_data(self, message_type: str, data: dict) -> CredFormatAttachment: """Get credential format and attachment objects for use in cred ex messages.""" - @abstractclassmethod + @classmethod + @abstractmethod def validate_fields(cls, message_type: str, attachment_data: dict) -> None: """Validate attachment data for specific message type and format.""" diff --git a/acapy_agent/protocols/issue_credential/v2_0/formats/indy/handler.py b/acapy_agent/protocols/issue_credential/v2_0/formats/indy/handler.py index ecadd98539..19a2857cf3 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/formats/indy/handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/formats/indy/handler.py @@ -7,6 +7,7 @@ from marshmallow import RAISE +from ......askar.profile_anon import AskarAnoncredsProfile from ......cache.base import BaseCache from ......core.profile import Profile from ......indy.holder import IndyHolder, IndyHolderError @@ -14,7 +15,6 @@ from ......indy.models.cred import IndyCredentialSchema from ......indy.models.cred_abstract import IndyCredAbstractSchema from ......indy.models.cred_request import IndyCredRequestSchema -from ......ledger.base import BaseLedger from ......ledger.multiple_ledger.ledger_requests_executor import ( GET_CRED_DEF, GET_SCHEMA, @@ -105,10 +105,6 @@ async def get_detail_record(self, cred_ex_id: str) -> V20CredExRecordIndy: session, cred_ex_id ) - # Temporary shim while the new anoncreds library integration is in progress - if self.anoncreds_handler: - return await self.anoncreds_handler.get_detail_record(cred_ex_id) - if len(records) > 1: LOGGER.warning( "Cred ex id %s has %d %s detail records: should be 1", @@ -140,9 +136,6 @@ def get_format_identifier(self, message_type: str) -> str: str: Issue credential attachment format identifier """ - # Temporary shim while the new anoncreds library integration is in progress - if self.anoncreds_handler: - return self.anoncreds_handler.get_format_identifier(message_type) return ATTACHMENT_FORMAT[message_type][IndyCredFormatHandler.format.api] @@ -162,9 +155,6 @@ def get_format_data(self, message_type: str, data: dict) -> CredFormatAttachment CredFormatAttachment: Credential format and attachment data objects """ - # Temporary shim while the new anoncreds library integration is in progress - if self.anoncreds_handler: - return self.anoncreds_handler.get_format_data(message_type, data) return ( V20CredFormat( @@ -192,7 +182,7 @@ async def create_proposal( self, cred_ex_record: V20CredExRecord, proposal_data: Mapping[str, str] ) -> Tuple[V20CredFormat, AttachDecorator]: """Create indy credential proposal.""" - # Temporary shim while the new anoncreds library integration is in progress + # Create the proposal with the anoncreds handler if agent is anoncreds capable if self.anoncreds_handler: return await self.anoncreds_handler.create_proposal( cred_ex_record, @@ -217,12 +207,12 @@ async def create_offer( ) -> CredFormatAttachment: """Create indy credential offer.""" - # Temporary shim while the new anoncreds library integration is in progress - if self.anoncreds_handler: - return await self.anoncreds_handler.create_offer(cred_proposal_message) + if isinstance(self.profile, AskarAnoncredsProfile): + raise V20CredFormatError( + "This issuer is anoncreds capable. Please use the anonreds format." + ) issuer = self.profile.inject(IndyIssuer) - ledger = self.profile.inject(BaseLedger) cache = self.profile.inject_or(BaseCache) cred_def_id = await self._match_sent_cred_def_id( @@ -275,11 +265,38 @@ async def receive_offer( ) -> None: """Receive indy credential offer.""" + async def create_cred_request_result(self, cred_offer, holder_did, cred_def_id): + """Create credential request result.""" + multitenant_mgr = self.profile.inject_or(BaseMultitenantManager) + if multitenant_mgr: + ledger_exec_inst = IndyLedgerRequestsExecutor(self.profile) + else: + ledger_exec_inst = self.profile.inject(IndyLedgerRequestsExecutor) + ledger = ( + await ledger_exec_inst.get_ledger_for_identifier( + cred_def_id, + txn_record_type=GET_CRED_DEF, + ) + )[1] + async with ledger: + cred_def = await ledger.get_credential_definition(cred_def_id) + + holder = self.profile.inject(IndyHolder) + request_json, metadata_json = await holder.create_credential_request( + cred_offer, cred_def, holder_did + ) + + return { + "request": json.loads(request_json), + "metadata": json.loads(metadata_json), + } + async def create_request( self, cred_ex_record: V20CredExRecord, request_data: Optional[Mapping] = None ) -> CredFormatAttachment: """Create indy credential request.""" - # Temporary shim while the new anoncreds library integration is in progress + + # Create the request with the anoncreds handler if agent is anoncreds capable if self.anoncreds_handler: return await self.anoncreds_handler.create_request( cred_ex_record, @@ -302,31 +319,6 @@ async def create_request( nonce = cred_offer["nonce"] cred_def_id = cred_offer["cred_def_id"] - async def _create(): - multitenant_mgr = self.profile.inject_or(BaseMultitenantManager) - if multitenant_mgr: - ledger_exec_inst = IndyLedgerRequestsExecutor(self.profile) - else: - ledger_exec_inst = self.profile.inject(IndyLedgerRequestsExecutor) - ledger = ( - await ledger_exec_inst.get_ledger_for_identifier( - cred_def_id, - txn_record_type=GET_CRED_DEF, - ) - )[1] - async with ledger: - cred_def = await ledger.get_credential_definition(cred_def_id) - - holder = self.profile.inject(IndyHolder) - request_json, metadata_json = await holder.create_credential_request( - cred_offer, cred_def, holder_did - ) - - return { - "request": json.loads(request_json), - "metadata": json.loads(metadata_json), - } - cache_key = f"credential_request::{cred_def_id}::{holder_did}::{nonce}" cred_req_result = None cache = self.profile.inject_or(BaseCache) @@ -335,10 +327,14 @@ async def _create(): if entry.result: cred_req_result = entry.result else: - cred_req_result = await _create() + cred_req_result = await self.create_cred_request_result( + cred_offer, holder_did, cred_def_id + ) await entry.set_result(cred_req_result, 3600) if not cred_req_result: - cred_req_result = await _create() + cred_req_result = await self.create_cred_request_result( + cred_offer, holder_did, cred_def_id + ) detail_record = V20CredExRecordIndy( cred_ex_id=cred_ex_record.cred_ex_id, @@ -354,7 +350,7 @@ async def receive_request( self, cred_ex_record: V20CredExRecord, cred_request_message: V20CredRequest ) -> None: """Receive indy credential request.""" - # Temporary shim while the new anoncreds library integration is in progress + # Receive the request with the anoncreds handler if agent is anoncreds capable if self.anoncreds_handler: return await self.anoncreds_handler.receive_request( cred_ex_record, @@ -445,9 +441,11 @@ async def issue_credential( await self._check_uniqueness(cred_ex_record.cred_ex_id) cred_offer = cred_ex_record.cred_offer.attachment(IndyCredFormatHandler.format) + from ..anoncreds.handler import AnonCredsCredFormatHandler + cred_request = cred_ex_record.cred_request.attachment( IndyCredFormatHandler.format - ) + ) or cred_ex_record.cred_request.attachment(AnonCredsCredFormatHandler.format) cred_values = cred_ex_record.cred_offer.credential_preview.attr_dict(decode=False) schema_id = cred_offer["schema_id"] cred_def_id = cred_offer["cred_def_id"] @@ -517,10 +515,14 @@ async def store_credential( ) -> None: """Store indy credential.""" # Temporary shim while the new anoncreds library integration is in progress - if self.anoncreds_handler: + if hasattr(self, "anoncreds_handler") and self.anoncreds_handler: return await self.anoncreds_handler.store_credential(cred_ex_record, cred_id) - cred = cred_ex_record.cred_issue.attachment(IndyCredFormatHandler.format) + from ..anoncreds.handler import AnonCredsCredFormatHandler + + cred = cred_ex_record.cred_issue.attachment( + IndyCredFormatHandler.format + ) or cred_ex_record.cred_issue.attachment(AnonCredsCredFormatHandler.format) rev_reg_def = None multitenant_mgr = self.profile.inject_or(BaseMultitenantManager) diff --git a/acapy_agent/protocols/issue_credential/v2_0/formats/indy/tests/test_handler.py b/acapy_agent/protocols/issue_credential/v2_0/formats/indy/tests/test_handler.py index 91c80e2b7a..78bd346d02 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/formats/indy/tests/test_handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/formats/indy/tests/test_handler.py @@ -1132,15 +1132,19 @@ async def test_store_credential(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object( - test_module, "RevocationRegistry", autospec=True - ) as mock_rev_reg, mock.patch.object( - test_module.IndyCredFormatHandler, "get_detail_record", autospec=True - ) as mock_get_detail_record: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object( + test_module, "RevocationRegistry", autospec=True + ) as mock_rev_reg, + mock.patch.object( + test_module.IndyCredFormatHandler, "get_detail_record", autospec=True + ) as mock_get_detail_record, + ): mock_rev_reg.from_definition = mock.MagicMock( return_value=mock.MagicMock( get_or_fetch_local_tails_path=mock.CoroutineMock() @@ -1236,11 +1240,14 @@ async def test_store_credential_holder_store_indy_error(self): side_effect=test_module.IndyHolderError("Problem", {"message": "Nope"}) ) - with mock.patch.object( - test_module.IndyCredFormatHandler, "get_detail_record", autospec=True - ) as mock_get_detail_record, mock.patch.object( - test_module.RevocationRegistry, "from_definition", mock.MagicMock() - ) as mock_rev_reg: + with ( + mock.patch.object( + test_module.IndyCredFormatHandler, "get_detail_record", autospec=True + ) as mock_get_detail_record, + mock.patch.object( + test_module.RevocationRegistry, "from_definition", mock.MagicMock() + ) as mock_rev_reg, + ): mock_get_detail_record.return_value = mock.MagicMock( cred_request_metadata=cred_req_meta, save=mock.CoroutineMock(), diff --git a/acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/models/cred_detail_options.py b/acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/models/cred_detail_options.py index 9d74382d8d..7a9b1ca549 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/models/cred_detail_options.py +++ b/acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/models/cred_detail_options.py @@ -6,8 +6,8 @@ from .......messaging.models.base import BaseModel, BaseModelSchema from .......messaging.valid import ( - INDY_ISO8601_DATETIME_EXAMPLE, - INDY_ISO8601_DATETIME_VALIDATE, + ISO8601_DATETIME_EXAMPLE, + ISO8601_DATETIME_VALIDATE, UUID4_EXAMPLE, ) @@ -109,13 +109,13 @@ class Meta: created = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": ( "The date and time of the proof (with a maximum accuracy in seconds)." " Defaults to current system time" ), - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) diff --git a/acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py b/acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py index 2b2e948adb..33a92abbc9 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/formats/ld_proof/tests/test_handler.py @@ -255,12 +255,13 @@ async def test_receive_proposal(self): await self.handler.receive_proposal(cred_ex_record, cred_proposal_message) async def test_create_offer(self): - with mock.patch.object( - VcLdpManager, - "assert_can_issue_with_id_and_proof_type", - mock.CoroutineMock(), - ) as mock_can_issue, patch.object( - test_module, "get_properties_without_context", return_value=[] + with ( + mock.patch.object( + VcLdpManager, + "assert_can_issue_with_id_and_proof_type", + mock.CoroutineMock(), + ) as mock_can_issue, + patch.object(test_module, "get_properties_without_context", return_value=[]), ): (cred_format, attachment) = await self.handler.create_offer( self.cred_proposal @@ -295,11 +296,14 @@ async def test_create_offer_adds_bbs_context(self): ], ) - with mock.patch.object( - VcLdpManager, - "assert_can_issue_with_id_and_proof_type", - mock.CoroutineMock(), - ), patch.object(test_module, "get_properties_without_context", return_value=[]): + with ( + mock.patch.object( + VcLdpManager, + "assert_can_issue_with_id_and_proof_type", + mock.CoroutineMock(), + ), + patch.object(test_module, "get_properties_without_context", return_value=[]), + ): (cred_format, attachment) = await self.handler.create_offer(cred_proposal) # assert BBS url added to context @@ -320,11 +324,14 @@ async def test_create_offer_adds_ed25519_2020_context(self): ], ) - with mock.patch.object( - VcLdpManager, - "assert_can_issue_with_id_and_proof_type", - mock.CoroutineMock(), - ), patch.object(test_module, "get_properties_without_context", return_value=[]): + with ( + mock.patch.object( + VcLdpManager, + "assert_can_issue_with_id_and_proof_type", + mock.CoroutineMock(), + ), + patch.object(test_module, "get_properties_without_context", return_value=[]), + ): (cred_format, attachment) = await self.handler.create_offer(cred_proposal) # assert BBS url added to context @@ -342,15 +349,19 @@ async def test_create_offer_x_no_proposal(self): async def test_create_offer_x_wrong_attributes(self): missing_properties = ["foo"] - with mock.patch.object( - self.manager, - "assert_can_issue_with_id_and_proof_type", - mock.CoroutineMock(), - ), patch.object( - test_module, - "get_properties_without_context", - return_value=missing_properties, - ), self.assertRaises(LinkedDataProofException) as context: + with ( + mock.patch.object( + self.manager, + "assert_can_issue_with_id_and_proof_type", + mock.CoroutineMock(), + ), + patch.object( + test_module, + "get_properties_without_context", + return_value=missing_properties, + ), + self.assertRaises(LinkedDataProofException) as context, + ): await self.handler.create_offer(self.cred_proposal) assert ( @@ -885,17 +896,24 @@ async def test_store_credential_x_not_verified(self): cred_id = "cred_id" self.holder.store_credential = mock.CoroutineMock() - with mock.patch.object( - self.manager, - "_get_suite", - mock.CoroutineMock(), - ), mock.patch.object( - self.manager, - "verify_credential", - mock.CoroutineMock(return_value=DocumentVerificationResult(verified=False)), - ), mock.patch.object( - self.manager, - "_get_proof_purpose", - ), self.assertRaises(V20CredFormatError) as context: + with ( + mock.patch.object( + self.manager, + "_get_suite", + mock.CoroutineMock(), + ), + mock.patch.object( + self.manager, + "verify_credential", + mock.CoroutineMock( + return_value=DocumentVerificationResult(verified=False) + ), + ), + mock.patch.object( + self.manager, + "_get_proof_purpose", + ), + self.assertRaises(V20CredFormatError) as context, + ): await self.handler.store_credential(cred_ex_record, cred_id) assert "Received invalid credential: " in str(context.exception) diff --git a/acapy_agent/protocols/issue_credential/v2_0/formats/vc_di/tests/test_handler.py b/acapy_agent/protocols/issue_credential/v2_0/formats/vc_di/tests/test_handler.py index ae8f23fa69..3ff75a5119 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/formats/vc_di/tests/test_handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/formats/vc_di/tests/test_handler.py @@ -9,11 +9,11 @@ from .......anoncreds.holder import AnonCredsHolder, AnonCredsHolderError from .......anoncreds.issuer import AnonCredsIssuer -from .......anoncreds.models.anoncreds_cred_def import ( +from .......anoncreds.models.credential_definition import ( CredDef, GetCredDefResult, ) -from .......anoncreds.models.anoncreds_revocation import ( +from .......anoncreds.models.revocation import ( GetRevRegDefResult, RevRegDef, ) diff --git a/acapy_agent/protocols/issue_credential/v2_0/handlers/cred_problem_report_handler.py b/acapy_agent/protocols/issue_credential/v2_0/handlers/cred_problem_report_handler.py index b8f56f119d..f513496c79 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/handlers/cred_problem_report_handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/handlers/cred_problem_report_handler.py @@ -40,7 +40,11 @@ async def handle(self, context: RequestContext, responder: BaseResponder): context.message, context.connection_record.connection_id, ) - except (StorageError, StorageNotFoundError): + except StorageNotFoundError: + self._logger.warning( + "Record not found while processing issue-credential v2.0 problem report" + ) + except StorageError: self._logger.exception( - "Error processing issue-credential v2.0 problem report message" + "Storage error while processing issue-credential v2.0 problem report" ) diff --git a/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_offer_handler.py b/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_offer_handler.py index b87034e70c..ccd1a854e2 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_offer_handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_offer_handler.py @@ -109,11 +109,14 @@ async def test_called_auto_request_x_indy(self): handler = test_module.V20CredOfferHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ) as mock_send_reply, mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object( + responder, "send_reply", mock.CoroutineMock() + ) as mock_send_reply, + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() @@ -145,11 +148,14 @@ async def test_called_auto_request_x_anoncreds(self): handler = test_module.V20CredOfferHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ) as mock_send_reply, mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object( + responder, "send_reply", mock.CoroutineMock() + ) as mock_send_reply, + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_proposal_handler.py b/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_proposal_handler.py index 8ece39bf7b..a901018d08 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_proposal_handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_proposal_handler.py @@ -86,11 +86,14 @@ async def test_called_auto_offer_x_indy(self): handler = test_module.V20CredProposalHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ) as mock_send_reply, mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object( + responder, "send_reply", mock.CoroutineMock() + ) as mock_send_reply, + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() @@ -115,11 +118,14 @@ async def test_called_auto_offer_x_anoncreds(self): handler = test_module.V20CredProposalHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ) as mock_send_reply, mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object( + responder, "send_reply", mock.CoroutineMock() + ) as mock_send_reply, + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_request_handler.py b/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_request_handler.py index 3fc7571b62..f2d9763e0f 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_request_handler.py +++ b/acapy_agent/protocols/issue_credential/v2_0/handlers/tests/test_cred_request_handler.py @@ -102,10 +102,11 @@ async def test_called_auto_issue_x_indy(self): ) request_context.injector.bind_instance(OobMessageProcessor, mock_oob_processor) - with mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - cred_ex_rec, "save_error_state", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(cred_ex_rec, "save_error_state", mock.CoroutineMock()), ): mock_cred_mgr.return_value.receive_request = mock.CoroutineMock( return_value=cred_ex_rec @@ -120,11 +121,14 @@ async def test_called_auto_issue_x_indy(self): handler = test_module.V20CredRequestHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ) as mock_send_reply, mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object( + responder, "send_reply", mock.CoroutineMock() + ) as mock_send_reply, + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() @@ -142,10 +146,11 @@ async def test_called_auto_issue_x_anoncreds(self): ) request_context.injector.bind_instance(OobMessageProcessor, mock_oob_processor) - with mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - cred_ex_rec, "save_error_state", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(cred_ex_rec, "save_error_state", mock.CoroutineMock()), ): mock_cred_mgr.return_value.receive_request = mock.CoroutineMock( return_value=cred_ex_rec @@ -160,11 +165,14 @@ async def test_called_auto_issue_x_anoncreds(self): handler = test_module.V20CredRequestHandler() responder = MockResponder() - with mock.patch.object( - responder, "send_reply", mock.CoroutineMock() - ) as mock_send_reply, mock.patch.object( - handler._logger, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object( + responder, "send_reply", mock.CoroutineMock() + ) as mock_send_reply, + mock.patch.object( + handler._logger, "exception", mock.MagicMock() + ) as mock_log_exc, + ): await handler.handle(request_context, responder) mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v2_0/manager.py b/acapy_agent/protocols/issue_credential/v2_0/manager.py index 068f94a4bd..124e832c47 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/manager.py +++ b/acapy_agent/protocols/issue_credential/v2_0/manager.py @@ -591,8 +591,14 @@ async def receive_credential( ] handled_formats = [] - # check that we didn't receive any formats not present in the request - if set(issue_formats) - set(req_formats): + def _check_formats(): + """Allow indy issue fomat and anoncreds req format or matching formats.""" + return ( + issue_formats == [V20CredFormat.Format.INDY] + and req_formats == [V20CredFormat.Format.ANONCREDS] + ) or len(set(issue_formats) - set(req_formats)) == 0 + + if not _check_formats(): raise V20CredManagerError( "Received issue credential format(s) not present in credential " f"request: {set(issue_formats) - set(req_formats)}" diff --git a/acapy_agent/protocols/issue_credential/v2_0/message_types.py b/acapy_agent/protocols/issue_credential/v2_0/message_types.py index 668d2b7332..80e56d2309 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/message_types.py +++ b/acapy_agent/protocols/issue_credential/v2_0/message_types.py @@ -37,21 +37,25 @@ # Format specifications ATTACHMENT_FORMAT = { CRED_20_PROPOSAL: { + V20CredFormat.Format.ANONCREDS.api: "anoncreds/credential-filter@v1.0", V20CredFormat.Format.INDY.api: "hlindy/cred-filter@v2.0", V20CredFormat.Format.LD_PROOF.api: "aries/ld-proof-vc-detail@v1.0", V20CredFormat.Format.VC_DI.api: "didcomm/w3c-di-vc@v0.1", }, CRED_20_OFFER: { + V20CredFormat.Format.ANONCREDS.api: "anoncreds/credential-offer@v1.0", V20CredFormat.Format.INDY.api: "hlindy/cred-abstract@v2.0", V20CredFormat.Format.LD_PROOF.api: "aries/ld-proof-vc-detail@v1.0", V20CredFormat.Format.VC_DI.api: "didcomm/w3c-di-vc-offer@v0.1", }, CRED_20_REQUEST: { + V20CredFormat.Format.ANONCREDS.api: "anoncreds/credential-request@v1.0", V20CredFormat.Format.INDY.api: "hlindy/cred-req@v2.0", V20CredFormat.Format.LD_PROOF.api: "aries/ld-proof-vc-detail@v1.0", V20CredFormat.Format.VC_DI.api: "didcomm/w3c-di-vc-request@v0.1", }, CRED_20_ISSUE: { + V20CredFormat.Format.ANONCREDS.api: "anoncreds/credential@v1.0", V20CredFormat.Format.INDY.api: "hlindy/cred@v2.0", V20CredFormat.Format.LD_PROOF.api: "aries/ld-proof-vc@v1.0", V20CredFormat.Format.VC_DI.api: "didcomm/w3c-di-vc@v0.1", diff --git a/acapy_agent/protocols/issue_credential/v2_0/messages/cred_format.py b/acapy_agent/protocols/issue_credential/v2_0/messages/cred_format.py index 0574d4736d..589dfcf579 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/messages/cred_format.py +++ b/acapy_agent/protocols/issue_credential/v2_0/messages/cred_format.py @@ -11,6 +11,7 @@ from .....messaging.models.base import BaseModel, BaseModelSchema from .....messaging.valid import UUID4_EXAMPLE from .....utils.classloader import DeferLoad +from ..models.detail.anoncreds import V20CredExRecordAnoncreds from ..models.detail.indy import V20CredExRecordIndy from ..models.detail.ld_proof import V20CredExRecordLDProof @@ -31,6 +32,14 @@ class Meta: class Format(Enum): """Attachment format.""" + ANONCREDS = FormatSpec( + "anoncreds/", + V20CredExRecordAnoncreds, + DeferLoad( + "acapy_agent.protocols.issue_credential.v2_0" + ".formats.anoncreds.handler.AnonCredsCredFormatHandler" + ), + ) INDY = FormatSpec( "hlindy/", V20CredExRecordIndy, @@ -39,23 +48,6 @@ class Format(Enum): ".formats.indy.handler.IndyCredFormatHandler" ), ) - """ - Once we switch to anoncreds this will replace the above INDY definition. - - In the meantime there are some hardcoded references in the - "...formats.indy.handler.IndyCredFormatHandler" class. - - :: - - INDY = FormatSpec( - "hlindy/", - V20CredExRecordIndy, - DeferLoad( - "acapy_agent.protocols.issue_credential.v2_0" - ".formats.anoncreds.handler.AnonCredsCredFormatHandler" - ), - ) - """ LD_PROOF = FormatSpec( "aries/", V20CredExRecordLDProof, @@ -97,7 +89,9 @@ def aries(self) -> str: return self.value.aries @property - def detail(self) -> Union[V20CredExRecordIndy, V20CredExRecordLDProof]: + def detail( + self, + ) -> Union[V20CredExRecordIndy, V20CredExRecordLDProof, V20CredExRecordAnoncreds]: """Accessor for credential exchange detail class.""" return self.value.detail diff --git a/acapy_agent/protocols/issue_credential/v2_0/models/detail/anoncreds.py b/acapy_agent/protocols/issue_credential/v2_0/models/detail/anoncreds.py new file mode 100644 index 0000000000..f683ff68ca --- /dev/null +++ b/acapy_agent/protocols/issue_credential/v2_0/models/detail/anoncreds.py @@ -0,0 +1,131 @@ +"""Anoncreds specific credential exchange information with non-secrets storage.""" + +from typing import Any, Mapping, Optional, Sequence + +from marshmallow import EXCLUDE, fields + +from ......core.profile import ProfileSession +from ......messaging.models.base_record import BaseRecord, BaseRecordSchema +from ......messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_REV_REG_ID_EXAMPLE, + UUID4_EXAMPLE, +) +from .. import UNENCRYPTED_TAGS + + +class V20CredExRecordAnoncreds(BaseRecord): + """Credential exchange anoncreds detail record.""" + + class Meta: + """V20CredExRecordAnoncreds metadata.""" + + schema_class = "V20CredExRecordAnoncredsSchema" + + RECORD_ID_NAME = "cred_ex_anoncreds_id" + RECORD_TYPE = "anoncreds_cred_ex_v20" + TAG_NAMES = {"~cred_ex_id"} if UNENCRYPTED_TAGS else {"cred_ex_id"} + RECORD_TOPIC = "issue_credential_v2_0_anoncreds" + + def __init__( + self, + cred_ex_anoncreds_id: Optional[str] = None, + *, + cred_ex_id: Optional[str] = None, + cred_id_stored: Optional[str] = None, + cred_request_metadata: Optional[Mapping] = None, + rev_reg_id: Optional[str] = None, + cred_rev_id: Optional[str] = None, + **kwargs, + ): + """Initialize anoncreds credential exchange record details.""" + super().__init__(cred_ex_anoncreds_id, **kwargs) + + self.cred_ex_id = cred_ex_id + self.cred_id_stored = cred_id_stored + self.cred_request_metadata = cred_request_metadata + self.rev_reg_id = rev_reg_id + self.cred_rev_id = cred_rev_id + + @property + def cred_ex_anoncreds_id(self) -> str: + """Accessor for the ID associated with this exchange.""" + return self._id + + @property + def record_value(self) -> dict: + """Accessor for the JSON record value generated for this credential exchange.""" + return { + prop: getattr(self, prop) + for prop in ( + "cred_id_stored", + "cred_request_metadata", + "rev_reg_id", + "cred_rev_id", + ) + } + + @classmethod + async def query_by_cred_ex_id( + cls, + session: ProfileSession, + cred_ex_id: str, + ) -> Sequence["V20CredExRecordAnoncreds"]: + """Retrieve credential exchange anoncreds detail record(s) by its cred ex id.""" + return await cls.query( + session=session, + tag_filter={"cred_ex_id": cred_ex_id}, + ) + + def __eq__(self, other: Any) -> bool: + """Comparison between records.""" + return super().__eq__(other) + + +class V20CredExRecordAnoncredsSchema(BaseRecordSchema): + """Credential exchange anoncreds detail record detail schema.""" + + class Meta: + """Credential exchange anoncreds detail record schema metadata.""" + + model_class = V20CredExRecordAnoncreds + unknown = EXCLUDE + + cred_ex_anoncreds_id = fields.Str( + required=False, + metadata={"description": "Record identifier", "example": UUID4_EXAMPLE}, + ) + cred_ex_id = fields.Str( + required=False, + metadata={ + "description": "Corresponding v2.0 credential exchange record identifier", + "example": UUID4_EXAMPLE, + }, + ) + cred_id_stored = fields.Str( + required=False, + metadata={ + "description": "Credential identifier stored in wallet", + "example": UUID4_EXAMPLE, + }, + ) + cred_request_metadata = fields.Dict( + required=False, + metadata={"description": "Credential request metadata for anoncreds holder"}, + ) + rev_reg_id = fields.Str( + required=False, + metadata={ + "description": "Revocation registry identifier", + "example": ANONCREDS_REV_REG_ID_EXAMPLE, + }, + ) + cred_rev_id = fields.Str( + required=False, + metadata={ + "description": ( + "Credential revocation identifier within revocation registry" + ), + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, + }, + ) diff --git a/acapy_agent/protocols/issue_credential/v2_0/models/tests/test_cred_ex_record.py b/acapy_agent/protocols/issue_credential/v2_0/models/tests/test_cred_ex_record.py index a3ef8a756d..b7fdaa2e7b 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/models/tests/test_cred_ex_record.py +++ b/acapy_agent/protocols/issue_credential/v2_0/models/tests/test_cred_ex_record.py @@ -125,11 +125,12 @@ async def test_save_error_state(self): record.state = V20CredExRecord.STATE_PROPOSAL_RECEIVED await record.save(session) - with mock.patch.object( - record, "save", mock.CoroutineMock() - ) as mock_save, mock.patch.object( - test_module.LOGGER, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object(record, "save", mock.CoroutineMock()) as mock_save, + mock.patch.object( + test_module.LOGGER, "exception", mock.MagicMock() + ) as mock_log_exc, + ): mock_save.side_effect = test_module.StorageError() await record.save_error_state(session, reason="test") mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/issue_credential/v2_0/routes.py b/acapy_agent/protocols/issue_credential/v2_0/routes.py index 7e3c2f20fb..ed9ec45919 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/routes.py +++ b/acapy_agent/protocols/issue_credential/v2_0/routes.py @@ -31,14 +31,17 @@ get_paginated_query_params, ) from ....messaging.valid import ( + ANONCREDS_CRED_DEF_ID_EXAMPLE, + ANONCREDS_DID_EXAMPLE, + ANONCREDS_SCHEMA_ID_EXAMPLE, INDY_CRED_DEF_ID_EXAMPLE, INDY_CRED_DEF_ID_VALIDATE, INDY_DID_EXAMPLE, INDY_DID_VALIDATE, INDY_SCHEMA_ID_EXAMPLE, INDY_SCHEMA_ID_VALIDATE, - INDY_VERSION_EXAMPLE, - INDY_VERSION_VALIDATE, + MAJOR_MINOR_VERSION_EXAMPLE, + MAJOR_MINOR_VERSION_VALIDATE, UUID4_EXAMPLE, UUID4_VALIDATE, ) @@ -135,6 +138,50 @@ class V20CredStoreRequestSchema(OpenAPISchema): credential_id = fields.Str(required=False) +class V20CredFilterAnoncredsSchema(OpenAPISchema): + """Anoncreds credential filtration criteria.""" + + schema_issuer_id = fields.Str( + required=False, + metadata={ + "description": "Schema issuer ID", + "example": ANONCREDS_DID_EXAMPLE, + }, + ) + schema_name = fields.Str( + required=False, + metadata={"description": "Schema name", "example": "preferences"}, + ) + schema_version = fields.Str( + required=False, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, + ) + schema_id = fields.Str( + required=False, + metadata={ + "description": "Schema identifier", + "example": ANONCREDS_SCHEMA_ID_EXAMPLE, + }, + ) + issuer_id = fields.Str( + required=False, + metadata={ + "description": "Credential issuer ID", + "example": ANONCREDS_DID_EXAMPLE, + }, + ) + cred_def_id = fields.Str( + required=False, + metadata={ + "description": "Credential definition identifier", + "example": ANONCREDS_CRED_DEF_ID_EXAMPLE, + }, + ) + + class V20CredFilterIndySchema(OpenAPISchema): """Indy credential filtration criteria.""" @@ -165,8 +212,11 @@ class V20CredFilterIndySchema(OpenAPISchema): ) schema_version = fields.Str( required=False, - validate=INDY_VERSION_VALIDATE, - metadata={"description": "Schema version", "example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, ) issuer_did = fields.Str( required=False, @@ -205,8 +255,11 @@ class V20CredFilterVCDISchema(OpenAPISchema): ) schema_version = fields.Str( required=False, - validate=INDY_VERSION_VALIDATE, - metadata={"description": "Schema version", "example": INDY_VERSION_EXAMPLE}, + validate=MAJOR_MINOR_VERSION_VALIDATE, + metadata={ + "description": "Schema version", + "example": MAJOR_MINOR_VERSION_EXAMPLE, + }, ) issuer_did = fields.Str( required=False, @@ -218,6 +271,11 @@ class V20CredFilterVCDISchema(OpenAPISchema): class V20CredFilterSchema(OpenAPISchema): """Credential filtration criteria.""" + anoncreds = fields.Nested( + V20CredFilterAnoncredsSchema, + required=False, + metadata={"description": "Credential filter for anoncreds"}, + ) indy = fields.Nested( V20CredFilterIndySchema, required=False, @@ -808,7 +866,12 @@ async def credential_exchange_send(request: web.BaseRequest): V20CredManagerError, V20CredFormatError, ) as err: - LOGGER.exception("Error preparing credential offer") + # Only log full exception for unexpected errors + if isinstance(err, (V20CredFormatError, V20CredManagerError)): + LOGGER.warning(f"Error preparing credential offer: {err.roll_up}") + else: + LOGGER.exception("Error preparing credential offer") + if cred_ex_record: async with profile.session() as session: await cred_ex_record.save_error_state(session, reason=err.roll_up) @@ -951,11 +1014,17 @@ async def _create_free_offer( ) cred_manager = V20CredManager(profile) - (cred_ex_record, cred_offer_message) = await cred_manager.create_offer( - cred_ex_record, - comment=comment, - replacement_id=replacement_id, - ) + try: + (cred_ex_record, cred_offer_message) = await cred_manager.create_offer( + cred_ex_record, + comment=comment, + replacement_id=replacement_id, + ) + except ValueError as err: + LOGGER.exception(f"Error creating credential offer: {err}") + async with profile.session() as session: + await cred_ex_record.save_error_state(session, reason=err) + raise web.HTTPBadRequest(reason=err) return (cred_ex_record, cred_offer_message) diff --git a/acapy_agent/protocols/issue_credential/v2_0/tests/test_manager.py b/acapy_agent/protocols/issue_credential/v2_0/tests/test_manager.py index 65062ad5ea..015033925e 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/tests/test_manager.py +++ b/acapy_agent/protocols/issue_credential/v2_0/tests/test_manager.py @@ -145,11 +145,10 @@ async def test_create_proposal(self): ) ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.create_proposal = mock.CoroutineMock( return_value=( V20CredFormat( @@ -186,11 +185,10 @@ async def test_create_proposal_no_preview(self): connection_id = "test_conn_id" comment = "comment" - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.create_proposal = mock.CoroutineMock( return_value=( V20CredFormat( @@ -236,11 +234,10 @@ async def test_receive_proposal(self): ) ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.receive_proposal = mock.CoroutineMock() cred_proposal = V20CredProposal( @@ -308,11 +305,10 @@ async def test_create_free_offer(self): cred_proposal=cred_proposal, ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.create_offer = mock.CoroutineMock( return_value=( V20CredFormat( @@ -384,11 +380,10 @@ async def test_create_bound_offer(self): cred_proposal=cred_proposal, ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.create_offer = mock.CoroutineMock( return_value=( V20CredFormat( @@ -492,15 +487,15 @@ async def test_receive_offer_proposed(self): thread_id=thread_id, ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredExRecord, - "retrieve_by_conn_and_thread", - mock.CoroutineMock(return_value=stored_cx_rec), - ) as mock_retrieve, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object( + V20CredExRecord, + "retrieve_by_conn_and_thread", + mock.CoroutineMock(return_value=stored_cx_rec), + ) as mock_retrieve, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.receive_offer = mock.CoroutineMock() cx_rec = await self.manager.receive_offer(cred_offer, connection_id) @@ -549,13 +544,13 @@ async def test_receive_free_offer(self): self.context.conn_record = mock.MagicMock() self.context.conn_record.connection_id = connection_id - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object( + V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.receive_offer = mock.CoroutineMock() mock_retrieve.side_effect = (StorageNotFoundError(),) cx_rec = await self.manager.receive_offer(cred_offer, connection_id) @@ -602,11 +597,10 @@ async def test_create_bound_request(self): self.cache = InMemoryCache() self.context.injector.bind_instance(BaseCache, self.cache) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.create_request = mock.CoroutineMock( return_value=( V20CredFormat( @@ -689,11 +683,10 @@ async def test_create_free_request(self): self.cache = InMemoryCache() self.context.injector.bind_instance(BaseCache, self.cache) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.create_request = mock.CoroutineMock( return_value=( V20CredFormat( @@ -754,13 +747,13 @@ async def test_receive_request(self): requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object( + V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_retrieve.side_effect = (StorageNotFoundError(),) mock_handler.return_value.receive_request = mock.CoroutineMock() @@ -799,13 +792,13 @@ async def test_receive_request_no_connection_cred_request(self): mock_conn = mock.MagicMock(connection_id="test_conn_id") mock_oob = mock.MagicMock() - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object( + V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_retrieve.return_value = stored_cx_rec mock_handler.return_value.receive_request = mock.CoroutineMock() @@ -834,11 +827,13 @@ async def test_receive_request_no_cred_ex_with_offer_found(self): requests_attach=[AttachDecorator.data_base64(INDY_CRED_REQ, ident="0")], ) - with mock.patch.object(V20CredExRecord, "save", autospec=True), mock.patch.object( - V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True), + mock.patch.object( + V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_retrieve.side_effect = (StorageNotFoundError(),) mock_handler.return_value.receive_request = mock.CoroutineMock() @@ -926,11 +921,10 @@ async def test_issue_credential_indy(self): ) self.context.injector.bind_instance(IndyIssuer, issuer) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.issue_credential = mock.CoroutineMock( return_value=( V20CredFormat( @@ -1033,11 +1027,10 @@ async def test_issue_credential_anoncreds(self): ) self.context.injector.bind_instance(AnonCredsIssuer, issuer) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.issue_credential = mock.CoroutineMock( return_value=( V20CredFormat( @@ -1139,15 +1132,15 @@ async def test_receive_cred(self): credentials_attach=[AttachDecorator.data_base64(INDY_CRED, ident="0")], ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredExRecord, - "retrieve_by_conn_and_thread", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object( + V20CredExRecord, + "retrieve_by_conn_and_thread", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.receive_credential = mock.CoroutineMock() mock_retrieve.return_value = stored_cx_rec ret_cx_rec = await self.manager.receive_credential( @@ -1282,13 +1275,13 @@ async def test_store_credential(self): thread_id=thread_id, ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - test_module.V20CredManager, "delete_cred_ex_record", autospec=True - ) as mock_delete, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object( + test_module.V20CredManager, "delete_cred_ex_record", autospec=True + ) as mock_delete, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_handler.return_value.store_credential = mock.CoroutineMock() ret_cx_rec = await self.manager.store_credential( @@ -1329,15 +1322,18 @@ async def test_send_cred_ack(self): auto_remove=True, ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save_ex, mock.patch.object( - V20CredExRecord, "delete_record", autospec=True - ) as mock_delete_ex, mock.patch.object( - test_module.LOGGER, "exception", mock.MagicMock() - ) as mock_log_exception, mock.patch.object( - test_module.LOGGER, "warning", mock.MagicMock() - ) as mock_log_warning: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save_ex, + mock.patch.object( + V20CredExRecord, "delete_record", autospec=True + ) as mock_delete_ex, + mock.patch.object( + test_module.LOGGER, "exception", mock.MagicMock() + ) as mock_log_exception, + mock.patch.object( + test_module.LOGGER, "warning", mock.MagicMock() + ) as mock_log_warning, + ): mock_delete_ex.side_effect = test_module.StorageError() (_, ack) = await self.manager.send_cred_ack(stored_exchange) assert ack._thread @@ -1361,15 +1357,18 @@ async def test_receive_cred_ack(self): ack = V20CredAck() - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as mock_save, mock.patch.object( - V20CredExRecord, "delete_record", autospec=True - ) as mock_delete, mock.patch.object( - V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - test_module.V20CredManager, "delete_cred_ex_record", autospec=True - ) as mock_delete: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as mock_save, + mock.patch.object( + V20CredExRecord, "delete_record", autospec=True + ) as mock_delete, + mock.patch.object( + V20CredExRecord, "retrieve_by_conn_and_thread", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object( + test_module.V20CredManager, "delete_cred_ex_record", autospec=True + ) as mock_delete, + ): mock_retrieve.return_value = stored_cx_rec ret_cx_rec = await self.manager.receive_credential_ack( ack, @@ -1386,13 +1385,15 @@ async def test_delete_cred_ex_record(self): stored_cx_rec = mock.MagicMock(delete_record=mock.CoroutineMock()) stored_indy = mock.MagicMock(delete_record=mock.CoroutineMock()) - with mock.patch.object( - V20CredExRecord, "delete_record", autospec=True - ), mock.patch.object( - V20CredExRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - test_module, "V20CredFormat", mock.MagicMock() - ) as mock_cred_format: + with ( + mock.patch.object(V20CredExRecord, "delete_record", autospec=True), + mock.patch.object( + V20CredExRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object( + test_module, "V20CredFormat", mock.MagicMock() + ) as mock_cred_format, + ): mock_retrieve.return_value = stored_cx_rec mock_cred_format.Format = [ mock.MagicMock( @@ -1428,13 +1429,14 @@ async def test_receive_problem_report(self): } ) - with mock.patch.object( - V20CredExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20CredExRecord, - "retrieve_by_conn_and_thread", - mock.CoroutineMock(), - ) as retrieve_ex: + with ( + mock.patch.object(V20CredExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20CredExRecord, + "retrieve_by_conn_and_thread", + mock.CoroutineMock(), + ) as retrieve_ex, + ): retrieve_ex.return_value = stored_exchange ret_exchange = await self.manager.receive_problem_report( diff --git a/acapy_agent/protocols/issue_credential/v2_0/tests/test_routes.py b/acapy_agent/protocols/issue_credential/v2_0/tests/test_routes.py index 5ca0854086..8691862f0d 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/tests/test_routes.py +++ b/acapy_agent/protocols/issue_credential/v2_0/tests/test_routes.py @@ -61,6 +61,29 @@ async def test_validate_cred_filter_schema(self): with self.assertRaises(test_module.ValidationError): schema.validate_fields({"veres-one": {"no": "support"}}) + async def test_validate_cred_filter_anoncreds_schema(self): + schema = test_module.V20CredFilterSchema() + schema.validate_fields({"anoncreds": {"issuer_id": TEST_DID}}) + schema.validate_fields( + {"anoncreds": {"issuer_id": TEST_DID, "schema_version": "1.0"}} + ) + schema.validate_fields( + { + "anoncreds": {"issuer_id": TEST_DID}, + } + ) + schema.validate_fields( + { + "anoncreds": {}, + } + ) + with self.assertRaises(test_module.ValidationError): + schema.validate_fields({}) + with self.assertRaises(test_module.ValidationError): + schema.validate_fields(["hopeless", "stop"]) + with self.assertRaises(test_module.ValidationError): + schema.validate_fields({"veres-one": {"no": "support"}}) + async def test_validate_create_schema(self): schema = test_module.V20IssueCredSchemaCore() schema.validate( @@ -135,11 +158,12 @@ async def test_credential_exchange_list_x(self): async def test_credential_exchange_retrieve(self): self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock() @@ -149,9 +173,10 @@ async def test_credential_exchange_retrieve(self): mock_handler.return_value.get_detail_record = mock.CoroutineMock( side_effect=[ - mock.MagicMock( # indy + mock.MagicMock( # anoncreds serialize=mock.MagicMock(return_value={"...": "..."}) ), + None, # indy None, # ld_proof None, # vc_di ] @@ -162,7 +187,8 @@ async def test_credential_exchange_retrieve(self): mock_response.assert_called_once_with( { "cred_ex_record": mock_cx_rec.serialize.return_value, - "indy": {"...": "..."}, + "anoncreds": {"...": "..."}, + "indy": None, "ld_proof": None, "vc_di": None, } @@ -171,11 +197,12 @@ async def test_credential_exchange_retrieve(self): async def test_credential_exchange_retrieve_indy_ld_proof(self): self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock() @@ -185,6 +212,9 @@ async def test_credential_exchange_retrieve_indy_ld_proof(self): mock_handler.return_value.get_detail_record = mock.CoroutineMock( side_effect=[ + mock.MagicMock( # anoncreds + serialize=mock.MagicMock(return_value={"anon": "creds"}) + ), mock.MagicMock( # indy serialize=mock.MagicMock(return_value={"in": "dy"}) ), @@ -202,6 +232,7 @@ async def test_credential_exchange_retrieve_indy_ld_proof(self): mock_response.assert_called_once_with( { "cred_ex_record": mock_cx_rec.serialize.return_value, + "anoncreds": {"anon": "creds"}, "indy": {"in": "dy"}, "ld_proof": {"ld": "proof"}, "vc_di": {"vc": "di"}, @@ -225,11 +256,12 @@ async def test_credential_exchange_retrieve_not_found(self): async def test_credential_exchange_retrieve_x(self): self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock() @@ -248,13 +280,14 @@ async def test_credential_exchange_retrieve_x(self): async def test_credential_exchange_create(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.V20CredPreview, "deserialize", autospec=True - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.V20CredPreview, "deserialize", autospec=True), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_mgr.return_value.create_offer = mock.CoroutineMock() mock_cred_mgr.return_value.create_offer.return_value = ( @@ -277,13 +310,14 @@ async def test_credential_exchange_create(self): async def test_credential_exchange_create_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.V20CredPreview, "deserialize", autospec=True - ), mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.V20CredPreview, "deserialize", autospec=True), + mock.patch.object(test_module.web, "json_response"), + ): mock_cred_mgr.return_value.create_offer = mock.CoroutineMock() mock_cred_mgr.return_value.create_offer.return_value = ( @@ -317,13 +351,14 @@ async def test_credential_exchange_create_no_filter(self): async def test_credential_exchange_send(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.V20CredPreview, "deserialize", autospec=True - ), mock.patch.object(test_module.web, "json_response") as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.V20CredPreview, "deserialize", autospec=True), + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_mgr.return_value.create_offer = mock.CoroutineMock() mock_cred_mgr.return_value.create_offer.return_value = ( @@ -347,17 +382,19 @@ async def test_credential_exchange_send_request_no_conn_no_holder_did(self): self.request.json = mock.CoroutineMock(return_value={}) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "OobRecord", autospec=True - ) as mock_oob_rec, mock.patch.object( - test_module, "default_did_from_verkey", autospec=True - ) as mock_default_did_from_verkey, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "OobRecord", autospec=True) as mock_oob_rec, + mock.patch.object( + test_module, "default_did_from_verkey", autospec=True + ) as mock_default_did_from_verkey, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cred_ex, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_oob_rec.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock.MagicMock(our_recipient_key="our-recipient_key") ) @@ -397,11 +434,12 @@ async def test_credential_exchange_send_no_conn_record(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + ): # Emulate storage not found (bad connection id) mock_conn_rec.retrieve_by_id = mock.CoroutineMock( side_effect=test_module.StorageNotFoundError() @@ -427,11 +465,12 @@ async def test_credential_exchange_send_not_ready(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + ): mock_conn_rec.retrieve_by_id.return_value.is_ready = False mock_cred_mgr.return_value.create_offer.return_value = ( @@ -445,12 +484,12 @@ async def test_credential_exchange_send_not_ready(self): async def test_credential_exchange_send_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.V20CredPreview, "deserialize", autospec=True + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.V20CredPreview, "deserialize", autospec=True), ): mock_cred_ex_record = mock.MagicMock( serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), @@ -487,13 +526,13 @@ async def test_credential_exchange_send_proposal(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cx_rec = mock.MagicMock() mock_cred_mgr.return_value.create_proposal.return_value = mock_cx_rec @@ -519,12 +558,12 @@ async def test_credential_exchange_send_proposal_no_filter(self): async def test_credential_exchange_send_proposal_no_conn_record(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.V20CredPreview, "deserialize", autospec=True + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.V20CredPreview, "deserialize", autospec=True), ): # Emulate storage not found (bad connection id) mock_conn_rec.retrieve_by_id = mock.CoroutineMock( @@ -548,11 +587,12 @@ async def test_credential_exchange_send_proposal_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + ): mock_cx_rec = mock.MagicMock( serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), save_error_state=mock.CoroutineMock(), @@ -565,12 +605,12 @@ async def test_credential_exchange_send_proposal_x(self): async def test_credential_exchange_send_proposal_not_ready(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.V20CredPreview, "deserialize", autospec=True + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.V20CredPreview, "deserialize", autospec=True), ): # Emulate connection not ready mock_conn_rec.retrieve_by_id = mock.CoroutineMock() @@ -593,13 +633,13 @@ async def test_credential_exchange_create_free_offer(self): ) self.context.update_settings({"debug.auto_respond_credential_offer": True}) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_mgr.return_value.create_offer = mock.CoroutineMock() mock_cx_rec = mock.MagicMock() mock_cred_mgr.return_value.create_offer.return_value = ( @@ -636,11 +676,12 @@ async def test_credential_exchange_create_free_offer_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + ): mock_cx_rec = mock.MagicMock( serialize=mock.MagicMock( side_effect=test_module.BaseModelError(), @@ -669,13 +710,13 @@ async def test_credential_exchange_send_free_offer(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_mgr.return_value.create_offer = mock.CoroutineMock() mock_cx_rec = mock.MagicMock() mock_cred_mgr.return_value.create_offer.return_value = ( @@ -707,13 +748,13 @@ async def test_credential_exchange_send_free_offer_vcdi(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): # Mock the creation of a credential offer, especially for handling VC-DI mock_cred_mgr.return_value.create_offer = mock.CoroutineMock() mock_cx_rec = mock.MagicMock() @@ -753,11 +794,12 @@ async def test_credential_exchange_send_free_offer_no_conn_record(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + ): # Emulate storage not found (bad connection id) mock_conn_rec.retrieve_by_id = mock.CoroutineMock( side_effect=test_module.StorageNotFoundError() @@ -783,11 +825,12 @@ async def test_credential_exchange_send_free_offer_not_ready(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + ): # Emulate connection not ready mock_conn_rec.retrieve_by_id = mock.CoroutineMock() mock_conn_rec.retrieve_by_id.return_value.is_ready = False @@ -812,11 +855,13 @@ async def test_credential_exchange_send_free_offer_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_cx_rec = mock.MagicMock( serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), save_error_state=mock.CoroutineMock(), @@ -837,15 +882,16 @@ async def test_credential_exchange_send_bound_offer(self): self.request.json = mock.CoroutineMock(return_value={}) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_cx_rec_cls.retrieve_by_id.return_value.state = ( test_module.V20CredExRecord.STATE_PROPOSAL_RECEIVED @@ -868,13 +914,16 @@ async def test_credential_exchange_send_bound_offer_linked_data_error(self): self.request.json = mock.CoroutineMock(return_value={}) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + mock.patch.object(test_module.web, "json_response"), + ): mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_cx_rec_cls.retrieve_by_id.return_value.state = ( test_module.V20CredExRecord.STATE_PROPOSAL_RECEIVED @@ -910,13 +959,15 @@ async def test_credential_exchange_send_bound_offer_no_conn_record(self): self.request.json = mock.CoroutineMock(return_value={}) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock( @@ -963,13 +1014,15 @@ async def test_credential_exchange_send_bound_offer_not_ready(self): self.request.json = mock.CoroutineMock(return_value={}) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock() @@ -994,15 +1047,16 @@ async def test_credential_exchange_send_request(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_cx_rec_cls.retrieve_by_id.return_value.state = ( test_module.V20CredExRecord.STATE_OFFER_RECEIVED @@ -1038,13 +1092,15 @@ async def test_credential_exchange_send_request_no_conn_record(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock() @@ -1071,13 +1127,15 @@ async def test_credential_exchange_send_request_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock() @@ -1105,13 +1163,13 @@ async def test_credential_exchange_send_free_request(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_mgr.return_value.create_request = mock.CoroutineMock() mock_cx_rec = mock.MagicMock() @@ -1139,11 +1197,12 @@ async def test_credential_exchange_send_free_request_no_conn_record(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + ): # Emulate storage not found (bad connection id) mock_conn_rec.retrieve_by_id = mock.CoroutineMock( side_effect=test_module.StorageNotFoundError() @@ -1165,11 +1224,12 @@ async def test_credential_exchange_send_free_request_not_ready(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + ): # Emulate connection not ready mock_conn_rec.retrieve_by_id = mock.CoroutineMock() mock_conn_rec.retrieve_by_id.return_value.is_ready = False @@ -1190,11 +1250,13 @@ async def test_credential_exchange_send_free_request_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_cred_mgr.return_value.create_request = mock.CoroutineMock( side_effect=[ test_module.LedgerError(), @@ -1211,17 +1273,17 @@ async def test_credential_exchange_issue(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_cx_rec_cls.retrieve_by_id.return_value.state = ( test_module.V20CredExRecord.STATE_REQUEST_RECEIVED @@ -1230,9 +1292,10 @@ async def test_credential_exchange_issue(self): mock_handler.return_value.get_detail_record = mock.CoroutineMock( side_effect=[ - mock.MagicMock( # indy + mock.MagicMock( # anoncreds serialize=mock.MagicMock(return_value={"...": "..."}) ), + None, None, # ld_proof None, # vc_di ] @@ -1248,7 +1311,8 @@ async def test_credential_exchange_issue(self): mock_response.assert_called_once_with( { "cred_ex_record": mock_cx_rec.serialize.return_value, - "indy": {"...": "..."}, + "anoncreds": {"...": "..."}, + "indy": None, "ld_proof": None, "vc_di": None, } @@ -1258,17 +1322,17 @@ async def test_credential_exchange_issue_vcdi(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_cx_rec_cls.retrieve_by_id.return_value.state = ( test_module.V20CredExRecord.STATE_REQUEST_RECEIVED @@ -1277,7 +1341,8 @@ async def test_credential_exchange_issue_vcdi(self): mock_handler.return_value.get_detail_record = mock.CoroutineMock( side_effect=[ - None, + None, # anoncreds + None, # indy None, # ld_proof mock.MagicMock( # indy serialize=mock.MagicMock(return_value={"...": "..."}) @@ -1295,6 +1360,7 @@ async def test_credential_exchange_issue_vcdi(self): mock_response.assert_called_once_with( { "cred_ex_record": mock_cx_rec.serialize.return_value, + "anoncreds": None, "indy": None, "ld_proof": None, "vc_di": {"...": "..."}, @@ -1325,13 +1391,15 @@ async def test_credential_exchange_issue_no_conn_record(self): serialize=mock.MagicMock(), save_error_state=mock.CoroutineMock(), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + ): mock_cx_rec.state = mock_cx_rec_cls.STATE_REQUEST_RECEIVED mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock(return_value=mock_cx_rec) @@ -1353,13 +1421,15 @@ async def test_credential_exchange_issue_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + ): mock_cx_rec.retrieve_by_id = mock.CoroutineMock() mock_cx_rec.retrieve_by_id.return_value.state = ( test_module.V20CredExRecord.STATE_REQUEST_RECEIVED @@ -1387,13 +1457,15 @@ async def test_credential_exchange_issue_rev_reg_full_indy(self): serialize=mock.MagicMock(), save_error_state=mock.CoroutineMock(), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + ): mock_cx_rec.state = mock_cx_rec_cls.STATE_REQUEST_RECEIVED mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock(return_value=mock_cx_rec) @@ -1417,13 +1489,15 @@ async def test_credential_exchange_issue_rev_reg_full_anoncreds(self): serialize=mock.MagicMock(), save_error_state=mock.CoroutineMock(), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + ): mock_cx_rec.state = mock_cx_rec_cls.STATE_REQUEST_RECEIVED mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock(return_value=mock_cx_rec) @@ -1449,13 +1523,15 @@ async def test_credential_exchange_issue_deser_x(self): mock_conn_rec = mock.MagicMock(ConnRecord, autospec=True) mock_conn_rec.retrieve_by_id = mock.CoroutineMock(return_value=ConnRecord()) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + ): mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock(return_value=mock_cx_rec) mock_cred_mgr.return_value = mock.MagicMock( issue_credential=mock.CoroutineMock( @@ -1481,23 +1557,24 @@ async def test_credential_exchange_store(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - V20CredFormat.Format, "handler" - ) as mock_handler: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_cx_rec_cls.retrieve_by_id.return_value.state = ( test_module.V20CredExRecord.STATE_CREDENTIAL_RECEIVED ) mock_handler.return_value.get_detail_record = mock.CoroutineMock( side_effect=[ + None, # anoncreds mock.MagicMock( # indy serialize=mock.MagicMock(return_value={"...": "..."}) ), @@ -1519,6 +1596,7 @@ async def test_credential_exchange_store(self): mock_response.assert_called_once_with( { "cred_ex_record": mock_cx_rec.serialize.return_value, + "anoncreds": None, "indy": {"...": "..."}, "ld_proof": None, "vc_di": None, @@ -1531,19 +1609,22 @@ async def test_credential_exchange_store_bad_cred_id_json(self): ) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response, mock.patch.object( - LDProofCredFormatHandler, "get_detail_record", autospec=True - ) as mock_ld_proof_get_detail_record, mock.patch.object( - IndyCredFormatHandler, "get_detail_record", autospec=True - ) as mock_indy_get_detail_record: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + mock.patch.object( + LDProofCredFormatHandler, "get_detail_record", autospec=True + ) as mock_ld_proof_get_detail_record, + mock.patch.object( + IndyCredFormatHandler, "get_detail_record", autospec=True + ) as mock_indy_get_detail_record, + ): mock_cx_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_cx_rec_cls.retrieve_by_id.return_value.state = ( test_module.V20CredExRecord.STATE_CREDENTIAL_RECEIVED @@ -1575,6 +1656,7 @@ async def test_credential_exchange_store_bad_cred_id_json(self): mock_response.assert_called_once_with( { "cred_ex_record": mock_cx_rec.serialize.return_value, + "anoncreds": None, "indy": {"...": "..."}, "ld_proof": None, "vc_di": None, @@ -1600,13 +1682,15 @@ async def test_credential_exchange_store_no_conn_record(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock( @@ -1634,13 +1718,13 @@ async def test_credential_exchange_store_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20CredManager", autospec=True - ), mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object(test_module, "V20CredManager", autospec=True), + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec, + ): mock_cx_rec.connection_id = "conn-123" mock_cx_rec.thread_id = "conn-123" mock_cx_rec.retrieve_by_id = mock.CoroutineMock() @@ -1659,15 +1743,17 @@ async def test_credential_exchange_store_x(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cx_rec_cls, mock.patch.object( - test_module.web, "json_response" - ), mock.patch.object(V20CredFormat.Format, "handler") as mock_handler: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cx_rec_cls, + mock.patch.object(test_module.web, "json_response"), + mock.patch.object(V20CredFormat.Format, "handler") as mock_handler, + ): mock_cx_rec = mock.MagicMock( state=mock_cx_rec_cls.STATE_CREDENTIAL_RECEIVED, serialize=mock.MagicMock(side_effect=test_module.BaseModelError()), @@ -1678,6 +1764,7 @@ async def test_credential_exchange_store_x(self): ) mock_handler.return_value.get_detail_record = mock.CoroutineMock( side_effect=[ + None, # anoncreds mock.MagicMock( # indy serialize=mock.MagicMock(return_value={"...": "..."}) ), @@ -1702,11 +1789,12 @@ async def test_credential_exchange_store_x(self): async def test_credential_exchange_remove(self): self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20CredManager", autospec=True - ) as mock_cred_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20CredManager", autospec=True + ) as mock_cred_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_mgr.return_value = mock.MagicMock( delete_cred_ex_record=mock.CoroutineMock() ) @@ -1751,15 +1839,16 @@ async def test_credential_exchange_problem_report(self): self.request.match_info = {"cred_ex_id": "dummy"} magic_report = mock.MagicMock() - with mock.patch.object( - test_module, "V20CredManager", autospec=True - ), mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cred_ex, mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ) as mock_problem_report, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "V20CredManager", autospec=True), + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cred_ex, + mock.patch.object( + test_module, "problem_report_for_record", mock.MagicMock() + ) as mock_problem_report, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock(save_error_state=mock.CoroutineMock()) ) @@ -1779,11 +1868,12 @@ async def test_credential_exchange_problem_report_bad_cred_ex_id(self): ) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20CredManager", autospec=True - ), mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "V20CredManager", autospec=True), + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock( side_effect=test_module.StorageNotFoundError() ) @@ -1797,13 +1887,13 @@ async def test_credential_exchange_problem_report_x(self): ) self.request.match_info = {"cred_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20CredManager", autospec=True - ), mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ), mock.patch.object( - test_module, "V20CredExRecord", autospec=True - ) as mock_cred_ex: + with ( + mock.patch.object(test_module, "V20CredManager", autospec=True), + mock.patch.object(test_module, "problem_report_for_record", mock.MagicMock()), + mock.patch.object( + test_module, "V20CredExRecord", autospec=True + ) as mock_cred_ex, + ): mock_cred_ex.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock( save_error_state=mock.CoroutineMock( diff --git a/acapy_agent/protocols/out_of_band/v1_0/tests/test_manager.py b/acapy_agent/protocols/out_of_band/v1_0/tests/test_manager.py index 9d1ae4b624..1e5b41ba7e 100644 --- a/acapy_agent/protocols/out_of_band/v1_0/tests/test_manager.py +++ b/acapy_agent/protocols/out_of_band/v1_0/tests/test_manager.py @@ -399,11 +399,14 @@ async def test_create_invitation_multitenant_local(self): } ) - with mock.patch.object( - AskarWallet, "create_signing_key", autospec=True - ) as mock_wallet_create_signing_key, mock.patch.object( - self.multitenant_mgr, "get_default_mediator" - ) as mock_get_default_mediator: + with ( + mock.patch.object( + AskarWallet, "create_signing_key", autospec=True + ) as mock_wallet_create_signing_key, + mock.patch.object( + self.multitenant_mgr, "get_default_mediator" + ) as mock_get_default_mediator, + ): mock_wallet_create_signing_key.return_value = KeyInfo( TestConfig.test_verkey, None, ED25519 ) @@ -455,11 +458,12 @@ async def test_create_invitation_mediation_overwrites_routing_and_endpoint(self) endpoint=self.test_mediator_endpoint, ) await mediation_record.save(session) - with mock.patch.object( - MediationManager, - "get_default_mediator_id", - ) as mock_get_default_mediator, mock.patch.object( - mock_conn_rec, "metadata_set", mock.CoroutineMock() + with ( + mock.patch.object( + MediationManager, + "get_default_mediator_id", + ) as mock_get_default_mediator, + mock.patch.object(mock_conn_rec, "metadata_set", mock.CoroutineMock()), ): invite = await self.manager.create_invitation( my_endpoint=TestConfig.test_endpoint, @@ -496,13 +500,16 @@ async def test_create_invitation_no_handshake_no_attachments_x(self): async def test_create_invitation_attachment_v1_0_cred_offer(self): self.profile.context.update_settings({"public_invites": True}) - with mock.patch.object( - AskarWallet, "get_public_did", autospec=True - ) as mock_wallet_get_public_did, mock.patch.object( - V10CredentialExchange, - "retrieve_by_id", - mock.CoroutineMock(), - ) as mock_retrieve_cxid: + with ( + mock.patch.object( + AskarWallet, "get_public_did", autospec=True + ) as mock_wallet_get_public_did, + mock.patch.object( + V10CredentialExchange, + "retrieve_by_id", + mock.CoroutineMock(), + ) as mock_retrieve_cxid, + ): mock_wallet_get_public_did.return_value = DIDInfo( TestConfig.test_did, TestConfig.test_verkey, @@ -530,13 +537,16 @@ async def test_create_invitation_attachment_v1_0_cred_offer(self): async def test_create_invitation_attachment_v1_0_cred_offer_no_handshake(self): self.profile.context.update_settings({"public_invites": True}) - with mock.patch.object( - AskarWallet, "get_public_did", autospec=True - ) as mock_wallet_get_public_did, mock.patch.object( - V10CredentialExchange, - "retrieve_by_id", - mock.CoroutineMock(), - ) as mock_retrieve_cxid: + with ( + mock.patch.object( + AskarWallet, "get_public_did", autospec=True + ) as mock_wallet_get_public_did, + mock.patch.object( + V10CredentialExchange, + "retrieve_by_id", + mock.CoroutineMock(), + ) as mock_retrieve_cxid, + ): mock_wallet_get_public_did.return_value = DIDInfo( TestConfig.test_did, TestConfig.test_verkey, @@ -564,17 +574,21 @@ async def test_create_invitation_attachment_v1_0_cred_offer_no_handshake(self): } async def test_create_invitation_attachment_v2_0_cred_offer(self): - with mock.patch.object( - AskarWallet, "get_public_did", autospec=True - ) as mock_wallet_get_public_did, mock.patch.object( - test_module.V10CredentialExchange, - "retrieve_by_id", - mock.CoroutineMock(), - ) as mock_retrieve_cxid_v1, mock.patch.object( - test_module.V20CredExRecord, - "retrieve_by_id", - mock.CoroutineMock(), - ) as mock_retrieve_cxid_v2: + with ( + mock.patch.object( + AskarWallet, "get_public_did", autospec=True + ) as mock_wallet_get_public_did, + mock.patch.object( + test_module.V10CredentialExchange, + "retrieve_by_id", + mock.CoroutineMock(), + ) as mock_retrieve_cxid_v1, + mock.patch.object( + test_module.V20CredExRecord, + "retrieve_by_id", + mock.CoroutineMock(), + ) as mock_retrieve_cxid_v2, + ): mock_wallet_get_public_did.return_value = DIDInfo( TestConfig.test_did, TestConfig.test_verkey, @@ -602,13 +616,16 @@ async def test_create_invitation_attachment_v2_0_cred_offer(self): async def test_create_invitation_attachment_present_proof_v1_0(self): self.profile.context.update_settings({"public_invites": True}) - with mock.patch.object( - AskarWallet, "get_public_did", autospec=True - ) as mock_wallet_get_public_did, mock.patch.object( - test_module.V10PresentationExchange, - "retrieve_by_id", - mock.CoroutineMock(), - ) as mock_retrieve_pxid: + with ( + mock.patch.object( + AskarWallet, "get_public_did", autospec=True + ) as mock_wallet_get_public_did, + mock.patch.object( + test_module.V10PresentationExchange, + "retrieve_by_id", + mock.CoroutineMock(), + ) as mock_retrieve_pxid, + ): mock_wallet_get_public_did.return_value = DIDInfo( TestConfig.test_did, TestConfig.test_verkey, @@ -637,17 +654,21 @@ async def test_create_invitation_attachment_present_proof_v1_0(self): async def test_create_invitation_attachment_present_proof_v2_0(self): self.profile.context.update_settings({"public_invites": True}) - with mock.patch.object( - AskarWallet, "get_public_did", autospec=True - ) as mock_wallet_get_public_did, mock.patch.object( - test_module.V10PresentationExchange, - "retrieve_by_id", - mock.CoroutineMock(), - ) as mock_retrieve_pxid_1, mock.patch.object( - test_module.V20PresExRecord, - "retrieve_by_id", - mock.CoroutineMock(), - ) as mock_retrieve_pxid_2: + with ( + mock.patch.object( + AskarWallet, "get_public_did", autospec=True + ) as mock_wallet_get_public_did, + mock.patch.object( + test_module.V10PresentationExchange, + "retrieve_by_id", + mock.CoroutineMock(), + ) as mock_retrieve_pxid_1, + mock.patch.object( + test_module.V20PresExRecord, + "retrieve_by_id", + mock.CoroutineMock(), + ) as mock_retrieve_pxid_2, + ): mock_wallet_get_public_did.return_value = DIDInfo( TestConfig.test_did, TestConfig.test_verkey, @@ -904,14 +925,17 @@ async def test_wait_for_conn_rec_active_retrieve_by_id(self): async def test_create_handshake_reuse_msg(self): self.profile.context.update_settings({"public_invites": True}) - with mock.patch.object( - OutOfBandManager, - "fetch_connection_targets", - autospec=True, - ) as oob_mgr_fetch_conn, mock.patch.object( - ConnRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=self.test_conn_rec), + with ( + mock.patch.object( + OutOfBandManager, + "fetch_connection_targets", + autospec=True, + ) as oob_mgr_fetch_conn, + mock.patch.object( + ConnRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=self.test_conn_rec), + ), ): oob_mgr_fetch_conn.return_value = ConnectionTarget( did=TestConfig.test_did, @@ -974,17 +998,19 @@ async def test_receive_reuse_message_existing_found(self): self.test_conn_rec.invitation_msg_id = "test_123" self.test_conn_rec.state = ConnRecord.State.COMPLETED.rfc160 - with mock.patch.object( - OutOfBandManager, - "fetch_connection_targets", - autospec=True, - ) as oob_mgr_fetch_conn, mock.patch.object( - OobRecord, - "retrieve_by_tag_filter", - autospec=True, - ) as mock_retrieve_oob, mock.patch.object( - self.profile, "notify", autospec=True - ) as mock_notify: + with ( + mock.patch.object( + OutOfBandManager, + "fetch_connection_targets", + autospec=True, + ) as oob_mgr_fetch_conn, + mock.patch.object( + OobRecord, + "retrieve_by_tag_filter", + autospec=True, + ) as mock_retrieve_oob, + mock.patch.object(self.profile, "notify", autospec=True) as mock_notify, + ): mock_retrieve_oob.return_value = mock.MagicMock( emit_event=mock.CoroutineMock(), delete_record=mock.CoroutineMock(), @@ -1031,17 +1057,19 @@ async def test_receive_reuse_message_existing_found_multi_use(self): self.test_conn_rec.invitation_msg_id = "test_123" self.test_conn_rec.state = ConnRecord.State.COMPLETED.rfc160 - with mock.patch.object( - OutOfBandManager, - "fetch_connection_targets", - autospec=True, - ) as oob_mgr_fetch_conn, mock.patch.object( - OobRecord, - "retrieve_by_tag_filter", - autospec=True, - ) as mock_retrieve_oob, mock.patch.object( - self.profile, "notify", autospec=True - ) as mock_notify: + with ( + mock.patch.object( + OutOfBandManager, + "fetch_connection_targets", + autospec=True, + ) as oob_mgr_fetch_conn, + mock.patch.object( + OobRecord, + "retrieve_by_tag_filter", + autospec=True, + ) as mock_retrieve_oob, + mock.patch.object(self.profile, "notify", autospec=True) as mock_notify, + ): mock_retrieve_oob.return_value = mock.MagicMock( emit_event=mock.CoroutineMock(), delete_record=mock.CoroutineMock(), @@ -1085,11 +1113,12 @@ async def test_receive_reuse_accepted(self): reuse_msg_accepted = HandshakeReuseAccept() reuse_msg_accepted.assign_thread_id(thid="the-thread-id", pthid="the-pthid") - with mock.patch.object( - self.profile, "notify", autospec=True - ) as mock_notify, mock.patch.object( - OobRecord, "retrieve_by_tag_filter", autospec=True - ) as mock_retrieve_oob: + with ( + mock.patch.object(self.profile, "notify", autospec=True) as mock_notify, + mock.patch.object( + OobRecord, "retrieve_by_tag_filter", autospec=True + ) as mock_retrieve_oob, + ): mock_retrieve_oob.return_value = mock.MagicMock( emit_event=mock.CoroutineMock(), delete_record=mock.CoroutineMock(), @@ -1122,11 +1151,12 @@ async def test_receive_reuse_accepted_x(self): reuse_msg_accepted = HandshakeReuseAccept() reuse_msg_accepted.assign_thread_id(thid="the-thread-id", pthid="the-pthid") - with mock.patch.object( - self.profile, "notify", autospec=True - ) as mock_notify, mock.patch.object( - OobRecord, "retrieve_by_tag_filter", autospec=True - ) as mock_retrieve_oob: + with ( + mock.patch.object(self.profile, "notify", autospec=True) as mock_notify, + mock.patch.object( + OobRecord, "retrieve_by_tag_filter", autospec=True + ) as mock_retrieve_oob, + ): mock_retrieve_oob.side_effect = (StorageNotFoundError,) with self.assertRaises(test_module.OutOfBandManagerError) as err: @@ -1219,11 +1249,14 @@ async def test_receive_invitation_with_valid_mediation(self): endpoint=self.test_mediator_endpoint, ) await mediation_record.save(session) - with mock.patch.object( - DIDXManager, "receive_invitation", mock.CoroutineMock() - ) as mock_didx_recv_invi, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve_conn_by_id: + with ( + mock.patch.object( + DIDXManager, "receive_invitation", mock.CoroutineMock() + ) as mock_didx_recv_invi, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve_conn_by_id, + ): invite = await self.manager.create_invitation( my_endpoint=TestConfig.test_endpoint, my_label="test123", @@ -1249,15 +1282,18 @@ async def test_receive_invitation_with_valid_mediation(self): async def test_receive_invitation_with_invalid_mediation(self): mock_conn = mock.MagicMock(connection_id="dummy-connection") - with mock.patch.object( - DIDXManager, - "receive_invitation", - mock.CoroutineMock(), - ) as mock_didx_recv_invi, mock.patch.object( - ConnRecord, - "retrieve_by_id", - mock.CoroutineMock(), - ) as mock_retrieve_conn_by_id: + with ( + mock.patch.object( + DIDXManager, + "receive_invitation", + mock.CoroutineMock(), + ) as mock_didx_recv_invi, + mock.patch.object( + ConnRecord, + "retrieve_by_id", + mock.CoroutineMock(), + ) as mock_retrieve_conn_by_id, + ): invite = await self.manager.create_invitation( my_endpoint=TestConfig.test_endpoint, my_label="test123", @@ -1287,11 +1323,12 @@ async def test_receive_invitation_didx_services_with_service_block(self): mock_conn = mock.MagicMock(connection_id="dummy-connection") - with mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as didx_mgr_cls, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve_conn_by_id: + with ( + mock.patch.object(test_module, "DIDXManager", autospec=True) as didx_mgr_cls, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve_conn_by_id, + ): didx_mgr_cls.return_value = mock.MagicMock( receive_invitation=mock.CoroutineMock(return_value=mock_conn) ) @@ -1316,11 +1353,14 @@ async def test_receive_invitation_connection_protocol(self): mock_conn = mock.MagicMock(connection_id="dummy-connection") - with mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as conn_mgr_cls, mock.patch.object( - ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_conn_retrieve_by_id: + with ( + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as conn_mgr_cls, + mock.patch.object( + ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_conn_retrieve_by_id, + ): conn_mgr_cls.return_value = mock.MagicMock( receive_invitation=mock.CoroutineMock(return_value=mock_conn) ) @@ -1405,17 +1445,20 @@ async def test_existing_conn_record_public_did(self): their_role=ConnRecord.Role.REQUESTER, ) - with mock.patch.object( - ConnRecord, - "find_existing_connection", - mock.CoroutineMock(), - ) as oob_mgr_find_existing_conn, mock.patch.object( - OobRecord, "save", mock.CoroutineMock() - ) as oob_record_save, mock.patch.object( - OobRecord, "retrieve_by_id", mock.CoroutineMock() - ) as oob_record_retrieve_by_id, mock.patch.object( - OutOfBandManager, "fetch_connection_targets", autospec=True - ) as oob_mgr_fetch_conn: + with ( + mock.patch.object( + ConnRecord, + "find_existing_connection", + mock.CoroutineMock(), + ) as oob_mgr_find_existing_conn, + mock.patch.object(OobRecord, "save", mock.CoroutineMock()) as oob_record_save, + mock.patch.object( + OobRecord, "retrieve_by_id", mock.CoroutineMock() + ) as oob_record_retrieve_by_id, + mock.patch.object( + OutOfBandManager, "fetch_connection_targets", autospec=True + ) as oob_mgr_fetch_conn, + ): oob_mgr_find_existing_conn.return_value = test_exist_conn oob_mgr_fetch_conn.return_value = [] oob_invitation = InvitationMessage( @@ -1450,18 +1493,22 @@ async def test_receive_invitation_handshake_reuse(self): their_role=ConnRecord.Role.REQUESTER, ) - with mock.patch.object( - test_module.OutOfBandManager, - "_handle_handshake_reuse", - mock.CoroutineMock(), - ) as handle_handshake_reuse, mock.patch.object( - test_module.OutOfBandManager, - "_perform_handshake", - mock.CoroutineMock(), - ) as perform_handshake, mock.patch.object( - ConnRecord, - "find_existing_connection", - mock.CoroutineMock(return_value=test_exist_conn), + with ( + mock.patch.object( + test_module.OutOfBandManager, + "_handle_handshake_reuse", + mock.CoroutineMock(), + ) as handle_handshake_reuse, + mock.patch.object( + test_module.OutOfBandManager, + "_perform_handshake", + mock.CoroutineMock(), + ) as perform_handshake, + mock.patch.object( + ConnRecord, + "find_existing_connection", + mock.CoroutineMock(return_value=test_exist_conn), + ), ): oob_invitation = InvitationMessage( handshake_protocols=[ @@ -1498,22 +1545,27 @@ async def test_receive_invitation_handshake_reuse_failed(self): their_role=ConnRecord.Role.REQUESTER, ) - with mock.patch.object( - test_module.OutOfBandManager, - "_handle_handshake_reuse", - mock.CoroutineMock(), - ) as handle_handshake_reuse, mock.patch.object( - test_module.OutOfBandManager, - "_perform_handshake", - mock.CoroutineMock(), - ) as perform_handshake, mock.patch.object( - ConnRecord, - "find_existing_connection", - mock.CoroutineMock(return_value=test_exist_conn), - ), mock.patch.object( - ConnRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=test_exist_conn), + with ( + mock.patch.object( + test_module.OutOfBandManager, + "_handle_handshake_reuse", + mock.CoroutineMock(), + ) as handle_handshake_reuse, + mock.patch.object( + test_module.OutOfBandManager, + "_perform_handshake", + mock.CoroutineMock(), + ) as perform_handshake, + mock.patch.object( + ConnRecord, + "find_existing_connection", + mock.CoroutineMock(return_value=test_exist_conn), + ), + mock.patch.object( + ConnRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=test_exist_conn), + ), ): oob_invitation = InvitationMessage( handshake_protocols=[ @@ -1562,12 +1614,13 @@ async def test_receive_invitation_services_with_service_did(self): mock_conn = mock.MagicMock(connection_id="dummy") - with mock.patch.object( - test_module, "DIDXManager", autospec=True - ) as didx_mgr_cls, mock.patch.object( - ConnRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_conn), + with ( + mock.patch.object(test_module, "DIDXManager", autospec=True) as didx_mgr_cls, + mock.patch.object( + ConnRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_conn), + ), ): didx_mgr_cls.return_value = mock.MagicMock( receive_invitation=mock.CoroutineMock(return_value=mock_conn) @@ -1598,15 +1651,18 @@ async def test_request_attach_oob_message_processor_connectionless(self): endpoint=self.test_endpoint, recipient_keys=[self.test_verkey] ) - with mock.patch.object( - AskarWallet, - "create_signing_key", - mock.CoroutineMock(), - ) as mock_create_signing_key, mock.patch.object( - OutOfBandManager, - "_service_decorator_from_service", - mock.CoroutineMock(), - ) as mock_service_decorator_from_service: + with ( + mock.patch.object( + AskarWallet, + "create_signing_key", + mock.CoroutineMock(), + ) as mock_create_signing_key, + mock.patch.object( + OutOfBandManager, + "_service_decorator_from_service", + mock.CoroutineMock(), + ) as mock_service_decorator_from_service, + ): mock_create_signing_key.return_value = KeyInfo( verkey="H3C2AVvLMv6gmMNam3uVAjZpfkcJCwDwnZn6z3wXmqPV", metadata={}, @@ -1696,13 +1752,16 @@ async def test_request_attach_wait_for_conn_rec_active(self): their_role=ConnRecord.Role.REQUESTER, ) - with mock.patch.object( - OutOfBandManager, "_wait_for_conn_rec_active" - ) as mock_wait_for_conn_rec_active, mock.patch.object( - ConnRecord, - "find_existing_connection", - mock.CoroutineMock(), - ) as oob_mgr_find_existing_conn: + with ( + mock.patch.object( + OutOfBandManager, "_wait_for_conn_rec_active" + ) as mock_wait_for_conn_rec_active, + mock.patch.object( + ConnRecord, + "find_existing_connection", + mock.CoroutineMock(), + ) as oob_mgr_find_existing_conn, + ): oob_mgr_find_existing_conn.return_value = test_exist_conn mock_wait_for_conn_rec_active.return_value = None oob_invitation = InvitationMessage( @@ -1837,11 +1896,14 @@ async def test_delete_stale_connection_by_invitation(self): updated_at=datetime_to_str(older_datetime), ) ] - with mock.patch.object( - ConnRecord, "query", mock.CoroutineMock() - ) as mock_connrecord_query, mock.patch.object( - ConnRecord, "delete_record", mock.CoroutineMock() - ) as mock_connrecord_delete: + with ( + mock.patch.object( + ConnRecord, "query", mock.CoroutineMock() + ) as mock_connrecord_query, + mock.patch.object( + ConnRecord, "delete_record", mock.CoroutineMock() + ) as mock_connrecord_delete, + ): mock_connrecord_query.return_value = records await self.manager.delete_stale_connection_by_invitation("test123") mock_connrecord_delete.assert_called_once() @@ -1868,15 +1930,20 @@ async def test_delete_conn_and_oob_record_invitation(self): invitation_msg_id="test123", ) ] - with mock.patch.object( - ConnRecord, "query", mock.CoroutineMock() - ) as mock_connrecord_query, mock.patch.object( - ConnRecord, "delete_record", mock.CoroutineMock() - ) as mock_connrecord_delete, mock.patch.object( - OobRecord, "query", mock.CoroutineMock() - ) as mock_oobrecord_query, mock.patch.object( - OobRecord, "delete_record", mock.CoroutineMock() - ) as mock_oobrecord_delete: + with ( + mock.patch.object( + ConnRecord, "query", mock.CoroutineMock() + ) as mock_connrecord_query, + mock.patch.object( + ConnRecord, "delete_record", mock.CoroutineMock() + ) as mock_connrecord_delete, + mock.patch.object( + OobRecord, "query", mock.CoroutineMock() + ) as mock_oobrecord_query, + mock.patch.object( + OobRecord, "delete_record", mock.CoroutineMock() + ) as mock_oobrecord_delete, + ): mock_connrecord_query.return_value = conn_records mock_oobrecord_query.return_value = oob_records await self.manager.delete_conn_and_oob_record_invitation("test123") diff --git a/acapy_agent/protocols/out_of_band/v1_0/tests/test_routes.py b/acapy_agent/protocols/out_of_band/v1_0/tests/test_routes.py index a42378c811..6e25915185 100644 --- a/acapy_agent/protocols/out_of_band/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/out_of_band/v1_0/tests/test_routes.py @@ -40,11 +40,14 @@ async def test_invitation_create(self): } self.request.json = mock.CoroutineMock(return_value=body) - with mock.patch.object( - test_module, "OutOfBandManager", autospec=True - ) as mock_oob_mgr, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "OutOfBandManager", autospec=True + ) as mock_oob_mgr, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_oob_mgr.return_value.create_invitation = mock.CoroutineMock( return_value=mock.MagicMock( serialize=mock.MagicMock(return_value={"abc": "123"}) @@ -75,11 +78,14 @@ async def test_invitation_create(self): async def test_invitation_remove(self): self.request.match_info = {"invi_msg_id": "dummy"} - with mock.patch.object( - test_module, "OutOfBandManager", autospec=True - ) as mock_oob_mgr, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "OutOfBandManager", autospec=True + ) as mock_oob_mgr, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_oob_mgr.return_value.delete_conn_and_oob_record_invitation = ( mock.CoroutineMock(return_value=None) ) @@ -100,11 +106,14 @@ async def test_invitation_create_with_accept(self): } self.request.json = mock.CoroutineMock(return_value=body) - with mock.patch.object( - test_module, "OutOfBandManager", autospec=True - ) as mock_oob_mgr, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "OutOfBandManager", autospec=True + ) as mock_oob_mgr, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_oob_mgr.return_value.create_invitation = mock.CoroutineMock( return_value=mock.MagicMock( serialize=mock.MagicMock(return_value={"abc": "123"}) @@ -142,11 +151,14 @@ async def test_invitation_create_x(self): } ) - with mock.patch.object( - test_module, "OutOfBandManager", autospec=True - ) as mock_oob_mgr, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "OutOfBandManager", autospec=True + ) as mock_oob_mgr, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_oob_mgr.return_value.create_invitation = mock.CoroutineMock( side_effect=test_module.OutOfBandManagerError() ) @@ -159,13 +171,15 @@ async def test_invitation_receive(self): self.request.json = mock.CoroutineMock() expected_connection_record = ConnRecord(connection_id="some-id") - with mock.patch.object( - test_module, "OutOfBandManager", autospec=True - ) as mock_oob_mgr, mock.patch.object( - test_module.InvitationMessage, "deserialize", mock.Mock() - ), mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "OutOfBandManager", autospec=True + ) as mock_oob_mgr, + mock.patch.object(test_module.InvitationMessage, "deserialize", mock.Mock()), + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_oob_mgr.return_value.receive_invitation = mock.CoroutineMock( return_value=expected_connection_record ) @@ -183,11 +197,13 @@ async def test_invitation_receive_forbidden_x(self): async def test_invitation_receive_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "OutOfBandManager", autospec=True - ) as mock_oob_mgr, mock.patch.object( - test_module.InvitationMessage, "deserialize", mock.Mock() - ), mock.patch.object(test_module.web, "json_response", mock.Mock()): + with ( + mock.patch.object( + test_module, "OutOfBandManager", autospec=True + ) as mock_oob_mgr, + mock.patch.object(test_module.InvitationMessage, "deserialize", mock.Mock()), + mock.patch.object(test_module.web, "json_response", mock.Mock()), + ): mock_oob_mgr.return_value.receive_invitation = mock.CoroutineMock( side_effect=test_module.StorageError("cannot write") ) diff --git a/acapy_agent/protocols/present_proof/anoncreds/pres_exch_handler.py b/acapy_agent/protocols/present_proof/anoncreds/pres_exch_handler.py index 0052a78873..d1d73f8a72 100644 --- a/acapy_agent/protocols/present_proof/anoncreds/pres_exch_handler.py +++ b/acapy_agent/protocols/present_proof/anoncreds/pres_exch_handler.py @@ -1,4 +1,4 @@ -"""Utilities for dif presentation exchange attachment.""" +"""Utilities for anoncreds presentation exchange attachment.""" import json import logging @@ -6,14 +6,15 @@ from typing import Dict, Optional, Tuple, Union from ....anoncreds.holder import AnonCredsHolder, AnonCredsHolderError -from ....anoncreds.models.anoncreds_cred_def import CredDef -from ....anoncreds.models.anoncreds_revocation import RevRegDef -from ....anoncreds.models.anoncreds_schema import AnonCredsSchema +from ....anoncreds.models.credential_definition import CredDef +from ....anoncreds.models.revocation import RevRegDef +from ....anoncreds.models.schema import AnonCredsSchema +from ....anoncreds.models.utils import extract_non_revocation_intervals_from_proof_request from ....anoncreds.registry import AnonCredsRegistry from ....anoncreds.revocation import AnonCredsRevocation +from ....askar.profile_anon import AskarAnoncredsProfile from ....core.error import BaseError from ....core.profile import Profile -from ....indy.models.xform import indy_proof_req2non_revoc_intervals from ..v1_0.models.presentation_exchange import V10PresentationExchange from ..v2_0.messages.pres_format import V20PresFormat from ..v2_0.models.pres_exchange import V20PresExRecord @@ -22,7 +23,7 @@ class AnonCredsPresExchHandlerError(BaseError): - """Base class for Indy Presentation Exchange related errors.""" + """Base class for Anoncreds Presentation Exchange related errors.""" class AnonCredsPresExchHandler: @@ -39,7 +40,9 @@ def __init__( def _extract_proof_request(self, pres_ex_record): if isinstance(pres_ex_record, V20PresExRecord): - return pres_ex_record.pres_request.attachment(V20PresFormat.Format.INDY) + return pres_ex_record.pres_request.attachment( + V20PresFormat.Format.ANONCREDS + ) or pres_ex_record.pres_request.attachment(V20PresFormat.Format.INDY) elif isinstance(pres_ex_record, V10PresentationExchange): return pres_ex_record._presentation_request.ser @@ -229,10 +232,23 @@ async def return_presentation( pres_ex_record: Union[V10PresentationExchange, V20PresExRecord], requested_credentials: Optional[dict] = None, ) -> dict: - """Return Indy proof request as dict.""" + """Return Anoncreds proof request as dict.""" + + # If not anoncreds capable, try to use indy handler. This should be removed when + # indy filter is completely retired + if not isinstance(self._profile, AskarAnoncredsProfile): + from ..indy.pres_exch_handler import IndyPresExchHandler + + handler = IndyPresExchHandler(self._profile) + return await handler.return_presentation( + pres_ex_record, requested_credentials + ) + requested_credentials = requested_credentials or {} proof_request = self._extract_proof_request(pres_ex_record) - non_revoc_intervals = indy_proof_req2non_revoc_intervals(proof_request) + non_revoc_intervals = extract_non_revocation_intervals_from_proof_request( + proof_request + ) requested_referents = self._get_requested_referents( proof_request, requested_credentials, non_revoc_intervals @@ -253,12 +269,12 @@ async def return_presentation( self._set_timestamps(requested_credentials, requested_referents) - indy_proof_json = await self.holder.create_presentation( + proof_json = await self.holder.create_presentation( proof_request, requested_credentials, schemas, cred_defs, revocation_states, ) - indy_proof = json.loads(indy_proof_json) - return indy_proof + proof = json.loads(proof_json) + return proof diff --git a/acapy_agent/protocols/present_proof/dif/tests/test_pres_exch_handler.py b/acapy_agent/protocols/present_proof/dif/tests/test_pres_exch_handler.py index 654c62f432..3af1efe80e 100644 --- a/acapy_agent/protocols/present_proof/dif/tests/test_pres_exch_handler.py +++ b/acapy_agent/protocols/present_proof/dif/tests/test_pres_exch_handler.py @@ -2177,27 +2177,33 @@ async def test_create_vp_no_issuer(self): cred_tags={"some": "tag"}, ), ] - with mock.patch.object( - DIFPresExchHandler, - "_did_info_for_did", - mock.CoroutineMock(), - ) as mock_did_info, mock.patch.object( - DIFPresExchHandler, - "make_requirement", - mock.CoroutineMock(), - ) as mock_make_req, mock.patch.object( - DIFPresExchHandler, - "apply_requirements", - mock.CoroutineMock(), - ) as mock_apply_req, mock.patch.object( - DIFPresExchHandler, - "merge", - mock.CoroutineMock(), - ) as mock_merge, mock.patch.object( - test_module, - "create_presentation", - mock.CoroutineMock(), - ) as mock_create_vp: + with ( + mock.patch.object( + DIFPresExchHandler, + "_did_info_for_did", + mock.CoroutineMock(), + ) as mock_did_info, + mock.patch.object( + DIFPresExchHandler, + "make_requirement", + mock.CoroutineMock(), + ) as mock_make_req, + mock.patch.object( + DIFPresExchHandler, + "apply_requirements", + mock.CoroutineMock(), + ) as mock_apply_req, + mock.patch.object( + DIFPresExchHandler, + "merge", + mock.CoroutineMock(), + ) as mock_merge, + mock.patch.object( + test_module, + "create_presentation", + mock.CoroutineMock(), + ) as mock_create_vp, + ): mock_make_req.return_value = mock.MagicMock() mock_apply_req.return_value = mock.MagicMock() mock_merge.return_value = (VC_RECORDS, {}) @@ -2229,31 +2235,38 @@ async def test_create_vp_with_bbs_suite(self): self.profile, proof_type=BbsBlsSignature2020.signature_type ) cred_list, pd_list = await self.setup_tuple(self.profile) - with mock.patch.object( - DIFPresExchHandler, - "_did_info_for_did", - mock.CoroutineMock(), - ) as mock_did_info, mock.patch.object( - DIFPresExchHandler, - "make_requirement", - mock.CoroutineMock(), - ) as mock_make_req, mock.patch.object( - DIFPresExchHandler, - "apply_requirements", - mock.CoroutineMock(), - ) as mock_apply_req, mock.patch.object( - DIFPresExchHandler, - "merge", - mock.CoroutineMock(), - ) as mock_merge, mock.patch.object( - test_module, - "create_presentation", - mock.CoroutineMock(), - ) as mock_create_vp, mock.patch.object( - test_module, - "sign_presentation", - mock.CoroutineMock(), - ) as mock_sign_vp: + with ( + mock.patch.object( + DIFPresExchHandler, + "_did_info_for_did", + mock.CoroutineMock(), + ) as mock_did_info, + mock.patch.object( + DIFPresExchHandler, + "make_requirement", + mock.CoroutineMock(), + ) as mock_make_req, + mock.patch.object( + DIFPresExchHandler, + "apply_requirements", + mock.CoroutineMock(), + ) as mock_apply_req, + mock.patch.object( + DIFPresExchHandler, + "merge", + mock.CoroutineMock(), + ) as mock_merge, + mock.patch.object( + test_module, + "create_presentation", + mock.CoroutineMock(), + ) as mock_create_vp, + mock.patch.object( + test_module, + "sign_presentation", + mock.CoroutineMock(), + ) as mock_sign_vp, + ): mock_make_req.return_value = mock.MagicMock() mock_apply_req.return_value = mock.MagicMock() mock_merge.return_value = (cred_list, {}) @@ -2286,31 +2299,38 @@ async def test_create_vp_no_issuer_with_bbs_suite(self): self.profile, proof_type=BbsBlsSignature2020.signature_type ) cred_list, pd_list = await self.setup_tuple(self.profile) - with mock.patch.object( - DIFPresExchHandler, - "_did_info_for_did", - mock.CoroutineMock(), - ) as mock_did_info, mock.patch.object( - DIFPresExchHandler, - "make_requirement", - mock.CoroutineMock(), - ) as mock_make_req, mock.patch.object( - DIFPresExchHandler, - "apply_requirements", - mock.CoroutineMock(), - ) as mock_apply_req, mock.patch.object( - DIFPresExchHandler, - "merge", - mock.CoroutineMock(), - ) as mock_merge, mock.patch.object( - test_module, - "create_presentation", - mock.CoroutineMock(), - ) as mock_create_vp, mock.patch.object( - DIFPresExchHandler, - "get_sign_key_credential_subject_id", - mock.CoroutineMock(), - ) as mock_sign_key_cred_subject: + with ( + mock.patch.object( + DIFPresExchHandler, + "_did_info_for_did", + mock.CoroutineMock(), + ) as mock_did_info, + mock.patch.object( + DIFPresExchHandler, + "make_requirement", + mock.CoroutineMock(), + ) as mock_make_req, + mock.patch.object( + DIFPresExchHandler, + "apply_requirements", + mock.CoroutineMock(), + ) as mock_apply_req, + mock.patch.object( + DIFPresExchHandler, + "merge", + mock.CoroutineMock(), + ) as mock_merge, + mock.patch.object( + test_module, + "create_presentation", + mock.CoroutineMock(), + ) as mock_create_vp, + mock.patch.object( + DIFPresExchHandler, + "get_sign_key_credential_subject_id", + mock.CoroutineMock(), + ) as mock_sign_key_cred_subject, + ): mock_make_req.return_value = mock.MagicMock() mock_apply_req.return_value = mock.MagicMock() mock_merge.return_value = (cred_list, {}) diff --git a/acapy_agent/protocols/present_proof/indy/pres_exch_handler.py b/acapy_agent/protocols/present_proof/indy/pres_exch_handler.py index 9c510afc9a..b62701ced1 100644 --- a/acapy_agent/protocols/present_proof/indy/pres_exch_handler.py +++ b/acapy_agent/protocols/present_proof/indy/pres_exch_handler.py @@ -55,6 +55,13 @@ async def return_presentation( proof_request = pres_ex_record.pres_request.attachment( V20PresFormat.Format.INDY ) + # If indy filter fails try anoncreds filter format. This is for a + # non-anoncreds agent that gets a anoncreds format proof request and + # should removed when indy format is fully retired. + if not proof_request: + proof_request = pres_ex_record.pres_request.attachment( + V20PresFormat.Format.ANONCREDS + ) elif isinstance(pres_ex_record, V10PresentationExchange): proof_request = pres_ex_record._presentation_request.ser non_revoc_intervals = indy_proof_req2non_revoc_intervals(proof_request) diff --git a/acapy_agent/protocols/present_proof/v1_0/handlers/tests/test_presentation_request_handler.py b/acapy_agent/protocols/present_proof/v1_0/handlers/tests/test_presentation_request_handler.py index e43c2e80b0..25ccd85984 100644 --- a/acapy_agent/protocols/present_proof/v1_0/handlers/tests/test_presentation_request_handler.py +++ b/acapy_agent/protocols/present_proof/v1_0/handlers/tests/test_presentation_request_handler.py @@ -97,11 +97,14 @@ async def test_called(self): auto_present=True, ) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance ) @@ -149,11 +152,14 @@ async def test_called_not_found(self): auto_present=True, ) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( side_effect=StorageNotFoundError ) @@ -222,11 +228,14 @@ async def test_called_auto_present(self): ) self.request_context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.return_value = px_rec_instance mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -302,11 +311,14 @@ async def test_called_auto_present_x(self): ) self.request_context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.return_value = mock_px_rec mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock_px_rec @@ -368,11 +380,14 @@ async def test_called_auto_present_no_preview(self): ) self.request_context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.return_value = px_rec_instance mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -435,11 +450,14 @@ async def test_called_auto_present_pred_no_match(self): ) self.request_context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.return_value = px_rec_instance mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -498,11 +516,14 @@ async def test_called_auto_present_pred_single_match(self): ) self.request_context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.return_value = px_rec_instance mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -570,11 +591,14 @@ async def test_called_auto_present_pred_multi_match(self): ) self.request_context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.return_value = px_rec_instance mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -694,11 +718,14 @@ async def test_called_auto_present_multi_cred_match_reft(self): self.request_context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.return_value = px_rec_instance mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -798,11 +825,14 @@ async def test_called_auto_present_bait_and_switch(self): mock_holder.get_credentials_for_presentation_request_by_referent = by_reft self.request_context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "PresentationManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V10PresentationExchange", autospec=True - ) as mock_pres_ex_cls: + with ( + mock.patch.object( + test_module, "PresentationManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V10PresentationExchange", autospec=True + ) as mock_pres_ex_cls, + ): mock_pres_ex_cls.return_value = px_rec_instance mock_pres_ex_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance diff --git a/acapy_agent/protocols/present_proof/v1_0/models/tests/test_record.py b/acapy_agent/protocols/present_proof/v1_0/models/tests/test_record.py index 6868be17f3..4556877338 100644 --- a/acapy_agent/protocols/present_proof/v1_0/models/tests/test_record.py +++ b/acapy_agent/protocols/present_proof/v1_0/models/tests/test_record.py @@ -129,11 +129,12 @@ async def test_save_error_state(self): record.state = V10PresentationExchange.STATE_PROPOSAL_RECEIVED await record.save(session) - with mock.patch.object( - record, "save", mock.CoroutineMock() - ) as mock_save, mock.patch.object( - test_module.LOGGER, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object(record, "save", mock.CoroutineMock()) as mock_save, + mock.patch.object( + test_module.LOGGER, "exception", mock.MagicMock() + ) as mock_log_exc, + ): mock_save.side_effect = test_module.StorageError() await record.save_error_state(session, reason="testing") mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/present_proof/v1_0/tests/test_manager.py b/acapy_agent/protocols/present_proof/v1_0/tests/test_manager.py index 7674f7e1f7..574acb5139 100644 --- a/acapy_agent/protocols/present_proof/v1_0/tests/test_manager.py +++ b/acapy_agent/protocols/present_proof/v1_0/tests/test_manager.py @@ -340,9 +340,10 @@ async def test_record_eq(self): async def test_create_exchange_for_proposal(self): proposal = PresentationProposal() - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object(PresentationProposal, "serialize", autospec=True): + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object(PresentationProposal, "serialize", autospec=True), + ): exchange = await self.manager.create_exchange_for_proposal( CONN_ID, proposal, @@ -441,13 +442,15 @@ async def test_create_presentation(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -484,13 +487,15 @@ async def test_create_presentation_proof_req_non_revoc_interval_none(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -545,13 +550,15 @@ async def test_create_presentation_self_asserted(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -616,13 +623,15 @@ async def test_create_presentation_no_revocation(self): self.holder.create_presentation = mock.CoroutineMock(return_value="{}") self.profile.context.injector.bind_instance(IndyHolder, self.holder) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module.LOGGER, "info", mock.MagicMock() - ) as mock_log_info: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module.LOGGER, "info", mock.MagicMock() + ) as mock_log_info, + ): mock_attach_decorator.data_base64 = mock.MagicMock( return_value=mock_attach_decorator ) @@ -690,13 +699,15 @@ async def test_create_presentation_bad_revoc_state(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ), mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True), + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -776,13 +787,15 @@ async def test_create_presentation_multi_matching_proposal_creds_names(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - test_module, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + test_module, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -921,13 +934,14 @@ async def test_receive_presentation(self): }, ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ), mock.patch.object( - V10PresentationExchange, - "retrieve_by_tag_filter", - mock.CoroutineMock(return_value=exchange_dummy), - ) as retrieve_ex: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True), + mock.patch.object( + V10PresentationExchange, + "retrieve_by_tag_filter", + mock.CoroutineMock(return_value=exchange_dummy), + ) as retrieve_ex, + ): retrieve_ex.side_effect = [exchange_dummy] exchange_out = await self.manager.receive_presentation( PRES, connection_record, None @@ -1024,11 +1038,12 @@ async def test_receive_presentation_oob(self): }, ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ), mock.patch.object( - V10PresentationExchange, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True), + mock.patch.object( + V10PresentationExchange, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [exchange_dummy] exchange_out = await self.manager.receive_presentation(PRES, None, None) assert exchange_out.state == ( @@ -1125,11 +1140,12 @@ async def test_receive_presentation_bait_and_switch(self): }, ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ), mock.patch.object( - V10PresentationExchange, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True), + mock.patch.object( + V10PresentationExchange, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = exchange_dummy with self.assertRaises(PresentationManagerError): await self.manager.receive_presentation(PRES, connection_record, None) @@ -1137,11 +1153,12 @@ async def test_receive_presentation_bait_and_switch(self): async def test_receive_presentation_connectionless(self): exchange_dummy = V10PresentationExchange() - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10PresentationExchange, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + V10PresentationExchange, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = exchange_dummy exchange_out = await self.manager.receive_presentation(PRES, None, None) save_ex.assert_called_once() @@ -1221,11 +1238,12 @@ async def test_receive_presentation_ack_a(self): exchange_dummy = V10PresentationExchange() message = mock.MagicMock() - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10PresentationExchange, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + V10PresentationExchange, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = exchange_dummy exchange_out = await self.manager.receive_presentation_ack( message, connection_record @@ -1242,11 +1260,12 @@ async def test_receive_presentation_ack_b(self): exchange_dummy = V10PresentationExchange() message = mock.MagicMock(_verification_result="true") - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10PresentationExchange, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + V10PresentationExchange, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = exchange_dummy exchange_out = await self.manager.receive_presentation_ack( message, connection_record @@ -1275,17 +1294,19 @@ async def test_receive_problem_report(self): } ) - with mock.patch.object( - V10PresentationExchange, "save", autospec=True - ) as save_ex, mock.patch.object( - V10PresentationExchange, - "retrieve_by_tag_filter", - mock.CoroutineMock(), - ) as retrieve_ex, mock.patch.object( - self.profile, - "session", - mock.MagicMock(return_value=self.profile.session()), - ) as session: + with ( + mock.patch.object(V10PresentationExchange, "save", autospec=True) as save_ex, + mock.patch.object( + V10PresentationExchange, + "retrieve_by_tag_filter", + mock.CoroutineMock(), + ) as retrieve_ex, + mock.patch.object( + self.profile, + "session", + mock.MagicMock(return_value=self.profile.session()), + ) as session, + ): retrieve_ex.return_value = stored_exchange ret_exchange = await self.manager.receive_problem_report( diff --git a/acapy_agent/protocols/present_proof/v1_0/tests/test_routes.py b/acapy_agent/protocols/present_proof/v1_0/tests/test_routes.py index afe923e8be..28c7930443 100644 --- a/acapy_agent/protocols/present_proof/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/present_proof/v1_0/tests/test_routes.py @@ -4,8 +4,10 @@ from marshmallow import ValidationError from .....admin.request_context import AdminRequestContext +from .....anoncreds.models.presentation_request import ( + AnoncredsPresentationReqAttrSpecSchema, +) from .....indy.holder import IndyHolder -from .....indy.models.proof_request import IndyProofReqAttrSpecSchema from .....indy.verifier import IndyVerifier from .....ledger.base import BaseLedger from .....storage.error import StorageNotFoundError @@ -35,7 +37,7 @@ async def asyncSetUp(self): ) async def test_validate_proof_req_attr_spec(self): - aspec = IndyProofReqAttrSpecSchema() + aspec = AnoncredsPresentationReqAttrSpecSchema() aspec.validate_fields({"name": "attr0"}) aspec.validate_fields( { @@ -298,16 +300,20 @@ async def test_presentation_exchange_retrieve_x(self): async def test_presentation_exchange_send_proposal(self): self.request.json = mock.CoroutineMock() - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ), mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.models.pres_preview.IndyPresPreview", - autospec=True, - ) as mock_preview: + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ), + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.models.pres_preview.IndyPresPreview", + autospec=True, + ) as mock_preview, + ): # Since we are mocking import importlib.reload(test_module) @@ -345,18 +351,22 @@ async def test_presentation_exchange_send_proposal_no_conn_record(self): async def test_presentation_exchange_send_proposal_not_ready(self): self.request.json = mock.CoroutineMock() - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.indy.models.pres_preview.IndyPresPreview", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "messages.presentation_proposal.PresentationProposal" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.indy.models.pres_preview.IndyPresPreview", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "messages.presentation_proposal.PresentationProposal" + ), + autospec=True, ), - autospec=True, ): # Since we are mocking import importlib.reload(test_module) @@ -370,15 +380,19 @@ async def test_presentation_exchange_send_proposal_not_ready(self): async def test_presentation_exchange_send_proposal_x(self): self.request.json = mock.CoroutineMock() - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ), mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.models.pres_preview.IndyPresPreview", - autospec=True, + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ), + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.models.pres_preview.IndyPresPreview", + autospec=True, + ), ): # Since we are mocking import importlib.reload(test_module) @@ -400,26 +414,31 @@ async def test_presentation_exchange_create_request(self): return_value={"comment": "dummy", "proof_request": {}} ) - with mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.models.pres_preview.IndyPresPreview", - autospec=True, - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ) as mock_attach_decorator, mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.models.pres_preview.IndyPresPreview", + autospec=True, + ), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ) as mock_attach_decorator, + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange, mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, ): # Since we are mocking import importlib.reload(test_module) @@ -449,26 +468,31 @@ async def test_presentation_exchange_create_request_x(self): return_value={"comment": "dummy", "proof_request": {}} ) - with mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.models.pres_preview.IndyPresPreview", - autospec=True, - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.models.pres_preview.IndyPresPreview", + autospec=True, + ), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ), + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, ), - autospec=True, - ), mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, ): # Since we are mocking import importlib.reload(test_module) @@ -494,30 +518,36 @@ async def test_presentation_exchange_send_free_request(self): } ) - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch( - "acapy_agent.indy.models.pres_preview.IndyPresPreview", - autospec=True, - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ) as mock_attach_decorator, mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange: + mock.patch( + "acapy_agent.indy.models.pres_preview.IndyPresPreview", + autospec=True, + ), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ) as mock_attach_decorator, + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -590,28 +620,32 @@ async def test_presentation_exchange_send_free_request_x(self): } ) - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ) as mock_attach_decorator, mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, + ), + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ) as mock_attach_decorator, + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, ), - autospec=True, ): # Since we are mocking import importlib.reload(test_module) @@ -653,27 +687,33 @@ async def test_presentation_exchange_send_bound_request(self): ), ) - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ) as mock_presentation_request, mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange", - autospec=True, - ) as mock_presentation_exchange: + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, + ), + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch.object( + test_module, "PresentationRequest", autospec=True + ) as mock_presentation_request, + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange", + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -710,29 +750,33 @@ async def test_presentation_exchange_send_bound_request_not_found(self): self.request.json = mock.CoroutineMock(return_value={"trace": False}) self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ), mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange: + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, + ), + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -754,29 +798,33 @@ async def test_presentation_exchange_send_bound_request_not_ready(self): self.request.json = mock.CoroutineMock(return_value={"trace": False}) self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ), mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange: + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, + ), + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -837,29 +885,33 @@ async def test_presentation_exchange_send_bound_request_x(self): self.request.json = mock.CoroutineMock(return_value={"trace": False}) self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange: + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -919,21 +971,24 @@ async def test_presentation_exchange_send_presentation(self): ), ) - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" - ), - autospec=True, - ) as mock_presentation_exchange: + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -985,29 +1040,33 @@ async def test_presentation_exchange_send_presentation_not_found(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ), mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange: + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, + ), + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -1029,29 +1088,33 @@ async def test_presentation_exchange_send_presentation_not_ready(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ), mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange: + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, + ), + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -1103,29 +1166,33 @@ async def test_presentation_exchange_send_presentation_x(self): ) self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch.object( - test_module, "IndyPresPreview", autospec=True - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange: + mock.patch.object(test_module, "IndyPresPreview", autospec=True), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -1156,30 +1223,36 @@ async def test_presentation_exchange_send_presentation_x(self): async def test_presentation_exchange_verify_presentation(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - "acapy_agent.indy.util.generate_pr_nonce", - autospec=True, - ), mock.patch( - "acapy_agent.indy.models.pres_preview.IndyPresPreview", - autospec=True, - ), mock.patch.object( - test_module, "PresentationRequest", autospec=True - ), mock.patch( - "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + "acapy_agent.indy.util.generate_pr_nonce", + autospec=True, ), - autospec=True, - ) as mock_presentation_exchange: + mock.patch( + "acapy_agent.indy.models.pres_preview.IndyPresPreview", + autospec=True, + ), + mock.patch.object(test_module, "PresentationRequest", autospec=True), + mock.patch( + "acapy_agent.messaging.decorators.attach_decorator.AttachDecorator", + autospec=True, + ), + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -1260,19 +1333,23 @@ async def test_presentation_exchange_verify_presentation_x(self): ), ) - with mock.patch( - "acapy_agent.connections.models.conn_record.ConnRecord", - autospec=True, - ) as mock_connection_record, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ) as mock_presentation_manager, mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" - ), - autospec=True, - ) as mock_presentation_exchange: + with ( + mock.patch( + "acapy_agent.connections.models.conn_record.ConnRecord", + autospec=True, + ) as mock_connection_record, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, + ) as mock_presentation_manager, + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_presentation_exchange, + ): # Since we are mocking import importlib.reload(test_module) @@ -1312,20 +1389,23 @@ async def test_presentation_exchange_problem_report(self): self.request.match_info = {"pres_ex_id": "dummy"} magic_report = mock.MagicMock() - with mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_pres_ex, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, ), - autospec=True, - ) as mock_pres_ex, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ), mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ) as mock_problem_report, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + mock.patch.object( + test_module, "problem_report_for_record", mock.MagicMock() + ) as mock_problem_report, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): # Since we are mocking import importlib.reload(test_module) @@ -1345,16 +1425,19 @@ async def test_presentation_exchange_problem_report_bad_pres_ex_id(self): ) self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ), mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, ), - autospec=True, - ) as mock_pres_ex: + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_pres_ex, + ): # Since we are mocking import importlib.reload(test_module) @@ -1369,18 +1452,21 @@ async def test_presentation_exchange_problem_report_x(self): self.request.json = mock.CoroutineMock() self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch( - ( - "acapy_agent.protocols.present_proof.v1_0." - "models.presentation_exchange.V10PresentationExchange" + with ( + mock.patch( + ( + "acapy_agent.protocols.present_proof.v1_0." + "models.presentation_exchange.V10PresentationExchange" + ), + autospec=True, + ) as mock_pres_ex, + mock.patch( + "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", + autospec=True, ), - autospec=True, - ) as mock_pres_ex, mock.patch( - "acapy_agent.protocols.present_proof.v1_0.manager.PresentationManager", - autospec=True, - ), mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ), mock.patch.object(test_module.web, "json_response"): + mock.patch.object(test_module, "problem_report_for_record", mock.MagicMock()), + mock.patch.object(test_module.web, "json_response"), + ): # Since we are mocking import importlib.reload(test_module) mock_pres_ex.retrieve_by_id = mock.CoroutineMock( diff --git a/acapy_agent/protocols/present_proof/v2_0/formats/anoncreds/handler.py b/acapy_agent/protocols/present_proof/v2_0/formats/anoncreds/handler.py index d5618f4a50..2c19d13443 100644 --- a/acapy_agent/protocols/present_proof/v2_0/formats/anoncreds/handler.py +++ b/acapy_agent/protocols/present_proof/v2_0/formats/anoncreds/handler.py @@ -1,4 +1,4 @@ -"""V2.0 present-proof indy presentation-exchange format handler.""" +"""V2.0 present-proof anoncreds presentation-exchange format handler.""" import json import logging @@ -7,12 +7,12 @@ from marshmallow import RAISE from ......anoncreds.holder import AnonCredsHolder +from ......anoncreds.models.predicate import Predicate +from ......anoncreds.models.presentation_request import AnoncredsPresentationRequestSchema +from ......anoncreds.models.proof import AnoncredsProofSchema +from ......anoncreds.models.utils import get_requested_creds_from_proof_request_preview from ......anoncreds.util import generate_pr_nonce from ......anoncreds.verifier import AnonCredsVerifier -from ......indy.models.predicate import Predicate -from ......indy.models.proof import IndyProofSchema -from ......indy.models.proof_request import IndyProofRequestSchema -from ......indy.models.xform import indy_proof_req_preview2indy_requested_creds from ......messaging.decorators.attach_decorator import AttachDecorator from ......messaging.util import canon from ....anoncreds.pres_exch_handler import AnonCredsPresExchHandler @@ -33,7 +33,7 @@ class AnonCredsPresExchangeHandler(V20PresFormatHandler): """Anoncreds presentation format handler.""" - format = V20PresFormat.Format.INDY + format = V20PresFormat.Format.ANONCREDS @classmethod def validate_fields(cls, message_type: str, attachment_data: Mapping): @@ -55,9 +55,9 @@ def validate_fields(cls, message_type: str, attachment_data: Mapping): """ mapping = { - PRES_20_REQUEST: IndyProofRequestSchema, - PRES_20_PROPOSAL: IndyProofRequestSchema, - PRES_20: IndyProofSchema, + PRES_20_REQUEST: AnoncredsPresentationRequestSchema, + PRES_20_PROPOSAL: AnoncredsPresentationRequestSchema, + PRES_20: AnoncredsProofSchema, } # Get schema class @@ -109,20 +109,20 @@ async def create_bound_request( A tuple (updated presentation exchange record, presentation request message) """ - indy_proof_request = pres_ex_record.pres_proposal.attachment( + proof_request = pres_ex_record.pres_proposal.attachment( AnonCredsPresExchangeHandler.format ) if request_data: - indy_proof_request["name"] = request_data.get("name", "proof-request") - indy_proof_request["version"] = request_data.get("version", "1.0") - indy_proof_request["nonce"] = ( + proof_request["name"] = request_data.get("name", "proof-request") + proof_request["version"] = request_data.get("version", "1.0") + proof_request["nonce"] = ( request_data.get("nonce") or await generate_pr_nonce() ) else: - indy_proof_request["name"] = "proof-request" - indy_proof_request["version"] = "1.0" - indy_proof_request["nonce"] = await generate_pr_nonce() - return self.get_format_data(PRES_20_REQUEST, indy_proof_request) + proof_request["name"] = "proof-request" + proof_request["version"] = "1.0" + proof_request["nonce"] = await generate_pr_nonce() + return self.get_format_data(PRES_20_REQUEST, proof_request) async def create_pres( self, @@ -131,45 +131,58 @@ async def create_pres( ) -> Tuple[V20PresFormat, AttachDecorator]: """Create a presentation.""" requested_credentials = {} + + # This is used for the fallback to indy format + from ..indy.handler import IndyPresExchangeHandler + if not request_data: try: proof_request = pres_ex_record.pres_request - indy_proof_request = proof_request.attachment( + # Fall back to indy format should be removed when indy format retired + proof_request = proof_request.attachment( AnonCredsPresExchangeHandler.format - ) - requested_credentials = await indy_proof_req_preview2indy_requested_creds( - indy_proof_request, - preview=None, - holder=AnonCredsHolder(self._profile), + ) or proof_request.attachment(IndyPresExchangeHandler.format) + requested_credentials = ( + await get_requested_creds_from_proof_request_preview( + proof_request, + holder=AnonCredsHolder(self._profile), + ) ) except ValueError as err: LOGGER.warning(f"{err}") - raise V20PresFormatHandlerError( - f"No matching Indy credentials found: {err}" - ) + raise V20PresFormatHandlerError(f"No matching credentials found: {err}") else: - if AnonCredsPresExchangeHandler.format.api in request_data: - indy_spec = request_data.get(AnonCredsPresExchangeHandler.format.api) + # Fall back to indy format should be removed when indy format retired + if ( + AnonCredsPresExchangeHandler.format.api in request_data + or IndyPresExchangeHandler.format.api in request_data + ): + spec = request_data.get( + AnonCredsPresExchangeHandler.format.api + ) or request_data.get(IndyPresExchangeHandler.format.api) requested_credentials = { - "self_attested_attributes": indy_spec["self_attested_attributes"], - "requested_attributes": indy_spec["requested_attributes"], - "requested_predicates": indy_spec["requested_predicates"], + "self_attested_attributes": spec["self_attested_attributes"], + "requested_attributes": spec["requested_attributes"], + "requested_predicates": spec["requested_predicates"], } - indy_handler = AnonCredsPresExchHandler(self._profile) - indy_proof = await indy_handler.return_presentation( + handler = AnonCredsPresExchHandler(self._profile) + presentation_proof = await handler.return_presentation( pres_ex_record=pres_ex_record, requested_credentials=requested_credentials, ) - return self.get_format_data(PRES_20, indy_proof) + return self.get_format_data(PRES_20, presentation_proof) async def receive_pres(self, message: V20Pres, pres_ex_record: V20PresExRecord): """Receive a presentation and check for presented values vs. proposal request.""" def _check_proof_vs_proposal(): """Check for bait and switch in presented values vs. proposal request.""" + from ..indy.handler import IndyPresExchangeHandler + + # Fall back to indy format should be removed when indy format retired proof_req = pres_ex_record.pres_request.attachment( AnonCredsPresExchangeHandler.format - ) + ) or pres_ex_record.pres_request.attachment(IndyPresExchangeHandler.format) # revealed attrs for reft, attr_spec in proof["requested_proof"]["revealed_attrs"].items(): @@ -256,7 +269,8 @@ def _check_proof_vs_proposal(): for req_restriction in req_restrictions: for k in list(req_restriction): # cannot modify en passant if k.startswith("attr::"): - req_restriction.pop(k) # let indy-sdk reject mismatch here + # let anoncreds-sdk reject mismatch here + req_restriction.pop(k) sub_proof_index = pred_spec["sub_proof_index"] for ge_proof in proof["proof"]["proofs"][sub_proof_index][ "primary_proof" @@ -313,10 +327,8 @@ async def verify_pres(self, pres_ex_record: V20PresExRecord) -> V20PresExRecord: """ pres_request_msg = pres_ex_record.pres_request - indy_proof_request = pres_request_msg.attachment( - AnonCredsPresExchangeHandler.format - ) - indy_proof = pres_ex_record.pres.attachment(AnonCredsPresExchangeHandler.format) + proof_request = pres_request_msg.attachment(AnonCredsPresExchangeHandler.format) + proof = pres_ex_record.pres.attachment(AnonCredsPresExchangeHandler.format) verifier = AnonCredsVerifier(self._profile) ( @@ -324,13 +336,13 @@ async def verify_pres(self, pres_ex_record: V20PresExRecord) -> V20PresExRecord: cred_defs, rev_reg_defs, rev_lists, - ) = await verifier.process_pres_identifiers(indy_proof["identifiers"]) + ) = await verifier.process_pres_identifiers(proof["identifiers"]) verifier = AnonCredsVerifier(self._profile) (verified, verified_msgs) = await verifier.verify_presentation( - indy_proof_request, - indy_proof, + proof_request, + proof, schemas, cred_defs, rev_reg_defs, diff --git a/acapy_agent/protocols/present_proof/v2_0/formats/dif/tests/test_handler.py b/acapy_agent/protocols/present_proof/v2_0/formats/dif/tests/test_handler.py index 820fe2771e..2d0f73d59d 100644 --- a/acapy_agent/protocols/present_proof/v2_0/formats/dif/tests/test_handler.py +++ b/acapy_agent/protocols/present_proof/v2_0/formats/dif/tests/test_handler.py @@ -727,17 +727,20 @@ async def test_create_pres_prover_proof_spec_with_record_ids(self): ) self.profile.context.injector.bind_instance(VCHolder, mock_holder) - with mock.patch.object( - DIFPresExchHandler, - "create_vp", - mock.CoroutineMock(), - ) as mock_create_vp, mock.patch.object( - VCHolder, - "search_credentials", - mock.CoroutineMock( - return_value=mock.MagicMock( - fetch=mock.CoroutineMock(return_value=cred_list) - ) + with ( + mock.patch.object( + DIFPresExchHandler, + "create_vp", + mock.CoroutineMock(), + ) as mock_create_vp, + mock.patch.object( + VCHolder, + "search_credentials", + mock.CoroutineMock( + return_value=mock.MagicMock( + fetch=mock.CoroutineMock(return_value=cred_list) + ) + ), ), ): mock_create_vp.return_value = DIF_PRES @@ -2211,11 +2214,12 @@ async def test_verify_received_pres_fail_schema_filter(self): auto_present=True, error_msg="error", ) - with mock.patch.object( - test_module.LOGGER, "error", mock.MagicMock() - ) as mock_log_err, mock.patch.object( - jsonld, "expand", mock.MagicMock() - ) as mock_jsonld_expand: + with ( + mock.patch.object( + test_module.LOGGER, "error", mock.MagicMock() + ) as mock_log_err, + mock.patch.object(jsonld, "expand", mock.MagicMock()) as mock_jsonld_expand, + ): mock_jsonld_expand.return_value = EXPANDED_CRED_FHIR_TYPE_2 await self.handler.receive_pres(message=dif_pres, pres_ex_record=record) mock_log_err.assert_called_once() diff --git a/acapy_agent/protocols/present_proof/v2_0/formats/handler.py b/acapy_agent/protocols/present_proof/v2_0/formats/handler.py index c4abf9d4c2..2a36cc3757 100644 --- a/acapy_agent/protocols/present_proof/v2_0/formats/handler.py +++ b/acapy_agent/protocols/present_proof/v2_0/formats/handler.py @@ -1,7 +1,7 @@ -"""present-proof-v2 format handler - supports DIF and INDY.""" +"""present-proof-v2 format handler - supports ANONCREDS, DIF and INDY.""" import logging -from abc import ABC, abstractclassmethod, abstractmethod +from abc import ABC, abstractmethod from typing import Optional, Tuple from .....core.error import BaseError @@ -56,7 +56,8 @@ def get_format_identifier(self, message_type: str) -> str: def get_format_data(self, message_type: str, data: dict) -> PresFormatAttachment: """Get presentation format and attach objects for use in pres_ex messages.""" - @abstractclassmethod + @classmethod + @abstractmethod def validate_fields(cls, message_type: str, attachment_data: dict) -> None: """Validate attachment data for specific message type and format.""" diff --git a/acapy_agent/protocols/present_proof/v2_0/formats/indy/handler.py b/acapy_agent/protocols/present_proof/v2_0/formats/indy/handler.py index 306ed3b1af..bac3933919 100644 --- a/acapy_agent/protocols/present_proof/v2_0/formats/indy/handler.py +++ b/acapy_agent/protocols/present_proof/v2_0/formats/indy/handler.py @@ -88,9 +88,6 @@ def get_format_identifier(self, message_type: str) -> str: str: Issue credential attachment format identifier """ - # Temporary shim while the new anoncreds library integration is in progress - if self.anoncreds_handler: - return self.anoncreds_handler.get_format_identifier(message_type) return ATTACHMENT_FORMAT[message_type][IndyPresExchangeHandler.format.api] @@ -98,9 +95,6 @@ def get_format_data( self, message_type: str, data: dict ) -> Tuple[V20PresFormat, AttachDecorator]: """Get presentation format and attach objects for use in pres_ex messages.""" - # Temporary shim while the new anoncreds library integration is in progress - if self.anoncreds_handler: - return self.anoncreds_handler.get_format_data(message_type, data) return ( V20PresFormat( @@ -154,9 +148,12 @@ async def create_pres( request_data: Optional[dict] = None, ) -> Tuple[V20PresFormat, AttachDecorator]: """Create a presentation.""" - # Temporary shim while the new anoncreds library integration is in progress + if self.anoncreds_handler: - return await self.anoncreds_handler.create_pres(pres_ex_record, request_data) + return await self.anoncreds_handler.create_pres( + pres_ex_record, + request_data, + ) requested_credentials = {} if not request_data: @@ -349,8 +346,14 @@ async def verify_pres(self, pres_ex_record: V20PresExRecord) -> V20PresExRecord: return await self.anoncreds_handler.verify_pres(pres_ex_record) pres_request_msg = pres_ex_record.pres_request - indy_proof_request = pres_request_msg.attachment(IndyPresExchangeHandler.format) - indy_proof = pres_ex_record.pres.attachment(IndyPresExchangeHandler.format) + + # The `or` anoncreds format is for the indy <--> anoncreds compatibility + indy_proof_request = pres_request_msg.attachment( + IndyPresExchangeHandler.format + ) or pres_request_msg.attachment(AnonCredsPresExchangeHandler.format) + indy_proof = pres_ex_record.pres.attachment( + IndyPresExchangeHandler.format + ) or pres_ex_record.pres.attachment(AnonCredsPresExchangeHandler.format) indy_handler = IndyPresExchHandler(self._profile) ( schemas, diff --git a/acapy_agent/protocols/present_proof/v2_0/handlers/pres_problem_report_handler.py b/acapy_agent/protocols/present_proof/v2_0/handlers/pres_problem_report_handler.py index be4aab8620..e10df27e2e 100644 --- a/acapy_agent/protocols/present_proof/v2_0/handlers/pres_problem_report_handler.py +++ b/acapy_agent/protocols/present_proof/v2_0/handlers/pres_problem_report_handler.py @@ -34,7 +34,11 @@ async def handle(self, context: RequestContext, responder: BaseResponder): else None ), ) - except (StorageError, StorageNotFoundError): + except StorageNotFoundError: + self._logger.warning( + "Record not found while processing present-proof v2.0 problem report" + ) + except StorageError: self._logger.exception( - "Error processing present-proof v2.0 problem report message" + "Storage error while processing present-proof v2.0 problem report" ) diff --git a/acapy_agent/protocols/present_proof/v2_0/handlers/tests/test_pres_request_handler.py b/acapy_agent/protocols/present_proof/v2_0/handlers/tests/test_pres_request_handler.py index 0168fa6a36..bbce190491 100644 --- a/acapy_agent/protocols/present_proof/v2_0/handlers/tests/test_pres_request_handler.py +++ b/acapy_agent/protocols/present_proof/v2_0/handlers/tests/test_pres_request_handler.py @@ -220,11 +220,14 @@ async def test_called(self): auto_present=True, ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance ) @@ -261,11 +264,14 @@ async def test_called_not_found(self): auto_present=True, ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( side_effect=StorageNotFoundError ) @@ -304,11 +310,14 @@ async def test_called_auto_present_x_indy(self): save_error_state=mock.CoroutineMock(), ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = mock_px_rec mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock_px_rec @@ -347,11 +356,14 @@ async def test_called_auto_present_x_anoncreds(self): save_error_state=mock.CoroutineMock(), ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = mock_px_rec mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock_px_rec @@ -389,11 +401,14 @@ async def test_called_auto_present_indy(self): auto_present=True, ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = mock_px_rec mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock_px_rec @@ -463,11 +478,14 @@ async def test_called_auto_present_anoncreds(self): auto_present=True, ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = mock_px_rec mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock_px_rec @@ -526,11 +544,14 @@ async def test_called_auto_present_dif(self): pres_proposal=pres_proposal, auto_present=True, ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -585,11 +606,14 @@ async def test_called_auto_present_no_preview_indy(self): ) self.request_context.injector.bind_instance(IndyHolder, self.mock_holder) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -644,11 +668,14 @@ async def test_called_auto_present_no_preview_anoncreds(self): ) self.request_context.injector.bind_instance(AnonCredsHolder, self.mock_holder) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -704,11 +731,14 @@ async def test_called_auto_present_pred_no_match_indy(self): ) self.request_context.injector.bind_instance(IndyHolder, self.mock_holder) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = mock_px_rec mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock_px_rec @@ -760,11 +790,14 @@ async def test_called_auto_present_pred_no_match_anoncreds(self): ) self.request_context.injector.bind_instance(AnonCredsHolder, self.mock_holder) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = mock_px_rec mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=mock_px_rec @@ -810,11 +843,14 @@ async def test_called_auto_present_pred_single_match_indy(self): ) self.request_context.injector.bind_instance(IndyHolder, self.mock_holder) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -864,11 +900,14 @@ async def test_called_auto_present_pred_single_match_anoncreds(self): ) self.request_context.injector.bind_instance(AnonCredsHolder, self.mock_holder) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -923,11 +962,14 @@ async def test_called_auto_present_pred_multi_match_indy(self): ) self.request_context.injector.bind_instance(IndyHolder, self.mock_holder) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -982,11 +1024,14 @@ async def test_called_auto_present_pred_multi_match_anoncreds(self): ) self.request_context.injector.bind_instance(AnonCredsHolder, self.mock_holder) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -1084,11 +1129,14 @@ async def test_called_auto_present_multi_cred_match_reft_indy(self): pres_proposal=pres_proposal.serialize(), auto_present=True, ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance @@ -1186,11 +1234,14 @@ async def test_called_auto_present_multi_cred_match_reft_anoncreds(self): pres_proposal=pres_proposal.serialize(), auto_present=True, ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + ): mock_pres_ex_rec_cls.return_value = px_rec_instance mock_pres_ex_rec_cls.retrieve_by_tag_filter = mock.CoroutineMock( return_value=px_rec_instance diff --git a/acapy_agent/protocols/present_proof/v2_0/message_types.py b/acapy_agent/protocols/present_proof/v2_0/message_types.py index 97b8f063fc..3c24ef7d72 100644 --- a/acapy_agent/protocols/present_proof/v2_0/message_types.py +++ b/acapy_agent/protocols/present_proof/v2_0/message_types.py @@ -32,14 +32,17 @@ # Format specifications ATTACHMENT_FORMAT = { PRES_20_PROPOSAL: { + V20PresFormat.Format.ANONCREDS.api: "anoncreds/proof-proposal@v1.0", V20PresFormat.Format.INDY.api: "hlindy/proof-req@v2.0", V20PresFormat.Format.DIF.api: "dif/presentation-exchange/definitions@v1.0", }, PRES_20_REQUEST: { + V20PresFormat.Format.ANONCREDS.api: "anoncreds/proof-request@v1.0", V20PresFormat.Format.INDY.api: "hlindy/proof-req@v2.0", V20PresFormat.Format.DIF.api: "dif/presentation-exchange/definitions@v1.0", }, PRES_20: { + V20PresFormat.Format.ANONCREDS.api: "anoncreds/proof@v1.0", V20PresFormat.Format.INDY.api: "hlindy/proof@v2.0", V20PresFormat.Format.DIF.api: "dif/presentation-exchange/submission@v1.0", }, diff --git a/acapy_agent/protocols/present_proof/v2_0/messages/pres_format.py b/acapy_agent/protocols/present_proof/v2_0/messages/pres_format.py index 5c55384c86..e65e98644f 100644 --- a/acapy_agent/protocols/present_proof/v2_0/messages/pres_format.py +++ b/acapy_agent/protocols/present_proof/v2_0/messages/pres_format.py @@ -30,6 +30,13 @@ class Meta: class Format(Enum): """Attachment format.""" + ANONCREDS = FormatSpec( + "anoncreds/", + DeferLoad( + "acapy_agent.protocols.present_proof.v2_0" + ".formats.anoncreds.handler.AnonCredsPresExchangeHandler" + ), + ) INDY = FormatSpec( "hlindy/", DeferLoad( @@ -37,19 +44,6 @@ class Format(Enum): ".formats.indy.handler.IndyPresExchangeHandler" ), ) - """ - To make the switch from indy to anoncreds replace the above with the following. - - :: - - INDY = FormatSpec( - "hlindy/", - DeferLoad( - "acapy_agent.protocols.present_proof.v2_0" - ".formats.anoncreds.handler.AnonCredsPresExchangeHandler" - ), - ) - """ DIF = FormatSpec( "dif/", DeferLoad( diff --git a/acapy_agent/protocols/present_proof/v2_0/models/tests/test_record.py b/acapy_agent/protocols/present_proof/v2_0/models/tests/test_record.py index ee0255e9a6..eafd51d68c 100644 --- a/acapy_agent/protocols/present_proof/v2_0/models/tests/test_record.py +++ b/acapy_agent/protocols/present_proof/v2_0/models/tests/test_record.py @@ -124,11 +124,12 @@ async def test_save_error_state(self): record.state = V20PresExRecord.STATE_PROPOSAL_RECEIVED await record.save(session) - with mock.patch.object( - record, "save", mock.CoroutineMock() - ) as mock_save, mock.patch.object( - test_module.LOGGER, "exception", mock.MagicMock() - ) as mock_log_exc: + with ( + mock.patch.object(record, "save", mock.CoroutineMock()) as mock_save, + mock.patch.object( + test_module.LOGGER, "exception", mock.MagicMock() + ) as mock_log_exc, + ): mock_save.side_effect = test_module.StorageError() await record.save_error_state(session, reason="testing") mock_log_exc.assert_called_once() diff --git a/acapy_agent/protocols/present_proof/v2_0/routes.py b/acapy_agent/protocols/present_proof/v2_0/routes.py index 76fe68c1f6..b428226aa5 100644 --- a/acapy_agent/protocols/present_proof/v2_0/routes.py +++ b/acapy_agent/protocols/present_proof/v2_0/routes.py @@ -16,6 +16,7 @@ from ....admin.decorators.auth import tenant_authentication from ....admin.request_context import AdminRequestContext from ....anoncreds.holder import AnonCredsHolder, AnonCredsHolderError +from ....anoncreds.models.presentation_request import AnoncredsPresentationRequestSchema from ....connections.models.conn_record import ConnRecord from ....indy.holder import IndyHolder, IndyHolderError from ....indy.models.cred_precis import IndyCredPrecisSchema @@ -116,6 +117,11 @@ class V20PresExRecordListSchema(OpenAPISchema): class V20PresProposalByFormatSchema(OpenAPISchema): """Schema for presentation proposal per format.""" + anoncreds = fields.Nested( + AnoncredsPresentationRequestSchema, + required=False, + metadata={"description": "Presentation proposal for anoncreds"}, + ) indy = fields.Nested( IndyProofRequestSchema, required=False, @@ -190,6 +196,11 @@ class V20PresProposalRequestSchema(AdminAPIMessageTracingSchema): class V20PresRequestByFormatSchema(OpenAPISchema): """Presentation request per format.""" + anoncreds = fields.Nested( + AnoncredsPresentationRequestSchema, + required=False, + metadata={"description": "Presentation proposal for anoncreds"}, + ) indy = fields.Nested( IndyProofRequestSchema, required=False, @@ -291,6 +302,11 @@ class V20PresentationSendRequestToProposalSchema(AdminAPIMessageTracingSchema): class V20PresSpecByFormatRequestSchema(AdminAPIMessageTracingSchema): """Presentation specification schema by format, for send-presentation request.""" + anoncreds = fields.Nested( + IndyPresSpecSchema, + required=False, + metadata={"description": "Presentation specification for anoncreds"}, + ) indy = fields.Nested( IndyPresSpecSchema, required=False, @@ -425,7 +441,10 @@ def _formats_attach(by_format: Mapping, msg_type: str, spec: str) -> Mapping: """Break out formats and proposals/requests/presentations for v2.0 messages.""" attach = [] for fmt_api, item_by_fmt in by_format.items(): - if fmt_api == V20PresFormat.Format.INDY.api: + if ( + fmt_api == V20PresFormat.Format.ANONCREDS.api + or fmt_api == V20PresFormat.Format.INDY.api + ): attach.append(AttachDecorator.data_base64(mapping=item_by_fmt, ident=fmt_api)) elif fmt_api == V20PresFormat.Format.DIF.api: attach.append(AttachDecorator.data_json(mapping=item_by_fmt, ident=fmt_api)) @@ -582,19 +601,24 @@ async def present_proof_credentials_list(request: web.BaseRequest): wallet_type = profile.settings.get_value("wallet.type") if wallet_type == "askar-anoncreds": - indy_holder = AnonCredsHolder(profile) + holder = AnonCredsHolder(profile) else: - indy_holder = profile.inject(IndyHolder) - indy_credentials = [] - # INDY + holder = profile.inject(IndyHolder) + credentials = [] + # ANONCREDS or INDY try: - indy_pres_request = pres_ex_record.by_format["pres_request"].get( - V20PresFormat.Format.INDY.api + # try anoncreds and fallback to indy + pres_request = pres_ex_record.by_format["pres_request"].get( + V20PresFormat.Format.ANONCREDS.api ) - if indy_pres_request: - indy_credentials = ( - await indy_holder.get_credentials_for_presentation_request_by_referent( - indy_pres_request, + if not pres_request: + pres_request = pres_ex_record.by_format["pres_request"].get( + V20PresFormat.Format.INDY.api + ) + if pres_request: + credentials = ( + await holder.get_credentials_for_presentation_request_by_referent( + pres_request, pres_referents, offset=offset, limit=limit, @@ -796,7 +820,7 @@ async def present_proof_credentials_list(request: web.BaseRequest): pres_ex_record, outbound_handler, ) - credentials = list(indy_credentials) + dif_cred_value_list + credentials = list(credentials) + dif_cred_value_list return web.json_response(credentials) @@ -936,8 +960,11 @@ async def present_proof_create_request(request: web.BaseRequest): comment = body.get("comment") pres_request_spec = body.get("presentation_request") - if pres_request_spec and V20PresFormat.Format.INDY.api in pres_request_spec: - await _add_nonce(pres_request_spec[V20PresFormat.Format.INDY.api]) + if pres_request_spec: + if V20PresFormat.Format.INDY.api in pres_request_spec: + await _add_nonce(pres_request_spec[V20PresFormat.Format.INDY.api]) + if V20PresFormat.Format.ANONCREDS.api in pres_request_spec: + await _add_nonce(pres_request_spec[V20PresFormat.Format.ANONCREDS.api]) pres_request_message = V20PresRequest( comment=comment, @@ -1020,8 +1047,11 @@ async def present_proof_send_free_request(request: web.BaseRequest): comment = body.get("comment") pres_request_spec = body.get("presentation_request") - if pres_request_spec and V20PresFormat.Format.INDY.api in pres_request_spec: - await _add_nonce(pres_request_spec[V20PresFormat.Format.INDY.api]) + if pres_request_spec: + if V20PresFormat.Format.INDY.api in pres_request_spec: + await _add_nonce(pres_request_spec[V20PresFormat.Format.INDY.api]) + if V20PresFormat.Format.ANONCREDS.api in pres_request_spec: + await _add_nonce(pres_request_spec[V20PresFormat.Format.ANONCREDS.api]) pres_request_message = V20PresRequest( comment=comment, will_confirm=True, @@ -1182,7 +1212,7 @@ async def present_proof_send_presentation(request: web.BaseRequest): outbound_handler = request["outbound_message_router"] pres_ex_id = request.match_info["pres_ex_id"] body = await request.json() - supported_formats = ["dif", "indy"] + supported_formats = ["anoncreds", "dif", "indy"] if not any(x in body for x in supported_formats): raise web.HTTPBadRequest( reason=( diff --git a/acapy_agent/protocols/present_proof/v2_0/tests/test_manager.py b/acapy_agent/protocols/present_proof/v2_0/tests/test_manager.py index 94a6ee2966..ccc823dabf 100644 --- a/acapy_agent/protocols/present_proof/v2_0/tests/test_manager.py +++ b/acapy_agent/protocols/present_proof/v2_0/tests/test_manager.py @@ -512,9 +512,10 @@ async def test_create_exchange_for_proposal(self): ] ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object(V20PresProposal, "serialize", autospec=True): + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object(V20PresProposal, "serialize", autospec=True), + ): px_rec = await self.manager.create_exchange_for_proposal( CONN_ID, proposal, @@ -704,11 +705,14 @@ async def test_receive_pres_catch_diferror(self): pres_request=pres_req.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object( - DIFPresFormatHandler, "receive_pres", autospec=True - ) as mock_receive_pres, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object( + DIFPresFormatHandler, "receive_pres", autospec=True + ) as mock_receive_pres, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): mock_receive_pres.return_value = False retrieve_ex.side_effect = [px_rec] with self.assertRaises(V20PresManagerError) as context: @@ -776,13 +780,15 @@ async def test_create_pres_indy(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -830,15 +836,18 @@ async def test_create_pres_indy_and_dif(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator_indy, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr, mock.patch.object( - DIFPresFormatHandler, "create_pres", autospec=True - ) as mock_create_pres: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator_indy, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + mock.patch.object( + DIFPresFormatHandler, "create_pres", autospec=True + ) as mock_create_pres, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator_indy.data_base64 = mock.MagicMock( @@ -891,17 +900,20 @@ async def test_create_pres_proof_req_non_revoc_interval_none(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -943,13 +955,15 @@ async def test_create_pres_self_asserted(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -1021,13 +1035,15 @@ async def test_create_pres_no_revocation(self): self.holder.create_presentation = mock.CoroutineMock(return_value="{}") self.profile.context.injector.bind_instance(IndyHolder, self.holder) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module.LOGGER, "info", mock.MagicMock() - ) as mock_log_info: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module.LOGGER, "info", mock.MagicMock() + ) as mock_log_info, + ): mock_attach_decorator.data_base64 = mock.MagicMock( return_value=mock_attach_decorator ) @@ -1116,12 +1132,15 @@ async def test_create_pres_bad_revoc_state(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr, mock.patch.object( - test_indy_util_module.LOGGER, "error", mock.MagicMock() + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + mock.patch.object(test_indy_util_module.LOGGER, "error", mock.MagicMock()), ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) @@ -1203,13 +1222,15 @@ async def test_create_pres_multi_matching_proposal_creds_names(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -1287,9 +1308,12 @@ async def test_no_matching_creds_indy_handler(self): get_creds = mock.CoroutineMock(return_value=()) self.holder.get_credentials_for_presentation_request_by_referent = get_creds - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + ): mock_attach_decorator.data_base64 = mock.MagicMock( return_value=mock_attach_decorator ) @@ -1352,11 +1376,12 @@ async def test_receive_pres(self): assert by_format.get("pres_proposal").get("indy") == INDY_PROOF_REQ_NAME assert by_format.get("pres_request").get("indy") == INDY_PROOF_REQ_NAME - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [px_rec_dummy] px_rec_out = await self.manager.receive_pres(pres, connection_record, None) assert retrieve_ex.call_args.args[1] == {"thread_id": "thread-id"} @@ -1421,11 +1446,12 @@ async def test_receive_pres_receive_pred_value_mismatch_punt_to_indy(self): assert by_format.get("pres_proposal").get("indy") == INDY_PROOF_REQ_NAME assert by_format.get("pres_request").get("indy") == indy_proof_req - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [px_rec_dummy] px_rec_out = await self.manager.receive_pres(pres, connection_record, None) assert retrieve_ex.call_args.args[1] == {"thread_id": "thread-id"} @@ -1497,11 +1523,12 @@ async def test_receive_pres_indy_no_predicate_restrictions(self): assert by_format.get("pres_request").get("indy") == indy_proof_req - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [px_rec_dummy] px_rec_out = await self.manager.receive_pres(pres, connection_record, None) assert retrieve_ex.call_args.args[1] == {"thread_id": "thread-id"} @@ -1569,11 +1596,12 @@ async def test_receive_pres_indy_no_attr_restrictions(self): assert by_format.get("pres_request").get("indy") == indy_proof_req - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [px_rec_dummy] px_rec_out = await self.manager.receive_pres(pres, connection_record, None) assert retrieve_ex.call_args.args[1] == {"thread_id": "thread-id"} @@ -1630,9 +1658,12 @@ async def test_receive_pres_bait_and_switch_attr_name(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1678,9 +1709,12 @@ async def test_receive_pres_bait_and_switch_attr_name(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1733,9 +1767,12 @@ async def test_receive_pres_bait_and_switch_attr_names(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1785,9 +1822,12 @@ async def test_receive_pres_bait_and_switch_attr_names(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1838,9 +1878,12 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1890,9 +1933,12 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1942,9 +1988,12 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1994,9 +2043,12 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -2036,11 +2088,14 @@ async def test_verify_pres(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + ): px_rec_out = await self.manager.verify_pres(px_rec_in) save_ex.assert_called_once() @@ -2096,32 +2151,40 @@ async def test_verify_pres_indy_and_dif(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + ): px_rec_out = await self.manager.verify_pres(px_rec_in) save_ex.assert_called_once() assert px_rec_out.state == (V20PresExRecord.STATE_DONE) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch( - "acapy_agent.vc.vc_ld.verify.verify_presentation", - mock.CoroutineMock( - return_value=PresentationVerificationResult(verified=False) + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), ), - ), mock.patch.object( - IndyVerifier, - "verify_presentation", - mock.CoroutineMock( - return_value=PresentationVerificationResult(verified=True) + mock.patch( + "acapy_agent.vc.vc_ld.verify.verify_presentation", + mock.CoroutineMock( + return_value=PresentationVerificationResult(verified=False) + ), + ), + mock.patch.object( + IndyVerifier, + "verify_presentation", + mock.CoroutineMock( + return_value=PresentationVerificationResult(verified=True) + ), ), - ), mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex: + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + ): px_rec_out = await self.manager.verify_pres(px_rec_in) save_ex.assert_called_once() assert px_rec_out.state == (V20PresExRecord.STATE_DONE) @@ -2167,11 +2230,12 @@ async def test_receive_pres_ack_a(self): px_rec_dummy = V20PresExRecord() message = mock.MagicMock() - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy px_rec_out = await self.manager.receive_pres_ack(message, conn_record) save_ex.assert_called_once() @@ -2184,11 +2248,12 @@ async def test_receive_pres_ack_b(self): px_rec_dummy = V20PresExRecord() message = mock.MagicMock(_verification_result="true") - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy px_rec_out = await self.manager.receive_pres_ack(message, conn_record) save_ex.assert_called_once() @@ -2213,17 +2278,19 @@ async def test_receive_problem_report(self): } ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, - "retrieve_by_tag_filter", - mock.CoroutineMock(), - ) as retrieve_ex, mock.patch.object( - self.profile, - "session", - mock.MagicMock(return_value=self.profile.session()), - ) as session: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, + "retrieve_by_tag_filter", + mock.CoroutineMock(), + ) as retrieve_ex, + mock.patch.object( + self.profile, + "session", + mock.MagicMock(return_value=self.profile.session()), + ) as session, + ): retrieve_ex.return_value = stored_exchange await self.manager.receive_problem_report(problem, connection_id) diff --git a/acapy_agent/protocols/present_proof/v2_0/tests/test_manager_anoncreds.py b/acapy_agent/protocols/present_proof/v2_0/tests/test_manager_anoncreds.py index 0ee4f1ad38..9f88377968 100644 --- a/acapy_agent/protocols/present_proof/v2_0/tests/test_manager_anoncreds.py +++ b/acapy_agent/protocols/present_proof/v2_0/tests/test_manager_anoncreds.py @@ -74,7 +74,7 @@ ) ], ) -INDY_PROOF_REQ_NAME = { +ANONCREDS_PROOF_REQ_NAME = { "name": PROOF_REQ_NAME, "version": PROOF_REQ_VERSION, "nonce": PROOF_REQ_NONCE, @@ -100,7 +100,7 @@ } }, } -INDY_PROOF_REQ_NAMES = { +ANONCREDS_PROOF_REQ_NAMES = { "name": PROOF_REQ_NAME, "version": PROOF_REQ_VERSION, "nonce": PROOF_REQ_NONCE, @@ -121,7 +121,7 @@ } }, } -INDY_PROOF_REQ_SELFIE = { +ANONCREDS_PROOF_REQ_SELFIE = { "name": PROOF_REQ_NAME, "version": PROOF_REQ_VERSION, "nonce": PROOF_REQ_NONCE, @@ -133,7 +133,7 @@ "0_highscore_GE_uuid": {"name": "highScore", "p_type": ">=", "p_value": 1000000} }, } -INDY_PROOF = { +ANONCREDS_PROOF = { "proof": { "proofs": [ { @@ -252,7 +252,7 @@ } ], } -INDY_PROOF_NAMES = { +ANONCREDS_PROOF_NAMES = { "proof": { "proofs": [ { @@ -512,13 +512,16 @@ async def test_record_eq(self): async def test_create_exchange_for_proposal(self): proposal = V20PresProposal( formats=[ - V20PresFormat(attach_id="indy", format_=V20PresFormat.Format.INDY.aries) + V20PresFormat( + attach_id="anoncreds", format_=V20PresFormat.Format.ANONCREDS.aries + ) ] ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object(V20PresProposal, "serialize", autospec=True): + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object(V20PresProposal, "serialize", autospec=True), + ): px_rec = await self.manager.create_exchange_for_proposal( CONN_ID, proposal, @@ -537,7 +540,9 @@ async def test_receive_proposal(self): connection_record = mock.MagicMock(connection_id=CONN_ID) proposal = V20PresProposal( formats=[ - V20PresFormat(attach_id="indy", format_=V20PresFormat.Format.INDY.aries) + V20PresFormat( + attach_id="anoncreds", format_=V20PresFormat.Format.ANONCREDS.aries + ) ] ) with mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex: @@ -555,14 +560,14 @@ async def test_create_bound_request_a(self): proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], proposals_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) px_rec = V20PresExRecord( @@ -589,14 +594,14 @@ async def test_create_bound_request_b(self): proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], proposals_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) px_rec = V20PresExRecord( @@ -708,11 +713,14 @@ async def test_receive_pres_catch_diferror(self): pres_request=pres_req.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object( - DIFPresFormatHandler, "receive_pres", autospec=True - ) as mock_receive_pres, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object( + DIFPresFormatHandler, "receive_pres", autospec=True + ) as mock_receive_pres, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): mock_receive_pres.return_value = False retrieve_ex.side_effect = [px_rec] with self.assertRaises(V20PresManagerError) as context: @@ -725,14 +733,16 @@ async def test_create_exchange_for_request(self): will_confirm=True, formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(mapping=INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64( + mapping=ANONCREDS_PROOF_REQ_NAME, ident="anoncreds" + ) ], ) pres_req.assign_thread_id("dummy") @@ -765,14 +775,14 @@ async def test_create_pres_indy(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) px_rec_in = V20PresExRecord(pres_request=pres_request.serialize()) @@ -781,13 +791,15 @@ async def test_create_pres_indy(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -795,9 +807,9 @@ async def test_create_pres_indy(self): ) req_creds = await indy_proof_req_preview2indy_requested_creds( - INDY_PROOF_REQ_NAME, preview=None, holder=self.holder + ANONCREDS_PROOF_REQ_NAME, preview=None, holder=self.holder ) - request_data = {"indy": req_creds} + request_data = {"anoncreds": req_creds} assert not req_creds["self_attested_attributes"] assert len(req_creds["requested_attributes"]) == 2 assert len(req_creds["requested_predicates"]) == 1 @@ -813,9 +825,9 @@ async def test_create_pres_indy_and_dif(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ), V20PresFormat( @@ -826,7 +838,7 @@ async def test_create_pres_indy_and_dif(self): ), ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy"), + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds"), AttachDecorator.data_json(DIF_PRES_REQ, ident="dif"), ], ) @@ -836,15 +848,18 @@ async def test_create_pres_indy_and_dif(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator_indy, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr, mock.patch.object( - DIFPresFormatHandler, "create_pres", autospec=True - ) as mock_create_pres: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator_indy, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + mock.patch.object( + DIFPresFormatHandler, "create_pres", autospec=True + ) as mock_create_pres, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator_indy.data_base64 = mock.MagicMock( @@ -857,9 +872,9 @@ async def test_create_pres_indy_and_dif(self): ) req_creds = await indy_proof_req_preview2indy_requested_creds( - INDY_PROOF_REQ_NAME, preview=None, holder=self.holder + ANONCREDS_PROOF_REQ_NAME, preview=None, holder=self.holder ) - request_data = {"indy": req_creds, "dif": DIF_PRES_REQ} + request_data = {"anoncreds": req_creds, "dif": DIF_PRES_REQ} assert not req_creds["self_attested_attributes"] assert len(req_creds["requested_attributes"]) == 2 assert len(req_creds["requested_predicates"]) == 1 @@ -872,19 +887,19 @@ async def test_create_pres_indy_and_dif(self): @pytest.mark.skip(reason="Anoncreds-break") async def test_create_pres_proof_req_non_revoc_interval_none(self): - indy_proof_req_vcx = deepcopy(INDY_PROOF_REQ_NAME) + indy_proof_req_vcx = deepcopy(ANONCREDS_PROOF_REQ_NAME) indy_proof_req_vcx["non_revoked"] = None # simulate interop with indy-vcx pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req_vcx, ident="indy") + AttachDecorator.data_base64(indy_proof_req_vcx, ident="anoncreds") ], ) px_rec_in = V20PresExRecord(pres_request=pres_request.serialize()) @@ -898,17 +913,20 @@ async def test_create_pres_proof_req_non_revoc_interval_none(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -918,7 +936,7 @@ async def test_create_pres_proof_req_non_revoc_interval_none(self): req_creds = await indy_proof_req_preview2indy_requested_creds( indy_proof_req_vcx, preview=None, holder=self.holder ) - request_data = {"indy": req_creds} + request_data = {"anoncreds": req_creds} assert not req_creds["self_attested_attributes"] assert len(req_creds["requested_attributes"]) == 2 assert len(req_creds["requested_predicates"]) == 1 @@ -934,14 +952,14 @@ async def test_create_pres_self_asserted(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_SELFIE, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_SELFIE, ident="anoncreds") ], ) px_rec_in = V20PresExRecord(pres_request=pres_request.serialize()) @@ -951,13 +969,15 @@ async def test_create_pres_self_asserted(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -965,9 +985,9 @@ async def test_create_pres_self_asserted(self): ) req_creds = await indy_proof_req_preview2indy_requested_creds( - INDY_PROOF_REQ_SELFIE, preview=None, holder=self.holder + ANONCREDS_PROOF_REQ_SELFIE, preview=None, holder=self.holder ) - request_data = {"indy": req_creds} + request_data = {"anoncreds": req_creds} assert len(req_creds["self_attested_attributes"]) == 3 assert not req_creds["requested_attributes"] @@ -991,14 +1011,14 @@ async def test_create_pres_no_revocation(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) px_rec_in = V20PresExRecord(pres_request=pres_request.serialize()) @@ -1030,22 +1050,24 @@ async def test_create_pres_no_revocation(self): self.holder.create_presentation = mock.AsyncMock(return_value="{}") self.profile.context.injector.bind_instance(AnonCredsHolder, self.holder) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module.LOGGER, "info", mock.MagicMock() - ) as mock_log_info: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module.LOGGER, "info", mock.MagicMock() + ) as mock_log_info, + ): mock_attach_decorator.data_base64 = mock.MagicMock( return_value=mock_attach_decorator ) req_creds = await indy_proof_req_preview2indy_requested_creds( - INDY_PROOF_REQ_NAME, preview=None, holder=self.holder + ANONCREDS_PROOF_REQ_NAME, preview=None, holder=self.holder ) request_data = { - "indy": { + "anoncreds": { "self_attested_attributes": req_creds["self_attested_attributes"], "requested_attributes": req_creds["requested_attributes"], "requested_predicates": req_creds["requested_predicates"], @@ -1062,7 +1084,7 @@ async def test_create_pres_no_revocation(self): for pred_reft_spec in req_creds["requested_predicates"].values(): pred_reft_spec["timestamp"] = 1234567890 request_data = { - "indy": { + "anoncreds": { "self_attested_attributes": req_creds["self_attested_attributes"], "requested_attributes": req_creds["requested_attributes"], "requested_predicates": req_creds["requested_predicates"], @@ -1076,14 +1098,14 @@ async def test_create_pres_bad_revoc_state(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) px_rec_in = V20PresExRecord(pres_request=pres_request.serialize()) @@ -1126,12 +1148,15 @@ async def test_create_pres_bad_revoc_state(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr, mock.patch.object( - test_indy_util_module.LOGGER, "error", mock.MagicMock() + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + mock.patch.object(test_indy_util_module.LOGGER, "error", mock.MagicMock()), ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) @@ -1147,14 +1172,14 @@ async def test_create_pres_multi_matching_proposal_creds_names(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAMES, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAMES, ident="anoncreds") ], ) px_rec_in = V20PresExRecord(pres_request=pres_request.serialize()) @@ -1214,13 +1239,15 @@ async def test_create_pres_multi_matching_proposal_creds_names(self): return_value="/tmp/sample/tails/path" ) ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator, mock.patch.object( - test_indy_util_module, "RevocationRegistry", autospec=True - ) as mock_rr: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + mock.patch.object( + test_indy_util_module, "RevocationRegistry", autospec=True + ) as mock_rr, + ): mock_rr.from_definition = mock.MagicMock(return_value=more_magic_rr) mock_attach_decorator.data_base64 = mock.MagicMock( @@ -1228,12 +1255,12 @@ async def test_create_pres_multi_matching_proposal_creds_names(self): ) req_creds = await indy_proof_req_preview2indy_requested_creds( - INDY_PROOF_REQ_NAMES, preview=None, holder=self.holder + ANONCREDS_PROOF_REQ_NAMES, preview=None, holder=self.holder ) assert not req_creds["self_attested_attributes"] assert len(req_creds["requested_attributes"]) == 1 assert len(req_creds["requested_predicates"]) == 1 - request_data = {"indy": req_creds} + request_data = {"anoncreds": req_creds} (px_rec_out, pres_msg) = await self.manager.create_pres( px_rec_in, request_data ) @@ -1244,14 +1271,14 @@ async def test_no_matching_creds_for_proof_req(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAMES, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAMES, ident="anoncreds") ], ) V20PresExRecord(pres_request=pres_request.serialize()) @@ -1260,7 +1287,7 @@ async def test_no_matching_creds_for_proof_req(self): with self.assertRaises(ValueError): await indy_proof_req_preview2indy_requested_creds( - INDY_PROOF_REQ_NAMES, preview=None, holder=self.holder + ANONCREDS_PROOF_REQ_NAMES, preview=None, holder=self.holder ) get_creds = mock.CoroutineMock( @@ -1277,30 +1304,33 @@ async def test_no_matching_creds_for_proof_req(self): ) self.holder.get_credentials_for_presentation_request_by_referent = get_creds await indy_proof_req_preview2indy_requested_creds( - INDY_PROOF_REQ_NAMES, preview=None, holder=self.holder + ANONCREDS_PROOF_REQ_NAMES, preview=None, holder=self.holder ) async def test_no_matching_creds_indy_handler(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAMES, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAMES, ident="anoncreds") ], ) px_rec_in = V20PresExRecord(pres_request=pres_request.serialize()) get_creds = mock.CoroutineMock(return_value=()) self.holder.get_credentials_for_presentation_request_by_referent = get_creds - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - test_indy_handler, "AttachDecorator", autospec=True - ) as mock_attach_decorator: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + test_indy_handler, "AttachDecorator", autospec=True + ) as mock_attach_decorator, + ): mock_attach_decorator.data_base64 = mock.MagicMock( return_value=mock_attach_decorator ) @@ -1311,44 +1341,50 @@ async def test_no_matching_creds_indy_handler(self): (px_rec_out, pres_msg) = await self.manager.create_pres( px_rec_in, request_data ) - assert "No matching Indy" in str(context.exception) + assert "AnonCreds interface requires AskarAnoncreds profile" in str( + context.exception + ) async def test_receive_pres(self): connection_record = mock.MagicMock(connection_id=CONN_ID) pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], proposals_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) pres = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) pres.assign_thread_id("thread-id") @@ -1360,14 +1396,15 @@ async def test_receive_pres(self): # cover by_format property by_format = px_rec_dummy.by_format - assert by_format.get("pres_proposal").get("indy") == INDY_PROOF_REQ_NAME - assert by_format.get("pres_request").get("indy") == INDY_PROOF_REQ_NAME + assert by_format.get("pres_proposal").get("anoncreds") == ANONCREDS_PROOF_REQ_NAME + assert by_format.get("pres_request").get("anoncreds") == ANONCREDS_PROOF_REQ_NAME - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [px_rec_dummy] px_rec_out = await self.manager.receive_pres(pres, connection_record, None) assert retrieve_ex.call_args.args[1] == {"thread_id": "thread-id"} @@ -1383,41 +1420,45 @@ async def test_receive_pres_receive_pred_value_mismatch_punt_to_indy(self): pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], proposals_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) - indy_proof_req = deepcopy(INDY_PROOF_REQ_NAME) + indy_proof_req = deepcopy(ANONCREDS_PROOF_REQ_NAME) indy_proof_req["requested_predicates"]["0_highscore_GE_uuid"]["restrictions"][0][ "attr::player::value" ] = "impostor" pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) pres.assign_thread_id("thread-id") @@ -1429,14 +1470,15 @@ async def test_receive_pres_receive_pred_value_mismatch_punt_to_indy(self): # cover by_format property by_format = px_rec_dummy.by_format - assert by_format.get("pres_proposal").get("indy") == INDY_PROOF_REQ_NAME - assert by_format.get("pres_request").get("indy") == indy_proof_req + assert by_format.get("pres_proposal").get("anoncreds") == ANONCREDS_PROOF_REQ_NAME + assert by_format.get("pres_request").get("anoncreds") == indy_proof_req - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [px_rec_dummy] px_rec_out = await self.manager.receive_pres(pres, connection_record, None) assert retrieve_ex.call_args.args[1] == {"thread_id": "thread-id"} @@ -1478,24 +1520,28 @@ async def test_receive_pres_indy_no_predicate_restrictions(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) pres.assign_thread_id("thread-id") @@ -1506,13 +1552,14 @@ async def test_receive_pres_indy_no_predicate_restrictions(self): # cover by_format property by_format = px_rec_dummy.by_format - assert by_format.get("pres_request").get("indy") == indy_proof_req + assert by_format.get("pres_request").get("anoncreds") == indy_proof_req - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [px_rec_dummy] px_rec_out = await self.manager.receive_pres(pres, connection_record, None) assert retrieve_ex.call_args.args[1] == {"thread_id": "thread-id"} @@ -1538,7 +1585,7 @@ async def test_receive_pres_indy_no_attr_restrictions(self): }, "requested_predicates": {}, } - proof = deepcopy(INDY_PROOF) + proof = deepcopy(ANONCREDS_PROOF) proof["requested_proof"]["revealed_attrs"] = { "0_player_uuid": { "sub_proof_index": 0, @@ -1550,24 +1597,26 @@ async def test_receive_pres_indy_no_attr_restrictions(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(proof, ident="indy")], + presentations_attach=[AttachDecorator.data_base64(proof, ident="anoncreds")], ) pres.assign_thread_id("thread-id") @@ -1578,13 +1627,14 @@ async def test_receive_pres_indy_no_attr_restrictions(self): # cover by_format property by_format = px_rec_dummy.by_format - assert by_format.get("pres_request").get("indy") == indy_proof_req + assert by_format.get("pres_request").get("anoncreds") == indy_proof_req - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.side_effect = [px_rec_dummy] px_rec_out = await self.manager.receive_pres(pres, connection_record, None) assert retrieve_ex.call_args.args[1] == {"thread_id": "thread-id"} @@ -1597,53 +1647,60 @@ async def test_receive_pres_indy_no_attr_restrictions(self): async def test_receive_pres_bait_and_switch_attr_name(self): connection_record = mock.MagicMock(connection_id=CONN_ID) - indy_proof_req = deepcopy(INDY_PROOF_REQ_NAME) + indy_proof_req = deepcopy(ANONCREDS_PROOF_REQ_NAME) indy_proof_req["requested_attributes"]["0_screencapture_uuid"]["restrictions"][0][ "attr::screenCapture::value" ] = "c2NyZWVuIGNhcHR1cmUgc2hvd2luZyBzY29yZSBpbiB0aGUgbWlsbGlvbnM=" pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], proposals_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres_x = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) px_rec_dummy = V20PresExRecord( pres_proposal=pres_proposal.serialize(), pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1655,33 +1712,41 @@ async def test_receive_pres_bait_and_switch_attr_name(self): pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], - proposals_attach=[AttachDecorator.data_base64(indy_proof_req, ident="indy")], + proposals_attach=[ + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") + ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres_x = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) px_rec_dummy = V20PresExRecord( @@ -1689,9 +1754,12 @@ async def test_receive_pres_bait_and_switch_attr_name(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1699,43 +1767,47 @@ async def test_receive_pres_bait_and_switch_attr_name(self): async def test_receive_pres_bait_and_switch_attr_names(self): connection_record = mock.MagicMock(connection_id=CONN_ID) - indy_proof_req = deepcopy(INDY_PROOF_REQ_NAMES) + indy_proof_req = deepcopy(ANONCREDS_PROOF_REQ_NAMES) indy_proof_req["requested_attributes"]["0_player_uuid"]["restrictions"][0][ "attr::screenCapture::value" ] = "c2NyZWVuIGNhcHR1cmUgc2hvd2luZyBzY29yZSBpbiB0aGUgbWlsbGlvbnM=" pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], - proposals_attach=[AttachDecorator.data_base64(indy_proof_req, ident="indy")], + proposals_attach=[ + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") + ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres_x = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_NAMES, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_NAMES, ident="anoncreds") ], ) @@ -1744,9 +1816,12 @@ async def test_receive_pres_bait_and_switch_attr_names(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1760,34 +1835,40 @@ async def test_receive_pres_bait_and_switch_attr_names(self): pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], - proposals_attach=[AttachDecorator.data_base64(indy_proof_req, ident="indy")], + proposals_attach=[ + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") + ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres_x = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_NAMES, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_NAMES, ident="anoncreds") ], ) @@ -1796,9 +1877,12 @@ async def test_receive_pres_bait_and_switch_attr_names(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1806,42 +1890,46 @@ async def test_receive_pres_bait_and_switch_attr_names(self): async def test_receive_pres_bait_and_switch_pred(self): connection_record = mock.MagicMock(connection_id=CONN_ID) - indy_proof_req = deepcopy(INDY_PROOF_REQ_NAME) + indy_proof_req = deepcopy(ANONCREDS_PROOF_REQ_NAME) indy_proof_req["requested_predicates"] = {} pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], proposals_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres_x = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) px_rec_dummy = V20PresExRecord( @@ -1849,9 +1937,12 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1867,33 +1958,41 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], - proposals_attach=[AttachDecorator.data_base64(indy_proof_req, ident="indy")], + proposals_attach=[ + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") + ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres_x = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) px_rec_dummy = V20PresExRecord( @@ -1901,9 +2000,12 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1919,33 +2021,41 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], - proposals_attach=[AttachDecorator.data_base64(indy_proof_req, ident="indy")], + proposals_attach=[ + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") + ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres_x = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) px_rec_dummy = V20PresExRecord( @@ -1953,9 +2063,12 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -1971,33 +2084,41 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_proposal = V20PresProposal( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_PROPOSAL][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], - proposals_attach=[AttachDecorator.data_base64(indy_proof_req, ident="indy")], + proposals_attach=[ + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") + ], ) pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], request_presentations_attach=[ - AttachDecorator.data_base64(indy_proof_req, ident="indy") + AttachDecorator.data_base64(indy_proof_req, ident="anoncreds") ], ) pres_x = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) px_rec_dummy = V20PresExRecord( @@ -2005,9 +2126,12 @@ async def test_receive_pres_bait_and_switch_pred(self): pres_request=pres_request.serialize(), pres=pres_x.serialize(), ) - with mock.patch.object(V20PresExRecord, "save", autospec=True), mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True), + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy with self.assertRaises(V20PresFormatHandlerError) as context: await self.manager.receive_pres(pres_x, connection_record, None) @@ -2020,25 +2144,29 @@ async def test_verify_pres(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ) ], will_confirm=True, request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy") + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds") ], ) pres = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ) ], - presentations_attach=[AttachDecorator.data_base64(INDY_PROOF, ident="indy")], + presentations_attach=[ + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds") + ], ) px_rec_in = V20PresExRecord( pres_request=pres_request, @@ -2048,11 +2176,14 @@ async def test_verify_pres(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + ): px_rec_out = await self.manager.verify_pres(px_rec_in) save_ex.assert_called_once() @@ -2063,9 +2194,9 @@ async def test_verify_pres_indy_and_dif(self): pres_request = V20PresRequest( formats=[ V20PresFormat( - attach_id="indy", + attach_id="anoncreds", format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ - V20PresFormat.Format.INDY.api + V20PresFormat.Format.ANONCREDS.api ], ), V20PresFormat( @@ -2077,15 +2208,17 @@ async def test_verify_pres_indy_and_dif(self): ], will_confirm=True, request_presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF_REQ_NAME, ident="indy"), + AttachDecorator.data_base64(ANONCREDS_PROOF_REQ_NAME, ident="anoncreds"), AttachDecorator.data_json(DIF_PRES_REQ, ident="dif"), ], ) pres = V20Pres( formats=[ V20PresFormat( - attach_id="indy", - format_=ATTACHMENT_FORMAT[PRES_20][V20PresFormat.Format.INDY.api], + attach_id="anoncreds", + format_=ATTACHMENT_FORMAT[PRES_20][ + V20PresFormat.Format.ANONCREDS.api + ], ), V20PresFormat( attach_id="dif", @@ -2093,7 +2226,7 @@ async def test_verify_pres_indy_and_dif(self): ), ], presentations_attach=[ - AttachDecorator.data_base64(INDY_PROOF, ident="indy"), + AttachDecorator.data_base64(ANONCREDS_PROOF, ident="anoncreds"), AttachDecorator.data_json(DIF_PRES, ident="dif"), ], ) @@ -2109,32 +2242,40 @@ async def test_verify_pres_indy_and_dif(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + ): px_rec_out = await self.manager.verify_pres(px_rec_in) save_ex.assert_called_once() assert px_rec_out.state == (V20PresExRecord.STATE_DONE) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), - ), mock.patch( - "acapy_agent.vc.vc_ld.verify.verify_presentation", - mock.CoroutineMock( - return_value=PresentationVerificationResult(verified=False) + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=("test_ledger_id", self.ledger)), + ), + mock.patch( + "acapy_agent.vc.vc_ld.verify.verify_presentation", + mock.CoroutineMock( + return_value=PresentationVerificationResult(verified=False) + ), ), - ), mock.patch.object( - AnonCredsVerifier, - "verify_presentation", - mock.CoroutineMock( - return_value=PresentationVerificationResult(verified=True) + mock.patch.object( + AnonCredsVerifier, + "verify_presentation", + mock.CoroutineMock( + return_value=PresentationVerificationResult(verified=True) + ), ), - ), mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex: + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + ): px_rec_out = await self.manager.verify_pres(px_rec_in) save_ex.assert_called_once() assert px_rec_out.state == (V20PresExRecord.STATE_DONE) @@ -2180,11 +2321,12 @@ async def test_receive_pres_ack_a(self): px_rec_dummy = V20PresExRecord() message = mock.MagicMock() - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy px_rec_out = await self.manager.receive_pres_ack(message, conn_record) save_ex.assert_called_once() @@ -2197,11 +2339,12 @@ async def test_receive_pres_ack_b(self): px_rec_dummy = V20PresExRecord() message = mock.MagicMock(_verification_result="true") - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, "retrieve_by_tag_filter", autospec=True - ) as retrieve_ex: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, "retrieve_by_tag_filter", autospec=True + ) as retrieve_ex, + ): retrieve_ex.return_value = px_rec_dummy px_rec_out = await self.manager.receive_pres_ack(message, conn_record) save_ex.assert_called_once() @@ -2226,17 +2369,19 @@ async def test_receive_problem_report(self): } ) - with mock.patch.object( - V20PresExRecord, "save", autospec=True - ) as save_ex, mock.patch.object( - V20PresExRecord, - "retrieve_by_tag_filter", - mock.CoroutineMock(), - ) as retrieve_ex, mock.patch.object( - self.profile, - "session", - mock.MagicMock(return_value=self.profile.session()), - ) as session: + with ( + mock.patch.object(V20PresExRecord, "save", autospec=True) as save_ex, + mock.patch.object( + V20PresExRecord, + "retrieve_by_tag_filter", + mock.CoroutineMock(), + ) as retrieve_ex, + mock.patch.object( + self.profile, + "session", + mock.MagicMock(return_value=self.profile.session()), + ) as session, + ): retrieve_ex.return_value = stored_exchange await self.manager.receive_problem_report(problem, connection_id) diff --git a/acapy_agent/protocols/present_proof/v2_0/tests/test_routes.py b/acapy_agent/protocols/present_proof/v2_0/tests/test_routes.py index af70cd2d0b..7d120b0052 100644 --- a/acapy_agent/protocols/present_proof/v2_0/tests/test_routes.py +++ b/acapy_agent/protocols/present_proof/v2_0/tests/test_routes.py @@ -6,8 +6,10 @@ from marshmallow import ValidationError from .....admin.request_context import AdminRequestContext +from .....anoncreds.models.presentation_request import ( + AnoncredsPresentationReqAttrSpecSchema, +) from .....indy.holder import IndyHolder -from .....indy.models.proof_request import IndyProofReqAttrSpecSchema from .....indy.verifier import IndyVerifier from .....ledger.base import BaseLedger from .....storage.error import StorageNotFoundError @@ -221,7 +223,7 @@ async def test_validate(self): schema.validate_fields({"veres-one": {"no": "support"}}) async def test_validate_proof_req_attr_spec(self): - aspec = IndyProofReqAttrSpecSchema() + aspec = AnoncredsPresentationReqAttrSpecSchema() aspec.validate_fields({"name": "attr0"}) aspec.validate_fields( { @@ -254,11 +256,14 @@ async def test_present_proof_list(self): mock_pres_ex_rec_inst = mock.MagicMock( serialize=mock.MagicMock(return_value={"thread_id": "sample-thread-id"}) ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.query = mock.CoroutineMock( return_value=[mock_pres_ex_rec_inst] ) @@ -337,11 +342,14 @@ async def test_present_proof_credentials_list_single_referent(self): ) self.profile.context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.return_value = mock.MagicMock( retrieve_by_id=mock.CoroutineMock() ) @@ -363,11 +371,14 @@ async def test_present_proof_credentials_list_multiple_referents(self): ) self.profile.context.injector.bind_instance(IndyHolder, mock_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.return_value = mock.MagicMock( retrieve_by_id=mock.CoroutineMock() ) @@ -427,11 +438,14 @@ async def test_present_proof_credentials_list_dif(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -504,11 +518,14 @@ async def test_present_proof_credentials_list_dif_one_of_filter(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -577,11 +594,14 @@ async def test_present_proof_credentials_dif_no_tag_query(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -650,11 +670,14 @@ async def test_present_proof_credentials_single_ldp_vp_claim_format(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -723,11 +746,14 @@ async def test_present_proof_credentials_double_ldp_vp_claim_format(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -789,10 +815,11 @@ async def test_present_proof_credentials_single_ldp_vp_error(self): mock_vc_holder.search_credentials = mock.MagicMock() self.profile.context.injector.bind_instance(VCHolder, mock_vc_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record with self.assertRaises(test_module.web.HTTPBadRequest): @@ -849,10 +876,11 @@ async def test_present_proof_credentials_double_ldp_vp_error(self): mock_vc_holder.search_credentials = mock.MagicMock() self.profile.context.injector.bind_instance(VCHolder, mock_vc_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record with self.assertRaises(test_module.web.HTTPBadRequest): @@ -906,10 +934,11 @@ async def test_present_proof_credentials_list_limit_disclosure_no_bbs(self): mock_vc_holder.search_credentials = mock.MagicMock() self.profile.context.injector.bind_instance(VCHolder, mock_vc_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record with self.assertRaises(test_module.web.HTTPBadRequest): @@ -966,10 +995,11 @@ async def test_present_proof_credentials_no_ldp_vp(self): mock_vc_holder.search_credentials = mock.MagicMock() self.profile.context.injector.bind_instance(VCHolder, mock_vc_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record with self.assertRaises(test_module.web.HTTPBadRequest): @@ -1032,11 +1062,14 @@ async def test_present_proof_credentials_list_schema_uri(self): ) self.profile.context.injector.bind_instance(VCHolder, mock_vc_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) mock_response.assert_called_once_with( @@ -1095,10 +1128,11 @@ async def test_present_proof_credentials_list_dif_error(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): with self.assertRaises(test_module.web.HTTPBadRequest): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record @@ -1107,11 +1141,14 @@ async def test_present_proof_credentials_list_dif_error(self): async def test_present_proof_retrieve(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock( serialize=mock.MagicMock( @@ -1163,15 +1200,16 @@ async def test_present_proof_send_proposal(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ), mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object(test_module, "V20PresExRecord", autospec=True), + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_conn_rec.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock(is_ready=True) ) @@ -1197,10 +1235,11 @@ async def test_present_proof_send_proposal_no_conn_record(self): async def test_present_proof_send_proposal_not_ready(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresProposal", autospec=True + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object(test_module, "V20PresProposal", autospec=True), ): mock_conn_rec_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock(is_ready=False) @@ -1212,11 +1251,12 @@ async def test_present_proof_send_proposal_not_ready(self): async def test_present_proof_send_proposal_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + ): mock_pres_mgr.return_value.create_exchange_for_proposal = mock.CoroutineMock( return_value=mock.MagicMock( serialize=mock.MagicMock(side_effect=test_module.StorageError()), @@ -1238,13 +1278,15 @@ async def test_present_proof_create_request(self): } ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresRequest", autospec=True - ), mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object(test_module, "V20PresRequest", autospec=True), + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_px_rec_inst = mock.MagicMock( serialize=mock.MagicMock(return_value={"thread_id": "sample-thread-id"}) ) @@ -1266,11 +1308,13 @@ async def test_present_proof_create_request_x(self): } ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresRequest", autospec=True - ), mock.patch.object(test_module.web, "json_response", mock.MagicMock()): + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object(test_module, "V20PresRequest", autospec=True), + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), + ): mock_pres_mgr_inst = mock.MagicMock( create_exchange_for_request=mock.CoroutineMock( return_value=mock.MagicMock( @@ -1293,17 +1337,19 @@ async def test_present_proof_send_free_request(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresRequest", autospec=True - ), mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ), mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object(test_module, "V20PresRequest", autospec=True), + mock.patch.object(test_module, "V20PresExRecord", autospec=True), + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_conn_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_px_rec_inst = mock.MagicMock( serialize=mock.MagicMock({"thread_id": "sample-thread-id"}) @@ -1357,13 +1403,16 @@ async def test_present_proof_send_free_request_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresRequest", autospec=True - ), mock.patch.object(test_module, "V20PresExRecord", autospec=True): + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object(test_module, "V20PresRequest", autospec=True), + mock.patch.object(test_module, "V20PresExRecord", autospec=True), + ): mock_conn_rec_inst = mock.MagicMock() mock_conn_rec_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock_conn_rec_inst @@ -1399,15 +1448,20 @@ async def test_present_proof_send_bound_request(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PROPOSAL_RECEIVED, @@ -1452,11 +1506,14 @@ async def test_present_proof_send_bound_request_not_found(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PROPOSAL_RECEIVED, @@ -1490,11 +1547,14 @@ async def test_present_proof_send_bound_request_not_ready(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PROPOSAL_RECEIVED, @@ -1578,13 +1638,17 @@ async def test_present_proof_send_bound_request_x(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PROPOSAL_RECEIVED, @@ -1632,15 +1696,18 @@ async def test_present_proof_send_presentation(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1683,15 +1750,18 @@ async def test_present_proof_send_presentation_dif(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1756,15 +1826,18 @@ async def test_present_proof_send_presentation_dif_error(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_px_rec_cls.retrieve_by_id = mock.CoroutineMock( return_value=px_rec_instance ) @@ -1829,11 +1902,14 @@ async def test_present_proof_send_presentation_not_found(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1871,11 +1947,14 @@ async def test_present_proof_send_presentation_not_ready(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1943,13 +2022,18 @@ async def test_present_proof_send_presentation_x(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response"), + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1983,15 +2067,20 @@ async def test_present_proof_send_presentation_x(self): async def test_present_proof_verify_presentation(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PRESENTATION_RECEIVED, @@ -2048,14 +2137,17 @@ async def test_present_proof_verify_presentation_bad_state(self): async def test_present_proof_verify_presentation_x(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", @@ -2093,15 +2185,16 @@ async def test_present_proof_problem_report(self): self.request.match_info = {"pres_ex_id": "dummy"} magic_report = mock.MagicMock() - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ), mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ) as mock_problem_report, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "V20PresManager", autospec=True), + mock.patch.object( + test_module, "problem_report_for_record", mock.MagicMock() + ) as mock_problem_report, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_px_rec.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock(save_error_state=mock.CoroutineMock()) ) @@ -2134,13 +2227,13 @@ async def test_present_proof_problem_report_x(self): ) self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ), mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ), mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec: + with ( + mock.patch.object(test_module, "V20PresManager", autospec=True), + mock.patch.object(test_module, "problem_report_for_record", mock.MagicMock()), + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec, + ): mock_px_rec.retrieve_by_id = mock.CoroutineMock( side_effect=test_module.StorageError() ) @@ -2151,11 +2244,14 @@ async def test_present_proof_problem_report_x(self): async def test_present_proof_remove(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_px_rec.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock( state=test_module.V20PresExRecord.STATE_DONE, diff --git a/acapy_agent/protocols/present_proof/v2_0/tests/test_routes_anoncreds.py b/acapy_agent/protocols/present_proof/v2_0/tests/test_routes_anoncreds.py index 96c3da744e..4a29ff2b08 100644 --- a/acapy_agent/protocols/present_proof/v2_0/tests/test_routes_anoncreds.py +++ b/acapy_agent/protocols/present_proof/v2_0/tests/test_routes_anoncreds.py @@ -8,8 +8,10 @@ from .....admin.request_context import AdminRequestContext from .....anoncreds.holder import AnonCredsHolder +from .....anoncreds.models.presentation_request import ( + AnoncredsPresentationReqAttrSpecSchema, +) from .....anoncreds.verifier import AnonCredsVerifier -from .....indy.models.proof_request import IndyProofReqAttrSpecSchema from .....ledger.base import BaseLedger from .....storage.error import StorageNotFoundError from .....storage.vc_holder.base import VCHolder @@ -223,7 +225,7 @@ async def test_validate(self): schema.validate_fields({"veres-one": {"no": "support"}}) async def test_validate_proof_req_attr_spec(self): - aspec = IndyProofReqAttrSpecSchema() + aspec = AnoncredsPresentationReqAttrSpecSchema() aspec.validate_fields({"name": "attr0"}) aspec.validate_fields( { @@ -256,11 +258,14 @@ async def test_present_proof_list(self): mock_pres_ex_rec_inst = mock.MagicMock( serialize=mock.MagicMock(return_value={"thread_id": "sample-thread-id"}) ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.query = mock.CoroutineMock( return_value=[mock_pres_ex_rec_inst] ) @@ -347,11 +352,14 @@ async def test_present_proof_credentials_list_single_referent(self): ), ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.return_value = mock.MagicMock( retrieve_by_id=mock.CoroutineMock() ) @@ -377,11 +385,14 @@ async def test_present_proof_credentials_list_multiple_referents(self): ), ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.return_value = mock.MagicMock( retrieve_by_id=mock.CoroutineMock() ) @@ -443,11 +454,14 @@ async def test_present_proof_credentials_list_dif(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -521,11 +535,14 @@ async def test_present_proof_credentials_list_dif_one_of_filter(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -596,11 +613,14 @@ async def test_present_proof_credentials_dif_no_tag_query(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -671,11 +691,14 @@ async def test_present_proof_credentials_single_ldp_vp_claim_format(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -746,11 +769,14 @@ async def test_present_proof_credentials_double_ldp_vp_claim_format(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) @@ -816,10 +842,11 @@ async def test_present_proof_credentials_single_ldp_vp_error(self): ) self.profile.context.injector.bind_instance(VCHolder, mock_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record with self.assertRaises(test_module.web.HTTPBadRequest): @@ -880,10 +907,11 @@ async def test_present_proof_credentials_double_ldp_vp_error(self): ) self.profile.context.injector.bind_instance(VCHolder, mock_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record with self.assertRaises(test_module.web.HTTPBadRequest): @@ -941,10 +969,11 @@ async def test_present_proof_credentials_list_limit_disclosure_no_bbs(self): ) self.profile.context.injector.bind_instance(VCHolder, mock_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record with self.assertRaises(test_module.web.HTTPBadRequest): @@ -1005,10 +1034,11 @@ async def test_present_proof_credentials_no_ldp_vp(self): ) self.profile.context.injector.bind_instance(VCHolder, mock_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record with self.assertRaises(test_module.web.HTTPBadRequest): @@ -1073,11 +1103,14 @@ async def test_present_proof_credentials_list_schema_uri(self): ) self.profile.context.injector.bind_instance(VCHolder, mock_holder) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record await test_module.present_proof_credentials_list(self.request) mock_response.assert_called_once_with( @@ -1137,10 +1170,11 @@ async def test_present_proof_credentials_list_dif_error(self): error_msg=None, ) - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): with self.assertRaises(test_module.web.HTTPBadRequest): mock_pres_ex_rec_cls.retrieve_by_id.return_value = record @@ -1149,11 +1183,14 @@ async def test_present_proof_credentials_list_dif_error(self): async def test_present_proof_retrieve(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_pres_ex_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_pres_ex_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_pres_ex_rec_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock( serialize=mock.MagicMock( @@ -1205,15 +1242,16 @@ async def test_present_proof_send_proposal(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ), mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True) as mock_conn_rec, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + mock.patch.object(test_module, "V20PresExRecord", autospec=True), + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_conn_rec.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock(is_ready=True) ) @@ -1239,10 +1277,11 @@ async def test_present_proof_send_proposal_no_conn_record(self): async def test_present_proof_send_proposal_not_ready(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresProposal", autospec=True + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object(test_module, "V20PresProposal", autospec=True), ): mock_conn_rec_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock(is_ready=False) @@ -1254,11 +1293,12 @@ async def test_present_proof_send_proposal_not_ready(self): async def test_present_proof_send_proposal_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ), mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr: + with ( + mock.patch.object(test_module, "ConnRecord", autospec=True), + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr, + ): mock_pres_mgr.return_value.create_exchange_for_proposal = mock.CoroutineMock( return_value=mock.MagicMock( serialize=mock.MagicMock(side_effect=test_module.StorageError()), @@ -1280,13 +1320,15 @@ async def test_present_proof_create_request(self): } ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresRequest", autospec=True - ), mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object(test_module, "V20PresRequest", autospec=True), + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_px_rec_inst = mock.MagicMock( serialize=mock.MagicMock(return_value={"thread_id": "sample-thread-id"}) ) @@ -1308,11 +1350,13 @@ async def test_present_proof_create_request_x(self): } ) - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresRequest", autospec=True - ), mock.patch.object(test_module.web, "json_response", mock.MagicMock()): + with ( + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object(test_module, "V20PresRequest", autospec=True), + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), + ): mock_pres_mgr_inst = mock.MagicMock( create_exchange_for_request=mock.CoroutineMock( return_value=mock.MagicMock( @@ -1335,17 +1379,19 @@ async def test_present_proof_send_free_request(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresRequest", autospec=True - ), mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ), mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object(test_module, "V20PresRequest", autospec=True), + mock.patch.object(test_module, "V20PresExRecord", autospec=True), + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_conn_rec_cls.retrieve_by_id = mock.CoroutineMock() mock_px_rec_inst = mock.MagicMock( serialize=mock.MagicMock({"thread_id": "sample-thread-id"}) @@ -1399,13 +1445,16 @@ async def test_present_proof_send_free_request_x(self): } ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresRequest", autospec=True - ), mock.patch.object(test_module, "V20PresExRecord", autospec=True): + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object(test_module, "V20PresRequest", autospec=True), + mock.patch.object(test_module, "V20PresExRecord", autospec=True), + ): mock_conn_rec_inst = mock.MagicMock() mock_conn_rec_cls.retrieve_by_id = mock.CoroutineMock( return_value=mock_conn_rec_inst @@ -1441,15 +1490,20 @@ async def test_present_proof_send_bound_request(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PROPOSAL_RECEIVED, @@ -1494,11 +1548,14 @@ async def test_present_proof_send_bound_request_not_found(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PROPOSAL_RECEIVED, @@ -1532,11 +1589,14 @@ async def test_present_proof_send_bound_request_not_ready(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PROPOSAL_RECEIVED, @@ -1620,13 +1680,17 @@ async def test_present_proof_send_bound_request_x(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PROPOSAL_RECEIVED, @@ -1674,15 +1738,18 @@ async def test_present_proof_send_presentation(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1725,15 +1792,18 @@ async def test_present_proof_send_presentation_dif(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1798,15 +1868,18 @@ async def test_present_proof_send_presentation_dif_error(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_px_rec_cls.retrieve_by_id = mock.CoroutineMock( return_value=px_rec_instance ) @@ -1871,11 +1944,14 @@ async def test_present_proof_send_presentation_not_found(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1912,11 +1988,14 @@ async def test_present_proof_send_presentation_not_ready(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -1984,13 +2063,18 @@ async def test_present_proof_send_presentation_x(self): ), ) - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response"), + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_REQUEST_RECEIVED, @@ -2024,15 +2108,20 @@ async def test_present_proof_send_presentation_x(self): async def test_present_proof_verify_presentation(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", state=test_module.V20PresExRecord.STATE_PRESENTATION_RECEIVED, @@ -2089,14 +2178,17 @@ async def test_present_proof_verify_presentation_bad_state(self): async def test_present_proof_verify_presentation_x(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "ConnRecord", autospec=True - ) as mock_conn_rec_cls, mock.patch.object( - test_module, "V20PresManager", autospec=True - ) as mock_pres_mgr_cls, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec_cls, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module, "ConnRecord", autospec=True + ) as mock_conn_rec_cls, + mock.patch.object( + test_module, "V20PresManager", autospec=True + ) as mock_pres_mgr_cls, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec_cls, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_px_rec_inst = mock.MagicMock( connection_id="dummy", @@ -2134,15 +2226,16 @@ async def test_present_proof_problem_report(self): self.request.match_info = {"pres_ex_id": "dummy"} magic_report = mock.MagicMock() - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ), mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ) as mock_problem_report, mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object(test_module, "V20PresManager", autospec=True), + mock.patch.object( + test_module, "problem_report_for_record", mock.MagicMock() + ) as mock_problem_report, + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_px_rec.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock(save_error_state=mock.CoroutineMock()) ) @@ -2175,13 +2268,13 @@ async def test_present_proof_problem_report_x(self): ) self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20PresManager", autospec=True - ), mock.patch.object( - test_module, "problem_report_for_record", mock.MagicMock() - ), mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec: + with ( + mock.patch.object(test_module, "V20PresManager", autospec=True), + mock.patch.object(test_module, "problem_report_for_record", mock.MagicMock()), + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec, + ): mock_px_rec.retrieve_by_id = mock.CoroutineMock( side_effect=test_module.StorageError() ) @@ -2192,11 +2285,14 @@ async def test_present_proof_problem_report_x(self): async def test_present_proof_remove(self): self.request.match_info = {"pres_ex_id": "dummy"} - with mock.patch.object( - test_module, "V20PresExRecord", autospec=True - ) as mock_px_rec, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as mock_response: + with ( + mock.patch.object( + test_module, "V20PresExRecord", autospec=True + ) as mock_px_rec, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as mock_response, + ): mock_px_rec.retrieve_by_id = mock.CoroutineMock( return_value=mock.MagicMock( state=test_module.V20PresExRecord.STATE_DONE, diff --git a/acapy_agent/protocols/routing/v1_0/handlers/tests/test_forward_handler.py b/acapy_agent/protocols/routing/v1_0/handlers/tests/test_forward_handler.py index 4e3b19f933..73c642c489 100644 --- a/acapy_agent/protocols/routing/v1_0/handlers/tests/test_forward_handler.py +++ b/acapy_agent/protocols/routing/v1_0/handlers/tests/test_forward_handler.py @@ -28,13 +28,15 @@ async def test_handle(self): handler = test_module.ForwardHandler() responder = MockResponder() - with mock.patch.object( - test_module, "RoutingManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module, "ConnectionManager", autospec=True - ) as mock_connection_mgr, mock.patch.object( - self.context.profile, "notify", autospec=True - ) as mock_notify: + with ( + mock.patch.object(test_module, "RoutingManager", autospec=True) as mock_mgr, + mock.patch.object( + test_module, "ConnectionManager", autospec=True + ) as mock_connection_mgr, + mock.patch.object( + self.context.profile, "notify", autospec=True + ) as mock_notify, + ): mock_mgr.return_value.get_recipient = mock.CoroutineMock( return_value=RouteRecord(connection_id="dummy") ) diff --git a/acapy_agent/protocols/trustping/v1_0/tests/test_routes.py b/acapy_agent/protocols/trustping/v1_0/tests/test_routes.py index cf05eae733..6012046e75 100644 --- a/acapy_agent/protocols/trustping/v1_0/tests/test_routes.py +++ b/acapy_agent/protocols/trustping/v1_0/tests/test_routes.py @@ -31,13 +31,15 @@ async def test_connections_send_ping(self): self.request.json = mock.CoroutineMock(return_value={"comment": "some comment"}) self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - test_module, "Ping", mock.MagicMock() - ) as mock_ping, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() - ) as json_response: + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object(test_module, "Ping", mock.MagicMock()) as mock_ping, + mock.patch.object( + test_module.web, "json_response", mock.MagicMock() + ) as json_response, + ): mock_ping.return_value = mock.MagicMock(_thread_id="dummy") mock_retrieve.return_value = mock.MagicMock(is_ready=True) result = await test_module.connections_send_ping(self.request) @@ -48,10 +50,11 @@ async def test_connections_send_ping_no_conn(self): self.request.json = mock.CoroutineMock(return_value={"comment": "some comment"}) self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_retrieve.side_effect = test_module.StorageNotFoundError() with self.assertRaises(test_module.web.HTTPNotFound): @@ -61,10 +64,11 @@ async def test_connections_send_ping_not_ready(self): self.request.json = mock.CoroutineMock(return_value={"comment": "some comment"}) self.request.match_info = {"conn_id": "dummy"} - with mock.patch.object( - test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() - ) as mock_retrieve, mock.patch.object( - test_module.web, "json_response", mock.MagicMock() + with ( + mock.patch.object( + test_module.ConnRecord, "retrieve_by_id", mock.CoroutineMock() + ) as mock_retrieve, + mock.patch.object(test_module.web, "json_response", mock.MagicMock()), ): mock_retrieve.return_value = mock.MagicMock(is_ready=False) with self.assertRaises(test_module.web.HTTPBadRequest): diff --git a/acapy_agent/resolver/default/tests/test_legacy_peer.py b/acapy_agent/resolver/default/tests/test_legacy_peer.py index fb7cb8f264..46f18caf8a 100644 --- a/acapy_agent/resolver/default/tests/test_legacy_peer.py +++ b/acapy_agent/resolver/default/tests/test_legacy_peer.py @@ -79,11 +79,10 @@ async def test_supports_x_unknown_did( @pytest.mark.asyncio async def test_resolve(self, resolver: LegacyPeerDIDResolver, profile: Profile): """Test resolve.""" - with mock.patch.object( - test_module, "BaseConnectionManager" - ) as mock_mgr, mock.patch.object( - test_module, "LegacyDocCorrections" - ) as mock_corrections: + with ( + mock.patch.object(test_module, "BaseConnectionManager") as mock_mgr, + mock.patch.object(test_module, "LegacyDocCorrections") as mock_corrections, + ): doc = object() mock_corrections.apply = mock.MagicMock(return_value=doc) mock_mgr.return_value = mock.MagicMock( @@ -102,11 +101,11 @@ async def test_resolve_x_not_found( This should be impossible in practice but still. """ - with mock.patch.object( - test_module, "BaseConnectionManager" - ) as mock_mgr, mock.patch.object( - test_module, "LegacyDocCorrections" - ) as mock_corrections, pytest.raises(test_module.DIDNotFound): + with ( + mock.patch.object(test_module, "BaseConnectionManager") as mock_mgr, + mock.patch.object(test_module, "LegacyDocCorrections") as mock_corrections, + pytest.raises(test_module.DIDNotFound), + ): doc = object mock_corrections.apply = mock.MagicMock(return_value=doc) mock_mgr.return_value = mock.MagicMock( diff --git a/acapy_agent/resolver/default/tests/test_universal.py b/acapy_agent/resolver/default/tests/test_universal.py index 36b2cc73db..c516ac7068 100644 --- a/acapy_agent/resolver/default/tests/test_universal.py +++ b/acapy_agent/resolver/default/tests/test_universal.py @@ -119,6 +119,7 @@ async def test_fetch_resolver_props(mock_client_session: MockClientSession): @pytest.mark.asyncio async def test_get_supported_did_regex(): + # Old response format props = {"example": {"http": {"pattern": "match a test string"}}} with mock.patch.object( UniversalResolver, @@ -128,6 +129,29 @@ async def test_get_supported_did_regex(): pattern = await UniversalResolver()._get_supported_did_regex() assert pattern.fullmatch("match a test string") + # Example response from dev universal resolver 1.0 + props = { + "^(did:sov:(?:(?:\\w[-\\w]*(?::\\w[-\\w]*)*):)?(?:[1-9A-HJ-NP-Za-km-z]{21,22}))$": { + "libIndyPath": "", + "openParallel": "false", + "poolVersions": "_;2;test;2;builder;2;danube;2;idunion;2;idunion:test;2;indicio;2;indicio:test;2;indicio:demo;2;nxd;2;findy:test;2;bcovrin;2;bcovrin:test;2;bcovrin:dev;2;candy;2;candy:test;2;candy:dev;2", + "submitterDidSeeds": "_;_;test;_;builder;_;danube;_;idunion;_;idunion:test;_;indicio;_;indicio:test;_;indicio:demo;_;nxd;_;findy:test;_;bcovrin;_;bcovrin:test;_;bcovrin:dev;_;candy;_;candy:test;_;candy:dev;_", + "http": { + "resolveUri": "http://driver-did-sov:8080/1.0/identifiers/", + "propertiesUri": "http://driver-did-sov:8080/1.0/properties", + }, + "walletNames": "_;w1;test;w2;builder;w3;danube;w4;idunion;w5;idunion:test;w6;indicio;w7;indicio:test;w8;indicio:demo;w9;nxd;w11;findy:test;w12;bcovrin;w13;bcovrin:test;w14;bcovrin:dev;w15;candy;w16;candy:test;w17;candy:dev;w18", + "poolConfigs": "_;./sovrin/_.txn;test;./sovrin/test.txn;builder;./sovrin/builder.txn;danube;./sovrin/danube.txn;idunion;./sovrin/idunion.txn;idunion:test;./sovrin/idunion-test.txn;indicio;./sovrin/indicio.txn;indicio:test;./sovrin/indicio-test.txn;indicio:demo;./sovrin/indicio-demo.txn;nxd;./sovrin/nxd.txn;bcovrin:test;./sovrin/bcovrin-test.txn;candy;./sovrin/candy.txn;candy:test;./sovrin/candy-test.txn;candy:dev;./sovrin/candy-dev.txn", + } + } + with mock.patch.object( + UniversalResolver, + "_fetch_resolver_props", + mock.CoroutineMock(return_value=props), + ): + pattern = await UniversalResolver()._get_supported_did_regex() + assert pattern.match("did:sov:WRfXPg8dantKVubE3HX8pw") + def test_compile_supported_did_regex(): patterns = ["one", "two", "three"] diff --git a/acapy_agent/resolver/default/universal.py b/acapy_agent/resolver/default/universal.py index 4d359a9a6e..8d4b1eb1d8 100644 --- a/acapy_agent/resolver/default/universal.py +++ b/acapy_agent/resolver/default/universal.py @@ -110,8 +110,16 @@ async def _fetch_resolver_props(self) -> dict: "Failed to retrieve resolver properties: " + await resp.text() ) - async def _get_supported_did_regex(self) -> Pattern: + async def _get_supported_did_regex(self): props = await self._fetch_resolver_props() - return _compile_supported_did_regex( - driver["http"]["pattern"] for driver in props.values() - ) + + def _get_patterns(): + """Handle both old and new properties responses.""" + patterns = list(props.values())[0].get("http", {}).get("pattern") + if not patterns: + return props.keys() + else: + return [driver["http"]["pattern"] for driver in props.values()] + + patterns = _get_patterns() + return _compile_supported_did_regex(patterns) diff --git a/acapy_agent/revocation/models/tests/test_issuer_rev_reg_record.py b/acapy_agent/revocation/models/tests/test_issuer_rev_reg_record.py index 8038414429..12488dd350 100644 --- a/acapy_agent/revocation/models/tests/test_issuer_rev_reg_record.py +++ b/acapy_agent/revocation/models/tests/test_issuer_rev_reg_record.py @@ -178,28 +178,32 @@ async def test_fix_ledger_entry(self, mock_handle): settings={"tails_server_base_url": "http://1.2.3.4:8088"}, ) _test_profile.context.injector.bind_instance(BaseLedger, self.ledger) - with mock.patch.object( - test_module.IssuerCredRevRecord, - "query_by_ids", - mock.CoroutineMock( - return_value=[ - test_module.IssuerCredRevRecord( - record_id=test_module.UUID4_EXAMPLE, - state=test_module.IssuerCredRevRecord.STATE_REVOKED, - cred_ex_id=test_module.UUID4_EXAMPLE, - rev_reg_id=REV_REG_ID, - cred_rev_id="1", - ) - ] + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "query_by_ids", + mock.CoroutineMock( + return_value=[ + test_module.IssuerCredRevRecord( + record_id=test_module.UUID4_EXAMPLE, + state=test_module.IssuerCredRevRecord.STATE_REVOKED, + cred_ex_id=test_module.UUID4_EXAMPLE, + rev_reg_id=REV_REG_ID, + cred_rev_id="1", + ) + ] + ), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_revoc_reg_id", + mock.CoroutineMock(return_value=rec), + ), + mock.patch.object( + test_module, + "generate_ledger_rrrecovery_txn", + mock.CoroutineMock(return_value=rev_reg_delta), ), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_revoc_reg_id", - mock.CoroutineMock(return_value=rec), - ), mock.patch.object( - test_module, - "generate_ledger_rrrecovery_txn", - mock.CoroutineMock(return_value=rev_reg_delta), ): assert ( _test_rev_reg_delta, diff --git a/acapy_agent/revocation/models/tests/test_revocation_registry.py b/acapy_agent/revocation/models/tests/test_revocation_registry.py index 6416d38767..d438a42aa3 100644 --- a/acapy_agent/revocation/models/tests/test_revocation_registry.py +++ b/acapy_agent/revocation/models/tests/test_revocation_registry.py @@ -128,13 +128,11 @@ async def test_retrieve_tails(self): rmtree(TAILS_DIR, ignore_errors=True) more_magic = mock.MagicMock() - with mock.patch.object( - test_module, "Session", autospec=True - ) as mock_session, mock.patch.object( - base58, "b58encode", mock.MagicMock() - ) as mock_b58enc, mock.patch.object( - Path, "is_file", autospec=True - ) as mock_is_file: + with ( + mock.patch.object(test_module, "Session", autospec=True) as mock_session, + mock.patch.object(base58, "b58encode", mock.MagicMock()) as mock_b58enc, + mock.patch.object(Path, "is_file", autospec=True) as mock_is_file, + ): mock_session.return_value.__enter__ = mock.MagicMock(return_value=more_magic) more_magic.get = mock.MagicMock( return_value=mock.MagicMock( diff --git a/acapy_agent/revocation/tests/test_indy.py b/acapy_agent/revocation/tests/test_indy.py index 26a44e35a2..224369b372 100644 --- a/acapy_agent/revocation/tests/test_indy.py +++ b/acapy_agent/revocation/tests/test_indy.py @@ -226,13 +226,16 @@ async def test_get_ledger_registry(self): BaseMultitenantManager, mock.MagicMock(MultitenantManager, autospec=True), ) - with mock.patch.object( - IndyLedgerRequestsExecutor, - "get_ledger_for_identifier", - mock.CoroutineMock(return_value=(None, self.ledger)), - ), mock.patch.object( - RevocationRegistry, "from_definition", mock.MagicMock() - ) as mock_from_def: + with ( + mock.patch.object( + IndyLedgerRequestsExecutor, + "get_ledger_for_identifier", + mock.CoroutineMock(return_value=(None, self.ledger)), + ), + mock.patch.object( + RevocationRegistry, "from_definition", mock.MagicMock() + ) as mock_from_def, + ): result = await self.revoc.get_ledger_registry("dummy2") assert result == mock_from_def.return_value assert "dummy2" in IndyRevocation.REV_REG_CACHE diff --git a/acapy_agent/revocation/tests/test_manager.py b/acapy_agent/revocation/tests/test_manager.py index 7e4d85baf5..3105141cb8 100644 --- a/acapy_agent/revocation/tests/test_manager.py +++ b/acapy_agent/revocation/tests/test_manager.py @@ -59,16 +59,18 @@ async def test_revoke_credential_publish(self): ) self.profile.context.injector.bind_instance(IndyIssuer, issuer) - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_cred_ex_id", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_cred_ex_id", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), ): mock_retrieve.return_value = mock.MagicMock( rev_reg_id="dummy-rr-id", cred_rev_id=CRED_REV_ID @@ -120,16 +122,18 @@ async def test_revoke_credential_notify(self): ) self.profile.context.injector.bind_instance(IndyIssuer, issuer) - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_cred_ex_id", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_cred_ex_id", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), ): mock_retrieve.return_value = mock.MagicMock( rev_reg_id="dummy-rr-id", cred_rev_id=CRED_REV_ID @@ -200,20 +204,23 @@ async def test_revoke_credential_publish_endorser(self): ) self.profile.context.injector.bind_instance(IndyIssuer, issuer) - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_cred_ex_id", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), - ), mock.patch.object( - test_module.ConnRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=conn_record), + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_cred_ex_id", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), + mock.patch.object( + test_module.ConnRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=conn_record), + ), ): mock_retrieve.return_value = mock.MagicMock( rev_reg_id="dummy-rr-id", cred_rev_id=CRED_REV_ID @@ -270,21 +277,24 @@ async def test_revoke_credential_publish_endorser_x(self): ) self.profile.context.injector.bind_instance(IndyIssuer, issuer) - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_cred_ex_id", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), - ), mock.patch.object( - ConnRecord, - "retrieve_by_id", - mock.CoroutineMock( - side_effect=test_module.StorageNotFoundError("no such rec") + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_cred_ex_id", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), + mock.patch.object( + ConnRecord, + "retrieve_by_id", + mock.CoroutineMock( + side_effect=test_module.StorageNotFoundError("no such rec") + ), ), ): mock_retrieve.return_value = mock.MagicMock( @@ -350,12 +360,13 @@ async def test_revoke_credential_pend(self): issuer = mock.MagicMock(IndyIssuer, autospec=True) self.profile.context.injector.bind_instance(IndyIssuer, issuer) - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + with ( + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), ): revoc.return_value.get_issuer_rev_reg_record = mock.CoroutineMock( return_value=mock_issuer_rev_reg_record @@ -420,15 +431,18 @@ async def test_publish_pending_revocations_endorser(self): ) conn_id = conn_record.connection_id assert conn_id is not None - with mock.patch.object( - test_module.IssuerRevRegRecord, - "query_by_pending", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock( - side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "query_by_pending", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock( + side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + ), ), ): issuer = mock.MagicMock(IndyIssuer, autospec=True) @@ -482,15 +496,18 @@ async def test_publish_pending_revocations_endorser_x(self): clear_pending=mock.CoroutineMock(), ), ] - with mock.patch.object( - test_module.IssuerRevRegRecord, - "query_by_pending", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock( - side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "query_by_pending", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock( + side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + ), ), ): issuer = mock.MagicMock(IndyIssuer, autospec=True) @@ -531,14 +548,17 @@ async def test_publish_pending_revocations_basic(self): send_entry=mock.CoroutineMock(), clear_pending=mock.CoroutineMock(), ) - with mock.patch.object( - test_module.IssuerRevRegRecord, - "query_by_pending", - mock.CoroutineMock(return_value=[mock_issuer_rev_reg_record]), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "query_by_pending", + mock.CoroutineMock(return_value=[mock_issuer_rev_reg_record]), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), ): issuer = mock.MagicMock(IndyIssuer, autospec=True) issuer.merge_revocation_registry_deltas = mock.CoroutineMock( @@ -588,15 +608,18 @@ async def test_publish_pending_revocations_1_rev_reg_all(self): clear_pending=mock.CoroutineMock(), ), ] - with mock.patch.object( - test_module.IssuerRevRegRecord, - "query_by_pending", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock( - side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "query_by_pending", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock( + side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + ), ), ): issuer = mock.MagicMock(IndyIssuer, autospec=True) @@ -648,15 +671,18 @@ async def test_publish_pending_revocations_1_rev_reg_some(self): clear_pending=mock.CoroutineMock(), ), ] - with mock.patch.object( - test_module.IssuerRevRegRecord, - "query_by_pending", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock( - side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "query_by_pending", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock( + side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + ), ), ): issuer = mock.MagicMock(IndyIssuer, autospec=True) diff --git a/acapy_agent/revocation/tests/test_routes.py b/acapy_agent/revocation/tests/test_routes.py index f79a5590f9..97f33c5cc8 100644 --- a/acapy_agent/revocation/tests/test_routes.py +++ b/acapy_agent/revocation/tests/test_routes.py @@ -117,11 +117,12 @@ async def test_revoke(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock() await test_module.revoke(self.request) @@ -137,14 +138,17 @@ async def test_revoke_endorser_no_conn_id_by_cred_ex_id(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module, - "get_endorser_connection_id", - mock.CoroutineMock(return_value="dummy-conn-id"), - ), mock.patch.object(test_module.web, "json_response"), mock.patch.object( - TransactionManager, "create_record", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object( + test_module, + "get_endorser_connection_id", + mock.CoroutineMock(return_value="dummy-conn-id"), + ), + mock.patch.object(test_module.web, "json_response"), + mock.patch.object(TransactionManager, "create_record", mock.CoroutineMock()), ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock( return_value={"result": "..."} @@ -163,15 +167,18 @@ async def test_revoke_endorser_by_cred_ex_id(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ), mock.patch.object( - test_module, - "get_endorser_connection_id", - mock.CoroutineMock(return_value="test_conn_id"), - ), mock.patch.object(TransactionManager, "create_record", mock.CoroutineMock()): + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response"), + mock.patch.object( + test_module, + "get_endorser_connection_id", + mock.CoroutineMock(return_value="test_conn_id"), + ), + mock.patch.object(TransactionManager, "create_record", mock.CoroutineMock()), + ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock( return_value={"result": "..."} ) @@ -187,14 +194,17 @@ async def test_revoke_endorser_no_conn_id(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module, - "get_endorser_connection_id", - mock.CoroutineMock(return_value=None), - ), mock.patch.object(test_module.web, "json_response"), mock.patch.object( - TransactionManager, "create_record", mock.CoroutineMock() + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object( + test_module, + "get_endorser_connection_id", + mock.CoroutineMock(return_value=None), + ), + mock.patch.object(test_module.web, "json_response"), + mock.patch.object(TransactionManager, "create_record", mock.CoroutineMock()), ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock( return_value={"result": "..."} @@ -213,15 +223,18 @@ async def test_revoke_endorser(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ), mock.patch.object( - test_module, - "get_endorser_connection_id", - mock.CoroutineMock(return_value="test_conn_id"), - ), mock.patch.object(TransactionManager, "create_record", mock.CoroutineMock()): + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response"), + mock.patch.object( + test_module, + "get_endorser_connection_id", + mock.CoroutineMock(return_value="test_conn_id"), + ), + mock.patch.object(TransactionManager, "create_record", mock.CoroutineMock()), + ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock( return_value={"result": "..."} ) @@ -237,12 +250,15 @@ async def test_revoke_endorser_x(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module, - "get_endorser_connection_id", - mock.CoroutineMock(return_value=None), + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object( + test_module, + "get_endorser_connection_id", + mock.CoroutineMock(return_value=None), + ), ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock() with self.assertRaises(test_module.web.HTTPBadRequest): @@ -256,11 +272,12 @@ async def test_revoke_by_cred_ex_id(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock() await test_module.revoke(self.request) @@ -276,9 +293,12 @@ async def test_revoke_not_found(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock( side_effect=test_module.StorageNotFoundError() ) @@ -289,11 +309,12 @@ async def test_revoke_not_found(self): async def test_publish_revocations(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): pub_pending = mock.CoroutineMock() mock_mgr.return_value.publish_pending_revocations = mock.CoroutineMock( return_value=({}, pub_pending.return_value) @@ -318,20 +339,25 @@ async def test_publish_revocations_x(self): async def test_publish_revocations_endorser(self): self.author_request.json = mock.CoroutineMock(return_value={}) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module, - "get_endorser_connection_id", - mock.CoroutineMock(return_value="dummy-conn-id"), - ), mock.patch.object( - TransactionManager, - "create_record", - mock.CoroutineMock(return_value=TransactionRecord()), - ), mock.patch.object( - TransactionManager, - "create_request", - mock.CoroutineMock(), + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object( + test_module, + "get_endorser_connection_id", + mock.CoroutineMock(return_value="dummy-conn-id"), + ), + mock.patch.object( + TransactionManager, + "create_record", + mock.CoroutineMock(return_value=TransactionRecord()), + ), + mock.patch.object( + TransactionManager, + "create_request", + mock.CoroutineMock(), + ), ): pub_pending = mock.CoroutineMock() mock_mgr.return_value.publish_pending_revocations = mock.CoroutineMock( @@ -385,13 +411,17 @@ async def test_publish_revocations_endorser_exceptions(self): async def test_publish_revocations_endorser_x(self): self.author_request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module, - "get_endorser_connection_id", - mock.CoroutineMock(return_value=None), - ), mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object( + test_module, + "get_endorser_connection_id", + mock.CoroutineMock(return_value=None), + ), + mock.patch.object(test_module.web, "json_response"), + ): pub_pending = mock.CoroutineMock() mock_mgr.return_value.publish_pending_revocations = mock.CoroutineMock( return_value=( @@ -410,11 +440,12 @@ async def test_publish_revocations_endorser_x(self): async def test_clear_pending_revocations(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): clear_pending = mock.CoroutineMock() mock_mgr.return_value.clear_pending_revocations = clear_pending @@ -427,9 +458,12 @@ async def test_clear_pending_revocations(self): async def test_clear_pending_revocations_x(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response"), + ): clear_pending = mock.CoroutineMock(side_effect=test_module.StorageError()) mock_mgr.return_value.clear_pending_revocations = clear_pending @@ -445,11 +479,15 @@ async def test_create_rev_reg(self): } ) - with mock.patch.object(AskarStorage, "find_all_records"), mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object(AskarStorage, "find_all_records"), + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( init_issuer_registry=mock.CoroutineMock( return_value=mock.MagicMock( @@ -472,11 +510,14 @@ async def test_create_rev_reg_no_such_cred_def(self): } ) - with mock.patch.object( - BaseStorage, "find_all_records", autospec=True - ) as mock_find, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + BaseStorage, "find_all_records", autospec=True + ) as mock_find, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_find.return_value = False with self.assertRaises(HTTPNotFound): @@ -492,13 +533,17 @@ async def test_create_rev_reg_no_revo_support(self): } ) - with mock.patch.object( - AskarStorage, "find_all_records", autospec=True - ) as mock_find, mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + AskarStorage, "find_all_records", autospec=True + ) as mock_find, + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_find.return_value = True mock_indy_revoc.return_value = mock.MagicMock( init_issuer_registry=mock.CoroutineMock( @@ -520,11 +565,14 @@ async def test_rev_regs_created(self): "state": test_module.IssuerRevRegRecord.STATE_ACTIVE, } - with mock.patch.object( - test_module.IssuerRevRegRecord, "query", mock.CoroutineMock() - ) as mock_query, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, "query", mock.CoroutineMock() + ) as mock_query, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_query.return_value = [mock.MagicMock(revoc_reg_id="dummy")] result = await test_module.rev_regs_created(self.request) @@ -537,11 +585,14 @@ async def test_get_rev_reg(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -560,11 +611,14 @@ async def test_get_rev_reg_not_found(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( side_effect=test_module.StorageNotFoundError(error_code="dummy") @@ -581,17 +635,21 @@ async def test_get_rev_reg_issued(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_revoc_reg_id", - mock.CoroutineMock(), - ), mock.patch.object( - test_module.IssuerCredRevRecord, - "query_by_ids", - mock.CoroutineMock(), - ) as mock_query, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_revoc_reg_id", + mock.CoroutineMock(), + ), + mock.patch.object( + test_module.IssuerCredRevRecord, + "query_by_ids", + mock.CoroutineMock(), + ) as mock_query, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_query.return_value = [{"...": "..."}, {"...": "..."}] result = await test_module.get_rev_reg_issued_count(self.request) @@ -625,13 +683,16 @@ async def test_get_cred_rev_record(self): "cred_rev_id": CRED_REV_ID, } - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_ids", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_ids", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value="dummy") ) @@ -645,13 +706,16 @@ async def test_get_cred_rev_record_by_cred_ex_id(self): self.request.query = {"cred_ex_id": CRED_EX_ID} - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_cred_ex_id", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_cred_ex_id", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value="dummy") ) @@ -687,11 +751,14 @@ async def test_get_active_rev_reg(self): CRED_DEF_ID = f"{self.test_did}:3:CL:1234:default" self.request.match_info = {"cred_def_id": CRED_DEF_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_active_issuer_rev_reg_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -708,11 +775,14 @@ async def test_get_active_rev_reg_not_found(self): CRED_DEF_ID = f"{self.test_did}:3:CL:1234:default" self.request.match_info = {"cred_def_id": CRED_DEF_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_active_issuer_rev_reg_record=mock.CoroutineMock( side_effect=test_module.StorageNotFoundError(error_code="dummy") @@ -729,11 +799,14 @@ async def test_get_tails_file(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "FileResponse", mock.Mock() - ) as mock_file_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "FileResponse", mock.Mock() + ) as mock_file_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( return_value=mock.MagicMock(tails_local_path="dummy") @@ -750,11 +823,14 @@ async def test_get_tails_file_not_found(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "FileResponse", mock.Mock() - ) as mock_file_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "FileResponse", mock.Mock() + ) as mock_file_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( side_effect=test_module.StorageNotFoundError(error_code="dummy") @@ -771,11 +847,14 @@ async def test_upload_tails_file_basic(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_upload = mock.CoroutineMock() mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( @@ -841,11 +920,14 @@ async def test_send_rev_reg_def(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -866,11 +948,14 @@ async def test_send_rev_reg_def_not_found(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "FileResponse", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "FileResponse", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( side_effect=test_module.StorageNotFoundError(error_code="dummy") @@ -909,11 +994,14 @@ async def test_send_rev_reg_entry(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -933,11 +1021,14 @@ async def test_send_rev_reg_entry_not_found(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "FileResponse", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "FileResponse", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( side_effect=test_module.StorageNotFoundError(error_code="dummy") @@ -979,11 +1070,14 @@ async def test_update_rev_reg(self): return_value={"tails_public_uri": f"http://sample.ca:8181/tails/{REV_REG_ID}"} ) - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -1007,11 +1101,14 @@ async def test_update_rev_reg_not_found(self): return_value={"tails_public_uri": f"http://sample.ca:8181/tails/{REV_REG_ID}"} ) - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "FileResponse", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "FileResponse", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( side_effect=test_module.StorageNotFoundError(error_code="dummy") @@ -1061,11 +1158,14 @@ async def test_set_rev_reg_state(self): "state": test_module.IssuerRevRegRecord.STATE_ACTIVE, } - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( return_value=mock.MagicMock( @@ -1094,11 +1194,14 @@ async def test_set_rev_reg_state_not_found(self): "state": test_module.IssuerRevRegRecord.STATE_ACTIVE, } - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as mock_indy_revoc, mock.patch.object( - test_module.web, "FileResponse", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "IndyRevocation", autospec=True + ) as mock_indy_revoc, + mock.patch.object( + test_module.web, "FileResponse", mock.Mock() + ) as mock_json_response, + ): mock_indy_revoc.return_value = mock.MagicMock( get_issuer_rev_reg_record=mock.CoroutineMock( side_effect=test_module.StorageNotFoundError(error_code="dummy") diff --git a/acapy_agent/revocation_anoncreds/routes.py b/acapy_agent/revocation_anoncreds/routes.py index 928ef0ebd8..4c5b3bd8b0 100644 --- a/acapy_agent/revocation_anoncreds/routes.py +++ b/acapy_agent/revocation_anoncreds/routes.py @@ -24,7 +24,7 @@ ) from ..anoncreds.default.legacy_indy.registry import LegacyIndyRegistry from ..anoncreds.issuer import AnonCredsIssuerError -from ..anoncreds.models.anoncreds_revocation import RevRegDefState +from ..anoncreds.models.revocation import RevRegDefState from ..anoncreds.revocation import AnonCredsRevocation, AnonCredsRevocationError from ..anoncreds.routes import ( create_transaction_for_endorser_description, diff --git a/acapy_agent/revocation_anoncreds/tests/test_manager.py b/acapy_agent/revocation_anoncreds/tests/test_manager.py index 9c62d37d9d..eeacc02929 100644 --- a/acapy_agent/revocation_anoncreds/tests/test_manager.py +++ b/acapy_agent/revocation_anoncreds/tests/test_manager.py @@ -61,16 +61,18 @@ async def test_revoke_credential_publish(self): ) self.profile.context.injector.bind_instance(AnonCredsIssuer, issuer) - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_cred_ex_id", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_cred_ex_id", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), ): mock_retrieve.return_value = mock.MagicMock( rev_reg_id="dummy-rr-id", cred_rev_id=CRED_REV_ID @@ -139,20 +141,23 @@ async def test_revoke_credential_pend(self): issuer = mock.MagicMock(AnonCredsIssuer, autospec=True) self.profile.context.injector.bind_instance(AnonCredsIssuer, issuer) - with mock.patch.object( - test_module, "IndyRevocation", autospec=True - ) as revoc, mock.patch.object( - self.profile, - "session", - mock.MagicMock(return_value=self.profile.session()), - ) as session, mock.patch.object( - self.profile, - "transaction", - mock.MagicMock(return_value=session.return_value), - ) as session, mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + with ( + mock.patch.object(test_module, "IndyRevocation", autospec=True) as revoc, + mock.patch.object( + self.profile, + "session", + mock.MagicMock(return_value=self.profile.session()), + ) as session, + mock.patch.object( + self.profile, + "transaction", + mock.MagicMock(return_value=session.return_value), + ) as session, + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), ): revoc.return_value.get_issuer_rev_reg_record = mock.CoroutineMock( return_value=mock_issuer_rev_reg_record @@ -189,14 +194,17 @@ async def test_publish_pending_revocations_basic(self): send_entry=mock.CoroutineMock(), clear_pending=mock.CoroutineMock(), ) - with mock.patch.object( - test_module.IssuerRevRegRecord, - "query_by_pending", - mock.CoroutineMock(return_value=[mock_issuer_rev_reg_record]), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "query_by_pending", + mock.CoroutineMock(return_value=[mock_issuer_rev_reg_record]), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_record), + ), ): issuer = mock.MagicMock(AnonCredsIssuer, autospec=True) issuer.merge_revocation_registry_deltas = mock.AsyncMock(side_effect=deltas) @@ -245,15 +253,18 @@ async def test_publish_pending_revocations_1_rev_reg_all(self): clear_pending=mock.CoroutineMock(), ), ] - with mock.patch.object( - test_module.IssuerRevRegRecord, - "query_by_pending", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock( - side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "query_by_pending", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock( + side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + ), ), ): issuer = mock.MagicMock(AnonCredsIssuer, autospec=True) @@ -304,15 +315,18 @@ async def test_publish_pending_revocations_1_rev_reg_some(self): clear_pending=mock.CoroutineMock(), ), ] - with mock.patch.object( - test_module.IssuerRevRegRecord, - "query_by_pending", - mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), - ), mock.patch.object( - test_module.IssuerRevRegRecord, - "retrieve_by_id", - mock.CoroutineMock( - side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + with ( + mock.patch.object( + test_module.IssuerRevRegRecord, + "query_by_pending", + mock.CoroutineMock(return_value=mock_issuer_rev_reg_records), + ), + mock.patch.object( + test_module.IssuerRevRegRecord, + "retrieve_by_id", + mock.CoroutineMock( + side_effect=lambda _, id, **args: mock_issuer_rev_reg_records[id] + ), ), ): issuer = mock.MagicMock(AnonCredsIssuer, autospec=True) diff --git a/acapy_agent/revocation_anoncreds/tests/test_routes.py b/acapy_agent/revocation_anoncreds/tests/test_routes.py index 11d4ea25e3..6f0ea1577b 100644 --- a/acapy_agent/revocation_anoncreds/tests/test_routes.py +++ b/acapy_agent/revocation_anoncreds/tests/test_routes.py @@ -6,7 +6,7 @@ from aiohttp.web import HTTPNotFound from ...admin.request_context import AdminRequestContext -from ...anoncreds.models.anoncreds_revocation import RevRegDef, RevRegDefValue +from ...anoncreds.models.revocation import RevRegDef, RevRegDefValue from ...tests import mock from ...utils.testing import create_test_profile from .. import routes as test_module @@ -85,11 +85,12 @@ async def test_revoke(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock() await test_module.revoke(self.request) @@ -104,11 +105,12 @@ async def test_revoke_by_cred_ex_id(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock() await test_module.revoke(self.request) @@ -124,9 +126,12 @@ async def test_revoke_not_found(self): } ) - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object(test_module.web, "json_response"): + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response"), + ): mock_mgr.return_value.revoke_credential = mock.CoroutineMock( side_effect=test_module.StorageNotFoundError() ) @@ -137,11 +142,12 @@ async def test_revoke_not_found(self): async def test_publish_revocations(self): self.request.json = mock.CoroutineMock() - with mock.patch.object( - test_module, "RevocationManager", autospec=True - ) as mock_mgr, mock.patch.object( - test_module.web, "json_response" - ) as mock_response: + with ( + mock.patch.object( + test_module, "RevocationManager", autospec=True + ) as mock_mgr, + mock.patch.object(test_module.web, "json_response") as mock_response, + ): pub_pending = mock.CoroutineMock() mock_mgr.return_value.publish_pending_revocations = pub_pending @@ -168,13 +174,16 @@ async def test_rev_regs_created(self): "state": test_module.IssuerRevRegRecord.STATE_ACTIVE, } - with mock.patch.object( - test_module.AnonCredsRevocation, - "get_created_revocation_registry_definitions", - mock.AsyncMock(), - ) as mock_query, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.AnonCredsRevocation, + "get_created_revocation_registry_definitions", + mock.AsyncMock(), + ) as mock_query, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_query.return_value = ["dummy"] result = await test_module.get_rev_regs(self.request) @@ -188,13 +197,15 @@ async def test_get_rev_reg(self): RECORD_ID = "4ba81d6e-f341-4e37-83d4-6b1d3e25a7bd" self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "AnonCredsRevocation", autospec=True - ) as mock_anon_creds_revoc, mock.patch.object( - test_module, "uuid4", mock.Mock() - ) as mock_uuid, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "AnonCredsRevocation", autospec=True + ) as mock_anon_creds_revoc, + mock.patch.object(test_module, "uuid4", mock.Mock()) as mock_uuid, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_uuid.return_value = RECORD_ID mock_anon_creds_revoc.return_value = mock.MagicMock( get_created_revocation_registry_definition=mock.AsyncMock( @@ -250,11 +261,14 @@ async def test_get_rev_reg_not_found(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module, "AnonCredsRevocation", autospec=True - ) as mock_anon_creds_revoc, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "AnonCredsRevocation", autospec=True + ) as mock_anon_creds_revoc, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_anon_creds_revoc.return_value = mock.MagicMock( get_created_revocation_registry_definition=mock.AsyncMock( return_value=None @@ -271,17 +285,21 @@ async def test_get_rev_reg_issued(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module.AnonCredsRevocation, - "get_created_revocation_registry_definition", - autospec=True, - ) as mock_rev_reg_def, mock.patch.object( - test_module.IssuerCredRevRecord, - "query_by_ids", - mock.CoroutineMock(), - ) as mock_query, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.AnonCredsRevocation, + "get_created_revocation_registry_definition", + autospec=True, + ) as mock_rev_reg_def, + mock.patch.object( + test_module.IssuerCredRevRecord, + "query_by_ids", + mock.CoroutineMock(), + ) as mock_query, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_rev_reg_def.return_value = {} mock_query.return_value = [{}, {}] result = await test_module.get_rev_reg_issued_count(self.request) @@ -316,13 +334,16 @@ async def test_get_cred_rev_record(self): "cred_rev_id": CRED_REV_ID, } - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_ids", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_ids", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value="dummy") ) @@ -336,13 +357,16 @@ async def test_get_cred_rev_record_by_cred_ex_id(self): self.request.query = {"cred_ex_id": CRED_EX_ID} - with mock.patch.object( - test_module.IssuerCredRevRecord, - "retrieve_by_cred_ex_id", - mock.CoroutineMock(), - ) as mock_retrieve, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.IssuerCredRevRecord, + "retrieve_by_cred_ex_id", + mock.CoroutineMock(), + ) as mock_retrieve, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_retrieve.return_value = mock.MagicMock( serialize=mock.MagicMock(return_value="dummy") ) @@ -379,13 +403,16 @@ async def test_get_tails_file(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module.AnonCredsRevocation, - "get_created_revocation_registry_definition", - mock.AsyncMock(), - ) as mock_get_rev_reg, mock.patch.object( - test_module.web, "FileResponse", mock.Mock() - ) as mock_file_response: + with ( + mock.patch.object( + test_module.AnonCredsRevocation, + "get_created_revocation_registry_definition", + mock.AsyncMock(), + ) as mock_get_rev_reg, + mock.patch.object( + test_module.web, "FileResponse", mock.Mock() + ) as mock_file_response, + ): mock_get_rev_reg.return_value = RevRegDef( issuer_id="issuer_id", type="CL_ACCUM", @@ -409,13 +436,16 @@ async def test_get_tails_file_not_found(self): ) self.request.match_info = {"rev_reg_id": REV_REG_ID} - with mock.patch.object( - test_module.AnonCredsRevocation, - "get_created_revocation_registry_definition", - mock.AsyncMock(), - ) as mock_get_rev_reg, mock.patch.object( - test_module.web, "FileResponse", mock.Mock() - ) as mock_file_response: + with ( + mock.patch.object( + test_module.AnonCredsRevocation, + "get_created_revocation_registry_definition", + mock.AsyncMock(), + ) as mock_get_rev_reg, + mock.patch.object( + test_module.web, "FileResponse", mock.Mock() + ) as mock_file_response, + ): mock_get_rev_reg.return_value = None with self.assertRaises(HTTPNotFound): @@ -433,13 +463,15 @@ async def test_set_rev_reg_state(self): "state": test_module.RevRegDefState.STATE_FINISHED, } - with mock.patch.object( - test_module, "AnonCredsRevocation", autospec=True - ) as mock_anon_creds_revoc, mock.patch.object( - test_module, "uuid4", mock.Mock() - ) as mock_uuid, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module, "AnonCredsRevocation", autospec=True + ) as mock_anon_creds_revoc, + mock.patch.object(test_module, "uuid4", mock.Mock()) as mock_uuid, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_uuid.return_value = RECORD_ID mock_anon_creds_revoc.return_value = mock.MagicMock( set_rev_reg_state=mock.AsyncMock(return_value={}), @@ -500,13 +532,16 @@ async def test_set_rev_reg_state_not_found(self): "state": test_module.RevRegDefState.STATE_FINISHED, } - with mock.patch.object( - test_module.AnonCredsRevocation, - "get_created_revocation_registry_definition", - mock.AsyncMock(), - ) as mock_rev_reg_def, mock.patch.object( - test_module.web, "json_response", mock.Mock() - ) as mock_json_response: + with ( + mock.patch.object( + test_module.AnonCredsRevocation, + "get_created_revocation_registry_definition", + mock.AsyncMock(), + ) as mock_rev_reg_def, + mock.patch.object( + test_module.web, "json_response", mock.Mock() + ) as mock_json_response, + ): mock_rev_reg_def.return_value = None with self.assertRaises(HTTPNotFound): diff --git a/acapy_agent/settings/tests/test_routes.py b/acapy_agent/settings/tests/test_routes.py index 7327093c78..707aa6760a 100644 --- a/acapy_agent/settings/tests/test_routes.py +++ b/acapy_agent/settings/tests/test_routes.py @@ -190,11 +190,12 @@ async def test_update_profile_settings(mock_response, profile): ), __getitem__=lambda _, k: request_dict[k], ) - with mock.patch.object( - multi_tenant_manager, "update_wallet" - ) as update_wallet, mock.patch.object( - multi_tenant_manager, "get_wallet_and_profile" - ) as get_wallet_and_profile: + with ( + mock.patch.object(multi_tenant_manager, "update_wallet") as update_wallet, + mock.patch.object( + multi_tenant_manager, "get_wallet_and_profile" + ) as get_wallet_and_profile, + ): get_wallet_and_profile.return_value = ( mock.MagicMock( settings={ diff --git a/acapy_agent/storage/tests/test_askar_storage.py b/acapy_agent/storage/tests/test_askar_storage.py index b36925ea7f..e9ddfce247 100644 --- a/acapy_agent/storage/tests/test_askar_storage.py +++ b/acapy_agent/storage/tests/test_askar_storage.py @@ -46,17 +46,23 @@ class TestAskarStorage: @pytest.mark.skip @pytest.mark.asyncio async def test_record(self): - with mock.patch.object( - indy.wallet, "create_wallet", mock.CoroutineMock() - ) as mock_create, mock.patch.object( - indy.wallet, "open_wallet", mock.CoroutineMock() - ) as mock_open, mock.patch.object( - indy.anoncreds, "prover_create_master_secret", mock.CoroutineMock() - ) as mock_master, mock.patch.object( - indy.wallet, "close_wallet", mock.CoroutineMock() - ) as mock_close, mock.patch.object( - indy.wallet, "delete_wallet", mock.CoroutineMock() - ) as mock_delete: + with ( + mock.patch.object( + indy.wallet, "create_wallet", mock.CoroutineMock() + ) as mock_create, + mock.patch.object( + indy.wallet, "open_wallet", mock.CoroutineMock() + ) as mock_open, + mock.patch.object( + indy.anoncreds, "prover_create_master_secret", mock.CoroutineMock() + ) as mock_master, + mock.patch.object( + indy.wallet, "close_wallet", mock.CoroutineMock() + ) as mock_close, + mock.patch.object( + indy.wallet, "delete_wallet", mock.CoroutineMock() + ) as mock_delete, + ): fake_wallet = AskarWallet( { "auto_create": True, @@ -154,19 +160,23 @@ async def test_record(self): with pytest.raises(test_module.StorageError): await storage.get_record("connection", "dummy-id") - with mock.patch.object( - test_module.non_secrets, - "update_wallet_record_value", - mock.CoroutineMock(), - ) as mock_update_value, mock.patch.object( - test_module.non_secrets, - "update_wallet_record_tags", - mock.CoroutineMock(), - ) as mock_update_tags, mock.patch.object( - test_module.non_secrets, - "delete_wallet_record", - mock.CoroutineMock(), - ) as mock_delete: + with ( + mock.patch.object( + test_module.non_secrets, + "update_wallet_record_value", + mock.CoroutineMock(), + ) as mock_update_value, + mock.patch.object( + test_module.non_secrets, + "update_wallet_record_tags", + mock.CoroutineMock(), + ) as mock_update_tags, + mock.patch.object( + test_module.non_secrets, + "delete_wallet_record", + mock.CoroutineMock(), + ) as mock_delete, + ): mock_update_value.side_effect = test_module.IndyError( test_module.ErrorCode.CommonInvalidStructure ) @@ -209,17 +219,23 @@ async def test_record(self): @pytest.mark.skip @pytest.mark.asyncio async def test_storage_search_x(self): - with mock.patch.object( - indy.wallet, "create_wallet", mock.CoroutineMock() - ) as mock_create, mock.patch.object( - indy.wallet, "open_wallet", mock.CoroutineMock() - ) as mock_open, mock.patch.object( - indy.anoncreds, "prover_create_master_secret", mock.CoroutineMock() - ) as mock_master, mock.patch.object( - indy.wallet, "close_wallet", mock.CoroutineMock() - ) as mock_close, mock.patch.object( - indy.wallet, "delete_wallet", mock.CoroutineMock() - ) as mock_delete: + with ( + mock.patch.object( + indy.wallet, "create_wallet", mock.CoroutineMock() + ) as mock_create, + mock.patch.object( + indy.wallet, "open_wallet", mock.CoroutineMock() + ) as mock_open, + mock.patch.object( + indy.anoncreds, "prover_create_master_secret", mock.CoroutineMock() + ) as mock_master, + mock.patch.object( + indy.wallet, "close_wallet", mock.CoroutineMock() + ) as mock_close, + mock.patch.object( + indy.wallet, "delete_wallet", mock.CoroutineMock() + ) as mock_delete, + ): fake_wallet = AskarWallet( { "auto_create": True, @@ -246,26 +262,33 @@ async def test_storage_search_x(self): with pytest.raises(StorageSearchError): await search.fetch(10) - with mock.patch.object( - indy.non_secrets, "open_wallet_search", mock.CoroutineMock() - ) as mock_indy_open_search, mock.patch.object( - indy.non_secrets, "close_wallet_search", mock.CoroutineMock() - ) as mock_indy_close_search: + with ( + mock.patch.object( + indy.non_secrets, "open_wallet_search", mock.CoroutineMock() + ) as mock_indy_open_search, + mock.patch.object( + indy.non_secrets, "close_wallet_search", mock.CoroutineMock() + ) as mock_indy_close_search, + ): mock_indy_open_search.side_effect = test_module.IndyError("no open") search = storage.search_records("connection") with pytest.raises(StorageSearchError): await search.open() await search.close() - with mock.patch.object( - indy.non_secrets, "open_wallet_search", mock.CoroutineMock() - ) as mock_indy_open_search, mock.patch.object( - indy.non_secrets, - "fetch_wallet_search_next_records", - mock.CoroutineMock(), - ) as mock_indy_fetch, mock.patch.object( - indy.non_secrets, "close_wallet_search", mock.CoroutineMock() - ) as mock_indy_close_search: + with ( + mock.patch.object( + indy.non_secrets, "open_wallet_search", mock.CoroutineMock() + ) as mock_indy_open_search, + mock.patch.object( + indy.non_secrets, + "fetch_wallet_search_next_records", + mock.CoroutineMock(), + ) as mock_indy_fetch, + mock.patch.object( + indy.non_secrets, "close_wallet_search", mock.CoroutineMock() + ) as mock_indy_close_search, + ): mock_indy_fetch.side_effect = test_module.IndyError("no fetch") search = storage.search_records("connection") await search.open() @@ -273,11 +296,14 @@ async def test_storage_search_x(self): await search.fetch(10) await search.close() - with mock.patch.object( - indy.non_secrets, "open_wallet_search", mock.CoroutineMock() - ) as mock_indy_open_search, mock.patch.object( - indy.non_secrets, "close_wallet_search", mock.CoroutineMock() - ) as mock_indy_close_search: + with ( + mock.patch.object( + indy.non_secrets, "open_wallet_search", mock.CoroutineMock() + ) as mock_indy_open_search, + mock.patch.object( + indy.non_secrets, "close_wallet_search", mock.CoroutineMock() + ) as mock_indy_close_search, + ): mock_indy_close_search.side_effect = test_module.IndyError("no close") search = storage.search_records("connection") await search.open() @@ -359,7 +385,7 @@ async def test_askar_storage_search_session(self): profile = "profileId" with mock.patch("acapy_agent.storage.askar.AskarProfile") as AskarProfile: - askar_profile = AskarProfile(None, True) + askar_profile = await AskarProfile.create(None, True) askar_profile_scan = mock.MagicMock() askar_profile.store.scan.return_value = askar_profile_scan askar_profile.settings.get.return_value = profile diff --git a/acapy_agent/tests/test_main.py b/acapy_agent/tests/test_main.py index ea2d7b0573..c403d0469d 100644 --- a/acapy_agent/tests/test_main.py +++ b/acapy_agent/tests/test_main.py @@ -5,11 +5,11 @@ class TestMain(TestCase): def test_main(self): - with mock.patch.object(test_module, "__name__", "__main__"), mock.patch.object( - test_module, "init_debug", mock.MagicMock() - ) as mock_debug, mock.patch.object( - test_module, "run", mock.MagicMock() - ) as mock_run: + with ( + mock.patch.object(test_module, "__name__", "__main__"), + mock.patch.object(test_module, "init_debug", mock.MagicMock()) as mock_debug, + mock.patch.object(test_module, "run", mock.MagicMock()) as mock_run, + ): args = ["aca-py"] test_module.main(args) mock_debug.assert_called_once_with(args) diff --git a/acapy_agent/transport/inbound/tests/test_session.py b/acapy_agent/transport/inbound/tests/test_session.py index 985fbc7f3a..421adcc3c8 100644 --- a/acapy_agent/transport/inbound/tests/test_session.py +++ b/acapy_agent/transport/inbound/tests/test_session.py @@ -134,11 +134,10 @@ async def test_receive(self): ) test_msg = mock.MagicMock() - with mock.patch.object( - sess, "parse_inbound", mock.CoroutineMock() - ) as encode, mock.patch.object( - sess, "receive_inbound", mock.MagicMock() - ) as receive: + with ( + mock.patch.object(sess, "parse_inbound", mock.CoroutineMock()) as encode, + mock.patch.object(sess, "receive_inbound", mock.MagicMock()) as receive, + ): result = await sess.receive(test_msg) encode.assert_awaited_once_with(test_msg) receive.assert_called_once_with(encode.return_value) @@ -165,11 +164,10 @@ async def test_receive_no_wallet_found(self): ) test_msg = mock.MagicMock() - with mock.patch.object( - sess, "parse_inbound", mock.CoroutineMock() - ) as encode, mock.patch.object( - sess, "receive_inbound", mock.MagicMock() - ) as receive: + with ( + mock.patch.object(sess, "parse_inbound", mock.CoroutineMock()) as encode, + mock.patch.object(sess, "receive_inbound", mock.MagicMock()) as receive, + ): result = await sess.receive(test_msg) encode.assert_awaited_once_with(test_msg) receive.assert_called_once_with(encode.return_value) diff --git a/acapy_agent/transport/outbound/tests/test_manager.py b/acapy_agent/transport/outbound/tests/test_manager.py index abdd0252a2..18ad129a8f 100644 --- a/acapy_agent/transport/outbound/tests/test_manager.py +++ b/acapy_agent/transport/outbound/tests/test_manager.py @@ -224,11 +224,13 @@ async def test_process_loop_new(self): message=mock.MagicMock(enc_payload=b"encr"), ) ] - with mock.patch.object( - mgr, "deliver_queued_message", mock.MagicMock() - ), mock.patch.object( - mgr.outbound_event, "wait", mock.CoroutineMock() - ) as mock_wait, mock.patch.object(test_module, "trace_event", mock.MagicMock()): + with ( + mock.patch.object(mgr, "deliver_queued_message", mock.MagicMock()), + mock.patch.object( + mgr.outbound_event, "wait", mock.CoroutineMock() + ) as mock_wait, + mock.patch.object(test_module, "trace_event", mock.MagicMock()), + ): mock_wait.side_effect = KeyError() # cover state=NEW logic and bail with self.assertRaises(KeyError): @@ -245,11 +247,13 @@ async def test_process_loop_new_deliver(self): message=mock.MagicMock(enc_payload=b"encr"), ) ] - with mock.patch.object( - mgr, "deliver_queued_message", mock.MagicMock() - ), mock.patch.object( - mgr.outbound_event, "wait", mock.CoroutineMock() - ) as mock_wait, mock.patch.object(test_module, "trace_event", mock.MagicMock()): + with ( + mock.patch.object(mgr, "deliver_queued_message", mock.MagicMock()), + mock.patch.object( + mgr.outbound_event, "wait", mock.CoroutineMock() + ) as mock_wait, + mock.patch.object(test_module, "trace_event", mock.MagicMock()), + ): mock_wait.side_effect = KeyError() # cover state=DELIVER logic and bail with self.assertRaises(KeyError): @@ -278,14 +282,13 @@ async def test_finished_deliver_x_log_debug(self): mock_handle_not_delivered = mock.MagicMock() mgr = OutboundTransportManager(self.profile, mock_handle_not_delivered) mgr.outbound_buffer.append(mock_queued) - with mock.patch.object( - test_module.LOGGER, "exception", mock.MagicMock() - ), mock.patch.object( - test_module.LOGGER, "error", mock.MagicMock() - ), mock.patch.object( - test_module.LOGGER, "isEnabledFor", mock.MagicMock() - ) as mock_logger_enabled, mock.patch.object( - mgr, "process_queued", mock.MagicMock() + with ( + mock.patch.object(test_module.LOGGER, "exception", mock.MagicMock()), + mock.patch.object(test_module.LOGGER, "error", mock.MagicMock()), + mock.patch.object( + test_module.LOGGER, "isEnabledFor", mock.MagicMock() + ) as mock_logger_enabled, + mock.patch.object(mgr, "process_queued", mock.MagicMock()), ): mock_logger_enabled.return_value = True # cover debug logging mgr.finished_deliver(mock_queued, mock_completed_x) diff --git a/acapy_agent/transport/queue/tests/test_basic_queue.py b/acapy_agent/transport/queue/tests/test_basic_queue.py index 6d54899f69..992ba3a7be 100644 --- a/acapy_agent/transport/queue/tests/test_basic_queue.py +++ b/acapy_agent/transport/queue/tests/test_basic_queue.py @@ -37,13 +37,16 @@ async def test_dequeue_x(self): test_value = "test value" await queue.enqueue(test_value) - with mock.patch.object( - test_module.asyncio, "get_event_loop", mock.MagicMock() - ) as mock_get_event_loop, mock.patch.object( - test_module.asyncio, "wait", mock.CoroutineMock() - ) as mock_wait, mock.patch.object( - queue, "stop_event" - ) as mock_stop_event, mock.patch.object(queue, "queue"): + with ( + mock.patch.object( + test_module.asyncio, "get_event_loop", mock.MagicMock() + ) as mock_get_event_loop, + mock.patch.object( + test_module.asyncio, "wait", mock.CoroutineMock() + ) as mock_wait, + mock.patch.object(queue, "stop_event") as mock_stop_event, + mock.patch.object(queue, "queue"), + ): mock_stop_event.is_set.return_value = False mock_wait.return_value = ( mock.MagicMock(), @@ -68,13 +71,16 @@ async def test_dequeue_none(self): test_value = "test value" await queue.enqueue(test_value) - with mock.patch.object( - test_module.asyncio, "get_event_loop", mock.MagicMock() - ) as mock_get_event_loop, mock.patch.object( - test_module.asyncio, "wait", mock.CoroutineMock() - ) as mock_wait, mock.patch.object( - queue, "stop_event" - ) as mock_stop_event, mock.patch.object(queue, "queue"): + with ( + mock.patch.object( + test_module.asyncio, "get_event_loop", mock.MagicMock() + ) as mock_get_event_loop, + mock.patch.object( + test_module.asyncio, "wait", mock.CoroutineMock() + ) as mock_wait, + mock.patch.object(queue, "stop_event") as mock_stop_event, + mock.patch.object(queue, "queue"), + ): mock_stop_event.is_set.return_value = False mock_wait.return_value = ( mock.MagicMock(), diff --git a/acapy_agent/transport/v2_pack_format.py b/acapy_agent/transport/v2_pack_format.py index 266c0b8b08..92e26da698 100644 --- a/acapy_agent/transport/v2_pack_format.py +++ b/acapy_agent/transport/v2_pack_format.py @@ -63,8 +63,7 @@ async def parse_message( try: message_unpack = await messaging.unpack(message_json) except CryptoServiceError: - LOGGER.debug("Message unpack failed, falling back to JSON") - print("HIT CRTYPTO SER ERR EXCEPT BLOC") + LOGGER.info("Message unpack failed, falling back to JSON") else: # Set message_dict to be the dictionary that we unpacked message_dict = message_unpack.message diff --git a/acapy_agent/utils/classloader.py b/acapy_agent/utils/classloader.py index 29fd81bc4d..0889f50dc8 100644 --- a/acapy_agent/utils/classloader.py +++ b/acapy_agent/utils/classloader.py @@ -1,6 +1,7 @@ """The classloader provides utilities to dynamically load classes and modules.""" import inspect +import logging import sys from importlib import import_module, resources from importlib.util import find_spec, resolve_name @@ -9,6 +10,8 @@ from ..core.error import BaseError +LOGGER = logging.getLogger(__name__) + class ModuleLoadError(BaseError): """Module load error.""" @@ -22,7 +25,9 @@ class ClassLoader: """Class used to load classes from modules dynamically.""" @classmethod - def load_module(cls, mod_path: str, package: Optional[str] = None) -> ModuleType: + def load_module( + cls, mod_path: str, package: Optional[str] = None + ) -> Optional[ModuleType]: """Load a module by its absolute path. Args: @@ -36,6 +41,7 @@ def load_module(cls, mod_path: str, package: Optional[str] = None) -> ModuleType ModuleLoadError: If there was an error loading the module """ + if package: # preload parent package if not cls.load_module(package): @@ -45,6 +51,7 @@ def load_module(cls, mod_path: str, package: Optional[str] = None) -> ModuleType mod_path = f".{mod_path}" full_path = resolve_name(mod_path, package) + if full_path in sys.modules: return sys.modules[full_path] @@ -58,7 +65,6 @@ def load_module(cls, mod_path: str, package: Optional[str] = None) -> ModuleType mod_path = f".{mod_name}" # Load the module spec first - # this means that a later ModuleNotFoundError indicates a code issue spec = find_spec(mod_path, package) if not spec: return None @@ -66,6 +72,7 @@ def load_module(cls, mod_path: str, package: Optional[str] = None) -> ModuleType try: return import_module(mod_path, package) except ModuleNotFoundError as e: + LOGGER.warning("Module %s not found during import", full_path) raise ModuleLoadError(f"Unable to import module {full_path}: {str(e)}") from e @classmethod @@ -96,24 +103,36 @@ def load_class( mod_path, class_name = class_name.rsplit(".", 1) elif default_module: mod_path = default_module + LOGGER.debug("No module in class name, using default_module: %s", mod_path) else: + LOGGER.warning( + "Cannot resolve class name %s with no default module", class_name + ) raise ClassNotFoundError( f"Cannot resolve class name with no default module: {class_name}" ) mod = cls.load_module(mod_path, package) if not mod: - raise ClassNotFoundError(f"Module '{mod_path}' not found") + LOGGER.warning( + "Module %s not found when loading class %s", mod_path, class_name + ) + raise ClassNotFoundError(f"Module {mod_path} not found") resolved = getattr(mod, class_name, None) if not resolved: + LOGGER.warning("Class %s not found in module %s", class_name, mod_path) raise ClassNotFoundError( f"Class '{class_name}' not defined in module: {mod_path}" ) if not isinstance(resolved, type): + LOGGER.warning( + "Resolved attribute %s in module %s is not a class", class_name, mod_path + ) raise ClassNotFoundError( f"Resolved value is not a class: {mod_path}.{class_name}" ) + LOGGER.debug("Successfully loaded class %s from module %s", class_name, mod_path) return resolved @classmethod @@ -138,9 +157,14 @@ def load_subclass_of( mod = cls.load_module(mod_path, package) if not mod: + LOGGER.warning( + "Module %s not found when loading subclass of %s", + mod_path, + base_class.__name__, + ) raise ClassNotFoundError(f"Module '{mod_path}' not found") - # Find an the first declared class that inherits from + # Find the first declared class that inherits from the base_class try: imported_class = next( obj @@ -148,6 +172,11 @@ def load_subclass_of( if issubclass(obj, base_class) and obj is not base_class ) except StopIteration: + LOGGER.debug( + "No subclass of %s found in module %s", + base_class.__name__, + mod_path, + ) raise ClassNotFoundError( f"Could not resolve a class that inherits from {base_class}" ) from None @@ -156,17 +185,22 @@ def load_subclass_of( @classmethod def scan_subpackages(cls, package: str) -> Sequence[str]: """Return a list of sub-packages defined under a named package.""" + LOGGER.debug("Scanning subpackages under package %s", package) if "." in package: package, sub_pkg = package.split(".", 1) + LOGGER.debug("Extracted main package: %s, sub-package: %s", package, sub_pkg) else: sub_pkg = "." + LOGGER.debug("No sub-package provided, defaulting to %s", sub_pkg) try: package_path = resources.files(package) except FileNotFoundError: + LOGGER.warning("Package %s not found during subpackage scan", package) raise ModuleLoadError(f"Undefined package {package}") if not (package_path / sub_pkg).is_dir(): + LOGGER.warning("Sub-package %s is not a directory under %s", sub_pkg, package) raise ModuleLoadError(f"Undefined package {package}") found = [] @@ -174,25 +208,30 @@ def scan_subpackages(cls, package: str) -> Sequence[str]: sub_path = package_path / sub_pkg for item in sub_path.iterdir(): if (item / "__init__.py").exists(): - found.append(f"{package}.{joiner}{item.name}") + subpackage = f"{package}.{joiner}{item.name}" + found.append(subpackage) + LOGGER.debug("%d sub-packages found under %s: %s", len(found), package, found) return found class DeferLoad: """Helper to defer loading of a class definition.""" + _class_cache = {} # Shared cache for resolved classes + def __init__(self, cls_path: str): """Initialize the `DeferLoad` instance with a qualified class path.""" self._cls_path = cls_path - self._inst = None def __call__(self, *args, **kwargs): """Magic method to call the `DeferLoad` as a function.""" - return (self.resolved)(*args, **kwargs) + return self.resolved(*args, **kwargs) @property def resolved(self): """Accessor for the resolved class instance.""" - if not self._inst: - self._inst = ClassLoader.load_class(self._cls_path) - return self._inst + if self._cls_path not in DeferLoad._class_cache: + DeferLoad._class_cache[self._cls_path] = ClassLoader.load_class( + self._cls_path + ) + return DeferLoad._class_cache[self._cls_path] diff --git a/acapy_agent/utils/testing.py b/acapy_agent/utils/testing.py index 2ee34cf125..169bfb3cd8 100644 --- a/acapy_agent/utils/testing.py +++ b/acapy_agent/utils/testing.py @@ -38,11 +38,11 @@ async def create_test_profile( opened = await store_config.open_store(provision=True, in_memory=True) if settings.get("wallet.type") == "askar-anoncreds": - return AskarAnoncredsProfile( + return await AskarAnoncredsProfile.create( opened=opened, context=context, ) - return AskarProfile( + return await AskarProfile.create( opened=opened, context=context, ) diff --git a/acapy_agent/utils/tests/test_classloader.py b/acapy_agent/utils/tests/test_classloader.py index 5a9c8be5e5..daead84132 100644 --- a/acapy_agent/utils/tests/test_classloader.py +++ b/acapy_agent/utils/tests/test_classloader.py @@ -42,9 +42,12 @@ def test_import_missing(self): assert ClassLoader.load_module("acapy_agent", "not.a-module") is None def test_import_error(self): - with mock.patch.object( - test_module, "import_module", autospec=True - ) as import_module, mock.patch.object(test_module.sys, "modules", {}): + with ( + mock.patch.object( + test_module, "import_module", autospec=True + ) as import_module, + mock.patch.object(test_module.sys, "modules", {}), + ): import_module.side_effect = ModuleNotFoundError with self.assertRaises(ModuleLoadError): ClassLoader.load_module("acapy_agent.config") diff --git a/acapy_agent/utils/tests/test_task_queue.py b/acapy_agent/utils/tests/test_task_queue.py index 26815e87cc..b079bf53bb 100644 --- a/acapy_agent/utils/tests/test_task_queue.py +++ b/acapy_agent/utils/tests/test_task_queue.py @@ -106,11 +106,10 @@ def done(complete: CompletedTask): async def noop(): return - with mock.patch.object( - queue, "drain", mock.MagicMock() - ) as mock_drain, mock.patch.object( - queue, "wait_for", mock.CoroutineMock() - ) as mock_wait_for: + with ( + mock.patch.object(queue, "drain", mock.MagicMock()) as mock_drain, + mock.patch.object(queue, "wait_for", mock.CoroutineMock()) as mock_wait_for, + ): mock_drain.side_effect = [queue.loop.create_task(noop()), None] await queue.complete(cleanup=True) diff --git a/acapy_agent/vc/ld_proofs/crypto/key_pair.py b/acapy_agent/vc/ld_proofs/crypto/key_pair.py index 0409bc3769..c11e249eea 100644 --- a/acapy_agent/vc/ld_proofs/crypto/key_pair.py +++ b/acapy_agent/vc/ld_proofs/crypto/key_pair.py @@ -1,6 +1,6 @@ """Base key pair class.""" -from abc import ABC, abstractmethod, abstractproperty +from abc import ABC, abstractmethod from typing import List, Optional, Union @@ -15,7 +15,8 @@ async def sign(self, message: Union[List[bytes], bytes]) -> bytes: async def verify(self, message: Union[List[bytes], bytes], signature: bytes) -> bool: """Verify message(s) against signature using key pair.""" - @abstractproperty + @property + @abstractmethod def has_public_key(self) -> bool: """Whether key pair has a public key. @@ -23,7 +24,8 @@ def has_public_key(self) -> bool: in the verification process. """ - @abstractproperty + @property + @abstractmethod def public_key(self) -> Optional[bytes]: """Getter for the public key bytes. diff --git a/acapy_agent/vc/vc_di/prove.py b/acapy_agent/vc/vc_di/prove.py index 33c94fa544..acba4359fe 100644 --- a/acapy_agent/vc/vc_di/prove.py +++ b/acapy_agent/vc/vc_di/prove.py @@ -1,6 +1,7 @@ """Verifiable Credential and Presentation proving methods.""" import asyncio +import logging import re from hashlib import sha256 from typing import Any, Optional, Tuple @@ -20,6 +21,8 @@ from ...core.profile import Profile from ..ld_proofs import LinkedDataProofException, ProofPurpose +LOGGER = logging.getLogger(__name__) + async def create_signed_anoncreds_presentation( *, @@ -311,7 +314,7 @@ async def prepare_data_for_presentation( # issuer_id = field["filter"]["const"] pass else: - print("... skipping:", path) + LOGGER.info("... skipping: %s", path) return anoncreds_proofrequest, w3c_creds_metadata diff --git a/acapy_agent/vc/vc_ld/models/linked_data_proof.py b/acapy_agent/vc/vc_ld/models/linked_data_proof.py index c441ff5911..57853000c6 100644 --- a/acapy_agent/vc/vc_ld/models/linked_data_proof.py +++ b/acapy_agent/vc/vc_ld/models/linked_data_proof.py @@ -6,8 +6,8 @@ from ....messaging.models.base import BaseModel, BaseModelSchema from ....messaging.valid import ( - INDY_ISO8601_DATETIME_EXAMPLE, - INDY_ISO8601_DATETIME_VALIDATE, + ISO8601_DATETIME_EXAMPLE, + ISO8601_DATETIME_VALIDATE, UUID4_EXAMPLE, Uri, ) @@ -93,13 +93,13 @@ class Meta: created = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": ( "The string value of an ISO8601 combined date and time string generated" " by the Signature Algorithm" ), - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) diff --git a/acapy_agent/vc/vc_ld/models/options.py b/acapy_agent/vc/vc_ld/models/options.py index 2d7adbe4e2..a939df56ac 100644 --- a/acapy_agent/vc/vc_ld/models/options.py +++ b/acapy_agent/vc/vc_ld/models/options.py @@ -5,8 +5,8 @@ from marshmallow import INCLUDE, Schema, fields from acapy_agent.messaging.valid import ( - INDY_ISO8601_DATETIME_EXAMPLE, - INDY_ISO8601_DATETIME_VALIDATE, + ISO8601_DATETIME_EXAMPLE, + ISO8601_DATETIME_VALIDATE, UUID4_EXAMPLE, ) @@ -124,13 +124,13 @@ class Meta: created = fields.Str( required=False, - validate=INDY_ISO8601_DATETIME_VALIDATE, + validate=ISO8601_DATETIME_VALIDATE, metadata={ "description": ( "The date and time of the proof (with a maximum accuracy in seconds)." " Defaults to current system time" ), - "example": INDY_ISO8601_DATETIME_EXAMPLE, + "example": ISO8601_DATETIME_EXAMPLE, }, ) diff --git a/acapy_agent/vc/vc_ld/tests/test_manager.py b/acapy_agent/vc/vc_ld/tests/test_manager.py index 7b5dd4c81b..bc6a5b3d4b 100644 --- a/acapy_agent/vc/vc_ld/tests/test_manager.py +++ b/acapy_agent/vc/vc_ld/tests/test_manager.py @@ -158,15 +158,18 @@ async def test_get_did_info_for_did_sov(self): assert did_info == did async def test_get_suite_for_document(self): - with mock.patch.object( - self.manager, - "assert_can_issue_with_id_and_proof_type", - mock.CoroutineMock(), - ) as mock_can_issue, mock.patch.object( - self.manager, - "_did_info_for_did", - mock.CoroutineMock(), - ) as mock_did_info: + with ( + mock.patch.object( + self.manager, + "assert_can_issue_with_id_and_proof_type", + mock.CoroutineMock(), + ) as mock_can_issue, + mock.patch.object( + self.manager, + "_did_info_for_did", + mock.CoroutineMock(), + ) as mock_did_info, + ): suite = await self.manager._get_suite_for_document(self.vc, self.options) assert suite.signature_type == self.options.proof_type diff --git a/acapy_agent/wallet/anoncreds_upgrade.py b/acapy_agent/wallet/anoncreds_upgrade.py index 12f2cb2dd3..4261acf0eb 100644 --- a/acapy_agent/wallet/anoncreds_upgrade.py +++ b/acapy_agent/wallet/anoncreds_upgrade.py @@ -21,15 +21,15 @@ CATEGORY_CRED_DEF_PRIVATE, CATEGORY_SCHEMA, ) -from ..anoncreds.models.anoncreds_cred_def import CredDef, CredDefState -from ..anoncreds.models.anoncreds_revocation import ( +from ..anoncreds.models.credential_definition import CredDef, CredDefState +from ..anoncreds.models.revocation import ( RevList, RevListState, RevRegDef, RevRegDefState, RevRegDefValue, ) -from ..anoncreds.models.anoncreds_schema import SchemaState +from ..anoncreds.models.schema import SchemaState from ..anoncreds.revocation import ( CATEGORY_REV_LIST, CATEGORY_REV_REG_DEF, @@ -699,6 +699,7 @@ async def check_upgrade_completion_loop(profile: Profile, is_subwallet=False): UpgradeInProgressSingleton().remove_wallet(profile.name) if is_subwallet: await upgrade_subwallet(profile) + await finish_upgrade(profile) LOGGER.info( f"""Upgrade of subwallet {profile.settings.get('wallet.name')} has completed. Profile is now askar-anoncreds""" # noqa: E501 ) diff --git a/acapy_agent/wallet/crypto.py b/acapy_agent/wallet/crypto.py index 0ceef63a91..37ddeb7a13 100644 --- a/acapy_agent/wallet/crypto.py +++ b/acapy_agent/wallet/crypto.py @@ -1,5 +1,6 @@ """Cryptography functions used by BasicWallet.""" +import logging import re from collections import OrderedDict from typing import Callable, List, Optional, Sequence, Tuple, Union @@ -20,6 +21,8 @@ from .key_type import BLS12381G2, ED25519, KeyType from .util import b58_to_bytes, b64_to_bytes, bytes_to_b58, random_seed +LOGGER = logging.getLogger(__name__) + def create_keypair( key_type: KeyType, seed: Optional[bytes] = None @@ -423,7 +426,7 @@ def decode_pack_message_outer(enc_message: bytes) -> Tuple[dict, dict, bool]: try: wrapper = JweEnvelope.from_json(enc_message) except ValidationError as err: - print(err) + LOGGER.error(err) raise ValueError("Invalid packed message") alg = wrapper.protected.get("alg") diff --git a/acapy_agent/wallet/routes.py b/acapy_agent/wallet/routes.py index 00bc48cfb1..cf539d61ac 100644 --- a/acapy_agent/wallet/routes.py +++ b/acapy_agent/wallet/routes.py @@ -9,11 +9,10 @@ from aiohttp_apispec import docs, querystring_schema, request_schema, response_schema from marshmallow import fields, validate -from acapy_agent.connections.base_manager import BaseConnectionManager - from ..admin.decorators.auth import tenant_authentication from ..admin.request_context import AdminRequestContext from ..config.injection_context import InjectionContext +from ..connections.base_manager import BaseConnectionManager from ..connections.models.conn_record import ConnRecord from ..core.event_bus import Event, EventBus from ..core.profile import Profile @@ -35,12 +34,12 @@ GENERIC_DID_VALIDATE, INDY_DID_EXAMPLE, INDY_DID_VALIDATE, - INDY_RAW_PUBLIC_KEY_EXAMPLE, - INDY_RAW_PUBLIC_KEY_VALIDATE, JWT_EXAMPLE, JWT_VALIDATE, NON_SD_LIST_EXAMPLE, NON_SD_LIST_VALIDATE, + RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, + RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, SD_JWT_EXAMPLE, SD_JWT_VALIDATE, UUID4_EXAMPLE, @@ -95,10 +94,10 @@ class DIDSchema(OpenAPISchema): ) verkey = fields.Str( required=True, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Public verification key", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) posture = fields.Str( @@ -293,10 +292,10 @@ class DIDListQueryStringSchema(OpenAPISchema): ) verkey = fields.Str( required=False, - validate=INDY_RAW_PUBLIC_KEY_VALIDATE, + validate=RAW_ED25519_2018_PUBLIC_KEY_VALIDATE, metadata={ "description": "Verification key of interest", - "example": INDY_RAW_PUBLIC_KEY_EXAMPLE, + "example": RAW_ED25519_2018_PUBLIC_KEY_EXAMPLE, }, ) posture = fields.Str( diff --git a/acapy_agent/wallet/tests/test_anoncreds_upgrade.py b/acapy_agent/wallet/tests/test_anoncreds_upgrade.py index 37f6ab94d1..9e6c0f04ad 100644 --- a/acapy_agent/wallet/tests/test_anoncreds_upgrade.py +++ b/acapy_agent/wallet/tests/test_anoncreds_upgrade.py @@ -329,17 +329,19 @@ async def test_failed_upgrade(self): ) ) - with mock.patch.object( - anoncreds_upgrade, "upgrade_and_delete_schema_records" - ), mock.patch.object( - anoncreds_upgrade, "upgrade_and_delete_cred_def_records" - ), mock.patch.object( - AskarProfileSession, "rollback" - ) as mock_rollback, mock.patch.object( - AskarProfileSession, - "commit", - # Don't wait for sleep in retry to speed up test - ) as mock_commit, mock.patch.object(asyncio, "sleep"): + with ( + mock.patch.object(anoncreds_upgrade, "upgrade_and_delete_schema_records"), + mock.patch.object( + anoncreds_upgrade, "upgrade_and_delete_cred_def_records" + ), + mock.patch.object(AskarProfileSession, "rollback") as mock_rollback, + mock.patch.object( + AskarProfileSession, + "commit", + # Don't wait for sleep in retry to speed up test + ) as mock_commit, + mock.patch.object(asyncio, "sleep"), + ): """ Only tests schemas and cred_defs failing to upgrade because the other objects are hard to mock. These tests should be enough to cover them as the logic is the same. diff --git a/acapy_agent/wallet/tests/test_crypto.py b/acapy_agent/wallet/tests/test_crypto.py index 0596f30821..429a551179 100644 --- a/acapy_agent/wallet/tests/test_crypto.py +++ b/acapy_agent/wallet/tests/test_crypto.py @@ -39,11 +39,14 @@ def test_seeds_keys(self): assert test_module.sign_pk_from_sk(secret_key) in secret_key def test_decode_pack_message_x(self): - with mock.patch.object( - test_module, "decode_pack_message_outer", mock.MagicMock() - ) as mock_decode_outer, mock.patch.object( - test_module, "extract_payload_key", mock.MagicMock() - ) as mock_extract: + with ( + mock.patch.object( + test_module, "decode_pack_message_outer", mock.MagicMock() + ) as mock_decode_outer, + mock.patch.object( + test_module, "extract_payload_key", mock.MagicMock() + ) as mock_extract, + ): mock_decode_outer.return_value = (b"wrapper", {"my": b"recip"}, True) with pytest.raises(ValueError) as excinfo: diff --git a/demo/bdd_support/agent_backchannel_client.py b/demo/bdd_support/agent_backchannel_client.py index 5d116e2fea..fa6db011c7 100644 --- a/demo/bdd_support/agent_backchannel_client.py +++ b/demo/bdd_support/agent_backchannel_client.py @@ -143,11 +143,13 @@ def aries_container_issue_credential( the_container: AgentContainer, cred_def_id: str, cred_attrs: list, + filter_type: str = "indy", ): return run_coroutine( the_container.issue_credential, cred_def_id, cred_attrs, + filter_type=filter_type, ) @@ -167,11 +169,13 @@ def aries_container_request_proof( the_container: AgentContainer, proof_request: dict, explicit_revoc_required: bool = False, + is_anoncreds: bool = False, ): return run_coroutine( the_container.request_proof, proof_request, explicit_revoc_required=explicit_revoc_required, + is_anoncreds=is_anoncreds, ) diff --git a/demo/features/0453-issue-credential.feature b/demo/features/0453-issue-credential.feature index 3927bbf4d9..4f9b47e46d 100644 --- a/demo/features/0453-issue-credential.feature +++ b/demo/features/0453-issue-credential.feature @@ -30,7 +30,7 @@ Feature: RFC 0453 Aries agent issue credential | --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 + @PR @Release @WalletType_Askar_AnonCreds Examples: | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Acme_extra | Bob_extra | | --public-did --wallet-type askar-anoncreds | | driverslicense | Data_DL_NormalizedValues | | | diff --git a/demo/features/steps/0453-issue-credential.py b/demo/features/steps/0453-issue-credential.py index 97106d3e1d..b85e5b6ef3 100644 --- a/demo/features/steps/0453-issue-credential.py +++ b/demo/features/steps/0453-issue-credential.py @@ -62,10 +62,9 @@ def step_impl(context, issuer, credential_data): agent = context.active_agents[issuer] cred_attrs = read_credential_data(context.schema_name, credential_data) + filter_type = "indy" if not is_anoncreds(agent) else "anoncreds" cred_exchange = aries_container_issue_credential( - agent["agent"], - context.cred_def_id, - cred_attrs, + agent["agent"], context.cred_def_id, cred_attrs, filter_type ) context.cred_attrs = cred_attrs @@ -171,8 +170,9 @@ def step_impl(context, holder): agent["agent"], "/issue-credential-2.0/records/" + cred_ex_id ) context.cred_exchange = cred_exchange - print("rev_reg_id:", cred_exchange["indy"]["rev_reg_id"]) - print("cred_rev_id:", cred_exchange["indy"]["cred_rev_id"]) + _format = "indy" if cred_exchange.get("indy") else "anoncreds" + print("rev_reg_id:", cred_exchange[_format]["rev_reg_id"]) + print("cred_rev_id:", cred_exchange[_format]["cred_rev_id"]) print("connection_id:", cred_exchange["cred_ex_record"]["connection_id"]) # revoke the credential @@ -185,8 +185,8 @@ def step_impl(context, holder): agent["agent"], endpoint, data={ - "rev_reg_id": cred_exchange["indy"]["rev_reg_id"], - "cred_rev_id": cred_exchange["indy"]["cred_rev_id"], + "rev_reg_id": cred_exchange[_format]["rev_reg_id"], + "cred_rev_id": cred_exchange[_format]["cred_rev_id"], "publish": "Y", "connection_id": cred_exchange["cred_ex_record"]["connection_id"], }, @@ -209,19 +209,22 @@ def step_impl(context, holder): # get the required revocation info from the last credential exchange cred_exchange = context.cred_exchange - print("rev_reg_id:", cred_exchange["indy"]["rev_reg_id"]) - print("cred_rev_id:", cred_exchange["indy"]["cred_rev_id"]) + _format = "indy" if cred_exchange.get("indy") else "anoncreds" + print("rev_reg_id:", cred_exchange[_format]["rev_reg_id"]) + print("cred_rev_id:", cred_exchange[_format]["cred_rev_id"]) print("connection_id:", cred_exchange["cred_ex_record"]["connection_id"]) # check wallet status wallet_revoked_creds = agent_container_GET( agent["agent"], - "/revocation/registry/" + cred_exchange["indy"]["rev_reg_id"] + "/issued/details", + "/revocation/registry/" + + cred_exchange[_format]["rev_reg_id"] + + "/issued/details", ) print("wallet_revoked_creds:", wallet_revoked_creds) matched = False for rec in wallet_revoked_creds: - if rec["cred_rev_id"] == cred_exchange["indy"]["cred_rev_id"]: + if rec["cred_rev_id"] == cred_exchange[_format]["cred_rev_id"]: matched = True assert rec["state"] == "revoked" assert matched @@ -230,18 +233,18 @@ def step_impl(context, holder): ledger_revoked_creds = agent_container_GET( agent["agent"], "/revocation/registry/" - + cred_exchange["indy"]["rev_reg_id"] + + cred_exchange[_format]["rev_reg_id"] + "/issued/indy_recs", ) print("ledger_revoked_creds:", ledger_revoked_creds) print( "assert", - cred_exchange["indy"]["cred_rev_id"], + cred_exchange[_format]["cred_rev_id"], "in", ledger_revoked_creds["rev_reg_delta"]["value"]["revoked"], ) assert ( - int(cred_exchange["indy"]["cred_rev_id"]) + int(cred_exchange[_format]["cred_rev_id"]) in ledger_revoked_creds["rev_reg_delta"]["value"]["revoked"] ) @@ -266,8 +269,9 @@ def step_impl(context, holder): agent["agent"], "/issue-credential-2.0/records/" + cred_ex_id ) context.cred_exchange = cred_exchange - print("rev_reg_id:", cred_exchange["indy"]["rev_reg_id"]) - print("cred_rev_id:", cred_exchange["indy"]["cred_rev_id"]) + _format = "indy" if cred_exchange.get("indy") else "anoncreds" + print("rev_reg_id:", cred_exchange[_format]["rev_reg_id"]) + print("cred_rev_id:", cred_exchange[_format]["cred_rev_id"]) print("connection_id:", cred_exchange["cred_ex_record"]["connection_id"]) # revoke the credential @@ -276,8 +280,8 @@ def step_impl(context, holder): agent["agent"], "/revocation/revoke", data={ - "rev_reg_id": cred_exchange["indy"]["rev_reg_id"], - "cred_rev_id": cred_exchange["indy"]["cred_rev_id"], + "rev_reg_id": cred_exchange[_format]["rev_reg_id"], + "cred_rev_id": cred_exchange[_format]["cred_rev_id"], "publish": "Y", "connection_id": cred_exchange["cred_ex_record"]["connection_id"], }, @@ -298,18 +302,21 @@ def step_impl(context, holder): # get the required revocation info from the last credential exchange cred_exchange = context.cred_exchange - print("rev_reg_id:", cred_exchange["indy"]["rev_reg_id"]) - print("cred_rev_id:", cred_exchange["indy"]["cred_rev_id"]) + _format = "indy" if cred_exchange.get("indy") else "anoncreds" + print("rev_reg_id:", cred_exchange[_format]["rev_reg_id"]) + print("cred_rev_id:", cred_exchange[_format]["cred_rev_id"]) print("connection_id:", cred_exchange["cred_ex_record"]["connection_id"]) # check wallet status wallet_revoked_creds = agent_container_GET( agent["agent"], - "/revocation/registry/" + cred_exchange["indy"]["rev_reg_id"] + "/issued/details", + "/revocation/registry/" + + cred_exchange[_format]["rev_reg_id"] + + "/issued/details", ) matched = False for rec in wallet_revoked_creds: - if rec["cred_rev_id"] == cred_exchange["indy"]["cred_rev_id"]: + if rec["cred_rev_id"] == cred_exchange[_format]["cred_rev_id"]: matched = True assert rec["state"] == "revoked" assert matched @@ -318,12 +325,12 @@ def step_impl(context, holder): ledger_revoked_creds = agent_container_GET( agent["agent"], "/revocation/registry/" - + cred_exchange["indy"]["rev_reg_id"] + + cred_exchange[_format]["rev_reg_id"] + "/issued/indy_recs", ) print("ledger_revoked_creds:", ledger_revoked_creds) assert ( - int(cred_exchange["indy"]["cred_rev_id"]) + int(cred_exchange[_format]["cred_rev_id"]) not in ledger_revoked_creds["rev_reg_delta"]["value"]["revoked"] ) diff --git a/demo/features/steps/0454-present-proof.py b/demo/features/steps/0454-present-proof.py index 984ee72e63..166712f4e0 100644 --- a/demo/features/steps/0454-present-proof.py +++ b/demo/features/steps/0454-present-proof.py @@ -34,7 +34,11 @@ def step_impl(context, verifier, request_for_proof, prover): "restrictions" ] = cred_def_restrictions - proof_exchange = aries_container_request_proof(agent["agent"], proof_request_info) + proof_exchange = aries_container_request_proof( + agent["agent"], + proof_request_info, + is_anoncreds=agent["agent"].wallet_type == "askar-anoncreds", + ) context.proof_request = proof_request_info context.proof_exchange = proof_exchange @@ -49,7 +53,10 @@ def step_impl(context, verifier, request_for_proof, prover): proof_request_info = read_proof_req_data(request_for_proof) proof_exchange = aries_container_request_proof( - agent["agent"], proof_request_info, explicit_revoc_required=True + agent["agent"], + proof_request_info, + explicit_revoc_required=True, + is_anoncreds=agent["agent"].wallet_type == "askar-anoncreds", ) context.proof_request = proof_request_info diff --git a/demo/features/steps/0586-sign-transaction.py b/demo/features/steps/0586-sign-transaction.py index bf5a8a0c3c..f8ade72f98 100644 --- a/demo/features/steps/0586-sign-transaction.py +++ b/demo/features/steps/0586-sign-transaction.py @@ -593,14 +593,15 @@ def step_impl(context, agent_name): agent["agent"], "/issue-credential-2.0/records/" + cred_exchange["cred_ex_id"] ) context.cred_exchange = cred_exchange + cred_exchange_format = cred_exchange.get("indy") or cred_exchange.get("anoncreds") agent_container_POST( agent["agent"], endpoint, data={ - "cred_rev_id": cred_exchange["indy"]["cred_rev_id"], + "cred_rev_id": cred_exchange_format["cred_rev_id"], "publish": False, - "rev_reg_id": cred_exchange["indy"]["rev_reg_id"], + "rev_reg_id": cred_exchange_format["rev_reg_id"], "connection_id": cred_exchange["cred_ex_record"]["connection_id"], }, ) @@ -627,11 +628,13 @@ def step_impl(context, agent_name): context.cred_exchange = cred_exchange connection_id = agent["agent"].agent.connection_id + cred_exchange_format = cred_exchange.get("indy") or cred_exchange.get("anoncreds") + # revoke the credential if not is_anoncreds(agent): data = { - "rev_reg_id": cred_exchange["indy"]["rev_reg_id"], - "cred_rev_id": cred_exchange["indy"]["cred_rev_id"], + "rev_reg_id": cred_exchange_format["rev_reg_id"], + "cred_rev_id": cred_exchange_format["cred_rev_id"], "publish": False, "connection_id": cred_exchange["cred_ex_record"]["connection_id"], } @@ -642,9 +645,9 @@ def step_impl(context, agent_name): endpoint = "/revocation/revoke" else: data = { - "cred_rev_id": cred_exchange["indy"]["cred_rev_id"], + "cred_rev_id": cred_exchange_format["cred_rev_id"], "publish": False, - "rev_reg_id": cred_exchange["indy"]["rev_reg_id"], + "rev_reg_id": cred_exchange_format["rev_reg_id"], "connection_id": cred_exchange["cred_ex_record"]["connection_id"], "options": { "endorser_connection_id": connection_id, @@ -676,15 +679,17 @@ def step_impl(context, agent_name): else: endpoint = "/anoncreds/revocation/publish-revocations" + cred_exchange_format = context.cred_exchange.get("indy") or context.cred_exchange.get( + "anoncreds" + ) + # create rev_reg entry transaction created_rev_reg = agent_container_POST( agent["agent"], endpoint, data={ "rrid2crid": { - context.cred_exchange["indy"]["rev_reg_id"]: [ - context.cred_exchange["indy"]["cred_rev_id"] - ] + cred_exchange_format["rev_reg_id"]: [cred_exchange_format["cred_rev_id"]] } }, params={}, @@ -703,14 +708,15 @@ def step_impl(context, agent_name): agent = context.active_agents[agent_name] connection_id = agent["agent"].agent.connection_id + cred_exchange_format = context.cred_exchange.get("indy") or context.cred_exchange.get( + "anoncreds" + ) # create rev_reg entry transaction if not is_anoncreds(agent): data = { "rrid2crid": { - context.cred_exchange["indy"]["rev_reg_id"]: [ - context.cred_exchange["indy"]["cred_rev_id"] - ] + cred_exchange_format["rev_reg_id"]: [cred_exchange_format["cred_rev_id"]] } } params = { @@ -721,9 +727,7 @@ def step_impl(context, agent_name): else: data = { "rrid2crid": { - context.cred_exchange["indy"]["rev_reg_id"]: [ - context.cred_exchange["indy"]["cred_rev_id"] - ] + cred_exchange_format["rev_reg_id"]: [cred_exchange_format["cred_rev_id"]] }, "options": { "endorser_connection_id": connection_id, diff --git a/demo/features/upgrade.feature b/demo/features/upgrade.feature index 259c7a485a..557dd75646 100644 --- a/demo/features/upgrade.feature +++ b/demo/features/upgrade.feature @@ -19,10 +19,7 @@ Feature: ACA-Py Anoncreds Upgrade Then "Faber" has the proof verification fail Then "Bob" can verify the credential from "" was revoked And "" upgrades the wallet to anoncreds - And "Bob" has an issued credential from "" And "Bob" upgrades the wallet to anoncreds - And "Bob" has an issued credential from "" - When "Faber" sends a request for proof presentation to "Bob" Examples: | issuer | Acme_capabilities | Bob_capabilities | Schema_name | Credential_data | Proof_request | diff --git a/demo/runners/agent_container.py b/demo/runners/agent_container.py index c2ad39fe5f..e529e6aefe 100644 --- a/demo/runners/agent_container.py +++ b/demo/runners/agent_container.py @@ -36,6 +36,8 @@ log_timer, ) +from .support.agent import CRED_FORMAT_ANONCREDS + CRED_PREVIEW_TYPE = "https://didcomm.org/issue-credential/2.0/credential-preview" SELF_ATTESTED = os.getenv("SELF_ATTESTED") TAILS_FILE_COUNT = int(os.getenv("TAILS_FILE_COUNT", 100)) @@ -272,16 +274,25 @@ async def handle_issue_credential_v2_0(self, message): elif state == "offer-received": log_status("#15 After receiving credential offer, send credential request") + + def _should_send_request_without_data(message): + """Formats that do not require credential request data.""" + cred_offer_by_format = message["by_format"].get("cred_offer") + + return ( + not message.get("by_format") + or cred_offer_by_format.get("anoncreds") + or cred_offer_by_format.get("indy") + or cred_offer_by_format.get("vc_di") + ) + # Should wait for a tiny bit for the delete tests await asyncio.sleep(0.2) if not message.get("by_format"): # this should not happen, something hinky when running in IDE... # this will work if using indy payloads self.log(f"No 'by_format' in message: {message}") - await self.admin_POST( - f"/issue-credential-2.0/records/{cred_ex_id}/send-request" - ) - elif message["by_format"]["cred_offer"].get("indy"): + elif _should_send_request_without_data(message): await self.admin_POST( f"/issue-credential-2.0/records/{cred_ex_id}/send-request" ) @@ -294,10 +305,6 @@ async def handle_issue_credential_v2_0(self, message): await self.admin_POST( f"/issue-credential-2.0/records/{cred_ex_id}/send-request", data ) - elif message["by_format"]["cred_offer"].get("vc_di"): - await self.admin_POST( - f"/issue-credential-2.0/records/{cred_ex_id}/send-request" - ) elif state == "done": pass @@ -327,6 +334,26 @@ async def handle_issue_credential_v2_0_indy(self, message): self.log(f"Revocation registry ID: {rev_reg_id}") self.log(f"Credential revocation ID: {cred_rev_id}") + async def handle_issue_credential_v2_0_anoncreds(self, message): + rev_reg_id = message.get("rev_reg_id") + cred_rev_id = message.get("cred_rev_id") + cred_id_stored = message.get("cred_id_stored") + + if cred_id_stored: + cred_id = message["cred_id_stored"] + log_status(f"#18.1 Stored credential {cred_id} in wallet") + cred = await self.admin_GET(f"/credential/{cred_id}") + log_json(cred, label="Credential details:") + self.log("credential_id", cred_id) + self.log("cred_def_id", cred["cred_def_id"]) + self.log("schema_id", cred["schema_id"]) + # track last successfully received credential + self.last_credential_received = cred + + if rev_reg_id and cred_rev_id: + self.log(f"Revocation registry ID: {rev_reg_id}") + self.log(f"Credential revocation ID: {cred_rev_id}") + async def handle_issue_credential_v2_0_vc_di(self, message): self.log(f"Handle VC_DI Credential: message = {message}") @@ -442,16 +469,18 @@ async def handle_present_proof_v2_0(self, message): # this should not happen, something hinky when running in IDE... self.log(f"No 'by_format' in message: {message}") else: - pres_request_indy = ( - message["by_format"].get("pres_request", {}).get("indy") - ) - pres_request_dif = message["by_format"].get("pres_request", {}).get("dif") + pres_request_by_format = message["by_format"].get("pres_request", {}) + pres_request = pres_request_by_format.get( + "indy" + ) or pres_request_by_format.get("anoncreds") + + pres_request_dif = pres_request_by_format.get("dif") request = {} - if not pres_request_dif and not pres_request_indy: + if not pres_request_dif and not pres_request: raise Exception("Invalid presentation request received") - if pres_request_indy: + if pres_request: # include self-attested attributes (not included in credentials) creds_by_reft = {} revealed = {} @@ -463,7 +492,6 @@ async def handle_present_proof_v2_0(self, message): creds = await self.admin_GET( f"/present-proof-2.0/records/{pres_ex_id}/credentials" ) - # print(">>> creds:", creds) if creds: # select only indy credentials creds = [x for x in creds if "cred_info" in x] @@ -484,7 +512,7 @@ async def handle_present_proof_v2_0(self, message): # submit the proof wit one unrevealed revealed attribute revealed_flag = False - for referent in pres_request_indy["requested_attributes"]: + for referent in pres_request["requested_attributes"]: if referent in creds_by_reft: revealed[referent] = { "cred_id": creds_by_reft[referent]["cred_info"][ @@ -496,7 +524,7 @@ async def handle_present_proof_v2_0(self, message): else: self_attested[referent] = "my self-attested value" - for referent in pres_request_indy["requested_predicates"]: + for referent in pres_request["requested_predicates"]: if referent in creds_by_reft: predicates[referent] = { "cred_id": creds_by_reft[referent]["cred_info"][ @@ -504,15 +532,15 @@ async def handle_present_proof_v2_0(self, message): ] } - log_status("#25 Generate the indy proof") - indy_request = { - "indy": { + log_status("#25 Generate the proof") + request = { + "indy" if "indy" in pres_request_by_format else "anoncreds": { "requested_predicates": predicates, "requested_attributes": revealed, "self_attested_attributes": self_attested, } } - request.update(indy_request) + request.update(request) except ClientError: pass @@ -779,7 +807,7 @@ def __init__( # endorsers and authors need public DIDs (assume cred_type is Indy) if endorser_role == "author" or endorser_role == "endorser": self.public_did = True - self.cred_type = CRED_FORMAT_INDY + # self.cred_type = CRED_FORMAT_INDY self.reuse_connections = reuse_connections self.multi_use_invitations = multi_use_invitations @@ -938,7 +966,7 @@ async def create_schema_and_cred_def( ): if not self.public_did: raise Exception("Can't create a schema/cred def without a public DID :-(") - if self.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: + if self.cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: # need to redister schema and cred def on the ledger self.cred_def_id = await self.agent.create_schema_and_cred_def( schema_name, @@ -981,20 +1009,26 @@ async def issue_credential( self, cred_def_id: str, cred_attrs: list, + filter_type: str = "indy", ): log_status("#13 Issue credential offer to X") - if self.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: + if self.cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: cred_preview = { "@type": CRED_PREVIEW_TYPE, "attributes": cred_attrs, } + if filter_type == "indy": + _filter = {"indy": {"cred_def_id": cred_def_id}} + else: + _filter = {"anoncreds": {"cred_def_id": cred_def_id}} + offer_request = { "connection_id": self.agent.connection_id, "comment": f"Offer on cred def id {cred_def_id}", "auto_remove": False, "credential_preview": cred_preview, - "filter": {"indy": {"cred_def_id": cred_def_id}}, + "filter": _filter, "trace": self.exchange_tracing, } cred_exchange = await self.agent.admin_POST( @@ -1041,11 +1075,13 @@ async def receive_credential( return matched - async def request_proof(self, proof_request, explicit_revoc_required: bool = False): + async def request_proof( + self, proof_request, explicit_revoc_required: bool = False, is_anoncreds=False + ): log_status("#20 Request proof of degree from alice") - if self.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: - indy_proof_request = { + if self.cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: + proof_request = { "name": ( proof_request["name"] if "name" in proof_request else "Proof of stuff" ), @@ -1061,24 +1097,24 @@ async def request_proof(self, proof_request, explicit_revoc_required: bool = Fal # plug in revocation where requested in the supplied proof request non_revoked = {"to": int(time.time())} if "non_revoked" in proof_request: - indy_proof_request["non_revoked"] = non_revoked + proof_request["non_revoked"] = non_revoked non_revoked_supplied = True for attr in proof_request["requested_attributes"]: if "non_revoked" in proof_request["requested_attributes"][attr]: - indy_proof_request["requested_attributes"][attr][ - "non_revoked" - ] = non_revoked + proof_request["requested_attributes"][attr]["non_revoked"] = ( + non_revoked + ) non_revoked_supplied = True for pred in proof_request["requested_predicates"]: if "non_revoked" in proof_request["requested_predicates"][pred]: - indy_proof_request["requested_predicates"][pred][ - "non_revoked" - ] = non_revoked + proof_request["requested_predicates"][pred]["non_revoked"] = ( + non_revoked + ) non_revoked_supplied = True if not non_revoked_supplied and not explicit_revoc_required: # else just make it global - indy_proof_request["non_revoked"] = non_revoked + proof_request["non_revoked"] = non_revoked else: # make sure we are not leaking non-revoc requests @@ -1091,13 +1127,16 @@ async def request_proof(self, proof_request, explicit_revoc_required: bool = Fal if "non_revoked" in proof_request["requested_predicates"][pred]: del proof_request["requested_predicates"][pred]["non_revoked"] - log_status(f" >>> asking for proof for request: {indy_proof_request}") + log_status(f" >>> asking for proof for request: {proof_request}") + + if is_anoncreds: + presentation_request = {"anoncreds": proof_request} + else: + presentation_request = {"indy": proof_request} proof_request_web_request = { "connection_id": self.agent.connection_id, - "presentation_request": { - "indy": indy_proof_request, - }, + "presentation_request": presentation_request, "trace": self.exchange_tracing, } proof_exchange = await self.agent.admin_POST( @@ -1108,7 +1147,6 @@ async def request_proof(self, proof_request, explicit_revoc_required: bool = Fal elif self.cred_type == CRED_FORMAT_JSON_LD: # TODO create and send the json-ld proof request - pass return None else: @@ -1125,7 +1163,7 @@ async def verify_proof(self, proof_request): # log_status(f">>> last proof received: {self.agent.last_proof_received}") - if self.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: + if self.cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: # return verified status return self.agent.last_proof_received["verified"] @@ -1328,7 +1366,7 @@ def arg_parser(ident: str = None, port: int = 8020): type=str, default=CRED_FORMAT_INDY, metavar=(""), - help="Credential type (indy, json-ld)", + help="Credential type (indy, json-ld, vc_di)", ) parser.add_argument( "--aip", @@ -1514,12 +1552,14 @@ async def create_agent_with_args(args, ident: str = None, extra_args: list = Non aip = 20 if "cred_type" in args and args.cred_type not in [ + CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI, ]: public_did = None aip = 20 elif "cred_type" in args and args.cred_type in [ + CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI, ]: @@ -1528,6 +1568,12 @@ async def create_agent_with_args(args, ident: str = None, extra_args: list = Non public_did = args.public_did if "public_did" in args else None cred_type = args.cred_type if "cred_type" in args else None + + # Set anoncreds agent to use anoncreds credential format + wallet_type = arg_file_dict.get("wallet-type") or args.wallet_type + if wallet_type == "askar-anoncreds" and cred_type == CRED_FORMAT_INDY: + cred_type = CRED_FORMAT_ANONCREDS + log_msg( f"Initializing demo agent {agent_ident} with AIP {aip} and credential type {cred_type}" ) @@ -1564,7 +1610,7 @@ async def create_agent_with_args(args, ident: str = None, extra_args: list = Non mediation=args.mediation, cred_type=cred_type, use_did_exchange=(aip == 20) if ("aip" in args) else args.did_exchange, - wallet_type=arg_file_dict.get("wallet-type") or args.wallet_type, + wallet_type=wallet_type, public_did=public_did, seed="random" if public_did else None, arg_file=arg_file, diff --git a/demo/runners/faber.py b/demo/runners/faber.py index 5cecf47d37..00cc9a2e98 100644 --- a/demo/runners/faber.py +++ b/demo/runners/faber.py @@ -17,6 +17,7 @@ create_agent_with_args, ) from runners.support.agent import ( # noqa:E402 + CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_JSON_LD, CRED_FORMAT_VC_DI, @@ -111,7 +112,7 @@ def generate_credential_offer(self, aip, cred_type, cred_def_id, exchange_tracin return offer_request elif aip == 20: - if cred_type == CRED_FORMAT_INDY: + if cred_type == CRED_FORMAT_ANONCREDS or cred_type == CRED_FORMAT_INDY: self.cred_attrs[cred_def_id] = { "name": "Alice Smith", "date": "2018-05-28", @@ -127,12 +128,16 @@ def generate_credential_offer(self, aip, cred_type, cred_def_id, exchange_tracin for (n, v) in self.cred_attrs[cred_def_id].items() ], } + if cred_type == CRED_FORMAT_ANONCREDS: + _filter = {"anoncreds": {"cred_def_id": cred_def_id}} + else: + _filter = {"indy": {"cred_def_id": cred_def_id}} offer_request = { "connection_id": self.connection_id, "comment": f"Offer on cred def id {cred_def_id}", "auto_remove": False, "credential_preview": cred_preview, - "filter": {"indy": {"cred_def_id": cred_def_id}}, + "filter": _filter, "trace": exchange_tracing, } return offer_request @@ -249,7 +254,7 @@ def generate_proof_request_web_request( "restrictions": [{"schema_name": "degree schema"}], } ] - indy_proof_request = { + proof_request = { "name": "Proof of Education", "version": "1.0", "requested_attributes": { @@ -261,10 +266,10 @@ def generate_proof_request_web_request( } if revocation: - indy_proof_request["non_revoked"] = {"to": int(time.time())} + proof_request["non_revoked"] = {"to": int(time.time())} proof_request_web_request = { - "proof_request": indy_proof_request, + "proof_request": proof_request, "trace": exchange_tracing, } if not connectionless: @@ -272,7 +277,7 @@ def generate_proof_request_web_request( return proof_request_web_request elif aip == 20: - if cred_type == CRED_FORMAT_INDY: + if cred_type == CRED_FORMAT_ANONCREDS or cred_type == CRED_FORMAT_INDY: req_attrs = [ { "name": "name", @@ -312,7 +317,7 @@ def generate_proof_request_web_request( "restrictions": [{"schema_name": "degree schema"}], } ] - indy_proof_request = { + proof_request = { "name": "Proof of Education", "version": "1.0", "requested_attributes": { @@ -325,14 +330,19 @@ def generate_proof_request_web_request( } if revocation: - indy_proof_request["non_revoked"] = {"to": int(time.time())} + proof_request["non_revoked"] = {"to": int(time.time())} + if cred_type == CRED_FORMAT_ANONCREDS: + presentation_request = {"anoncreds": proof_request} + else: + presentation_request = {"indy": proof_request} proof_request_web_request = { - "presentation_request": {"indy": indy_proof_request}, + "presentation_request": presentation_request, "trace": exchange_tracing, } if not connectionless: proof_request_web_request["connection_id"] = self.connection_id + return proof_request_web_request elif cred_type == CRED_FORMAT_VC_DI: @@ -537,7 +547,11 @@ async def main(args): "birthdate_dateint", "timestamp", ] - if faber_agent.cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: + if faber_agent.cred_type in [ + CRED_FORMAT_ANONCREDS, + CRED_FORMAT_INDY, + CRED_FORMAT_VC_DI, + ]: faber_agent.public_did = True await faber_agent.initialize( the_agent=agent, @@ -569,6 +583,7 @@ async def main(args): exchange_tracing = False options = " (1) Issue Credential\n" if faber_agent.cred_type in [ + CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI, ]: @@ -664,12 +679,14 @@ async def main(args): elif option == "1a": new_cred_type = await prompt( - "Enter credential type ({}, {}): ".format( + "Enter credential type ({}, {}, {}): ".format( + CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI, ) ) if new_cred_type in [ + CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI, ]: @@ -689,7 +706,11 @@ async def main(args): ) elif faber_agent.aip == 20: - if faber_agent.cred_type == CRED_FORMAT_INDY: + if faber_agent.cred_type in [ + CRED_FORMAT_ANONCREDS, + CRED_FORMAT_INDY, + CRED_FORMAT_VC_DI, + ]: offer_request = faber_agent.agent.generate_credential_offer( faber_agent.aip, faber_agent.cred_type, @@ -705,14 +726,6 @@ async def main(args): exchange_tracing, ) - elif faber_agent.cred_type == CRED_FORMAT_VC_DI: - offer_request = faber_agent.agent.generate_credential_offer( - faber_agent.aip, - faber_agent.cred_type, - faber_agent.cred_def_id, - exchange_tracing, - ) - else: raise Exception( f"Error invalid credential type: {faber_agent.cred_type}" @@ -742,27 +755,12 @@ async def main(args): pass elif faber_agent.aip == 20: - if faber_agent.cred_type == CRED_FORMAT_INDY: - proof_request_web_request = ( - faber_agent.agent.generate_proof_request_web_request( - faber_agent.aip, - faber_agent.cred_type, - faber_agent.revocation, - exchange_tracing, - ) - ) - - elif faber_agent.cred_type == CRED_FORMAT_JSON_LD: - proof_request_web_request = ( - faber_agent.agent.generate_proof_request_web_request( - faber_agent.aip, - faber_agent.cred_type, - faber_agent.revocation, - exchange_tracing, - ) - ) - - elif faber_agent.cred_type == CRED_FORMAT_VC_DI: + if faber_agent.cred_type in [ + CRED_FORMAT_ANONCREDS, + CRED_FORMAT_INDY, + CRED_FORMAT_VC_DI, + CRED_FORMAT_JSON_LD, + ]: proof_request_web_request = ( faber_agent.agent.generate_proof_request_web_request( faber_agent.aip, @@ -771,7 +769,6 @@ async def main(args): exchange_tracing, ) ) - else: raise Exception( "Error invalid credential type:" + faber_agent.cred_type @@ -819,28 +816,12 @@ async def main(args): qr.print_ascii(invert=True) elif faber_agent.aip == 20: - if faber_agent.cred_type == CRED_FORMAT_INDY: - proof_request_web_request = ( - faber_agent.agent.generate_proof_request_web_request( - faber_agent.aip, - faber_agent.cred_type, - faber_agent.revocation, - exchange_tracing, - connectionless=True, - ) - ) - elif faber_agent.cred_type == CRED_FORMAT_JSON_LD: - proof_request_web_request = ( - faber_agent.agent.generate_proof_request_web_request( - faber_agent.aip, - faber_agent.cred_type, - faber_agent.revocation, - exchange_tracing, - connectionless=True, - ) - ) - - elif faber_agent.cred_type == CRED_FORMAT_VC_DI: + if faber_agent.cred_type in [ + CRED_FORMAT_ANONCREDS, + CRED_FORMAT_INDY, + CRED_FORMAT_VC_DI, + CRED_FORMAT_JSON_LD, + ]: proof_request_web_request = ( faber_agent.agent.generate_proof_request_web_request( faber_agent.aip, diff --git a/demo/runners/support/agent.py b/demo/runners/support/agent.py index 2905ad4912..5d1e10ccd6 100644 --- a/demo/runners/support/agent.py +++ b/demo/runners/support/agent.py @@ -70,6 +70,7 @@ WALLET_TYPE_ASKAR = "askar" WALLET_TYPE_ANONCREDS = "askar-anoncreds" +CRED_FORMAT_ANONCREDS = "anoncreds" CRED_FORMAT_INDY = "indy" CRED_FORMAT_JSON_LD = "json-ld" CRED_FORMAT_VC_DI = "vc_di" @@ -672,7 +673,7 @@ async def register_did( role: str = "TRUST_ANCHOR", cred_type: str = CRED_FORMAT_INDY, ): - if cred_type in [CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: + if cred_type in [CRED_FORMAT_ANONCREDS, CRED_FORMAT_INDY, CRED_FORMAT_VC_DI]: # if registering a did for issuing indy credentials, publish the did on the ledger self.log(f"Registering {self.ident} ...") if not ledger_url: diff --git a/docker/Dockerfile b/docker/Dockerfile index acf36cc46e..f7744094fc 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -14,7 +14,7 @@ ARG uid=1001 ARG user=aries ARG acapy_name="aries-cloudagent" ARG acapy_version -ARG acapy_reqs=[askar,didcommv2] +ARG acapy_reqs=[didcommv2] ENV HOME="/home/$user" ENV APP_ROOT="$HOME" \ diff --git a/docker/Dockerfile.demo b/docker/Dockerfile.demo index cfb6c6c868..db63f2cb28 100644 --- a/docker/Dockerfile.demo +++ b/docker/Dockerfile.demo @@ -15,7 +15,7 @@ RUN pip install --no-cache-dir poetry ADD README.md pyproject.toml poetry.lock ./ ARG all_extras=0 -RUN if ! [ -z ${all_extras} ]; then poetry install --no-root --no-directory --all-extras; else poetry install --no-root --no-directory -E "askar didcommv2"; fi +RUN if ! [ -z ${all_extras} ]; then poetry install --no-root --no-directory --all-extras; else poetry install --no-root --no-directory -E "didcommv2"; fi ADD acapy_agent ./acapy_agent ADD scripts ./scripts diff --git a/docker/Dockerfile.run b/docker/Dockerfile.run index 7211df51cb..90bfb05ad9 100644 --- a/docker/Dockerfile.run +++ b/docker/Dockerfile.run @@ -19,7 +19,7 @@ ADD pyproject.toml poetry.lock README.md ./ RUN mkdir -p log && chmod -R ug+rw log ARG all_extras=0 -RUN if ! [ -z ${all_extras} ]; then poetry install --all-extras; else poetry install -E "askar didcommv2"; fi +RUN if ! [ -z ${all_extras} ]; then poetry install --all-extras; else poetry install -E "didcommv2"; fi ADD . . diff --git a/docker/Dockerfile.test b/docker/Dockerfile.test index ad8b66de2a..5351bccdcd 100644 --- a/docker/Dockerfile.test +++ b/docker/Dockerfile.test @@ -15,7 +15,7 @@ ADD ./README.md pyproject.toml ./poetry.lock ./ RUN mkdir acapy_agent && touch acapy_agent/__init__.py ARG all_extras=0 -RUN if ! [ -z ${all_extras} ]; then poetry install --no-directory --all-extras --with=dev; else poetry install --no-directory -E "askar didcommv2" --with=dev; fi +RUN if ! [ -z ${all_extras} ]; then poetry install --no-directory --all-extras --with=dev; else poetry install --no-directory -E "didcommv2" --with=dev; fi ADD . . diff --git a/docs/UpdateRTD.md b/docs/UpdateRTD.md index b37e028992..c9307936b2 100644 --- a/docs/UpdateRTD.md +++ b/docs/UpdateRTD.md @@ -17,7 +17,7 @@ and verify the installation on your system. To rebuild the project and settings from scratch: ``` bash -cd docs; rm -rf generated; sphinx-apidoc -f -M -o ./generated ../acapy_agent/ $(find ../acapy_agent/ -name '*tests*', cd ..) +cd docs; rm -rf generated; sphinx-apidoc -f -M -o ./generated ../acapy_agent/ $(find ../acapy_agent/ -name '*tests*'); cd .. ``` Note that the `find` command that is used to exclude any of the `test` python files from the RTD documentation. diff --git a/docs/features/SupportedRFCs.md b/docs/features/SupportedRFCs.md index 23b370c03b..8118b283c7 100644 --- a/docs/features/SupportedRFCs.md +++ b/docs/features/SupportedRFCs.md @@ -8,7 +8,7 @@ ACA-Py or the repository `main` branch. Reminders (and PRs!) to update this page welcome! If you have any questions, please contact us on the #aries channel on [OpenWallet Foundation Discord](https://discord.gg/openwallet-foundation) or through an issue in this repo. -**Last Update**: 2024-10-15, Release 1.1.0 +**Last Update**: 2024-12-02, Release 1.1.1 > The checklist version of this document was created as a joint effort > between [Northern Block](https://northernblock.io/), [Animo Solutions](https://animo.id/) and the Ontario government, on behalf of the Ontario government. diff --git a/docs/features/W3cCredentials.md b/docs/features/W3cCredentials.md index 72d871b7d9..02ddaa7d0c 100644 --- a/docs/features/W3cCredentials.md +++ b/docs/features/W3cCredentials.md @@ -1,62 +1,60 @@ -## Verifiable Credential Data Integrity (VC-DI) Credentials in ACA-Py +# Verifiable Credential Data Integrity (VC-DI) Credentials in ACA-Py This document outlines a new functionality within Aries Agent that facilitates the issuance of credentials and presentations in compliance with the W3C standard. -### Table of Contents - -- [Verifiable Credential Data Integrity (VC-DI) Credentials in ACA-Py](#verifiable-credential-data-integrity-vc-di-credentials-in-aca-py) - - [Table of Contents](#table-of-contents) - - [General Concept](#general-concept) - - [Prerequisites](#prerequisites) - - [Verifiable Credentials Data Model](#verifiable-credentials-data-model) - - [Verifiable Presentations Data Model](#verifiable-presentations-data-model) - - [DIF Presentation Format](#dif-presentation-format) - - [Preparing to Issue a Credential](#preparing-to-issue-a-credential) - - [VC-DI Context](#vc-di-context) - - [Signature Suite](#signature-suite) - - [DID Method](#did-method) - - [`did:key`](#didkey) - - [Issue a Credential](#issue-a-credential) - - [Verify a Credential](#verify-a-credential) - - [Present Proof](#present-proof) - - [Requesting Proof](#requesting-proof) - - [Presenting Proof](#presenting-proof) - - [Verifying Proof](#verifying-proof) - - [Appendix](#appendix) - - [Glossary of Terms](#glossary-of-terms) - - [References and Resources](#references-and-resources) - -### General Concept +## Table of Contents + +- [General Concept](#general-concept) +- [Prerequisites](#prerequisites) + - [Verifiable Credentials Data Model](#verifiable-credentials-data-model) + - [Verifiable Presentations Data Model](#verifiable-presentations-data-model) + - [DIF Presentation Format](#dif-presentation-format) +- [Preparing to Issue a Credential](#preparing-to-issue-a-credential) + - [VC-DI Context](#vc-di-context) + - [Signature Suite](#signature-suite) + - [DID Method](#did-method) + - [`did:key`](#didkey) +- [Issue a Credential](#issue-a-credential) +- [Verify a Credential](#verify-a-credential) +- [Present Proof](#present-proof) + - [Requesting Proof](#requesting-proof) + - [Presenting Proof](#presenting-proof) + - [Verifying Proof](#verifying-proof) +- [Appendix](#appendix) + - [Glossary of Terms](#glossary-of-terms) + - [References and Resources](#references-and-resources) + +## General Concept The introduction of VC-DI credentials in ACA-Py facilitates the issuance of credentials and presentations in adherence to the W3C standard. -### Prerequisites +## Prerequisites Before utilizing this feature, it is essential to have the following: -#### Verifiable Credentials Data Model +### Verifiable Credentials Data Model A basic understanding of the Verifiable Credentials Data Model is required. Resources for reference include: - [Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) -#### Verifiable Presentations Data Model +### Verifiable Presentations Data Model Familiarity with the Verifiable Presentations Data Model is necessary. Relevant resources can be found at: - [Verifiable Presentations Data Model](https://www.w3.org/TR/vc-data-model/#presentations) -#### DIF Presentation Format +### DIF Presentation Format Understanding the DIF Presentation Format is recommended. Access resources at: - [DIF Presentation Format](https://identity.foundation/presentation-exchange/) -### Preparing to Issue a Credential +## Preparing to Issue a Credential To prepare for credential issuance, the following steps must be taken: -#### VC-DI Context +### VC-DI Context Ensure that every property key in the document is mappable to an IRI. This requires either the property key to be an IRI by default or to have the shorthand property mapped in the `@context` of the document. @@ -72,17 +70,17 @@ Ensure that every property key in the document is mappable to an IRI. This requi } ``` -#### Signature Suite +### Signature Suite Select a signature suite for use. VC-DI format currently supports EdDSA signature suites for issuing credentials. - [`Ed25519Signature2020`](https://w3c.github.io/vc-di-eddsa/#ed25519signature2020-0) -#### DID Method +### DID Method Choose a DID method for issuing the credential. VC-DI format currently supports the `did:key` method. -##### `did:key` +#### `did:key` A `did:key` did is not anchored to a ledger, but embeds the key directly in the identifier part of the did. See the [did:key Method Specification](https://w3c-ccg.github.io/did-method-key/) for more information. @@ -97,7 +95,7 @@ You can create a `did:key` using the `/wallet/did/create` endpoint with the foll } ``` -### Issue a Credential +## Issue a Credential The issuance of W3C credentials is facilitated through the `/issue-credential-2.0/send` endpoint. This process adheres to the formats described in [RFC 0809 VC-DI](https://github.com/hyperledger/aries-rfcs/blob/main/features/0809-w3c-data-integrity-credential-attachment/README.md) and utilizes `didcomm` for communication between agents. @@ -184,7 +182,7 @@ The response should confirm the credential issuance. ``` -### Verify a Credential +## Verify a Credential To verify a credential, follow these steps: @@ -303,9 +301,9 @@ The response should confirm the credential verification. ``` -### Present Proof +## Present Proof -#### Requesting Proof +### Requesting Proof To request proof, follow these steps: @@ -399,7 +397,7 @@ To request proof, follow these steps: ``` -#### Presenting Proof +### Presenting Proof To present proof, follow these steps: @@ -499,7 +497,7 @@ To present proof, follow these steps: ``` -#### Verifying Proof +### Verifying Proof To verify presented proof, follow these steps: @@ -621,9 +619,9 @@ To verify presented proof, follow these steps: ``` -### Appendix +## Appendix -#### Glossary of Terms +### Glossary of Terms - **VC-DI:** Verifiable Credential Data Integrity - **W3C:** World Wide Web Consortium @@ -631,7 +629,7 @@ To verify presented proof, follow these steps: - **EdDSA:** Edwards-curve Digital Signature Algorithm - **DIF:** Decentralized Identity Foundation -#### References and Resources +### References and Resources - [ACA-Py Documentation](https://aca-py.org) - [Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) diff --git a/docs/generated/acapy_agent.anoncreds.models.rst b/docs/generated/acapy_agent.anoncreds.models.rst index 0539f9285a..58f7a28113 100644 --- a/docs/generated/acapy_agent.anoncreds.models.rst +++ b/docs/generated/acapy_agent.anoncreds.models.rst @@ -9,26 +9,106 @@ acapy\_agent.anoncreds.models package Submodules ---------- -acapy\_agent.anoncreds.models.anoncreds\_cred\_def module +acapy\_agent.anoncreds.models.credential module +----------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.credential + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.credential\_definition module +----------------------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.credential_definition + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.credential\_offer module +------------------------------------------------------ + +.. automodule:: acapy_agent.anoncreds.models.credential_offer + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.credential\_proposal module --------------------------------------------------------- -.. automodule:: acapy_agent.anoncreds.models.anoncreds_cred_def +.. automodule:: acapy_agent.anoncreds.models.credential_proposal + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.credential\_request module +-------------------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.credential_request + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.non\_rev\_interval module +------------------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.non_rev_interval :members: :undoc-members: :show-inheritance: -acapy\_agent.anoncreds.models.anoncreds\_revocation module +acapy\_agent.anoncreds.models.predicate module +---------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.predicate + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.presentation\_request module ---------------------------------------------------------- -.. automodule:: acapy_agent.anoncreds.models.anoncreds_revocation +.. automodule:: acapy_agent.anoncreds.models.presentation_request :members: :undoc-members: :show-inheritance: -acapy\_agent.anoncreds.models.anoncreds\_schema module ------------------------------------------------------- +acapy\_agent.anoncreds.models.proof module +------------------------------------------ + +.. automodule:: acapy_agent.anoncreds.models.proof + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.requested\_credentials module +----------------------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.requested_credentials + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.revocation module +----------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.revocation + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.schema module +------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.schema + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.anoncreds.models.utils module +------------------------------------------ -.. automodule:: acapy_agent.anoncreds.models.anoncreds_schema +.. automodule:: acapy_agent.anoncreds.models.utils :members: :undoc-members: :show-inheritance: diff --git a/docs/generated/acapy_agent.config.logging.rst b/docs/generated/acapy_agent.config.logging.rst new file mode 100644 index 0000000000..3db38f2b8b --- /dev/null +++ b/docs/generated/acapy_agent.config.logging.rst @@ -0,0 +1,42 @@ +acapy\_agent.config.logging package +=================================== + +.. automodule:: acapy_agent.config.logging + :members: + :undoc-members: + :show-inheritance: + +Submodules +---------- + +acapy\_agent.config.logging.base module +--------------------------------------- + +.. automodule:: acapy_agent.config.logging.base + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.config.logging.configurator module +----------------------------------------------- + +.. automodule:: acapy_agent.config.logging.configurator + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.config.logging.filters module +------------------------------------------ + +.. automodule:: acapy_agent.config.logging.filters + :members: + :undoc-members: + :show-inheritance: + +acapy\_agent.config.logging.timed\_rotating\_file\_multi\_process\_handler module +--------------------------------------------------------------------------------- + +.. automodule:: acapy_agent.config.logging.timed_rotating_file_multi_process_handler + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/generated/acapy_agent.config.rst b/docs/generated/acapy_agent.config.rst index ad606129b8..51d632e56b 100644 --- a/docs/generated/acapy_agent.config.rst +++ b/docs/generated/acapy_agent.config.rst @@ -6,6 +6,14 @@ acapy\_agent.config package :undoc-members: :show-inheritance: +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + acapy_agent.config.logging + Submodules ---------- @@ -81,14 +89,6 @@ acapy\_agent.config.ledger module :undoc-members: :show-inheritance: -acapy\_agent.config.logging module ----------------------------------- - -.. automodule:: acapy_agent.config.logging - :members: - :undoc-members: - :show-inheritance: - acapy\_agent.config.plugin\_settings module ------------------------------------------- diff --git a/docs/generated/acapy_agent.core.in_memory.didcomm.rst b/docs/generated/acapy_agent.core.in_memory.didcomm.rst deleted file mode 100644 index 3842f254f3..0000000000 --- a/docs/generated/acapy_agent.core.in_memory.didcomm.rst +++ /dev/null @@ -1,26 +0,0 @@ -acapy\_agent.core.in\_memory.didcomm package -============================================ - -.. automodule:: acapy_agent.core.in_memory.didcomm - :members: - :undoc-members: - :show-inheritance: - -Submodules ----------- - -acapy\_agent.core.in\_memory.didcomm.derive\_1pu module -------------------------------------------------------- - -.. automodule:: acapy_agent.core.in_memory.didcomm.derive_1pu - :members: - :undoc-members: - :show-inheritance: - -acapy\_agent.core.in\_memory.didcomm.derive\_ecdh module --------------------------------------------------------- - -.. automodule:: acapy_agent.core.in_memory.didcomm.derive_ecdh - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/generated/acapy_agent.core.in_memory.rst b/docs/generated/acapy_agent.core.in_memory.rst deleted file mode 100644 index ea101cb0b9..0000000000 --- a/docs/generated/acapy_agent.core.in_memory.rst +++ /dev/null @@ -1,26 +0,0 @@ -acapy\_agent.core.in\_memory package -==================================== - -.. automodule:: acapy_agent.core.in_memory - :members: - :undoc-members: - :show-inheritance: - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - acapy_agent.core.in_memory.didcomm - -Submodules ----------- - -acapy\_agent.core.in\_memory.profile module -------------------------------------------- - -.. automodule:: acapy_agent.core.in_memory.profile - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/generated/acapy_agent.core.rst b/docs/generated/acapy_agent.core.rst index 6dbd9e3fb6..aea168d472 100644 --- a/docs/generated/acapy_agent.core.rst +++ b/docs/generated/acapy_agent.core.rst @@ -6,14 +6,6 @@ acapy\_agent.core package :undoc-members: :show-inheritance: -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - acapy_agent.core.in_memory - Submodules ---------- diff --git a/docs/generated/acapy_agent.protocols.issue_credential.v2_0.models.detail.rst b/docs/generated/acapy_agent.protocols.issue_credential.v2_0.models.detail.rst index 52d5cd892d..464c0f5161 100644 --- a/docs/generated/acapy_agent.protocols.issue_credential.v2_0.models.detail.rst +++ b/docs/generated/acapy_agent.protocols.issue_credential.v2_0.models.detail.rst @@ -9,6 +9,14 @@ acapy\_agent.protocols.issue\_credential.v2\_0.models.detail package Submodules ---------- +acapy\_agent.protocols.issue\_credential.v2\_0.models.detail.anoncreds module +----------------------------------------------------------------------------- + +.. automodule:: acapy_agent.protocols.issue_credential.v2_0.models.detail.anoncreds + :members: + :undoc-members: + :show-inheritance: + acapy\_agent.protocols.issue\_credential.v2\_0.models.detail.indy module ------------------------------------------------------------------------ diff --git a/docs/generated/acapy_agent.resolver.default.rst b/docs/generated/acapy_agent.resolver.default.rst index 78165b9692..32a0f44cc9 100644 --- a/docs/generated/acapy_agent.resolver.default.rst +++ b/docs/generated/acapy_agent.resolver.default.rst @@ -73,6 +73,14 @@ acapy\_agent.resolver.default.peer4 module :undoc-members: :show-inheritance: +acapy\_agent.resolver.default.tdw module +---------------------------------------- + +.. automodule:: acapy_agent.resolver.default.tdw + :members: + :undoc-members: + :show-inheritance: + acapy\_agent.resolver.default.universal module ---------------------------------------------- diff --git a/docs/generated/acapy_agent.storage.rst b/docs/generated/acapy_agent.storage.rst index 95998a741d..8eda05694e 100644 --- a/docs/generated/acapy_agent.storage.rst +++ b/docs/generated/acapy_agent.storage.rst @@ -41,14 +41,6 @@ acapy\_agent.storage.error module :undoc-members: :show-inheritance: -acapy\_agent.storage.in\_memory module --------------------------------------- - -.. automodule:: acapy_agent.storage.in_memory - :members: - :undoc-members: - :show-inheritance: - acapy\_agent.storage.record module ---------------------------------- diff --git a/docs/generated/acapy_agent.storage.vc_holder.rst b/docs/generated/acapy_agent.storage.vc_holder.rst index ca74bd8aed..3a1b74eff5 100644 --- a/docs/generated/acapy_agent.storage.vc_holder.rst +++ b/docs/generated/acapy_agent.storage.vc_holder.rst @@ -25,14 +25,6 @@ acapy\_agent.storage.vc\_holder.base module :undoc-members: :show-inheritance: -acapy\_agent.storage.vc\_holder.in\_memory module -------------------------------------------------- - -.. automodule:: acapy_agent.storage.vc_holder.in_memory - :members: - :undoc-members: - :show-inheritance: - acapy\_agent.storage.vc\_holder.vc\_record module ------------------------------------------------- diff --git a/docs/generated/acapy_agent.utils.rst b/docs/generated/acapy_agent.utils.rst index 70c61f2d1a..4a8fd038e3 100644 --- a/docs/generated/acapy_agent.utils.rst +++ b/docs/generated/acapy_agent.utils.rst @@ -49,6 +49,14 @@ acapy\_agent.utils.env module :undoc-members: :show-inheritance: +acapy\_agent.utils.extract\_validation\_error module +---------------------------------------------------- + +.. automodule:: acapy_agent.utils.extract_validation_error + :members: + :undoc-members: + :show-inheritance: + acapy\_agent.utils.general module --------------------------------- @@ -121,6 +129,14 @@ acapy\_agent.utils.task\_queue module :undoc-members: :show-inheritance: +acapy\_agent.utils.testing module +--------------------------------- + +.. automodule:: acapy_agent.utils.testing + :members: + :undoc-members: + :show-inheritance: + acapy\_agent.utils.tracing module --------------------------------- diff --git a/docs/generated/acapy_agent.wallet.rst b/docs/generated/acapy_agent.wallet.rst index 9f075046ae..d09130188d 100644 --- a/docs/generated/acapy_agent.wallet.rst +++ b/docs/generated/acapy_agent.wallet.rst @@ -106,14 +106,6 @@ acapy\_agent.wallet.error module :undoc-members: :show-inheritance: -acapy\_agent.wallet.in\_memory module -------------------------------------- - -.. automodule:: acapy_agent.wallet.in_memory - :members: - :undoc-members: - :show-inheritance: - acapy\_agent.wallet.jwt module ------------------------------ diff --git a/mkdocs-requirements.txt b/mkdocs-requirements.txt index eb1ee40600..a3290d9569 100644 --- a/mkdocs-requirements.txt +++ b/mkdocs-requirements.txt @@ -1,3 +1,3 @@ -mkdocs-material==9.5.44 +mkdocs-material==9.5.47 mike==2.1.3 diff --git a/mkdocs.yml b/mkdocs.yml index 0f8593cb94..cebeffcc7e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -97,6 +97,7 @@ nav: - Configuring Multiple Indy Ledgers: features/Multiledger.md - Automatically Endorsing Indy Transations: features/Endorser.md - Using W3C JSON-LD Signed Credentials: features/JsonLdCredentials.md + - Issuing and Presenting W3C Data Integrity VCs: features/W3cCredentials.md - Using SD-JWTs: features/SelectiveDisclosureJWTs.md - AnonCreds Presentation Validation: features/AnoncredsProofValidation.md - Multiple Credential Types: features/Multicredentials.md diff --git a/open-api/openapi.json b/open-api/openapi.json index 398b1d02ef..58fa0ee6b6 100644 --- a/open-api/openapi.json +++ b/open-api/openapi.json @@ -2,7 +2,7 @@ "openapi" : "3.0.1", "info" : { "title" : "Aries Cloud Agent", - "version" : "v1.1.0" + "version" : "v1.1.1" }, "servers" : [ { "url" : "/" @@ -390,7 +390,7 @@ "description" : "" } }, - "summary" : "Create a credential definition on the connected ledger", + "summary" : "Create a credential definition on the connected datastore", "tags" : [ "anoncreds - credential definitions" ], "x-codegen-request-body-name" : "body" } @@ -549,7 +549,7 @@ "description" : "" } }, - "summary" : "Create and publish a revocation status list on the connected ledger", + "summary" : "Create and publish a revocation status list on the connected datastore", "tags" : [ "anoncreds - revocation" ], "x-codegen-request-body-name" : "body" } @@ -578,7 +578,7 @@ "description" : "" } }, - "summary" : "Create and publish a registration revocation on the connected ledger", + "summary" : "Create and publish a registration revocation on the connected datastore", "tags" : [ "anoncreds - revocation" ], "x-codegen-request-body-name" : "body" } @@ -1012,7 +1012,7 @@ "description" : "" } }, - "summary" : "Create a schema on the connected ledger", + "summary" : "Create a schema on the connected datastore", "tags" : [ "anoncreds - schemas" ], "x-codegen-request-body-name" : "body" } @@ -7770,7 +7770,7 @@ }, "issuerId" : { "description" : "Issuer Identifier of the credential definition or schema", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "type" : "string" }, "name" : { @@ -7786,6 +7786,170 @@ }, "type" : "object" }, + "AnoncredsPresentationRequestNonRevoked" : { + "properties" : { + "from" : { + "description" : "Earliest time of interest in non-revocation interval", + "example" : 1640995199, + "maximum" : 18446744073709551615, + "minimum" : 0, + "type" : "integer" + }, + "to" : { + "description" : "Latest time of interest in non-revocation interval", + "example" : 1640995199, + "maximum" : 18446744073709551615, + "minimum" : 0, + "type" : "integer" + } + }, + "type" : "object" + }, + "AnoncredsPresentationReqAttrSpec" : { + "properties" : { + "name" : { + "description" : "Attribute name", + "example" : "favouriteDrink", + "type" : "string" + }, + "names" : { + "description" : "Attribute name group", + "items" : { + "example" : "age", + "type" : "string" + }, + "type" : "array" + }, + "non_revoked" : { + "$ref" : "#/components/schemas/AnoncredsPresentationReqAttrSpecNonRevoked" + }, + "restrictions" : { + "description" : "If present, credential must satisfy one of given restrictions: specify schema_id, schema_issuer_did, schema_name, schema_version, issuer_did, cred_def_id, and/or attr::::value where represents a credential attribute name", + "items" : { + "additionalProperties" : { + "example" : "did:(method):3:CL:20:tag", + "type" : "string" + }, + "type" : "object" + }, + "type" : "array" + } + }, + "type" : "object" + }, + "AnoncredsPresentationReqAttrSpecNonRevoked" : { + "properties" : { + "from" : { + "description" : "Earliest time of interest in non-revocation interval", + "example" : 1640995199, + "maximum" : 18446744073709551615, + "minimum" : 0, + "type" : "integer" + }, + "to" : { + "description" : "Latest time of interest in non-revocation interval", + "example" : 1640995199, + "maximum" : 18446744073709551615, + "minimum" : 0, + "type" : "integer" + } + }, + "type" : "object" + }, + "AnoncredsPresentationReqPredSpec" : { + "properties" : { + "name" : { + "description" : "Attribute name", + "example" : "index", + "type" : "string" + }, + "non_revoked" : { + "$ref" : "#/components/schemas/AnoncredsPresentationReqPredSpecNonRevoked" + }, + "p_type" : { + "description" : "Predicate type ('<', '<=', '>=', or '>')", + "enum" : [ "<", "<=", ">=", ">" ], + "example" : ">=", + "type" : "string" + }, + "p_value" : { + "description" : "Threshold value", + "type" : "integer" + }, + "restrictions" : { + "description" : "If present, credential must satisfy one of given restrictions: specify schema_id, schema_issuer_did, schema_name, schema_version, issuer_did, cred_def_id, and/or attr::::value where represents a credential attribute name", + "items" : { + "additionalProperties" : { + "example" : "did:(method):3:CL:20:tag", + "type" : "string" + }, + "type" : "object" + }, + "type" : "array" + } + }, + "required" : [ "name", "p_type", "p_value" ], + "type" : "object" + }, + "AnoncredsPresentationReqPredSpecNonRevoked" : { + "properties" : { + "from" : { + "description" : "Earliest time of interest in non-revocation interval", + "example" : 1640995199, + "maximum" : 18446744073709551615, + "minimum" : 0, + "type" : "integer" + }, + "to" : { + "description" : "Latest time of interest in non-revocation interval", + "example" : 1640995199, + "maximum" : 18446744073709551615, + "minimum" : 0, + "type" : "integer" + } + }, + "type" : "object" + }, + "AnoncredsPresentationRequest" : { + "properties" : { + "name" : { + "description" : "Proof request name", + "example" : "Proof request", + "type" : "string" + }, + "non_revoked" : { + "$ref" : "#/components/schemas/AnoncredsPresentationRequestNonRevoked" + }, + "nonce" : { + "description" : "Nonce", + "example" : "1", + "pattern" : "^[1-9][0-9]*$", + "type" : "string" + }, + "requested_attributes" : { + "additionalProperties" : { + "$ref" : "#/components/schemas/AnoncredsPresentationReqAttrSpec" + }, + "description" : "Requested attribute specifications of proof request", + "type" : "object" + }, + "requested_predicates" : { + "additionalProperties" : { + "$ref" : "#/components/schemas/AnoncredsPresentationReqPredSpec" + }, + "description" : "Requested predicate specifications of proof request", + "type" : "object" + }, + "version" : { + "description" : "Proof request version", + "example" : "1.0", + "pattern" : "^[0-9.]+$", + "type" : "string" + } + }, + "required" : [ "requested_attributes", "requested_predicates" ], + "type" : "object" + }, "AttachDecorator" : { "properties" : { "@id" : { @@ -8578,12 +8742,12 @@ "properties" : { "issuerId" : { "description" : "Issuer Identifier of the credential definition or schema", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "type" : "string" }, "schemaId" : { "description" : "Schema identifier", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "type" : "string" }, "tag" : { @@ -8666,7 +8830,7 @@ }, "credential_definition_id" : { "description" : "credential definition id", - "example" : "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag", + "example" : "did:(method):3:CL:20:tag", "nullable" : true, "type" : "string" }, @@ -9885,7 +10049,7 @@ }, "credential_definition_id" : { "description" : "credential definition id", - "example" : "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag", + "example" : "did:(method):3:CL:20:tag", "type" : "string" }, "credential_definitions_metadata" : { @@ -9958,7 +10122,7 @@ }, "schema_id" : { "description" : "Schema identifier", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "type" : "string" }, "schema_metadata" : { @@ -9973,7 +10137,7 @@ "schema_ids" : { "items" : { "description" : "Schema identifiers", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "type" : "string" }, "type" : "array" @@ -11038,12 +11202,12 @@ "properties" : { "issuerId" : { "description" : "Issuer Identifier of the credential definition", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "type" : "string" }, "schemaId" : { "description" : "Schema identifier", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "type" : "string" }, "tag" : { @@ -11059,12 +11223,12 @@ "properties" : { "credDefId" : { "description" : "Credential definition identifier", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "type" : "string" }, "issuerId" : { "description" : "Issuer Identifier of the credential definition or schema", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "type" : "string" }, "maxCredNum" : { @@ -12836,12 +13000,12 @@ }, "issuerId" : { "description" : "Issuer Identifier of the credential definition or schema", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "type" : "string" }, "revRegDefId" : { "description" : "The ID of the revocation registry definition", - "example" : "WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0", + "example" : "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0", "type" : "string" }, "revocationList" : { @@ -12866,7 +13030,7 @@ }, "rev_reg_def_id" : { "description" : "Revocation registry definition identifier", - "example" : "WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0", + "example" : "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0", "type" : "string" } }, @@ -12955,12 +13119,12 @@ "properties" : { "credDefId" : { "description" : "Credential definition identifier", - "example" : "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag", + "example" : "did:(method):3:CL:20:tag", "type" : "string" }, "issuerId" : { "description" : "Issuer Identifier of the credential definition or schema", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "type" : "string" }, "revocDefType" : { @@ -13022,7 +13186,7 @@ }, "revocation_registry_definition_id" : { "description" : "revocation registry definition id", - "example" : "WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0", + "example" : "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0", "type" : "string" }, "state" : { @@ -13582,7 +13746,7 @@ }, "schema_id" : { "description" : "Schema identifier", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "type" : "string" }, "state" : { @@ -15358,6 +15522,13 @@ }, "V20CredFilter" : { "properties" : { + "anoncreds" : { + "allOf" : [ { + "$ref" : "#/components/schemas/V20CredFilterAnoncreds" + } ], + "description" : "Credential filter for anoncreds", + "type" : "object" + }, "indy" : { "allOf" : [ { "$ref" : "#/components/schemas/V20CredFilterIndy" @@ -15382,6 +15553,31 @@ }, "type" : "object" }, + "V20CredFilterAnoncreds" : { + "properties" : { + "cred_def_id" : { + "description" : "Credential definition identifier", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", + "type" : "string" + }, + "epoch" : { + "description" : "Credential epoch time", + "example" : "2021-08-24", + "type" : "string" + }, + "issuer_id" : { + "description" : "Credential issuer DID", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", + "type" : "string" + }, + "schema_id" : { + "description" : "Schema identifier", + "example" : "did:(method):2:schema_name:1.0", + "type" : "string" + } + }, + "type" : "object" + }, "V20CredFilterIndy" : { "properties" : { "cred_def_id" : { @@ -16215,6 +16411,13 @@ }, "V20PresProposalByFormat" : { "properties" : { + "anoncreds" : { + "allOf" : [ { + "$ref" : "#/components/schemas/AnoncredsPresentationRequest" + } ], + "description" : "Presentation proposal for anoncreds", + "type" : "object" + }, "dif" : { "allOf" : [ { "$ref" : "#/components/schemas/DIFProofProposal" @@ -16304,6 +16507,13 @@ }, "V20PresRequestByFormat" : { "properties" : { + "anoncreds" : { + "allOf" : [ { + "$ref" : "#/components/schemas/AnoncredsPresentationRequest" + } ], + "description" : "Presentation proposal for anoncreds", + "type" : "object" + }, "dif" : { "allOf" : [ { "$ref" : "#/components/schemas/DIFProofRequest" @@ -16355,6 +16565,13 @@ }, "V20PresSpecByFormatRequest" : { "properties" : { + "anoncreds" : { + "allOf" : [ { + "$ref" : "#/components/schemas/IndyPresSpec" + } ], + "description" : "Presentation specification for anoncreds", + "type" : "object" + }, "auto_remove" : { "description" : "Whether to remove the presentation exchange record on completion (overrides --preserve-exchange-records configuration setting)", "type" : "boolean" diff --git a/open-api/swagger.json b/open-api/swagger.json index b3f325664f..df7b2ee84e 100644 --- a/open-api/swagger.json +++ b/open-api/swagger.json @@ -1,7 +1,7 @@ { "swagger" : "2.0", "info" : { - "version" : "v1.1.0", + "version" : "v1.1.1", "title" : "Aries Cloud Agent" }, "tags" : [ { @@ -333,7 +333,7 @@ "/anoncreds/credential-definition" : { "post" : { "tags" : [ "anoncreds - credential definitions" ], - "summary" : "Create a credential definition on the connected ledger", + "summary" : "Create a credential definition on the connected datastore", "produces" : [ "application/json" ], "parameters" : [ { "in" : "body", @@ -464,7 +464,7 @@ "/anoncreds/revocation-list" : { "post" : { "tags" : [ "anoncreds - revocation" ], - "summary" : "Create and publish a revocation status list on the connected ledger", + "summary" : "Create and publish a revocation status list on the connected datastore", "produces" : [ "application/json" ], "parameters" : [ { "in" : "body", @@ -487,7 +487,7 @@ "/anoncreds/revocation-registry-definition" : { "post" : { "tags" : [ "anoncreds - revocation" ], - "summary" : "Create and publish a registration revocation on the connected ledger", + "summary" : "Create and publish a registration revocation on the connected datastore", "produces" : [ "application/json" ], "parameters" : [ { "in" : "body", @@ -843,7 +843,7 @@ "/anoncreds/schema" : { "post" : { "tags" : [ "anoncreds - schemas" ], - "summary" : "Create a schema on the connected ledger", + "summary" : "Create a schema on the connected datastore", "produces" : [ "application/json" ], "parameters" : [ { "in" : "body", @@ -6402,7 +6402,7 @@ }, "issuerId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "description" : "Issuer Identifier of the credential definition or schema" }, "name" : { @@ -6417,6 +6417,170 @@ } } }, + "AnoncredsPresentationRequestNonRevoked" : { + "type" : "object", + "properties" : { + "from" : { + "type" : "integer", + "example" : 1640995199, + "description" : "Earliest time of interest in non-revocation interval", + "minimum" : 0, + "maximum" : 18446744073709551615 + }, + "to" : { + "type" : "integer", + "example" : 1640995199, + "description" : "Latest time of interest in non-revocation interval", + "minimum" : 0, + "maximum" : 18446744073709551615 + } + } + }, + "AnoncredsPresentationReqAttrSpec" : { + "type" : "object", + "properties" : { + "name" : { + "type" : "string", + "example" : "favouriteDrink", + "description" : "Attribute name" + }, + "names" : { + "type" : "array", + "description" : "Attribute name group", + "items" : { + "type" : "string", + "example" : "age" + } + }, + "non_revoked" : { + "$ref" : "#/definitions/AnoncredsPresentationReqAttrSpecNonRevoked" + }, + "restrictions" : { + "type" : "array", + "description" : "If present, credential must satisfy one of given restrictions: specify schema_id, schema_issuer_did, schema_name, schema_version, issuer_did, cred_def_id, and/or attr::::value where represents a credential attribute name", + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "example" : "did:(method):3:CL:20:tag" + } + } + } + } + }, + "AnoncredsPresentationReqAttrSpecNonRevoked" : { + "type" : "object", + "properties" : { + "from" : { + "type" : "integer", + "example" : 1640995199, + "description" : "Earliest time of interest in non-revocation interval", + "minimum" : 0, + "maximum" : 18446744073709551615 + }, + "to" : { + "type" : "integer", + "example" : 1640995199, + "description" : "Latest time of interest in non-revocation interval", + "minimum" : 0, + "maximum" : 18446744073709551615 + } + } + }, + "AnoncredsPresentationReqPredSpec" : { + "type" : "object", + "required" : [ "name", "p_type", "p_value" ], + "properties" : { + "name" : { + "type" : "string", + "example" : "index", + "description" : "Attribute name" + }, + "non_revoked" : { + "$ref" : "#/definitions/AnoncredsPresentationReqPredSpecNonRevoked" + }, + "p_type" : { + "type" : "string", + "example" : ">=", + "description" : "Predicate type ('<', '<=', '>=', or '>')", + "enum" : [ "<", "<=", ">=", ">" ] + }, + "p_value" : { + "type" : "integer", + "description" : "Threshold value" + }, + "restrictions" : { + "type" : "array", + "description" : "If present, credential must satisfy one of given restrictions: specify schema_id, schema_issuer_did, schema_name, schema_version, issuer_did, cred_def_id, and/or attr::::value where represents a credential attribute name", + "items" : { + "type" : "object", + "additionalProperties" : { + "type" : "string", + "example" : "did:(method):3:CL:20:tag" + } + } + } + } + }, + "AnoncredsPresentationReqPredSpecNonRevoked" : { + "type" : "object", + "properties" : { + "from" : { + "type" : "integer", + "example" : 1640995199, + "description" : "Earliest time of interest in non-revocation interval", + "minimum" : 0, + "maximum" : 18446744073709551615 + }, + "to" : { + "type" : "integer", + "example" : 1640995199, + "description" : "Latest time of interest in non-revocation interval", + "minimum" : 0, + "maximum" : 18446744073709551615 + } + } + }, + "AnoncredsPresentationRequest" : { + "type" : "object", + "required" : [ "requested_attributes", "requested_predicates" ], + "properties" : { + "name" : { + "type" : "string", + "example" : "Proof request", + "description" : "Proof request name" + }, + "non_revoked" : { + "$ref" : "#/definitions/AnoncredsPresentationRequestNonRevoked" + }, + "nonce" : { + "type" : "string", + "example" : "1", + "description" : "Nonce", + "pattern" : "^[1-9][0-9]*$" + }, + "requested_attributes" : { + "type" : "object", + "description" : "Requested attribute specifications of proof request", + "additionalProperties" : { + "$ref" : "#/definitions/AnoncredsPresentationReqAttrSpec" + } + }, + "requested_predicates" : { + "type" : "object", + "description" : "Requested predicate specifications of proof request", + "additionalProperties" : { + "$ref" : "#/definitions/AnoncredsPresentationReqPredSpec" + } + }, + "version" : { + "type" : "string", + "example" : "1.0", + "description" : "Proof request version", + "pattern" : "^[0-9.]+$" + } + } + }, "AttachDecorator" : { "type" : "object", "required" : [ "data" ], @@ -7205,12 +7369,12 @@ "properties" : { "issuerId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "description" : "Issuer Identifier of the credential definition or schema" }, "schemaId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "description" : "Schema identifier" }, "tag" : { @@ -7289,7 +7453,7 @@ }, "credential_definition_id" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag", + "example" : "did:(method):3:CL:20:tag", "description" : "credential definition id", "x-nullable" : true }, @@ -8447,7 +8611,7 @@ }, "credential_definition_id" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag", + "example" : "did:(method):3:CL:20:tag", "description" : "credential definition id" }, "credential_definitions_metadata" : { @@ -8520,7 +8684,7 @@ }, "schema_id" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "description" : "Schema identifier" }, "schema_metadata" : { @@ -8536,7 +8700,7 @@ "type" : "array", "items" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "description" : "Schema identifiers" } } @@ -9551,12 +9715,12 @@ "properties" : { "issuerId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "description" : "Issuer Identifier of the credential definition" }, "schemaId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "description" : "Schema identifier" }, "tag" : { @@ -9571,12 +9735,12 @@ "properties" : { "credDefId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "description" : "Credential definition identifier" }, "issuerId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "description" : "Issuer Identifier of the credential definition or schema" }, "maxCredNum" : { @@ -11266,12 +11430,12 @@ }, "issuerId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "description" : "Issuer Identifier of the credential definition or schema" }, "revRegDefId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0", + "example" : "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0", "description" : "The ID of the revocation registry definition" }, "revocationList" : { @@ -11297,7 +11461,7 @@ }, "rev_reg_def_id" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0", + "example" : "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0", "description" : "Revocation registry definition identifier" } } @@ -11382,12 +11546,12 @@ "properties" : { "credDefId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:3:CL:20:tag", + "example" : "did:(method):3:CL:20:tag", "description" : "Credential definition identifier" }, "issuerId" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "description" : "Issuer Identifier of the credential definition or schema" }, "revocDefType" : { @@ -11445,7 +11609,7 @@ }, "revocation_registry_definition_id" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0", + "example" : "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0", "description" : "revocation registry definition id" }, "state" : { @@ -11999,7 +12163,7 @@ }, "schema_id" : { "type" : "string", - "example" : "WgWxqztrNooG92RXvxSTWv:2:schema_name:1.0", + "example" : "did:(method):2:schema_name:1.0", "description" : "Schema identifier" }, "state" : { @@ -13655,6 +13819,9 @@ "V20CredFilter" : { "type" : "object", "properties" : { + "anoncreds" : { + "$ref" : "#/definitions/V20CredFilter_anoncreds" + }, "indy" : { "$ref" : "#/definitions/V20CredFilter_indy" }, @@ -13666,6 +13833,31 @@ } } }, + "V20CredFilterAnoncreds" : { + "type" : "object", + "properties" : { + "cred_def_id" : { + "type" : "string", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", + "description" : "Credential definition identifier" + }, + "epoch" : { + "type" : "string", + "example" : "2021-08-24", + "description" : "Credential epoch time" + }, + "issuer_id" : { + "type" : "string", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", + "description" : "Credential issuer DID" + }, + "schema_id" : { + "type" : "string", + "example" : "did:(method):2:schema_name:1.0", + "description" : "Schema identifier" + } + } + }, "V20CredFilterIndy" : { "type" : "object", "properties" : { @@ -14448,6 +14640,9 @@ "V20PresProposalByFormat" : { "type" : "object", "properties" : { + "anoncreds" : { + "$ref" : "#/definitions/V20PresProposalByFormat_anoncreds" + }, "dif" : { "$ref" : "#/definitions/V20PresProposalByFormat_dif" }, @@ -14529,6 +14724,9 @@ "V20PresRequestByFormat" : { "type" : "object", "properties" : { + "anoncreds" : { + "$ref" : "#/definitions/V20PresProposalByFormat_anoncreds" + }, "dif" : { "$ref" : "#/definitions/V20PresRequestByFormat_dif" }, @@ -14572,6 +14770,9 @@ "V20PresSpecByFormatRequest" : { "type" : "object", "properties" : { + "anoncreds" : { + "$ref" : "#/definitions/V20PresSpecByFormatRequest_anoncreds" + }, "auto_remove" : { "type" : "boolean", "description" : "Whether to remove the presentation exchange record on completion (overrides --preserve-exchange-records configuration setting)" @@ -15266,6 +15467,10 @@ "type" : "object", "description" : "Credential exchange record" }, + "V20CredFilter_anoncreds" : { + "type" : "object", + "description" : "Credential filter for anoncreds" + }, "V20CredFilter_indy" : { "type" : "object", "description" : "Credential filter for indy" @@ -15302,6 +15507,10 @@ "type" : "object", "description" : "Presentation message" }, + "V20PresProposalByFormat_anoncreds" : { + "type" : "object", + "description" : "Presentation proposal for anoncreds" + }, "V20PresProposalByFormat_dif" : { "type" : "object", "description" : "Presentation proposal for DIF" @@ -15318,6 +15527,10 @@ "type" : "object", "description" : "Presentation request for indy" }, + "V20PresSpecByFormatRequest_anoncreds" : { + "type" : "object", + "description" : "Presentation specification for anoncreds" + }, "V20PresSpecByFormatRequest_dif" : { "type" : "object", "description" : "Optional Presentation specification for DIF, overrides the PresentationExchange record's PresRequest" diff --git a/poetry.lock b/poetry.lock index fc7b8e046d..3c259443fd 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2,98 +2,98 @@ [[package]] name = "aiohappyeyeballs" -version = "2.4.3" +version = "2.4.4" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "aiohappyeyeballs-2.4.3-py3-none-any.whl", hash = "sha256:8a7a83727b2756f394ab2895ea0765a0a8c475e3c71e98d43d76f22b4b435572"}, - {file = "aiohappyeyeballs-2.4.3.tar.gz", hash = "sha256:75cf88a15106a5002a8eb1dab212525c00d1f4c0fa96e551c9fbe6f09a621586"}, + {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, + {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, ] [[package]] name = "aiohttp" -version = "3.11.0" +version = "3.11.9" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" files = [ - {file = "aiohttp-3.11.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:024409c1b1d6076d0ed933dcebd7e4fc6f3320a227bfa0c1b6b93a8b5a146f04"}, - {file = "aiohttp-3.11.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:62502b8ffee8c6a4b5c6bf99d1de277d42bf51b2fb713975d9b63b560150b7ac"}, - {file = "aiohttp-3.11.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c54c635d1f52490cde7ef3a423645167a8284e452a35405d5c7dc1242a8e75c9"}, - {file = "aiohttp-3.11.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:104ea21994b1403e4c1b398866f1187c1694fa291314ad7216ec1d8ec6b49f38"}, - {file = "aiohttp-3.11.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:04b24497b3baf15035730de5f207ade88a67d4483a5f16ced7ece348933a5b47"}, - {file = "aiohttp-3.11.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08474e71772a516ba2e2167b4707af8361d2c452b3d8a5364c984f4867869499"}, - {file = "aiohttp-3.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f40380c96dd407dfa84eb2d264e68aa47717b53bdbe210a59cc3c35a4635f195"}, - {file = "aiohttp-3.11.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1668ef2f3a7ec9881f4b6a917e5f97c87a343fa6b0d5fc826b7b0297ddd0887"}, - {file = "aiohttp-3.11.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f3bf5c132eb48002bcc3825702d241d35b4e9585009e65e9dcf9c4635d0b7424"}, - {file = "aiohttp-3.11.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c0315978b2a4569e03fb59100f6a7e7d23f718a4521491f5c13d946d37549f3d"}, - {file = "aiohttp-3.11.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d5cae4cd271e20b7ab757e966cc919186b9f02535418ab36c471a5377ef4deaa"}, - {file = "aiohttp-3.11.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:31b91ff3a1fcb206a1fa76e0de1f08c9ffb1dc0deb7296fa2618adfe380fc676"}, - {file = "aiohttp-3.11.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ebf610c37df4f09c71c9bbf8309b4b459107e6fe889ac0d7e16f6e4ebd975f86"}, - {file = "aiohttp-3.11.0-cp310-cp310-win32.whl", hash = "sha256:b40c304ab01e89ad0aeeecf91bbaa6ae3b00e27b796c9e8d50b71a4a7e885cc8"}, - {file = "aiohttp-3.11.0-cp310-cp310-win_amd64.whl", hash = "sha256:cd0834e4260eab78671b81d34f110fbaac449563e48d419cec0030d9a8e58693"}, - {file = "aiohttp-3.11.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:89a96a0696dc67d548f69cb518c581a7a33cc1f26ab42229dea1709217c9d926"}, - {file = "aiohttp-3.11.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f6b925c7775ab857bdc1e52e1f5abcae7d18751c09b751aeb641a5276d9b990e"}, - {file = "aiohttp-3.11.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7867d0808614f04e78e0a8d5a2c1f8ac6bc626a0c0e2f62be48be6b749e2f8b2"}, - {file = "aiohttp-3.11.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:229ae13959a5f499d90ffbb4b9eac2255d8599315027d6f7c22fa9803a94d5b1"}, - {file = "aiohttp-3.11.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:62a2f5268b672087c45b33479ba1bb1d5a48c6d76c133cfce3a4f77410c200d1"}, - {file = "aiohttp-3.11.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a896059b6937d1a22d8ee8377cdcd097bd26cd8c653b8f972051488b9baadee9"}, - {file = "aiohttp-3.11.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:104deb7873681273c5daa13c41924693df394043a118dae90387d35bc5531788"}, - {file = "aiohttp-3.11.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae36ae52b0c22fb69fb8b744eff82a20db512a29eafc6e3a4ab43b17215b219d"}, - {file = "aiohttp-3.11.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7349205bb163318dcc102329d30be59a647a3d24c82c3d91ed35b7e7301ea7e"}, - {file = "aiohttp-3.11.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9095580806d9ed07c0c29b23364a0b1fb78258ef9f4bddf7e55bac0e475d4edf"}, - {file = "aiohttp-3.11.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:4d218d3eca40196384ad3b481309c56fd60e664128885d1734da0a8aa530d433"}, - {file = "aiohttp-3.11.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6533dd06df3d17d1756829b68b365b1583929b54082db8f65083a4184bf68322"}, - {file = "aiohttp-3.11.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:72cd984f7f14e8c01b3e38f18f39ea85dba84e52ea05e37116ba5e2a72eef396"}, - {file = "aiohttp-3.11.0-cp311-cp311-win32.whl", hash = "sha256:c1828e10c3a49e2b234b87600ecb68a92b8a8dcf8b99bca9447f16c4baaa1630"}, - {file = "aiohttp-3.11.0-cp311-cp311-win_amd64.whl", hash = "sha256:900ff74d78eb580ae4aa5883242893b123a0c442a46570902500f08d6a7e6696"}, - {file = "aiohttp-3.11.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f8f0d79b923070f25674e4ea8f3d61c9d89d24d9598d50ff32c5b9b23c79a25b"}, - {file = "aiohttp-3.11.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:113bf06b029143e94a47c4f36e11a8b7e396e9d1f1fc8cea58e6b7e370cfed38"}, - {file = "aiohttp-3.11.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3e1ed8d152cccceffb1ee7a2ac227c16372e453fb11b3aeaa56783049b85d3f6"}, - {file = "aiohttp-3.11.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2e82e515e268b965424ecabebd91834a41b36260b6ef5db015ee12ddb28ef3"}, - {file = "aiohttp-3.11.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c1c49bc393d854d4421ebc174a0a41f9261f50d3694d8ca277146cbbcfd24ee7"}, - {file = "aiohttp-3.11.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57e17c6d71f2dc857a8a1d09be1be7802e35d90fb4ba4b06cf1aab6414a57894"}, - {file = "aiohttp-3.11.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12071dd2cc95ba81e0f2737bebcb98b2a8656015e87772e84e8fb9e635b5da6e"}, - {file = "aiohttp-3.11.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97056d3422594e0787733ac4c45bef58722d452f4dc6615fee42f59fe51707dd"}, - {file = "aiohttp-3.11.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2ec5efbc872b00ddd85e3904059d274f284cff314e13f48776050ca2c58f451d"}, - {file = "aiohttp-3.11.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:dd505a1121ad5b666191840b7bd1d8cb917df2647deeca6f3474331b72452362"}, - {file = "aiohttp-3.11.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:600b1d9f86a130131915e2f2127664311b33902c486b21a747d626f5144b4471"}, - {file = "aiohttp-3.11.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:8c47a0ba6c2b3d3e5715f8338d657badd21f778c6be16701922c65521c5ecfc9"}, - {file = "aiohttp-3.11.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8b323b5d3aef7dd811424c269322eec58a977c0c8152e650159e47210d900504"}, - {file = "aiohttp-3.11.0-cp312-cp312-win32.whl", hash = "sha256:aabc4e92cb153636d6be54e84dad1b252ddb9aebe077942b6dcffe5e468d476a"}, - {file = "aiohttp-3.11.0-cp312-cp312-win_amd64.whl", hash = "sha256:508cfcc99534b1282595357592d8367b44392b21f6eb5d4dc021f8d0d809e94d"}, - {file = "aiohttp-3.11.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:c98a596ac20e8980cc6f34c0c92a113e98eb08f3997c150064d26d2aeb043e5a"}, - {file = "aiohttp-3.11.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ad14cdc0fba4df31c0f6e06c21928c5b924725cbf60d0ccc5f6e7132636250e9"}, - {file = "aiohttp-3.11.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:170fb2324826bb9f08055a8291f42192ae5ee2f25b2966c8f0f4537c61d73a7b"}, - {file = "aiohttp-3.11.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cdad66685fcf2ad14ce522cf849d4a025f4fd206d6cfc3f403d9873e4c243b03"}, - {file = "aiohttp-3.11.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8b95a63a8e8b5f0464bd8b1b0d59d2bec98a59b6aacc71e9be23df6989b3dfb"}, - {file = "aiohttp-3.11.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7bcfcede95531589295f56e924702cef7f9685c9e4e5407592e04ded6a65bf3"}, - {file = "aiohttp-3.11.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ecc2fb1a0a9d48cf773add34196cddf7e488e48e9596e090849751bf43098f4"}, - {file = "aiohttp-3.11.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fef105113d56e817cb9bcc609667ee461321413a7b972b03f5b4939f40f307c"}, - {file = "aiohttp-3.11.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d33b4490026968bdc7f0729b9d87a3a6b1e09043557d2fc1c605c6072deb2f11"}, - {file = "aiohttp-3.11.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6362f50a6f0e5482c4330d2151cb682779230683da0e155c15ec9fc58cb50b6a"}, - {file = "aiohttp-3.11.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4f698aa61879df64425191d41213dfd99efdc1627e6398e6d7aa5c312fac9702"}, - {file = "aiohttp-3.11.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0e7a0762cc29cd3acd01a4d2b547b3af7956ad230ebb80b529a8e4f3e4740fe8"}, - {file = "aiohttp-3.11.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b3e4fb7f5354d39490d8209aefdf5830b208d01c7293a2164e404312c3d8bc55"}, - {file = "aiohttp-3.11.0-cp313-cp313-win32.whl", hash = "sha256:6c5a6958f4366496004cf503d847093d464814543f157ef3b738bbf604232415"}, - {file = "aiohttp-3.11.0-cp313-cp313-win_amd64.whl", hash = "sha256:3ed360d6672a9423aad39902a4e9fe305464d20ed7931dbdba30a4625782d875"}, - {file = "aiohttp-3.11.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d1ea006426edf7e1299c52a58b0443158012f7a56fed3515164b60bfcb1503a9"}, - {file = "aiohttp-3.11.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c5e6a1f8b0268ffa1c84d7c3558724956002ba8361176e76406233e704bbcffb"}, - {file = "aiohttp-3.11.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:40dc9446cff326672fcbf93efdb8ef7e949824de1097624efe4f61ac7f0d2c43"}, - {file = "aiohttp-3.11.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21b4545e8d96870da9652930c5198366605ff8f982757030e2148cf341e5746b"}, - {file = "aiohttp-3.11.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:37f8cf3c43f292d9bb3e6760476c2b55b9663a581fad682a586a410c43a7683e"}, - {file = "aiohttp-3.11.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:329f5059e0bf6983dceebac8e6ed20e75eaff6163b3414f4a4cb59e0d7037672"}, - {file = "aiohttp-3.11.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85ae6f182be72c3531915e90625cc65afce4df8a0fc4988bd52d8a5d5faaeb68"}, - {file = "aiohttp-3.11.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d664e5f937c08adb7908ea9f391fbf2928a9b09cb412ac0aba602bde9e499e4"}, - {file = "aiohttp-3.11.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:feca9fafa4385aea6759c171cd25ea82f7375312fca04178dae35331be45e538"}, - {file = "aiohttp-3.11.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c415b9601ff50709d6050c8a9281733a9b042b9e589265ac40305b875cf9c463"}, - {file = "aiohttp-3.11.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:91d3991fad8b65e5dbc13cd95669ea689fe0a96ff63e4e64ac24ed724e4f8103"}, - {file = "aiohttp-3.11.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9231d610754724273a6ac05a1f177979490bfa6f84d49646df3928af2e88cfd5"}, - {file = "aiohttp-3.11.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4e4e155968040e32c124a89852a1a5426d0e920a35f4331e1b3949037bfe93a3"}, - {file = "aiohttp-3.11.0-cp39-cp39-win32.whl", hash = "sha256:76d6ee8bb132f8ee0fcb0e205b4708ddb6fba524eb515ee168113063d825131b"}, - {file = "aiohttp-3.11.0-cp39-cp39-win_amd64.whl", hash = "sha256:577c7429f8869fa30186fc2c9eee64d75a30b51b61f26aac9725866ae5985cfd"}, - {file = "aiohttp-3.11.0.tar.gz", hash = "sha256:f57a0de48dda792629e7952d34a0c7b81ea336bb9b721391c7c58145b237fe55"}, + {file = "aiohttp-3.11.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0411777249f25d11bd2964a230b3ffafcbed6cd65d0f2b132bc2b8f5b8c347c7"}, + {file = "aiohttp-3.11.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:499368eb904566fbdf1a3836a1532000ef1308f34a1bcbf36e6351904cced771"}, + {file = "aiohttp-3.11.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0b5a5009b0159a8f707879dc102b139466d8ec6db05103ec1520394fdd8ea02c"}, + {file = "aiohttp-3.11.9-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:176f8bb8931da0613bb0ed16326d01330066bb1e172dd97e1e02b1c27383277b"}, + {file = "aiohttp-3.11.9-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6435a66957cdba1a0b16f368bde03ce9c79c57306b39510da6ae5312a1a5b2c1"}, + {file = "aiohttp-3.11.9-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:202f40fb686e5f93908eee0c75d1e6fbe50a43e9bd4909bf3bf4a56b560ca180"}, + {file = "aiohttp-3.11.9-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39625703540feb50b6b7f938b3856d1f4886d2e585d88274e62b1bd273fae09b"}, + {file = "aiohttp-3.11.9-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c6beeac698671baa558e82fa160be9761cf0eb25861943f4689ecf9000f8ebd0"}, + {file = "aiohttp-3.11.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:96726839a42429318017e67a42cca75d4f0d5248a809b3cc2e125445edd7d50d"}, + {file = "aiohttp-3.11.9-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3f5461c77649358610fb9694e790956b4238ac5d9e697a17f63619c096469afe"}, + {file = "aiohttp-3.11.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4313f3bc901255b22f01663eeeae167468264fdae0d32c25fc631d5d6e15b502"}, + {file = "aiohttp-3.11.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:d6e274661c74195708fc4380a4ef64298926c5a50bb10fbae3d01627d7a075b7"}, + {file = "aiohttp-3.11.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:db2914de2559809fdbcf3e48f41b17a493b58cb7988d3e211f6b63126c55fe82"}, + {file = "aiohttp-3.11.9-cp310-cp310-win32.whl", hash = "sha256:27935716f8d62c1c73010428db310fd10136002cfc6d52b0ba7bdfa752d26066"}, + {file = "aiohttp-3.11.9-cp310-cp310-win_amd64.whl", hash = "sha256:afbe85b50ade42ddff5669947afde9e8a610e64d2c80be046d67ec4368e555fa"}, + {file = "aiohttp-3.11.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:afcda759a69c6a8be3aae764ec6733155aa4a5ad9aad4f398b52ba4037942fe3"}, + {file = "aiohttp-3.11.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5bba6b83fde4ca233cfda04cbd4685ab88696b0c8eaf76f7148969eab5e248a"}, + {file = "aiohttp-3.11.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:442356e8924fe1a121f8c87866b0ecdc785757fd28924b17c20493961b3d6697"}, + {file = "aiohttp-3.11.9-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f737fef6e117856400afee4f17774cdea392b28ecf058833f5eca368a18cf1bf"}, + {file = "aiohttp-3.11.9-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea142255d4901b03f89cb6a94411ecec117786a76fc9ab043af8f51dd50b5313"}, + {file = "aiohttp-3.11.9-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e1e9e447856e9b7b3d38e1316ae9a8c92e7536ef48373de758ea055edfd5db5"}, + {file = "aiohttp-3.11.9-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7f6173302f8a329ca5d1ee592af9e628d3ade87816e9958dcf7cdae2841def7"}, + {file = "aiohttp-3.11.9-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7c6147c6306f537cff59409609508a1d2eff81199f0302dd456bb9e7ea50c39"}, + {file = "aiohttp-3.11.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e9d036a9a41fc78e8a3f10a86c2fc1098fca8fab8715ba9eb999ce4788d35df0"}, + {file = "aiohttp-3.11.9-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2ac9fd83096df36728da8e2f4488ac3b5602238f602706606f3702f07a13a409"}, + {file = "aiohttp-3.11.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:d3108f0ad5c6b6d78eec5273219a5bbd884b4aacec17883ceefaac988850ce6e"}, + {file = "aiohttp-3.11.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:96bbec47beb131bbf4bae05d8ef99ad9e5738f12717cfbbf16648b78b0232e87"}, + {file = "aiohttp-3.11.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fc726c3fa8f606d07bd2b500e5dc4c0fd664c59be7788a16b9e34352c50b6b6b"}, + {file = "aiohttp-3.11.9-cp311-cp311-win32.whl", hash = "sha256:5720ebbc7a1b46c33a42d489d25d36c64c419f52159485e55589fbec648ea49a"}, + {file = "aiohttp-3.11.9-cp311-cp311-win_amd64.whl", hash = "sha256:17af09d963fa1acd7e4c280e9354aeafd9e3d47eaa4a6bfbd2171ad7da49f0c5"}, + {file = "aiohttp-3.11.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c1f2d7fd583fc79c240094b3e7237d88493814d4b300d013a42726c35a734bc9"}, + {file = "aiohttp-3.11.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d4b8a1b6c7a68c73191f2ebd3bf66f7ce02f9c374e309bdb68ba886bbbf1b938"}, + {file = "aiohttp-3.11.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bd3f711f4c99da0091ced41dccdc1bcf8be0281dc314d6d9c6b6cf5df66f37a9"}, + {file = "aiohttp-3.11.9-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44cb1a1326a0264480a789e6100dc3e07122eb8cd1ad6b784a3d47d13ed1d89c"}, + {file = "aiohttp-3.11.9-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7a7ddf981a0b953ade1c2379052d47ccda2f58ab678fca0671c7c7ca2f67aac2"}, + {file = "aiohttp-3.11.9-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ffa45cc55b18d4ac1396d1ddb029f139b1d3480f1594130e62bceadf2e1a838"}, + {file = "aiohttp-3.11.9-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cca505829cdab58c2495ff418c96092d225a1bbd486f79017f6de915580d3c44"}, + {file = "aiohttp-3.11.9-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44d323aa80a867cb6db6bebb4bbec677c6478e38128847f2c6b0f70eae984d72"}, + {file = "aiohttp-3.11.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b2fab23003c4bb2249729a7290a76c1dda38c438300fdf97d4e42bf78b19c810"}, + {file = "aiohttp-3.11.9-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:be0c7c98e38a1e3ad7a6ff64af8b6d6db34bf5a41b1478e24c3c74d9e7f8ed42"}, + {file = "aiohttp-3.11.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5cc5e0d069c56645446c45a4b5010d4b33ac6c5ebfd369a791b5f097e46a3c08"}, + {file = "aiohttp-3.11.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9bcf97b971289be69638d8b1b616f7e557e1342debc7fc86cf89d3f08960e411"}, + {file = "aiohttp-3.11.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c7333e7239415076d1418dbfb7fa4df48f3a5b00f8fdf854fca549080455bc14"}, + {file = "aiohttp-3.11.9-cp312-cp312-win32.whl", hash = "sha256:9384b07cfd3045b37b05ed002d1c255db02fb96506ad65f0f9b776b762a7572e"}, + {file = "aiohttp-3.11.9-cp312-cp312-win_amd64.whl", hash = "sha256:f5252ba8b43906f206048fa569debf2cd0da0316e8d5b4d25abe53307f573941"}, + {file = "aiohttp-3.11.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:282e0a7ddd36ebc411f156aeaa0491e8fe7f030e2a95da532cf0c84b0b70bc66"}, + {file = "aiohttp-3.11.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ebd3e6b0c7d4954cca59d241970011f8d3327633d555051c430bd09ff49dc494"}, + {file = "aiohttp-3.11.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:30f9f89ae625d412043f12ca3771b2ccec227cc93b93bb1f994db6e1af40a7d3"}, + {file = "aiohttp-3.11.9-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7a3b5b2c012d70c63d9d13c57ed1603709a4d9d7d473e4a9dfece0e4ea3d5f51"}, + {file = "aiohttp-3.11.9-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ef1550bb5f55f71b97a6a395286db07f7f2c01c8890e613556df9a51da91e8d"}, + {file = "aiohttp-3.11.9-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:317251b9c9a2f1a9ff9cd093775b34c6861d1d7df9439ce3d32a88c275c995cd"}, + {file = "aiohttp-3.11.9-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21cbe97839b009826a61b143d3ca4964c8590d7aed33d6118125e5b71691ca46"}, + {file = "aiohttp-3.11.9-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:618b18c3a2360ac940a5503da14fa4f880c5b9bc315ec20a830357bcc62e6bae"}, + {file = "aiohttp-3.11.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a0cf4d814689e58f57ecd5d8c523e6538417ca2e72ff52c007c64065cef50fb2"}, + {file = "aiohttp-3.11.9-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:15c4e489942d987d5dac0ba39e5772dcbed4cc9ae3710d1025d5ba95e4a5349c"}, + {file = "aiohttp-3.11.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ec8df0ff5a911c6d21957a9182402aad7bf060eaeffd77c9ea1c16aecab5adbf"}, + {file = "aiohttp-3.11.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ed95d66745f53e129e935ad726167d3a6cb18c5d33df3165974d54742c373868"}, + {file = "aiohttp-3.11.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:647ec5bee7e4ec9f1034ab48173b5fa970d9a991e565549b965e93331f1328fe"}, + {file = "aiohttp-3.11.9-cp313-cp313-win32.whl", hash = "sha256:ef2c9499b7bd1e24e473dc1a85de55d72fd084eea3d8bdeec7ee0720decb54fa"}, + {file = "aiohttp-3.11.9-cp313-cp313-win_amd64.whl", hash = "sha256:84de955314aa5e8d469b00b14d6d714b008087a0222b0f743e7ffac34ef56aff"}, + {file = "aiohttp-3.11.9-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e738aabff3586091221044b7a584865ddc4d6120346d12e28e788307cd731043"}, + {file = "aiohttp-3.11.9-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:28f29bce89c3b401a53d6fd4bee401ee943083bf2bdc12ef297c1d63155070b0"}, + {file = "aiohttp-3.11.9-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:31de2f10f63f96cc19e04bd2df9549559beadd0b2ee2da24a17e7ed877ca8c60"}, + {file = "aiohttp-3.11.9-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f31cebd8c27a36af6c7346055ac564946e562080ee1a838da724585c67474f"}, + {file = "aiohttp-3.11.9-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0bcb7f6976dc0b6b56efde13294862adf68dd48854111b422a336fa729a82ea6"}, + {file = "aiohttp-3.11.9-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a8b13b9950d8b2f8f58b6e5842c4b842b5887e2c32e3f4644d6642f1659a530"}, + {file = "aiohttp-3.11.9-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9c23e62f3545c2216100603614f9e019e41b9403c47dd85b8e7e5015bf1bde0"}, + {file = "aiohttp-3.11.9-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec656680fc53a13f849c71afd0c84a55c536206d524cbc831cde80abbe80489e"}, + {file = "aiohttp-3.11.9-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:36df00e0541f264ce42d62280281541a47474dfda500bc5b7f24f70a7f87be7a"}, + {file = "aiohttp-3.11.9-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:8dcfd14c712aa9dd18049280bfb2f95700ff6a8bde645e09f17c3ed3f05a0130"}, + {file = "aiohttp-3.11.9-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:14624d96f0d69cf451deed3173079a68c322279be6030208b045ab77e1e8d550"}, + {file = "aiohttp-3.11.9-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4b01d9cfcb616eeb6d40f02e66bebfe7b06d9f2ef81641fdd50b8dd981166e0b"}, + {file = "aiohttp-3.11.9-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:928f92f80e2e8d6567b87d3316c1fd9860ccfe36e87a9a7f5237d4cda8baa1ba"}, + {file = "aiohttp-3.11.9-cp39-cp39-win32.whl", hash = "sha256:c8a02f74ae419e3955af60f570d83187423e42e672a6433c5e292f1d23619269"}, + {file = "aiohttp-3.11.9-cp39-cp39-win_amd64.whl", hash = "sha256:0a97d657f6cf8782a830bb476c13f7d777cfcab8428ac49dde15c22babceb361"}, + {file = "aiohttp-3.11.9.tar.gz", hash = "sha256:a9266644064779840feec0e34f10a89b3ff1d2d6b751fe90017abcad1864fa7c"}, ] [package.dependencies] @@ -179,7 +179,7 @@ files = [ name = "anoncreds" version = "0.2.0" description = "" -optional = true +optional = false python-versions = ">=3.6.3" files = [ {file = "anoncreds-0.2.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:ec57e224d5f1b8749c3d6ff75bb61229a4f9c31df1ee863835f025c78ec10cd0"}, @@ -213,7 +213,7 @@ yaml = ["PyYAML (>=3.10)"] name = "aries-askar-ff137" version = "0.3.3b0" description = "UNKNOWN" -optional = true +optional = false python-versions = ">=3.6.3" files = [ {file = "aries_askar_ff137-0.3.3b0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:32d6ed2366527b733a6025c19fb6f52f4547a3b2693cc11a1175b0ca3bfc8792"}, @@ -292,7 +292,7 @@ tests = ["PyHamcrest (>=2.0.2)", "mypy", "pytest (>=4.6)", "pytest-benchmark", " name = "cached-property" version = "1.5.2" description = "A decorator for caching properties in classes." -optional = true +optional = false python-versions = "*" files = [ {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, @@ -564,73 +564,73 @@ yaml = ["PyYAML"] [[package]] name = "coverage" -version = "7.6.4" +version = "7.6.8" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" files = [ - {file = "coverage-7.6.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f8ae553cba74085db385d489c7a792ad66f7f9ba2ee85bfa508aeb84cf0ba07"}, - {file = "coverage-7.6.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8165b796df0bd42e10527a3f493c592ba494f16ef3c8b531288e3d0d72c1f6f0"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7c8b95bf47db6d19096a5e052ffca0a05f335bc63cef281a6e8fe864d450a72"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ed9281d1b52628e81393f5eaee24a45cbd64965f41857559c2b7ff19385df51"}, - {file = "coverage-7.6.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0809082ee480bb8f7416507538243c8863ac74fd8a5d2485c46f0f7499f2b491"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d541423cdd416b78626b55f123412fcf979d22a2c39fce251b350de38c15c15b"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:58809e238a8a12a625c70450b48e8767cff9eb67c62e6154a642b21ddf79baea"}, - {file = "coverage-7.6.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c9b8e184898ed014884ca84c70562b4a82cbc63b044d366fedc68bc2b2f3394a"}, - {file = "coverage-7.6.4-cp310-cp310-win32.whl", hash = "sha256:6bd818b7ea14bc6e1f06e241e8234508b21edf1b242d49831831a9450e2f35fa"}, - {file = "coverage-7.6.4-cp310-cp310-win_amd64.whl", hash = "sha256:06babbb8f4e74b063dbaeb74ad68dfce9186c595a15f11f5d5683f748fa1d172"}, - {file = "coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b"}, - {file = "coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b"}, - {file = "coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db"}, - {file = "coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522"}, - {file = "coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf"}, - {file = "coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2"}, - {file = "coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27"}, - {file = "coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1"}, - {file = "coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5"}, - {file = "coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17"}, - {file = "coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9"}, - {file = "coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06"}, - {file = "coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21"}, - {file = "coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a"}, - {file = "coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e"}, - {file = "coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f"}, - {file = "coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3"}, - {file = "coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70"}, - {file = "coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef"}, - {file = "coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e"}, - {file = "coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1"}, - {file = "coverage-7.6.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9cb7fa111d21a6b55cbf633039f7bc2749e74932e3aa7cb7333f675a58a58bf3"}, - {file = "coverage-7.6.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11a223a14e91a4693d2d0755c7a043db43d96a7450b4f356d506c2562c48642c"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a413a096c4cbac202433c850ee43fa326d2e871b24554da8327b01632673a076"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00a1d69c112ff5149cabe60d2e2ee948752c975d95f1e1096742e6077affd376"}, - {file = "coverage-7.6.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f76846299ba5c54d12c91d776d9605ae33f8ae2b9d1d3c3703cf2db1a67f2c0"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe439416eb6380de434886b00c859304338f8b19f6f54811984f3420a2e03858"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0294ca37f1ba500667b1aef631e48d875ced93ad5e06fa665a3295bdd1d95111"}, - {file = "coverage-7.6.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6f01ba56b1c0e9d149f9ac85a2f999724895229eb36bd997b61e62999e9b0901"}, - {file = "coverage-7.6.4-cp39-cp39-win32.whl", hash = "sha256:bc66f0bf1d7730a17430a50163bb264ba9ded56739112368ba985ddaa9c3bd09"}, - {file = "coverage-7.6.4-cp39-cp39-win_amd64.whl", hash = "sha256:c481b47f6b5845064c65a7bc78bc0860e635a9b055af0df46fdf1c58cebf8e8f"}, - {file = "coverage-7.6.4-pp39.pp310-none-any.whl", hash = "sha256:3c65d37f3a9ebb703e710befdc489a38683a5b152242664b973a7b7b22348a4e"}, - {file = "coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73"}, + {file = "coverage-7.6.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b39e6011cd06822eb964d038d5dff5da5d98652b81f5ecd439277b32361a3a50"}, + {file = "coverage-7.6.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:63c19702db10ad79151a059d2d6336fe0c470f2e18d0d4d1a57f7f9713875dcf"}, + {file = "coverage-7.6.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3985b9be361d8fb6b2d1adc9924d01dec575a1d7453a14cccd73225cb79243ee"}, + {file = "coverage-7.6.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:644ec81edec0f4ad17d51c838a7d01e42811054543b76d4ba2c5d6af741ce2a6"}, + {file = "coverage-7.6.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f188a2402f8359cf0c4b1fe89eea40dc13b52e7b4fd4812450da9fcd210181d"}, + {file = "coverage-7.6.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e19122296822deafce89a0c5e8685704c067ae65d45e79718c92df7b3ec3d331"}, + {file = "coverage-7.6.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:13618bed0c38acc418896005732e565b317aa9e98d855a0e9f211a7ffc2d6638"}, + {file = "coverage-7.6.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:193e3bffca48ad74b8c764fb4492dd875038a2f9925530cb094db92bb5e47bed"}, + {file = "coverage-7.6.8-cp310-cp310-win32.whl", hash = "sha256:3988665ee376abce49613701336544041f2117de7b7fbfe91b93d8ff8b151c8e"}, + {file = "coverage-7.6.8-cp310-cp310-win_amd64.whl", hash = "sha256:f56f49b2553d7dd85fd86e029515a221e5c1f8cb3d9c38b470bc38bde7b8445a"}, + {file = "coverage-7.6.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:86cffe9c6dfcfe22e28027069725c7f57f4b868a3f86e81d1c62462764dc46d4"}, + {file = "coverage-7.6.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d82ab6816c3277dc962cfcdc85b1efa0e5f50fb2c449432deaf2398a2928ab94"}, + {file = "coverage-7.6.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13690e923a3932e4fad4c0ebfb9cb5988e03d9dcb4c5150b5fcbf58fd8bddfc4"}, + {file = "coverage-7.6.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4be32da0c3827ac9132bb488d331cb32e8d9638dd41a0557c5569d57cf22c9c1"}, + {file = "coverage-7.6.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:44e6c85bbdc809383b509d732b06419fb4544dca29ebe18480379633623baafb"}, + {file = "coverage-7.6.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:768939f7c4353c0fac2f7c37897e10b1414b571fd85dd9fc49e6a87e37a2e0d8"}, + {file = "coverage-7.6.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e44961e36cb13c495806d4cac67640ac2866cb99044e210895b506c26ee63d3a"}, + {file = "coverage-7.6.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3ea8bb1ab9558374c0ab591783808511d135a833c3ca64a18ec927f20c4030f0"}, + {file = "coverage-7.6.8-cp311-cp311-win32.whl", hash = "sha256:629a1ba2115dce8bf75a5cce9f2486ae483cb89c0145795603d6554bdc83e801"}, + {file = "coverage-7.6.8-cp311-cp311-win_amd64.whl", hash = "sha256:fb9fc32399dca861584d96eccd6c980b69bbcd7c228d06fb74fe53e007aa8ef9"}, + {file = "coverage-7.6.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e683e6ecc587643f8cde8f5da6768e9d165cd31edf39ee90ed7034f9ca0eefee"}, + {file = "coverage-7.6.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1defe91d41ce1bd44b40fabf071e6a01a5aa14de4a31b986aa9dfd1b3e3e414a"}, + {file = "coverage-7.6.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7ad66e8e50225ebf4236368cc43c37f59d5e6728f15f6e258c8639fa0dd8e6d"}, + {file = "coverage-7.6.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3fe47da3e4fda5f1abb5709c156eca207eacf8007304ce3019eb001e7a7204cb"}, + {file = "coverage-7.6.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:202a2d645c5a46b84992f55b0a3affe4f0ba6b4c611abec32ee88358db4bb649"}, + {file = "coverage-7.6.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4674f0daa1823c295845b6a740d98a840d7a1c11df00d1fd62614545c1583787"}, + {file = "coverage-7.6.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:74610105ebd6f33d7c10f8907afed696e79c59e3043c5f20eaa3a46fddf33b4c"}, + {file = "coverage-7.6.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:37cda8712145917105e07aab96388ae76e787270ec04bcb9d5cc786d7cbb8443"}, + {file = "coverage-7.6.8-cp312-cp312-win32.whl", hash = "sha256:9e89d5c8509fbd6c03d0dd1972925b22f50db0792ce06324ba069f10787429ad"}, + {file = "coverage-7.6.8-cp312-cp312-win_amd64.whl", hash = "sha256:379c111d3558272a2cae3d8e57e6b6e6f4fe652905692d54bad5ea0ca37c5ad4"}, + {file = "coverage-7.6.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0b0c69f4f724c64dfbfe79f5dfb503b42fe6127b8d479b2677f2b227478db2eb"}, + {file = "coverage-7.6.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c15b32a7aca8038ed7644f854bf17b663bc38e1671b5d6f43f9a2b2bd0c46f63"}, + {file = "coverage-7.6.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63068a11171e4276f6ece913bde059e77c713b48c3a848814a6537f35afb8365"}, + {file = "coverage-7.6.8-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f4548c5ead23ad13fb7a2c8ea541357474ec13c2b736feb02e19a3085fac002"}, + {file = "coverage-7.6.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b4b4299dd0d2c67caaaf286d58aef5e75b125b95615dda4542561a5a566a1e3"}, + {file = "coverage-7.6.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c9ebfb2507751f7196995142f057d1324afdab56db1d9743aab7f50289abd022"}, + {file = "coverage-7.6.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c1b4474beee02ede1eef86c25ad4600a424fe36cff01a6103cb4533c6bf0169e"}, + {file = "coverage-7.6.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d9fd2547e6decdbf985d579cf3fc78e4c1d662b9b0ff7cc7862baaab71c9cc5b"}, + {file = "coverage-7.6.8-cp313-cp313-win32.whl", hash = "sha256:8aae5aea53cbfe024919715eca696b1a3201886ce83790537d1c3668459c7146"}, + {file = "coverage-7.6.8-cp313-cp313-win_amd64.whl", hash = "sha256:ae270e79f7e169ccfe23284ff5ea2d52a6f401dc01b337efb54b3783e2ce3f28"}, + {file = "coverage-7.6.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:de38add67a0af869b0d79c525d3e4588ac1ffa92f39116dbe0ed9753f26eba7d"}, + {file = "coverage-7.6.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b07c25d52b1c16ce5de088046cd2432b30f9ad5e224ff17c8f496d9cb7d1d451"}, + {file = "coverage-7.6.8-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62a66ff235e4c2e37ed3b6104d8b478d767ff73838d1222132a7a026aa548764"}, + {file = "coverage-7.6.8-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09b9f848b28081e7b975a3626e9081574a7b9196cde26604540582da60235fdf"}, + {file = "coverage-7.6.8-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:093896e530c38c8e9c996901858ac63f3d4171268db2c9c8b373a228f459bbc5"}, + {file = "coverage-7.6.8-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a7b8ac36fd688c8361cbc7bf1cb5866977ece6e0b17c34aa0df58bda4fa18a4"}, + {file = "coverage-7.6.8-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:38c51297b35b3ed91670e1e4efb702b790002e3245a28c76e627478aa3c10d83"}, + {file = "coverage-7.6.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2e4e0f60cb4bd7396108823548e82fdab72d4d8a65e58e2c19bbbc2f1e2bfa4b"}, + {file = "coverage-7.6.8-cp313-cp313t-win32.whl", hash = "sha256:6535d996f6537ecb298b4e287a855f37deaf64ff007162ec0afb9ab8ba3b8b71"}, + {file = "coverage-7.6.8-cp313-cp313t-win_amd64.whl", hash = "sha256:c79c0685f142ca53256722a384540832420dff4ab15fec1863d7e5bc8691bdcc"}, + {file = "coverage-7.6.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3ac47fa29d8d41059ea3df65bd3ade92f97ee4910ed638e87075b8e8ce69599e"}, + {file = "coverage-7.6.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:24eda3a24a38157eee639ca9afe45eefa8d2420d49468819ac5f88b10de84f4c"}, + {file = "coverage-7.6.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4c81ed2820b9023a9a90717020315e63b17b18c274a332e3b6437d7ff70abe0"}, + {file = "coverage-7.6.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd55f8fc8fa494958772a2a7302b0354ab16e0b9272b3c3d83cdb5bec5bd1779"}, + {file = "coverage-7.6.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f39e2f3530ed1626c66e7493be7a8423b023ca852aacdc91fb30162c350d2a92"}, + {file = "coverage-7.6.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:716a78a342679cd1177bc8c2fe957e0ab91405bd43a17094324845200b2fddf4"}, + {file = "coverage-7.6.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:177f01eeaa3aee4a5ffb0d1439c5952b53d5010f86e9d2667963e632e30082cc"}, + {file = "coverage-7.6.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:912e95017ff51dc3d7b6e2be158dedc889d9a5cc3382445589ce554f1a34c0ea"}, + {file = "coverage-7.6.8-cp39-cp39-win32.whl", hash = "sha256:4db3ed6a907b555e57cc2e6f14dc3a4c2458cdad8919e40b5357ab9b6db6c43e"}, + {file = "coverage-7.6.8-cp39-cp39-win_amd64.whl", hash = "sha256:428ac484592f780e8cd7b6b14eb568f7c85460c92e2a37cb0c0e5186e1a0d076"}, + {file = "coverage-7.6.8-pp39.pp310-none-any.whl", hash = "sha256:5c52a036535d12590c32c49209e79cabaad9f9ad8aa4cbd875b68c4d67a9cbce"}, + {file = "coverage-7.6.8.tar.gz", hash = "sha256:8b2b8503edb06822c86d82fa64a4a5cb0760bb8f31f26e138ec743f422f37cfc"}, ] [package.extras] @@ -638,51 +638,53 @@ toml = ["tomli"] [[package]] name = "cryptography" -version = "43.0.3" +version = "44.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false -python-versions = ">=3.7" -files = [ - {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18"}, - {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd"}, - {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73"}, - {file = "cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2"}, - {file = "cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd"}, - {file = "cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405"}, - {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16"}, - {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73"}, - {file = "cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995"}, - {file = "cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff"}, - {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, +python-versions = "!=3.9.0,!=3.9.1,>=3.7" +files = [ + {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, + {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, + {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, + {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, + {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, + {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, + {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, ] [package.dependencies] cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] -nox = ["nox"] -pep8test = ["check-sdist", "click", "mypy", "ruff"] -sdist = ["build"] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "cryptography-vectors (==43.0.3)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] test-randomorder = ["pytest-randomly"] [[package]] @@ -788,37 +790,37 @@ cython = ["cython"] [[package]] name = "debugpy" -version = "1.8.8" +version = "1.8.9" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" files = [ - {file = "debugpy-1.8.8-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:e59b1607c51b71545cb3496876544f7186a7a27c00b436a62f285603cc68d1c6"}, - {file = "debugpy-1.8.8-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6531d952b565b7cb2fbd1ef5df3d333cf160b44f37547a4e7cf73666aca5d8d"}, - {file = "debugpy-1.8.8-cp310-cp310-win32.whl", hash = "sha256:b01f4a5e5c5fb1d34f4ccba99a20ed01eabc45a4684f4948b5db17a319dfb23f"}, - {file = "debugpy-1.8.8-cp310-cp310-win_amd64.whl", hash = "sha256:535f4fb1c024ddca5913bb0eb17880c8f24ba28aa2c225059db145ee557035e9"}, - {file = "debugpy-1.8.8-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:c399023146e40ae373753a58d1be0a98bf6397fadc737b97ad612886b53df318"}, - {file = "debugpy-1.8.8-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09cc7b162586ea2171eea055985da2702b0723f6f907a423c9b2da5996ad67ba"}, - {file = "debugpy-1.8.8-cp311-cp311-win32.whl", hash = "sha256:eea8821d998ebeb02f0625dd0d76839ddde8cbf8152ebbe289dd7acf2cdc6b98"}, - {file = "debugpy-1.8.8-cp311-cp311-win_amd64.whl", hash = "sha256:d4483836da2a533f4b1454dffc9f668096ac0433de855f0c22cdce8c9f7e10c4"}, - {file = "debugpy-1.8.8-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:0cc94186340be87b9ac5a707184ec8f36547fb66636d1029ff4f1cc020e53996"}, - {file = "debugpy-1.8.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64674e95916e53c2e9540a056e5f489e0ad4872645399d778f7c598eacb7b7f9"}, - {file = "debugpy-1.8.8-cp312-cp312-win32.whl", hash = "sha256:5c6e885dbf12015aed73770f29dec7023cb310d0dc2ba8bfbeb5c8e43f80edc9"}, - {file = "debugpy-1.8.8-cp312-cp312-win_amd64.whl", hash = "sha256:19ffbd84e757a6ca0113574d1bf5a2298b3947320a3e9d7d8dc3377f02d9f864"}, - {file = "debugpy-1.8.8-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:705cd123a773d184860ed8dae99becd879dfec361098edbefb5fc0d3683eb804"}, - {file = "debugpy-1.8.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:890fd16803f50aa9cb1a9b9b25b5ec321656dd6b78157c74283de241993d086f"}, - {file = "debugpy-1.8.8-cp313-cp313-win32.whl", hash = "sha256:90244598214bbe704aa47556ec591d2f9869ff9e042e301a2859c57106649add"}, - {file = "debugpy-1.8.8-cp313-cp313-win_amd64.whl", hash = "sha256:4b93e4832fd4a759a0c465c967214ed0c8a6e8914bced63a28ddb0dd8c5f078b"}, - {file = "debugpy-1.8.8-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:143ef07940aeb8e7316de48f5ed9447644da5203726fca378f3a6952a50a9eae"}, - {file = "debugpy-1.8.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f95651bdcbfd3b27a408869a53fbefcc2bcae13b694daee5f1365b1b83a00113"}, - {file = "debugpy-1.8.8-cp38-cp38-win32.whl", hash = "sha256:26b461123a030e82602a750fb24d7801776aa81cd78404e54ab60e8b5fecdad5"}, - {file = "debugpy-1.8.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3cbf1833e644a3100eadb6120f25be8a532035e8245584c4f7532937edc652a"}, - {file = "debugpy-1.8.8-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:53709d4ec586b525724819dc6af1a7703502f7e06f34ded7157f7b1f963bb854"}, - {file = "debugpy-1.8.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a9c013077a3a0000e83d97cf9cc9328d2b0bbb31f56b0e99ea3662d29d7a6a2"}, - {file = "debugpy-1.8.8-cp39-cp39-win32.whl", hash = "sha256:ffe94dd5e9a6739a75f0b85316dc185560db3e97afa6b215628d1b6a17561cb2"}, - {file = "debugpy-1.8.8-cp39-cp39-win_amd64.whl", hash = "sha256:5c0e5a38c7f9b481bf31277d2f74d2109292179081f11108e668195ef926c0f9"}, - {file = "debugpy-1.8.8-py2.py3-none-any.whl", hash = "sha256:ec684553aba5b4066d4de510859922419febc710df7bba04fe9e7ef3de15d34f"}, - {file = "debugpy-1.8.8.zip", hash = "sha256:e6355385db85cbd666be703a96ab7351bc9e6c61d694893206f8001e22aee091"}, + {file = "debugpy-1.8.9-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:cfe1e6c6ad7178265f74981edf1154ffce97b69005212fbc90ca22ddfe3d017e"}, + {file = "debugpy-1.8.9-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ada7fb65102a4d2c9ab62e8908e9e9f12aed9d76ef44880367bc9308ebe49a0f"}, + {file = "debugpy-1.8.9-cp310-cp310-win32.whl", hash = "sha256:c36856343cbaa448171cba62a721531e10e7ffb0abff838004701454149bc037"}, + {file = "debugpy-1.8.9-cp310-cp310-win_amd64.whl", hash = "sha256:17c5e0297678442511cf00a745c9709e928ea4ca263d764e90d233208889a19e"}, + {file = "debugpy-1.8.9-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:b74a49753e21e33e7cf030883a92fa607bddc4ede1aa4145172debc637780040"}, + {file = "debugpy-1.8.9-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:62d22dacdb0e296966d7d74a7141aaab4bec123fa43d1a35ddcb39bf9fd29d70"}, + {file = "debugpy-1.8.9-cp311-cp311-win32.whl", hash = "sha256:8138efff315cd09b8dcd14226a21afda4ca582284bf4215126d87342bba1cc66"}, + {file = "debugpy-1.8.9-cp311-cp311-win_amd64.whl", hash = "sha256:ff54ef77ad9f5c425398efb150239f6fe8e20c53ae2f68367eba7ece1e96226d"}, + {file = "debugpy-1.8.9-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:957363d9a7a6612a37458d9a15e72d03a635047f946e5fceee74b50d52a9c8e2"}, + {file = "debugpy-1.8.9-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e565fc54b680292b418bb809f1386f17081d1346dca9a871bf69a8ac4071afe"}, + {file = "debugpy-1.8.9-cp312-cp312-win32.whl", hash = "sha256:3e59842d6c4569c65ceb3751075ff8d7e6a6ada209ceca6308c9bde932bcef11"}, + {file = "debugpy-1.8.9-cp312-cp312-win_amd64.whl", hash = "sha256:66eeae42f3137eb428ea3a86d4a55f28da9bd5a4a3d369ba95ecc3a92c1bba53"}, + {file = "debugpy-1.8.9-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:957ecffff80d47cafa9b6545de9e016ae8c9547c98a538ee96ab5947115fb3dd"}, + {file = "debugpy-1.8.9-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1efbb3ff61487e2c16b3e033bc8595aea578222c08aaf3c4bf0f93fadbd662ee"}, + {file = "debugpy-1.8.9-cp313-cp313-win32.whl", hash = "sha256:7c4d65d03bee875bcb211c76c1d8f10f600c305dbd734beaed4077e902606fee"}, + {file = "debugpy-1.8.9-cp313-cp313-win_amd64.whl", hash = "sha256:e46b420dc1bea64e5bbedd678148be512442bc589b0111bd799367cde051e71a"}, + {file = "debugpy-1.8.9-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:472a3994999fe6c0756945ffa359e9e7e2d690fb55d251639d07208dbc37caea"}, + {file = "debugpy-1.8.9-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:365e556a4772d7d0d151d7eb0e77ec4db03bcd95f26b67b15742b88cacff88e9"}, + {file = "debugpy-1.8.9-cp38-cp38-win32.whl", hash = "sha256:54a7e6d3014c408eb37b0b06021366ee985f1539e12fe49ca2ee0d392d9ceca5"}, + {file = "debugpy-1.8.9-cp38-cp38-win_amd64.whl", hash = "sha256:8e99c0b1cc7bf86d83fb95d5ccdc4ad0586d4432d489d1f54e4055bcc795f693"}, + {file = "debugpy-1.8.9-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:7e8b079323a56f719977fde9d8115590cb5e7a1cba2fcee0986ef8817116e7c1"}, + {file = "debugpy-1.8.9-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6953b335b804a41f16a192fa2e7851bdcfd92173cbb2f9f777bb934f49baab65"}, + {file = "debugpy-1.8.9-cp39-cp39-win32.whl", hash = "sha256:7e646e62d4602bb8956db88b1e72fe63172148c1e25c041e03b103a25f36673c"}, + {file = "debugpy-1.8.9-cp39-cp39-win_amd64.whl", hash = "sha256:3d9755e77a2d680ce3d2c5394a444cf42be4a592caaf246dbfbdd100ffcf7ae5"}, + {file = "debugpy-1.8.9-py2.py3-none-any.whl", hash = "sha256:cc37a6c9987ad743d9c3a14fa1b1a14b7e4e6041f9dd0c8abf8895fe7a97b899"}, + {file = "debugpy-1.8.9.zip", hash = "sha256:1339e14c7d980407248f09824d1b25ff5c5616651689f1e0f0e51bdead3ea13e"}, ] [[package]] @@ -1161,13 +1163,13 @@ files = [ [[package]] name = "identify" -version = "2.6.2" +version = "2.6.3" description = "File identification library for Python" optional = false python-versions = ">=3.9" files = [ - {file = "identify-2.6.2-py2.py3-none-any.whl", hash = "sha256:c097384259f49e372f4ea00a19719d95ae27dd5ff0fd77ad630aa891306b82f3"}, - {file = "identify-2.6.2.tar.gz", hash = "sha256:fab5c716c24d7a789775228823797296a2994b075fb6080ac83a102772a98cbd"}, + {file = "identify-2.6.3-py2.py3-none-any.whl", hash = "sha256:9edba65473324c2ea9684b1f944fe3191db3345e50b6d04571d10ed164f8d7bd"}, + {file = "identify-2.6.3.tar.gz", hash = "sha256:62f5dae9b5fef52c84cc188514e9ea4f3f636b1d8799ab5ebc475471f9e47a02"}, ] [package.extras] @@ -1202,7 +1204,7 @@ files = [ name = "indy-credx" version = "1.1.1" description = "" -optional = true +optional = false python-versions = ">=3.6.3" files = [ {file = "indy_credx-1.1.1-py3-none-macosx_10_9_universal2.whl", hash = "sha256:522b90a2362de681e8224b7e5173a9a6093dc48b2ed13599c9eca3df36e29128"}, @@ -1215,7 +1217,7 @@ files = [ name = "indy-vdr" version = "0.4.2" description = "" -optional = true +optional = false python-versions = ">=3.6.3" files = [ {file = "indy_vdr-0.4.2-py3-none-macosx_10_9_universal2.whl", hash = "sha256:21e4cc22bdb1de581e4abe00e2201d970f46e05d2420437fe023052614867553"}, @@ -1871,109 +1873,93 @@ wcwidth = "*" [[package]] name = "propcache" -version = "0.2.0" +version = "0.2.1" description = "Accelerated property cache" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, - {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, - {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, - {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, - {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, - {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, - {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, - {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, - {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, - {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, - {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, - {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, - {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, - {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, - {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, - {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, - {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, - {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, - {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, - {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, - {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, - {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, - {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, - {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, - {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, - {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, - {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, - {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, - {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, - {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, - {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, - {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, - {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, + {file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"}, + {file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"}, + {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"}, + {file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"}, + {file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"}, + {file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"}, + {file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"}, + {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"}, + {file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"}, + {file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"}, + {file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"}, + {file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"}, + {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"}, + {file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"}, + {file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"}, + {file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"}, + {file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"}, + {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"}, + {file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"}, + {file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"}, + {file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"}, + {file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"}, + {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"}, + {file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"}, + {file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"}, + {file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"}, + {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, ] [[package]] @@ -1989,22 +1975,19 @@ files = [ [[package]] name = "pydantic" -version = "2.9.2" +version = "2.10.3" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.9.2-py3-none-any.whl", hash = "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12"}, - {file = "pydantic-2.9.2.tar.gz", hash = "sha256:d155cef71265d1e9807ed1c32b4c8deec042a44a50a4188b25ac67ecd81a9c0f"}, + {file = "pydantic-2.10.3-py3-none-any.whl", hash = "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d"}, + {file = "pydantic-2.10.3.tar.gz", hash = "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.23.4" -typing-extensions = [ - {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, - {version = ">=4.6.1", markers = "python_version < \"3.13\""}, -] +pydantic-core = "2.27.1" +typing-extensions = ">=4.12.2" [package.extras] email = ["email-validator (>=2.0.0)"] @@ -2012,100 +1995,111 @@ timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.23.4" +version = "2.27.1" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.23.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:b10bd51f823d891193d4717448fab065733958bdb6a6b351967bd349d48d5c9b"}, - {file = "pydantic_core-2.23.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4fc714bdbfb534f94034efaa6eadd74e5b93c8fa6315565a222f7b6f42ca1166"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63e46b3169866bd62849936de036f901a9356e36376079b05efa83caeaa02ceb"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed1a53de42fbe34853ba90513cea21673481cd81ed1be739f7f2efb931b24916"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cfdd16ab5e59fc31b5e906d1a3f666571abc367598e3e02c83403acabc092e07"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:255a8ef062cbf6674450e668482456abac99a5583bbafb73f9ad469540a3a232"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a7cd62e831afe623fbb7aabbb4fe583212115b3ef38a9f6b71869ba644624a2"}, - {file = "pydantic_core-2.23.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f09e2ff1f17c2b51f2bc76d1cc33da96298f0a036a137f5440ab3ec5360b624f"}, - {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e38e63e6f3d1cec5a27e0afe90a085af8b6806ee208b33030e65b6516353f1a3"}, - {file = "pydantic_core-2.23.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0dbd8dbed2085ed23b5c04afa29d8fd2771674223135dc9bc937f3c09284d071"}, - {file = "pydantic_core-2.23.4-cp310-none-win32.whl", hash = "sha256:6531b7ca5f951d663c339002e91aaebda765ec7d61b7d1e3991051906ddde119"}, - {file = "pydantic_core-2.23.4-cp310-none-win_amd64.whl", hash = "sha256:7c9129eb40958b3d4500fa2467e6a83356b3b61bfff1b414c7361d9220f9ae8f"}, - {file = "pydantic_core-2.23.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:77733e3892bb0a7fa797826361ce8a9184d25c8dffaec60b7ffe928153680ba8"}, - {file = "pydantic_core-2.23.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1b84d168f6c48fabd1f2027a3d1bdfe62f92cade1fb273a5d68e621da0e44e6d"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df49e7a0861a8c36d089c1ed57d308623d60416dab2647a4a17fe050ba85de0e"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ff02b6d461a6de369f07ec15e465a88895f3223eb75073ffea56b84d9331f607"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:996a38a83508c54c78a5f41456b0103c30508fed9abcad0a59b876d7398f25fd"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d97683ddee4723ae8c95d1eddac7c192e8c552da0c73a925a89fa8649bf13eea"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:216f9b2d7713eb98cb83c80b9c794de1f6b7e3145eef40400c62e86cee5f4e1e"}, - {file = "pydantic_core-2.23.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6f783e0ec4803c787bcea93e13e9932edab72068f68ecffdf86a99fd5918878b"}, - {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d0776dea117cf5272382634bd2a5c1b6eb16767c223c6a5317cd3e2a757c61a0"}, - {file = "pydantic_core-2.23.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d5f7a395a8cf1621939692dba2a6b6a830efa6b3cee787d82c7de1ad2930de64"}, - {file = "pydantic_core-2.23.4-cp311-none-win32.whl", hash = "sha256:74b9127ffea03643e998e0c5ad9bd3811d3dac8c676e47db17b0ee7c3c3bf35f"}, - {file = "pydantic_core-2.23.4-cp311-none-win_amd64.whl", hash = "sha256:98d134c954828488b153d88ba1f34e14259284f256180ce659e8d83e9c05eaa3"}, - {file = "pydantic_core-2.23.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f3e0da4ebaef65158d4dfd7d3678aad692f7666877df0002b8a522cdf088f231"}, - {file = "pydantic_core-2.23.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f69a8e0b033b747bb3e36a44e7732f0c99f7edd5cea723d45bc0d6e95377ffee"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:723314c1d51722ab28bfcd5240d858512ffd3116449c557a1336cbe3919beb87"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb2802e667b7051a1bebbfe93684841cc9351004e2badbd6411bf357ab8d5ac8"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d18ca8148bebe1b0a382a27a8ee60350091a6ddaf475fa05ef50dc35b5df6327"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33e3d65a85a2a4a0dc3b092b938a4062b1a05f3a9abde65ea93b233bca0e03f2"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:128585782e5bfa515c590ccee4b727fb76925dd04a98864182b22e89a4e6ed36"}, - {file = "pydantic_core-2.23.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:68665f4c17edcceecc112dfed5dbe6f92261fb9d6054b47d01bf6371a6196126"}, - {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:20152074317d9bed6b7a95ade3b7d6054845d70584216160860425f4fbd5ee9e"}, - {file = "pydantic_core-2.23.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9261d3ce84fa1d38ed649c3638feefeae23d32ba9182963e465d58d62203bd24"}, - {file = "pydantic_core-2.23.4-cp312-none-win32.whl", hash = "sha256:4ba762ed58e8d68657fc1281e9bb72e1c3e79cc5d464be146e260c541ec12d84"}, - {file = "pydantic_core-2.23.4-cp312-none-win_amd64.whl", hash = "sha256:97df63000f4fea395b2824da80e169731088656d1818a11b95f3b173747b6cd9"}, - {file = "pydantic_core-2.23.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7530e201d10d7d14abce4fb54cfe5b94a0aefc87da539d0346a484ead376c3cc"}, - {file = "pydantic_core-2.23.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:df933278128ea1cd77772673c73954e53a1c95a4fdf41eef97c2b779271bd0bd"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cb3da3fd1b6a5d0279a01877713dbda118a2a4fc6f0d821a57da2e464793f05"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c6dcb030aefb668a2b7009c85b27f90e51e6a3b4d5c9bc4c57631292015b0d"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:696dd8d674d6ce621ab9d45b205df149399e4bb9aa34102c970b721554828510"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2971bb5ffe72cc0f555c13e19b23c85b654dd2a8f7ab493c262071377bfce9f6"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8394d940e5d400d04cad4f75c0598665cbb81aecefaca82ca85bd28264af7f9b"}, - {file = "pydantic_core-2.23.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0dff76e0602ca7d4cdaacc1ac4c005e0ce0dcfe095d5b5259163a80d3a10d327"}, - {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7d32706badfe136888bdea71c0def994644e09fff0bfe47441deaed8e96fdbc6"}, - {file = "pydantic_core-2.23.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ed541d70698978a20eb63d8c5d72f2cc6d7079d9d90f6b50bad07826f1320f5f"}, - {file = "pydantic_core-2.23.4-cp313-none-win32.whl", hash = "sha256:3d5639516376dce1940ea36edf408c554475369f5da2abd45d44621cb616f769"}, - {file = "pydantic_core-2.23.4-cp313-none-win_amd64.whl", hash = "sha256:5a1504ad17ba4210df3a045132a7baeeba5a200e930f57512ee02909fc5c4cb5"}, - {file = "pydantic_core-2.23.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d4488a93b071c04dc20f5cecc3631fc78b9789dd72483ba15d423b5b3689b555"}, - {file = "pydantic_core-2.23.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:81965a16b675b35e1d09dd14df53f190f9129c0202356ed44ab2728b1c905658"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffa2ebd4c8530079140dd2d7f794a9d9a73cbb8e9d59ffe24c63436efa8f271"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:61817945f2fe7d166e75fbfb28004034b48e44878177fc54d81688e7b85a3665"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:29d2c342c4bc01b88402d60189f3df065fb0dda3654744d5a165a5288a657368"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5e11661ce0fd30a6790e8bcdf263b9ec5988e95e63cf901972107efc49218b13"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d18368b137c6295db49ce7218b1a9ba15c5bc254c96d7c9f9e924a9bc7825ad"}, - {file = "pydantic_core-2.23.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ec4e55f79b1c4ffb2eecd8a0cfba9955a2588497d96851f4c8f99aa4a1d39b12"}, - {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:374a5e5049eda9e0a44c696c7ade3ff355f06b1fe0bb945ea3cac2bc336478a2"}, - {file = "pydantic_core-2.23.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5c364564d17da23db1106787675fc7af45f2f7b58b4173bfdd105564e132e6fb"}, - {file = "pydantic_core-2.23.4-cp38-none-win32.whl", hash = "sha256:d7a80d21d613eec45e3d41eb22f8f94ddc758a6c4720842dc74c0581f54993d6"}, - {file = "pydantic_core-2.23.4-cp38-none-win_amd64.whl", hash = "sha256:5f5ff8d839f4566a474a969508fe1c5e59c31c80d9e140566f9a37bba7b8d556"}, - {file = "pydantic_core-2.23.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a4fa4fc04dff799089689f4fd502ce7d59de529fc2f40a2c8836886c03e0175a"}, - {file = "pydantic_core-2.23.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a7df63886be5e270da67e0966cf4afbae86069501d35c8c1b3b6c168f42cb36"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dcedcd19a557e182628afa1d553c3895a9f825b936415d0dbd3cd0bbcfd29b4b"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f54b118ce5de9ac21c363d9b3caa6c800341e8c47a508787e5868c6b79c9323"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86d2f57d3e1379a9525c5ab067b27dbb8a0642fb5d454e17a9ac434f9ce523e3"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de6d1d1b9e5101508cb37ab0d972357cac5235f5c6533d1071964c47139257df"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1278e0d324f6908e872730c9102b0112477a7f7cf88b308e4fc36ce1bdb6d58c"}, - {file = "pydantic_core-2.23.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a6b5099eeec78827553827f4c6b8615978bb4b6a88e5d9b93eddf8bb6790f55"}, - {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e55541f756f9b3ee346b840103f32779c695a19826a4c442b7954550a0972040"}, - {file = "pydantic_core-2.23.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a5c7ba8ffb6d6f8f2ab08743be203654bb1aaa8c9dcb09f82ddd34eadb695605"}, - {file = "pydantic_core-2.23.4-cp39-none-win32.whl", hash = "sha256:37b0fe330e4a58d3c58b24d91d1eb102aeec675a3db4c292ec3928ecd892a9a6"}, - {file = "pydantic_core-2.23.4-cp39-none-win_amd64.whl", hash = "sha256:1498bec4c05c9c787bde9125cfdcc63a41004ff167f495063191b863399b1a29"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:f455ee30a9d61d3e1a15abd5068827773d6e4dc513e795f380cdd59932c782d5"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1e90d2e3bd2c3863d48525d297cd143fe541be8bbf6f579504b9712cb6b643ec"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e203fdf807ac7e12ab59ca2bfcabb38c7cf0b33c41efeb00f8e5da1d86af480"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e08277a400de01bc72436a0ccd02bdf596631411f592ad985dcee21445bd0068"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f220b0eea5965dec25480b6333c788fb72ce5f9129e8759ef876a1d805d00801"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d06b0c8da4f16d1d1e352134427cb194a0a6e19ad5db9161bf32b2113409e728"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ba1a0996f6c2773bd83e63f18914c1de3c9dd26d55f4ac302a7efe93fb8e7433"}, - {file = "pydantic_core-2.23.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:9a5bce9d23aac8f0cf0836ecfc033896aa8443b501c58d0602dbfd5bd5b37753"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:78ddaaa81421a29574a682b3179d4cf9e6d405a09b99d93ddcf7e5239c742e21"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:883a91b5dd7d26492ff2f04f40fbb652de40fcc0afe07e8129e8ae779c2110eb"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88ad334a15b32a791ea935af224b9de1bf99bcd62fabf745d5f3442199d86d59"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:233710f069d251feb12a56da21e14cca67994eab08362207785cf8c598e74577"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19442362866a753485ba5e4be408964644dd6a09123d9416c54cd49171f50744"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:624e278a7d29b6445e4e813af92af37820fafb6dcc55c012c834f9e26f9aaaef"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f5ef8f42bec47f21d07668a043f077d507e5bf4e668d5c6dfe6aaba89de1a5b8"}, - {file = "pydantic_core-2.23.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:aea443fffa9fbe3af1a9ba721a87f926fe548d32cab71d188a6ede77d0ff244e"}, - {file = "pydantic_core-2.23.4.tar.gz", hash = "sha256:2584f7cf844ac4d970fba483a717dbe10c1c1c96a969bf65d61ffe94df1b2863"}, + {file = "pydantic_core-2.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a"}, + {file = "pydantic_core-2.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:121ceb0e822f79163dd4699e4c54f5ad38b157084d97b34de8b232bcaad70278"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4603137322c18eaf2e06a4495f426aa8d8388940f3c457e7548145011bb68e05"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a33cd6ad9017bbeaa9ed78a2e0752c5e250eafb9534f308e7a5f7849b0b1bfb4"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15cc53a3179ba0fcefe1e3ae50beb2784dede4003ad2dfd24f81bba4b23a454f"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45d9c5eb9273aa50999ad6adc6be5e0ecea7e09dbd0d31bd0c65a55a2592ca08"}, + {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8bf7b66ce12a2ac52d16f776b31d16d91033150266eb796967a7e4621707e4f6"}, + {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:655d7dd86f26cb15ce8a431036f66ce0318648f8853d709b4167786ec2fa4807"}, + {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:5556470f1a2157031e676f776c2bc20acd34c1990ca5f7e56f1ebf938b9ab57c"}, + {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f69ed81ab24d5a3bd93861c8c4436f54afdf8e8cc421562b0c7504cf3be58206"}, + {file = "pydantic_core-2.27.1-cp310-none-win32.whl", hash = "sha256:f5a823165e6d04ccea61a9f0576f345f8ce40ed533013580e087bd4d7442b52c"}, + {file = "pydantic_core-2.27.1-cp310-none-win_amd64.whl", hash = "sha256:57866a76e0b3823e0b56692d1a0bf722bffb324839bb5b7226a7dbd6c9a40b17"}, + {file = "pydantic_core-2.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac3b20653bdbe160febbea8aa6c079d3df19310d50ac314911ed8cc4eb7f8cb8"}, + {file = "pydantic_core-2.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a5a8e19d7c707c4cadb8c18f5f60c843052ae83c20fa7d44f41594c644a1d330"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f7059ca8d64fea7f238994c97d91f75965216bcbe5f695bb44f354893f11d52"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bed0f8a0eeea9fb72937ba118f9db0cb7e90773462af7962d382445f3005e5a4"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3cb37038123447cf0f3ea4c74751f6a9d7afef0eb71aa07bf5f652b5e6a132c"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84286494f6c5d05243456e04223d5a9417d7f443c3b76065e75001beb26f88de"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acc07b2cfc5b835444b44a9956846b578d27beeacd4b52e45489e93276241025"}, + {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4fefee876e07a6e9aad7a8c8c9f85b0cdbe7df52b8a9552307b09050f7512c7e"}, + {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:258c57abf1188926c774a4c94dd29237e77eda19462e5bb901d88adcab6af919"}, + {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:35c14ac45fcfdf7167ca76cc80b2001205a8d5d16d80524e13508371fb8cdd9c"}, + {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d1b26e1dff225c31897696cab7d4f0a315d4c0d9e8666dbffdb28216f3b17fdc"}, + {file = "pydantic_core-2.27.1-cp311-none-win32.whl", hash = "sha256:2cdf7d86886bc6982354862204ae3b2f7f96f21a3eb0ba5ca0ac42c7b38598b9"}, + {file = "pydantic_core-2.27.1-cp311-none-win_amd64.whl", hash = "sha256:3af385b0cee8df3746c3f406f38bcbfdc9041b5c2d5ce3e5fc6637256e60bbc5"}, + {file = "pydantic_core-2.27.1-cp311-none-win_arm64.whl", hash = "sha256:81f2ec23ddc1b476ff96563f2e8d723830b06dceae348ce02914a37cb4e74b89"}, + {file = "pydantic_core-2.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f"}, + {file = "pydantic_core-2.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35"}, + {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089"}, + {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381"}, + {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb"}, + {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae"}, + {file = "pydantic_core-2.27.1-cp312-none-win32.whl", hash = "sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c"}, + {file = "pydantic_core-2.27.1-cp312-none-win_amd64.whl", hash = "sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16"}, + {file = "pydantic_core-2.27.1-cp312-none-win_arm64.whl", hash = "sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e"}, + {file = "pydantic_core-2.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073"}, + {file = "pydantic_core-2.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51"}, + {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a"}, + {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc"}, + {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960"}, + {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23"}, + {file = "pydantic_core-2.27.1-cp313-none-win32.whl", hash = "sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05"}, + {file = "pydantic_core-2.27.1-cp313-none-win_amd64.whl", hash = "sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337"}, + {file = "pydantic_core-2.27.1-cp313-none-win_arm64.whl", hash = "sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5"}, + {file = "pydantic_core-2.27.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5897bec80a09b4084aee23f9b73a9477a46c3304ad1d2d07acca19723fb1de62"}, + {file = "pydantic_core-2.27.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0165ab2914379bd56908c02294ed8405c252250668ebcb438a55494c69f44ab"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b9af86e1d8e4cfc82c2022bfaa6f459381a50b94a29e95dcdda8442d6d83864"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f6c8a66741c5f5447e047ab0ba7a1c61d1e95580d64bce852e3df1f895c4067"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a42d6a8156ff78981f8aa56eb6394114e0dedb217cf8b729f438f643608cbcd"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64c65f40b4cd8b0e049a8edde07e38b476da7e3aaebe63287c899d2cff253fa5"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdcf339322a3fae5cbd504edcefddd5a50d9ee00d968696846f089b4432cf78"}, + {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf99c8404f008750c846cb4ac4667b798a9f7de673ff719d705d9b2d6de49c5f"}, + {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f1edcea27918d748c7e5e4d917297b2a0ab80cad10f86631e488b7cddf76a36"}, + {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:159cac0a3d096f79ab6a44d77a961917219707e2a130739c64d4dd46281f5c2a"}, + {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:029d9757eb621cc6e1848fa0b0310310de7301057f623985698ed7ebb014391b"}, + {file = "pydantic_core-2.27.1-cp38-none-win32.whl", hash = "sha256:a28af0695a45f7060e6f9b7092558a928a28553366519f64083c63a44f70e618"}, + {file = "pydantic_core-2.27.1-cp38-none-win_amd64.whl", hash = "sha256:2d4567c850905d5eaaed2f7a404e61012a51caf288292e016360aa2b96ff38d4"}, + {file = "pydantic_core-2.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e9386266798d64eeb19dd3677051f5705bf873e98e15897ddb7d76f477131967"}, + {file = "pydantic_core-2.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4228b5b646caa73f119b1ae756216b59cc6e2267201c27d3912b592c5e323b60"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3dfe500de26c52abe0477dde16192ac39c98f05bf2d80e76102d394bd13854"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aee66be87825cdf72ac64cb03ad4c15ffef4143dbf5c113f64a5ff4f81477bf9"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b748c44bb9f53031c8cbc99a8a061bc181c1000c60a30f55393b6e9c45cc5bd"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ca038c7f6a0afd0b2448941b6ef9d5e1949e999f9e5517692eb6da58e9d44be"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e0bd57539da59a3e4671b90a502da9a28c72322a4f17866ba3ac63a82c4498e"}, + {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac6c2c45c847bbf8f91930d88716a0fb924b51e0c6dad329b793d670ec5db792"}, + {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b94d4ba43739bbe8b0ce4262bcc3b7b9f31459ad120fb595627eaeb7f9b9ca01"}, + {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:00e6424f4b26fe82d44577b4c842d7df97c20be6439e8e685d0d715feceb9fb9"}, + {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:38de0a70160dd97540335b7ad3a74571b24f1dc3ed33f815f0880682e6880131"}, + {file = "pydantic_core-2.27.1-cp39-none-win32.whl", hash = "sha256:7ccebf51efc61634f6c2344da73e366c75e735960b5654b63d7e6f69a5885fa3"}, + {file = "pydantic_core-2.27.1-cp39-none-win_amd64.whl", hash = "sha256:a57847b090d7892f123726202b7daa20df6694cbd583b67a592e856bff603d6c"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3fa80ac2bd5856580e242dbc202db873c60a01b20309c8319b5c5986fbe53ce6"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d950caa237bb1954f1b8c9227b5065ba6875ac9771bb8ec790d956a699b78676"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e4216e64d203e39c62df627aa882f02a2438d18a5f21d7f721621f7a5d3611d"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a3d637bd387c41d46b002f0e49c52642281edacd2740e5a42f7017feea3f2c"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:161c27ccce13b6b0c8689418da3885d3220ed2eae2ea5e9b2f7f3d48f1d52c27"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:19910754e4cc9c63bc1c7f6d73aa1cfee82f42007e407c0f413695c2f7ed777f"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e173486019cc283dc9778315fa29a363579372fe67045e971e89b6365cc035ed"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:af52d26579b308921b73b956153066481f064875140ccd1dfd4e77db89dbb12f"}, + {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:981fb88516bd1ae8b0cbbd2034678a39dedc98752f264ac9bc5839d3923fa04c"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5fde892e6c697ce3e30c61b239330fc5d569a71fefd4eb6512fc6caec9dd9e2f"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:816f5aa087094099fff7edabb5e01cc370eb21aa1a1d44fe2d2aefdfb5599b31"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c10c309e18e443ddb108f0ef64e8729363adbfd92d6d57beec680f6261556f3"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98476c98b02c8e9b2eec76ac4156fd006628b1b2d0ef27e548ffa978393fd154"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3027001c28434e7ca5a6e1e527487051136aa81803ac812be51802150d880dd"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7699b1df36a48169cdebda7ab5a2bac265204003f153b4bd17276153d997670a"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1c39b07d90be6b48968ddc8c19e7585052088fd7ec8d568bb31ff64c70ae3c97"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:46ccfe3032b3915586e469d4972973f893c0a2bb65669194a5bdea9bacc088c2"}, + {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:62ba45e21cf6571d7f716d903b5b7b6d2617e2d5d67c0923dc47b9d41369f840"}, + {file = "pydantic_core-2.27.1.tar.gz", hash = "sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235"}, ] [package.dependencies] @@ -2173,13 +2167,13 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyjwt" -version = "2.9.0" +version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "PyJWT-2.9.0-py3-none-any.whl", hash = "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850"}, - {file = "pyjwt-2.9.0.tar.gz", hash = "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c"}, + {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, + {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, ] [package.extras] @@ -2238,13 +2232,13 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] [[package]] name = "pytest" -version = "8.3.3" +version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, + {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, + {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, ] [package.dependencies] @@ -2506,29 +2500,29 @@ test = ["hypothesis (==5.19.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "ruff" -version = "0.7.3" +version = "0.8.1" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.7.3-py3-none-linux_armv6l.whl", hash = "sha256:34f2339dc22687ec7e7002792d1f50712bf84a13d5152e75712ac08be565d344"}, - {file = "ruff-0.7.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fb397332a1879b9764a3455a0bb1087bda876c2db8aca3a3cbb67b3dbce8cda0"}, - {file = "ruff-0.7.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:37d0b619546103274e7f62643d14e1adcbccb242efda4e4bdb9544d7764782e9"}, - {file = "ruff-0.7.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d59f0c3ee4d1a6787614e7135b72e21024875266101142a09a61439cb6e38a5"}, - {file = "ruff-0.7.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:44eb93c2499a169d49fafd07bc62ac89b1bc800b197e50ff4633aed212569299"}, - {file = "ruff-0.7.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6d0242ce53f3a576c35ee32d907475a8d569944c0407f91d207c8af5be5dae4e"}, - {file = "ruff-0.7.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:6b6224af8b5e09772c2ecb8dc9f3f344c1aa48201c7f07e7315367f6dd90ac29"}, - {file = "ruff-0.7.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c50f95a82b94421c964fae4c27c0242890a20fe67d203d127e84fbb8013855f5"}, - {file = "ruff-0.7.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f3eff9961b5d2644bcf1616c606e93baa2d6b349e8aa8b035f654df252c8c67"}, - {file = "ruff-0.7.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8963cab06d130c4df2fd52c84e9f10d297826d2e8169ae0c798b6221be1d1d2"}, - {file = "ruff-0.7.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:61b46049d6edc0e4317fb14b33bd693245281a3007288b68a3f5b74a22a0746d"}, - {file = "ruff-0.7.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:10ebce7696afe4644e8c1a23b3cf8c0f2193a310c18387c06e583ae9ef284de2"}, - {file = "ruff-0.7.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3f36d56326b3aef8eeee150b700e519880d1aab92f471eefdef656fd57492aa2"}, - {file = "ruff-0.7.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5d024301109a0007b78d57ab0ba190087b43dce852e552734ebf0b0b85e4fb16"}, - {file = "ruff-0.7.3-py3-none-win32.whl", hash = "sha256:4ba81a5f0c5478aa61674c5a2194de8b02652f17addf8dfc40c8937e6e7d79fc"}, - {file = "ruff-0.7.3-py3-none-win_amd64.whl", hash = "sha256:588a9ff2fecf01025ed065fe28809cd5a53b43505f48b69a1ac7707b1b7e4088"}, - {file = "ruff-0.7.3-py3-none-win_arm64.whl", hash = "sha256:1713e2c5545863cdbfe2cbce21f69ffaf37b813bfd1fb3b90dc9a6f1963f5a8c"}, - {file = "ruff-0.7.3.tar.gz", hash = "sha256:e1d1ba2e40b6e71a61b063354d04be669ab0d39c352461f3d789cac68b54a313"}, + {file = "ruff-0.8.1-py3-none-linux_armv6l.whl", hash = "sha256:fae0805bd514066f20309f6742f6ee7904a773eb9e6c17c45d6b1600ca65c9b5"}, + {file = "ruff-0.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8a4f7385c2285c30f34b200ca5511fcc865f17578383db154e098150ce0a087"}, + {file = "ruff-0.8.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd054486da0c53e41e0086e1730eb77d1f698154f910e0cd9e0d64274979a209"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2029b8c22da147c50ae577e621a5bfbc5d1fed75d86af53643d7a7aee1d23871"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2666520828dee7dfc7e47ee4ea0d928f40de72056d929a7c5292d95071d881d1"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:333c57013ef8c97a53892aa56042831c372e0bb1785ab7026187b7abd0135ad5"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:288326162804f34088ac007139488dcb43de590a5ccfec3166396530b58fb89d"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b12c39b9448632284561cbf4191aa1b005882acbc81900ffa9f9f471c8ff7e26"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:364e6674450cbac8e998f7b30639040c99d81dfb5bbc6dfad69bc7a8f916b3d1"}, + {file = "ruff-0.8.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b22346f845fec132aa39cd29acb94451d030c10874408dbf776af3aaeb53284c"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2f2f7a7e7648a2bfe6ead4e0a16745db956da0e3a231ad443d2a66a105c04fa"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:adf314fc458374c25c5c4a4a9270c3e8a6a807b1bec018cfa2813d6546215540"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a885d68342a231b5ba4d30b8c6e1b1ee3a65cf37e3d29b3c74069cdf1ee1e3c9"}, + {file = "ruff-0.8.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d2c16e3508c8cc73e96aa5127d0df8913d2290098f776416a4b157657bee44c5"}, + {file = "ruff-0.8.1-py3-none-win32.whl", hash = "sha256:93335cd7c0eaedb44882d75a7acb7df4b77cd7cd0d2255c93b28791716e81790"}, + {file = "ruff-0.8.1-py3-none-win_amd64.whl", hash = "sha256:2954cdbe8dfd8ab359d4a30cd971b589d335a44d444b6ca2cb3d1da21b75e4b6"}, + {file = "ruff-0.8.1-py3-none-win_arm64.whl", hash = "sha256:55873cc1a473e5ac129d15eccb3c008c096b94809d693fc7053f588b67822737"}, + {file = "ruff-0.8.1.tar.gz", hash = "sha256:3583db9a6450364ed5ca3f3b4225958b24f78178908d5c4bc0f46251ccca898f"}, ] [[package]] @@ -2548,13 +2542,13 @@ pyyaml = ">=5.4" [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [[package]] @@ -2793,98 +2787,49 @@ files = [ [[package]] name = "uuid-utils" -version = "0.9.0" +version = "0.10.0" description = "Drop-in replacement for Python UUID in Rust" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "uuid_utils-0.9.0-cp310-cp310-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:28da15c275ef06a759efe0fcba7c58eab8ae2217f7a7f66289dee6ae332605a0"}, - {file = "uuid_utils-0.9.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:81144165068e84a1ac8b92f23bfc961e5b5dbb89ddcff70c5e7d096ae07a439c"}, - {file = "uuid_utils-0.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:362695ed7756b1b89d9a2dd193fe2523ca1d4a31235606f7cb516a322789ffc4"}, - {file = "uuid_utils-0.9.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:36cb70e29f5749b554ae06f1a88926c9b47d5b48004b6903fb7ea47e8b398080"}, - {file = "uuid_utils-0.9.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fa39a95eb67e2b98a61d4e64ddf622ee902fe9142b579921ab3e9027472f5080"}, - {file = "uuid_utils-0.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9b7029044d40f66366cebb6a94ecb04d8c0a745029561552d527ac52dc0deb9"}, - {file = "uuid_utils-0.9.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c883c6f815d2af344dab585d7b16a77410fcb1f6c097e6ad0384bd12cd84e16e"}, - {file = "uuid_utils-0.9.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:be5f83e9002a43aac868fa9cbc73f28cfb0b4e8b14f5a449fef04fea31bf2904"}, - {file = "uuid_utils-0.9.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8f84b0fd38df8a211230b8bbd02d5e7e631f1d35c1ba67efb895f80c7d9215aa"}, - {file = "uuid_utils-0.9.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:89cc342b061d8e3f669b8aaeb8d9e2973407c93aaa675dc6a59e985feda2805c"}, - {file = "uuid_utils-0.9.0-cp310-none-win32.whl", hash = "sha256:3d5554f44aeab9706770169316897f79089b51a061800684b7f29bccf663ad0f"}, - {file = "uuid_utils-0.9.0-cp310-none-win_amd64.whl", hash = "sha256:db35df169f17617129cc070e3a8fba00598ee55adcbe22c79b2c2f306eeb3b9e"}, - {file = "uuid_utils-0.9.0-cp311-cp311-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:cdb7224fb8b1f18edcd4357f83fcbe33b9f82ac392095e5d9e0e05336d65d587"}, - {file = "uuid_utils-0.9.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5312449ea5427a94edab3aebf2cff8f99a3112f273dd9d5919e332bc4e6a031f"}, - {file = "uuid_utils-0.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d6837677217b3d0aa375f8aa7b89935c3ebf2ee5e1667be50b2090741684baa"}, - {file = "uuid_utils-0.9.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:402e522f62ceb8344f579e37f9a25c9274d484675afd71ad725ddd61ced7cd36"}, - {file = "uuid_utils-0.9.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e24a27724b2289d66d75358ffecf698ae36816458897cfdec972e6ede1ead328"}, - {file = "uuid_utils-0.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db04420c0b1a99f3160ddc90ba52986484ce8304b54586ea161133f755a4605b"}, - {file = "uuid_utils-0.9.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:152f3c1a0634558e329b64ff4a9592ee83b722e3fdc214f648f851fa14163c36"}, - {file = "uuid_utils-0.9.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5710b6ca95966f80125f48dad9e3d70ef99f48dd892bec3cb38673d087a7d71a"}, - {file = "uuid_utils-0.9.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3b9b9cf0cc544ef552c955bc2caaecf5e38cc8ed65e23f208b0dcdb6d37719e"}, - {file = "uuid_utils-0.9.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6d715b6321d4728a1aa0d5e26a338c97aaba2bf337f3ef9804ef5027f07de61d"}, - {file = "uuid_utils-0.9.0-cp311-none-win32.whl", hash = "sha256:3b61b0543404c99f7f23fb556b69090bc58358e8bd9d570381722221281f3706"}, - {file = "uuid_utils-0.9.0-cp311-none-win_amd64.whl", hash = "sha256:b4bdd9e80c92b1f253e66392e1d6ad0ec4926d5c7e2de3d852ee6fed1939f58b"}, - {file = "uuid_utils-0.9.0-cp312-cp312-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:9cfcfb222f62612bea58bdec32b6842d9636fca53ca4579f88c1b620b1c4cbf7"}, - {file = "uuid_utils-0.9.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7253039ecfa534b3177b3225764cede9c6dae5db572e17d8582dd7cc5b3af484"}, - {file = "uuid_utils-0.9.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6fb6e792ae1e3a7bf9d357f87dcf628923d0881f1d13a9cba826b848ca1774b1"}, - {file = "uuid_utils-0.9.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fbea3bb9ad319de7f69d6a60b6921acaa97d577aaeceb247b1ff4a8a92b3aa6a"}, - {file = "uuid_utils-0.9.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09043b3f48e20d631c7a81030be8c4f6ea9a6d44cccda8cbbdc1ad18da301c89"}, - {file = "uuid_utils-0.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9ba2681f5f177f800e40f5a0f09ed03c49f4290a245e4273d21cb48a7e88969"}, - {file = "uuid_utils-0.9.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:866811473f3d9dc38c02dd08e076e333b9e4d41ce952353941b49d0724d2327b"}, - {file = "uuid_utils-0.9.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:14aa9917ef11bd0ee1648237dddbf33aa0459e609ebe2f9202ffb259ca80f763"}, - {file = "uuid_utils-0.9.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:22cae83bc486a6c12b38239eb0546f2f81c81c34fcf833f84c2c7cd0cab1ad8f"}, - {file = "uuid_utils-0.9.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9513399045169435563c284caba0f1802748b02f27c95769426b7a00ed246e1"}, - {file = "uuid_utils-0.9.0-cp312-none-win_amd64.whl", hash = "sha256:284e6d24ba659d003bd47fcfc404d374c7807983407d4d61f26c80a3b7f4cb41"}, - {file = "uuid_utils-0.9.0-cp38-cp38-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fd3d09c53d5a96c78c77211786fa25bbdbe031566b927383c10ab81a27c7e431"}, - {file = "uuid_utils-0.9.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:2b052d01176d2d1afa476ebe158eae052e265c92110d987d5801f0c3c1c8852a"}, - {file = "uuid_utils-0.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85e636a9603dc04e15b8305129619b2b45843f883e58355c91dc6cc22d51dde8"}, - {file = "uuid_utils-0.9.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:37d2f9ec3a99caf29531fe257b7906f8a5946a3ee7000c744d73e5187a2542a1"}, - {file = "uuid_utils-0.9.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ace932d10a83141d22c42287a0c707cfa41522ecb797f17e63820f09688c6d7"}, - {file = "uuid_utils-0.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:843ec54337233d5f99a99b156ba5be5659f5ea193db8287035bf85d6a6a00c58"}, - {file = "uuid_utils-0.9.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f16a60ef4ddf9fe16fcd4793f83932d2b5198af6873d0a0478acfe0bd19d8e2f"}, - {file = "uuid_utils-0.9.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:901da31d61f78ec8df96741326541ae7af156a2628ca82ccf2806bcee257de1a"}, - {file = "uuid_utils-0.9.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:fad20ba28a11f2b33f06b2d7e0e77be73a8c3a41de833a123c6d93025d463b4b"}, - {file = "uuid_utils-0.9.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:c5c30716a0dcffd1a7a66853f5a8372a276d454510f48fc7e4c39c13212bb1f6"}, - {file = "uuid_utils-0.9.0-cp38-none-win32.whl", hash = "sha256:2912c9a810e74cb3abaebd0fdfa5b1f202cf60a8f0fec9cc76117dab6c42cb77"}, - {file = "uuid_utils-0.9.0-cp38-none-win_amd64.whl", hash = "sha256:b55bcffc260356c84a09ac3a391e2442ad4df0beaaf71670d4e8ffd8b7328e75"}, - {file = "uuid_utils-0.9.0-cp39-cp39-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:08aec826a8ed4d3baab29d144ad634091e5accabcb88dfa0a834b9ba9e74930f"}, - {file = "uuid_utils-0.9.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e7de8fcf3d22e299582ab61c67390abdf37cc7d5b330066c3f792a082167c419"}, - {file = "uuid_utils-0.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8de8da71bc5a6a527952648357acca8d6d1717bbbc044304c5a9cf53eb06568c"}, - {file = "uuid_utils-0.9.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ce3ef96aa6ba760e1d0481ed076fe9e8f0386e27c7039bc6ffa377c98979fae7"}, - {file = "uuid_utils-0.9.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69dd8c0d622e4e40b1b993a2e452bbed21127b97f8e4a3fdbde6e5f556253265"}, - {file = "uuid_utils-0.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4600d5dcd9d0759be4bc580daf6d521da99a825a25db3d492abcbb12f6dc98f6"}, - {file = "uuid_utils-0.9.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:067d5f36ccc70896c76a9dafc8220a942db0e42ab58b84c43208e0ff84c1bdf0"}, - {file = "uuid_utils-0.9.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7a23d20f08636899a1b24394a12a2c469262af56d5279dbac1c6b14b059e5d4b"}, - {file = "uuid_utils-0.9.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6a2cbc5da89f0e701d2b80df0e6b30da16a0adcd2883da3d3e1f7aac1f046c1c"}, - {file = "uuid_utils-0.9.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bbf93bdd3c8a3e3b2b2f82ad4dfafcd2aaecc1d6ec924fd5da2b712ab324ee51"}, - {file = "uuid_utils-0.9.0-cp39-none-win32.whl", hash = "sha256:9d9b3ba5be11a017c568e904eac76f6cd6f82f956ca65ffbaa73ee8d7cdbe13b"}, - {file = "uuid_utils-0.9.0-cp39-none-win_amd64.whl", hash = "sha256:b3e494547cfef124f0c51831a303bfc0278e3c33b9ab9d9db90d94728d9871c2"}, - {file = "uuid_utils-0.9.0-pp38-pypy38_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:98c7c7b414b405b547c9bc1f972513b3a0bfb3dca248c89c623ab60efdd36ad8"}, - {file = "uuid_utils-0.9.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:7b75241666cae4bc5786e6c68e862ccf4e15b2f98c81e47a6b0a85c907b7b6fa"}, - {file = "uuid_utils-0.9.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf6b43723a2d4af21c07fec98385a97e2023a808fd6eaf4296a163bffca76cf5"}, - {file = "uuid_utils-0.9.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4c260bb9a9fdd484cadc437cdb26ad07d66c8049a365c4ef49c9f09d7ed9ac2e"}, - {file = "uuid_utils-0.9.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4605c6326a7914d1b59c548f0ae4ef119619fe09c3ab4f07d99f3fbec39d470"}, - {file = "uuid_utils-0.9.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d498673249826ce7c47aa481709a5dd647bbff764fb64370bc691c7e43c7a2a1"}, - {file = "uuid_utils-0.9.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a37c48cba2f4eb6182a3857d045aa1420fa9878bfd268f6855fce7293a006677"}, - {file = "uuid_utils-0.9.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:eeb9c56d401e4a422ae7fd818ef1376bda384ae0bed86e339c9a256c6b10d252"}, - {file = "uuid_utils-0.9.0-pp39-pypy39_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:33dd97e9c59891fbfb4e4a11596c42cc3d10774b843daaf75316d036a0a07799"}, - {file = "uuid_utils-0.9.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5e67fc3c6def9d62de4caf19529bd8044e821eb2f5c39821cfd011940f96394"}, - {file = "uuid_utils-0.9.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:241ab8ddb76ef8d4294c09cd6045dd62a1aa46acf8ff0a017796a54a530a87ae"}, - {file = "uuid_utils-0.9.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5a9a16d2af4b4ad59d4cef7f43ba33644353b12769fafabf6e1663aa230cca38"}, - {file = "uuid_utils-0.9.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:897a167659d30a8431a094533bcb58d2b16005f7456408bd40f3e5872e1b2f46"}, - {file = "uuid_utils-0.9.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b4f56ab5ce19697552df9689c24c742054e8fd8e2ef8c26f9b8393f6d7ae893"}, - {file = "uuid_utils-0.9.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7b219d9341de117e2e608f3fe08e31480ad60fb6128f8fffd2151ba88e53508c"}, - {file = "uuid_utils-0.9.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:b5c08de8a94181c0ba209a8b8275993499f424b57958bea6c39739311526fd18"}, - {file = "uuid_utils-0.9.0.tar.gz", hash = "sha256:239f45b7e71d0ea61e3a4957aa4b8f3b49bfb009cf768d11c3f464787dbb737f"}, + {file = "uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d5a4508feefec62456cd6a41bcdde458d56827d908f226803b886d22a3d5e63"}, + {file = "uuid_utils-0.10.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:dbefc2b9113f9dfe56bdae58301a2b3c53792221410d422826f3d1e3e6555fe7"}, + {file = "uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffc49c33edf87d1ec8112a9b43e4cf55326877716f929c165a2cc307d31c73d5"}, + {file = "uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0636b6208f69d5a4e629707ad2a89a04dfa8d1023e1999181f6830646ca048a1"}, + {file = "uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7bc06452856b724df9dedfc161c3582199547da54aeb81915ec2ed54f92d19b0"}, + {file = "uuid_utils-0.10.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:263b2589111c61decdd74a762e8f850c9e4386fb78d2cf7cb4dfc537054cda1b"}, + {file = "uuid_utils-0.10.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a558db48b7096de6b4d2d2210d82bba8586a6d55f99106b03bb7d01dc5c5bcd6"}, + {file = "uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:807465067f3c892514230326ac71a79b28a8dfe2c88ecd2d5675fc844f3c76b5"}, + {file = "uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:57423d4a2b9d7b916de6dbd75ba85465a28f9578a89a97f7d3e098d9aa4e5d4a"}, + {file = "uuid_utils-0.10.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:76d8d660f18ff6b767e319b1b5f927350cd92eafa4831d7ef5b57fdd1d91f974"}, + {file = "uuid_utils-0.10.0-cp39-abi3-win32.whl", hash = "sha256:6c11a71489338837db0b902b75e1ba7618d5d29f05fde4f68b3f909177dbc226"}, + {file = "uuid_utils-0.10.0-cp39-abi3-win_amd64.whl", hash = "sha256:11c55ae64f6c0a7a0c741deae8ca2a4eaa11e9c09dbb7bec2099635696034cf7"}, + {file = "uuid_utils-0.10.0-pp310-pypy310_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:acea543dfc7b87df749e3e814c54ac739a82ff5e3800d25bd25a3e00599e1554"}, + {file = "uuid_utils-0.10.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0767eefa7b1e96f06cfa9b95758d286240c01bbf19e9d8f1b6043cdbe76cc639"}, + {file = "uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:973fe4bb5258fd2ccb144d8b40c2d3158f16cc856a20527f8b40d14b2ae1dee9"}, + {file = "uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71b8505b67a0d77d0fbd765d8463094a8f447677125da7647bec7ea0b99406f0"}, + {file = "uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6bdcb1211bb61476cbef12a87101fa48243e20ed82b2bd324c816b1b5826bd5e"}, + {file = "uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c5247f1df040aae71ea313819b563debe69bca7086a2cc6a3ac0eaddd3dadac"}, + {file = "uuid_utils-0.10.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a50bd29ef89660b93aa07ffa95ac691a0e12832375030569a8bd5c9272f3b8e6"}, + {file = "uuid_utils-0.10.0-pp39-pypy39_pp73-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a778cd9d8f995b94bba6e51f3ebee5b338fd834b0c4ecc8f932bd23e29db3e19"}, + {file = "uuid_utils-0.10.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d3d5b5c5ed66ff923961b9ebb902232cd67f6a7ec6b6f7a58e05e00ff44e3c7f"}, + {file = "uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:789ed6335225326c66f5d6162649bed978105a85f232be7811387c395c226801"}, + {file = "uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:05d1aa7b944b719eb1ee472435ae5444a3f8a00eb6350e3b1d1217d738477d33"}, + {file = "uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa8d8559c2d25d6ac87e0adeee601d2c91ec40b357ab780bcf79061cc23324e6"}, + {file = "uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0badcbfe3c72b5b30d59c2b12f120923127abd95a0d2aa64ddc1234e495abc2"}, + {file = "uuid_utils-0.10.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0a7c1c494012335113748815156c5b6234c59b0fe0d3a8eede1b1a46f7e25a69"}, + {file = "uuid_utils-0.10.0.tar.gz", hash = "sha256:5db0e1890e8f008657ffe6ded4d9459af724ab114cfe82af1557c87545301539"}, ] [[package]] name = "virtualenv" -version = "20.27.1" +version = "20.28.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" files = [ - {file = "virtualenv-20.27.1-py3-none-any.whl", hash = "sha256:f11f1b8a29525562925f745563bfd48b189450f61fb34c4f9cc79dd5aa32a1f4"}, - {file = "virtualenv-20.27.1.tar.gz", hash = "sha256:142c6be10212543b32c6c45d3d3893dff89112cc588b7d0879ae5a1ec03a47ba"}, + {file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"}, + {file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"}, ] [package.dependencies] @@ -2931,93 +2876,93 @@ tests = ["Django (>=2.2.0)", "Flask (>=0.12.5)", "aiohttp (>=3.0.8)", "bottle (> [[package]] name = "yarl" -version = "1.17.1" +version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" files = [ - {file = "yarl-1.17.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1794853124e2f663f0ea54efb0340b457f08d40a1cef78edfa086576179c91"}, - {file = "yarl-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:fbea1751729afe607d84acfd01efd95e3b31db148a181a441984ce9b3d3469da"}, - {file = "yarl-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ee427208c675f1b6e344a1f89376a9613fc30b52646a04ac0c1f6587c7e46ec"}, - {file = "yarl-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b74ff4767d3ef47ffe0cd1d89379dc4d828d4873e5528976ced3b44fe5b0a21"}, - {file = "yarl-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:62a91aefff3d11bf60e5956d340eb507a983a7ec802b19072bb989ce120cd948"}, - {file = "yarl-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:846dd2e1243407133d3195d2d7e4ceefcaa5f5bf7278f0a9bda00967e6326b04"}, - {file = "yarl-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e844be8d536afa129366d9af76ed7cb8dfefec99f5f1c9e4f8ae542279a6dc3"}, - {file = "yarl-1.17.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc7c92c1baa629cb03ecb0c3d12564f172218fb1739f54bf5f3881844daadc6d"}, - {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ae3476e934b9d714aa8000d2e4c01eb2590eee10b9d8cd03e7983ad65dfbfcba"}, - {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c7e177c619342e407415d4f35dec63d2d134d951e24b5166afcdfd1362828e17"}, - {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:64cc6e97f14cf8a275d79c5002281f3040c12e2e4220623b5759ea7f9868d6a5"}, - {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:84c063af19ef5130084db70ada40ce63a84f6c1ef4d3dbc34e5e8c4febb20822"}, - {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:482c122b72e3c5ec98f11457aeb436ae4aecca75de19b3d1de7cf88bc40db82f"}, - {file = "yarl-1.17.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:380e6c38ef692b8fd5a0f6d1fa8774d81ebc08cfbd624b1bca62a4d4af2f9931"}, - {file = "yarl-1.17.1-cp310-cp310-win32.whl", hash = "sha256:16bca6678a83657dd48df84b51bd56a6c6bd401853aef6d09dc2506a78484c7b"}, - {file = "yarl-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:561c87fea99545ef7d692403c110b2f99dced6dff93056d6e04384ad3bc46243"}, - {file = "yarl-1.17.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:cbad927ea8ed814622305d842c93412cb47bd39a496ed0f96bfd42b922b4a217"}, - {file = "yarl-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fca4b4307ebe9c3ec77a084da3a9d1999d164693d16492ca2b64594340999988"}, - {file = "yarl-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff5c6771c7e3511a06555afa317879b7db8d640137ba55d6ab0d0c50425cab75"}, - {file = "yarl-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b29beab10211a746f9846baa39275e80034e065460d99eb51e45c9a9495bcca"}, - {file = "yarl-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a52a1ffdd824fb1835272e125385c32fd8b17fbdefeedcb4d543cc23b332d74"}, - {file = "yarl-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:58c8e9620eb82a189c6c40cb6b59b4e35b2ee68b1f2afa6597732a2b467d7e8f"}, - {file = "yarl-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d216e5d9b8749563c7f2c6f7a0831057ec844c68b4c11cb10fc62d4fd373c26d"}, - {file = "yarl-1.17.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:881764d610e3269964fc4bb3c19bb6fce55422828e152b885609ec176b41cf11"}, - {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8c79e9d7e3d8a32d4824250a9c6401194fb4c2ad9a0cec8f6a96e09a582c2cc0"}, - {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:299f11b44d8d3a588234adbe01112126010bd96d9139c3ba7b3badd9829261c3"}, - {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cc7d768260f4ba4ea01741c1b5fe3d3a6c70eb91c87f4c8761bbcce5181beafe"}, - {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:de599af166970d6a61accde358ec9ded821234cbbc8c6413acfec06056b8e860"}, - {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2b24ec55fad43e476905eceaf14f41f6478780b870eda5d08b4d6de9a60b65b4"}, - {file = "yarl-1.17.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9fb815155aac6bfa8d86184079652c9715c812d506b22cfa369196ef4e99d1b4"}, - {file = "yarl-1.17.1-cp311-cp311-win32.whl", hash = "sha256:7615058aabad54416ddac99ade09a5510cf77039a3b903e94e8922f25ed203d7"}, - {file = "yarl-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:14bc88baa44e1f84164a392827b5defb4fa8e56b93fecac3d15315e7c8e5d8b3"}, - {file = "yarl-1.17.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:327828786da2006085a4d1feb2594de6f6d26f8af48b81eb1ae950c788d97f61"}, - {file = "yarl-1.17.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:cc353841428d56b683a123a813e6a686e07026d6b1c5757970a877195f880c2d"}, - {file = "yarl-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c73df5b6e8fabe2ddb74876fb82d9dd44cbace0ca12e8861ce9155ad3c886139"}, - {file = "yarl-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bdff5e0995522706c53078f531fb586f56de9c4c81c243865dd5c66c132c3b5"}, - {file = "yarl-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:06157fb3c58f2736a5e47c8fcbe1afc8b5de6fb28b14d25574af9e62150fcaac"}, - {file = "yarl-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1654ec814b18be1af2c857aa9000de7a601400bd4c9ca24629b18486c2e35463"}, - {file = "yarl-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f6595c852ca544aaeeb32d357e62c9c780eac69dcd34e40cae7b55bc4fb1147"}, - {file = "yarl-1.17.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:459e81c2fb920b5f5df744262d1498ec2c8081acdcfe18181da44c50f51312f7"}, - {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e48cdb8226644e2fbd0bdb0a0f87906a3db07087f4de77a1b1b1ccfd9e93685"}, - {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d9b6b28a57feb51605d6ae5e61a9044a31742db557a3b851a74c13bc61de5172"}, - {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e594b22688d5747b06e957f1ef822060cb5cb35b493066e33ceac0cf882188b7"}, - {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5f236cb5999ccd23a0ab1bd219cfe0ee3e1c1b65aaf6dd3320e972f7ec3a39da"}, - {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:a2a64e62c7a0edd07c1c917b0586655f3362d2c2d37d474db1a509efb96fea1c"}, - {file = "yarl-1.17.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:d0eea830b591dbc68e030c86a9569826145df485b2b4554874b07fea1275a199"}, - {file = "yarl-1.17.1-cp312-cp312-win32.whl", hash = "sha256:46ddf6e0b975cd680eb83318aa1d321cb2bf8d288d50f1754526230fcf59ba96"}, - {file = "yarl-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:117ed8b3732528a1e41af3aa6d4e08483c2f0f2e3d3d7dca7cf538b3516d93df"}, - {file = "yarl-1.17.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5d1d42556b063d579cae59e37a38c61f4402b47d70c29f0ef15cee1acaa64488"}, - {file = "yarl-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0167540094838ee9093ef6cc2c69d0074bbf84a432b4995835e8e5a0d984374"}, - {file = "yarl-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2f0a6423295a0d282d00e8701fe763eeefba8037e984ad5de44aa349002562ac"}, - {file = "yarl-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5b078134f48552c4d9527db2f7da0b5359abd49393cdf9794017baec7506170"}, - {file = "yarl-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d401f07261dc5aa36c2e4efc308548f6ae943bfff20fcadb0a07517a26b196d8"}, - {file = "yarl-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5f1ac7359e17efe0b6e5fec21de34145caef22b260e978336f325d5c84e6938"}, - {file = "yarl-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f63d176a81555984e91f2c84c2a574a61cab7111cc907e176f0f01538e9ff6e"}, - {file = "yarl-1.17.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e275792097c9f7e80741c36de3b61917aebecc08a67ae62899b074566ff8556"}, - {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:81713b70bea5c1386dc2f32a8f0dab4148a2928c7495c808c541ee0aae614d67"}, - {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:aa46dce75078fceaf7cecac5817422febb4355fbdda440db55206e3bd288cfb8"}, - {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1ce36ded585f45b1e9bb36d0ae94765c6608b43bd2e7f5f88079f7a85c61a4d3"}, - {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2d374d70fdc36f5863b84e54775452f68639bc862918602d028f89310a034ab0"}, - {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:2d9f0606baaec5dd54cb99667fcf85183a7477f3766fbddbe3f385e7fc253299"}, - {file = "yarl-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b0341e6d9a0c0e3cdc65857ef518bb05b410dbd70d749a0d33ac0f39e81a4258"}, - {file = "yarl-1.17.1-cp313-cp313-win32.whl", hash = "sha256:2e7ba4c9377e48fb7b20dedbd473cbcbc13e72e1826917c185157a137dac9df2"}, - {file = "yarl-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:949681f68e0e3c25377462be4b658500e85ca24323d9619fdc41f68d46a1ffda"}, - {file = "yarl-1.17.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8994b29c462de9a8fce2d591028b986dbbe1b32f3ad600b2d3e1c482c93abad6"}, - {file = "yarl-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f9cbfbc5faca235fbdf531b93aa0f9f005ec7d267d9d738761a4d42b744ea159"}, - {file = "yarl-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b40d1bf6e6f74f7c0a567a9e5e778bbd4699d1d3d2c0fe46f4b717eef9e96b95"}, - {file = "yarl-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5efe0661b9fcd6246f27957f6ae1c0eb29bc60552820f01e970b4996e016004"}, - {file = "yarl-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5c4804e4039f487e942c13381e6c27b4b4e66066d94ef1fae3f6ba8b953f383"}, - {file = "yarl-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b5d6a6c9602fd4598fa07e0389e19fe199ae96449008d8304bf5d47cb745462e"}, - {file = "yarl-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4c9156c4d1eb490fe374fb294deeb7bc7eaccda50e23775b2354b6a6739934"}, - {file = "yarl-1.17.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6324274b4e0e2fa1b3eccb25997b1c9ed134ff61d296448ab8269f5ac068c4c"}, - {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d8a8b74d843c2638f3864a17d97a4acda58e40d3e44b6303b8cc3d3c44ae2d29"}, - {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:7fac95714b09da9278a0b52e492466f773cfe37651cf467a83a1b659be24bf71"}, - {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c180ac742a083e109c1a18151f4dd8675f32679985a1c750d2ff806796165b55"}, - {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:578d00c9b7fccfa1745a44f4eddfdc99d723d157dad26764538fbdda37209857"}, - {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:1a3b91c44efa29e6c8ef8a9a2b583347998e2ba52c5d8280dbd5919c02dfc3b5"}, - {file = "yarl-1.17.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a7ac5b4984c468ce4f4a553df281450df0a34aefae02e58d77a0847be8d1e11f"}, - {file = "yarl-1.17.1-cp39-cp39-win32.whl", hash = "sha256:7294e38f9aa2e9f05f765b28ffdc5d81378508ce6dadbe93f6d464a8c9594473"}, - {file = "yarl-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:eb6dce402734575e1a8cc0bb1509afca508a400a57ce13d306ea2c663bad1138"}, - {file = "yarl-1.17.1-py3-none-any.whl", hash = "sha256:f1790a4b1e8e8e028c391175433b9c8122c39b46e1663228158e61e6f915bf06"}, - {file = "yarl-1.17.1.tar.gz", hash = "sha256:067a63fcfda82da6b198fa73079b1ca40b7c9b7994995b6ee38acda728b64d47"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, + {file = "yarl-1.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc"}, + {file = "yarl-1.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b"}, + {file = "yarl-1.18.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690"}, + {file = "yarl-1.18.3-cp310-cp310-win32.whl", hash = "sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6"}, + {file = "yarl-1.18.3-cp310-cp310-win_amd64.whl", hash = "sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193"}, + {file = "yarl-1.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae"}, + {file = "yarl-1.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e"}, + {file = "yarl-1.18.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a"}, + {file = "yarl-1.18.3-cp311-cp311-win32.whl", hash = "sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1"}, + {file = "yarl-1.18.3-cp311-cp311-win_amd64.whl", hash = "sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576"}, + {file = "yarl-1.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba"}, + {file = "yarl-1.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393"}, + {file = "yarl-1.18.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285"}, + {file = "yarl-1.18.3-cp312-cp312-win32.whl", hash = "sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2"}, + {file = "yarl-1.18.3-cp312-cp312-win_amd64.whl", hash = "sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa"}, + {file = "yarl-1.18.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58"}, + {file = "yarl-1.18.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10"}, + {file = "yarl-1.18.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8"}, + {file = "yarl-1.18.3-cp313-cp313-win32.whl", hash = "sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d"}, + {file = "yarl-1.18.3-cp313-cp313-win_amd64.whl", hash = "sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719"}, + {file = "yarl-1.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c"}, + {file = "yarl-1.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910"}, + {file = "yarl-1.18.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1"}, + {file = "yarl-1.18.3-cp39-cp39-win32.whl", hash = "sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5"}, + {file = "yarl-1.18.3-cp39-cp39-win_amd64.whl", hash = "sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9"}, + {file = "yarl-1.18.3-py3-none-any.whl", hash = "sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b"}, + {file = "yarl-1.18.3.tar.gz", hash = "sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1"}, ] [package.dependencies] @@ -3026,11 +2971,10 @@ multidict = ">=4.0" propcache = ">=0.2.0" [extras] -askar = ["anoncreds", "aries-askar-ff137", "indy-credx", "indy-vdr"] bbs = ["ursa-bbs-signatures"] didcommv2 = ["didcomm-messaging"] [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "32b3a449d520f812a5be03ed306d923d4476c1fcaf8750470587a3a8da09fed3" +content-hash = "0ec4a165fc3c5503157ee57736700b931a6c920d7cacc39b91463dad311676e7" diff --git a/pyproject.toml b/pyproject.toml index 8d3365a8e7..b13065d41c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "acapy_agent_didx" -version = "1.1.1-20241115" +version = "1.2.0-20241205" description = "(ACA-Py) A Cloud Agent Python is a foundation for building decentralized identity applications and services running in non-mobile environments. " authors = [] license = "Apache-2.0" @@ -16,7 +16,7 @@ repository = "https://github.com/openwallet-foundation/acapy" [tool.poetry.dependencies] python = "^3.12" -aiohttp = "~3.11.0" +aiohttp = "~3.11.9" aiohttp-apispec-acapy = "~3.0.2" aiohttp-cors = "~0.7.0" apispec = "^6.6.0" @@ -34,7 +34,7 @@ packaging = "~23.2" portalocker = "~2.10.1" prompt_toolkit = ">=2.0.9,<2.1.0" pydid = "^0.5.1" -pyjwt = "~2.9.0" +pyjwt = "~2.10.1" pyld = "^2.0.4" pynacl = "~1.5.0" python-dateutil = "^2.9.0" @@ -45,15 +45,21 @@ requests = "~2.32.3" rlp = "4.0.1" unflatten = "~0.2" sd-jwt = "^0.10.3" +uuid_utils = "^0.10.0" + +# did libraries did-peer-2 = "^0.1.2" did-peer-4 = "^0.1.4" -uuid_utils = "^0.9.0" + +# Verifiable Credentials +indy-credx = "~1.1.1" +anoncreds = "0.2.0" # askar -aries-askar-ff137 = {version = "==0.3.3b0", source = "testpypi", optional = true} -indy-credx = { version = "~1.1.1", optional = true } -indy-vdr = { version = "~0.4.0", optional = true } -anoncreds = { version = "0.2.0", optional = true } +aries-askar-ff137 = {version = "==0.3.3b0", source = "testpypi"} + +# indy +indy-vdr = "~0.4.0" # bbs ursa-bbs-signatures = { version = "~1.0.1", optional = true } @@ -65,7 +71,7 @@ canonicaljson = "^2.0.0" [tool.poetry.group.dev.dependencies] pre-commit = "~3.8.0" # Sync with version in .pre-commit-config.yaml -ruff = "0.7.3" +ruff = "0.8.1" sphinx = "^5.3.0" sphinx-rtd-theme = ">=0.4.3" @@ -75,15 +81,14 @@ pydevd = "1.5.1" pydevd-pycharm = "~193.7288.30" # testing -pytest = "^8.3.3" +pytest = "^8.3.4" pytest-asyncio = "^0.24.0" pytest-cov = "^5.0.0" pytest-ruff = "^0.4.1" pytest-xdist = "^3.6.1" -debugpy = "^1.8.8" +debugpy = "^1.8.9" [tool.poetry.extras] -askar = ["aries-askar-ff137", "indy-credx", "indy-vdr", "anoncreds"] bbs = ["ursa-bbs-signatures"] didcommv2 = ["didcomm-messaging"] diff --git a/scenarios/examples/anoncreds_issuance_and_revocation/docker-compose.yml b/scenarios/examples/anoncreds_issuance_and_revocation/docker-compose.yml index 247a0b7daf..6e0a757fbd 100644 --- a/scenarios/examples/anoncreds_issuance_and_revocation/docker-compose.yml +++ b/scenarios/examples/anoncreds_issuance_and_revocation/docker-compose.yml @@ -1,22 +1,26 @@ services: - alice: + agency: image: acapy-test ports: - "3001:3001" command: > start - --label Alice + --label Agency --inbound-transport http 0.0.0.0 3000 --outbound-transport http - --endpoint http://alice:3000 + --endpoint http://agency:3000 --admin 0.0.0.0 3001 --admin-insecure-mode --tails-server-base-url http://tails:6543 --genesis-url http://test.bcovrin.vonx.io/genesis - --wallet-type askar-anoncreds - --wallet-name alice + --wallet-type askar + --wallet-name agency --wallet-key insecure --auto-provision + --multitenant + --multitenant-admin + --jwt-secret insecure + --multitenancy-config wallet_type=single-wallet-askar key_derivation_method=RAW --log-level info --debug-webhooks --notify-revocation @@ -30,22 +34,50 @@ tails: condition: service_started - bob: + holder_anoncreds: image: acapy-test ports: - "3002:3001" command: > start - --label Bob + --label Holder-Anoncreds --inbound-transport http 0.0.0.0 3000 --outbound-transport http - --endpoint http://bob:3000 + --endpoint http://holder_anoncreds:3000 --admin 0.0.0.0 3001 --admin-insecure-mode --tails-server-base-url http://tails:6543 --genesis-url http://test.bcovrin.vonx.io/genesis --wallet-type askar-anoncreds - --wallet-name bob + --wallet-name holder_anoncreds + --wallet-key insecure + --auto-provision + --log-level info + --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 + + holder_indy: + image: acapy-test + ports: + - "3003:3001" + command: > + start + --label Holder-Indy + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://holder_indy:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url http://test.bcovrin.vonx.io/genesis + --wallet-type askar + --wallet-name holder_indy --wallet-key insecure --auto-provision --log-level info @@ -63,15 +95,18 @@ build: context: ../.. environment: - - ALICE=http://alice:3001 - - BOB=http://bob:3001 + - AGENCY=http://agency:3001 + - HOLDER_ANONCREDS=http://holder_anoncreds:3001 + - HOLDER_INDY=http://holder_indy:3001 volumes: - ./example.py:/usr/src/app/example.py:ro,z command: python -m example depends_on: - alice: + agency: + condition: service_healthy + holder_anoncreds: condition: service_healthy - bob: + holder_indy: condition: service_healthy tails: diff --git a/scenarios/examples/anoncreds_issuance_and_revocation/example.py b/scenarios/examples/anoncreds_issuance_and_revocation/example.py index 6d7d1a1bd2..05a68c395a 100644 --- a/scenarios/examples/anoncreds_issuance_and_revocation/example.py +++ b/scenarios/examples/anoncreds_issuance_and_revocation/example.py @@ -7,23 +7,30 @@ import json from dataclasses import dataclass from os import getenv -from secrets import token_hex +from secrets import randbelow, token_hex +from typing import Any, Dict, List, Mapping, Optional, Tuple, Type, Union +from uuid import uuid4 from acapy_controller import Controller -from acapy_controller.controller import Minimal +from acapy_controller.controller import Minimal, MinType from acapy_controller.logging import logging_to_stdout -from acapy_controller.models import V20PresExRecord, V20PresExRecordList +from acapy_controller.models import ( + CreateWalletResponse, + V20CredExRecordIndy, + V20PresExRecord, + V20PresExRecordList, +) from acapy_controller.protocols import ( DIDResult, didexchange, - indy_issue_credential_v2, - indy_present_proof_v2, + indy_anoncred_credential_artifacts, params, ) from aiohttp import ClientSession -ALICE = getenv("ALICE", "http://alice:3001") -BOB = getenv("BOB", "http://bob:3001") +AGENCY = getenv("AGENCY", "http://agency:3001") +HOLDER_ANONCREDS = getenv("HOLDER_ANONCREDS", "http://holder_anoncreds:3001") +HOLDER_INDY = getenv("HOLDER_INDY", "http://holder_indy:3001") def summary(presentation: V20PresExRecord) -> str: @@ -33,7 +40,9 @@ def summary(presentation: V20PresExRecord) -> str: { "state": presentation.state, "verified": presentation.verified, - "presentation_request": request.dict(by_alias=True) if request else None, + "presentation_request": request.model_dump(by_alias=True) + if request + else None, }, indent=2, sort_keys=True, @@ -41,32 +50,395 @@ def summary(presentation: V20PresExRecord) -> str: @dataclass -class SchemaResult(Minimal): +class SchemaResultAnoncreds(Minimal): """Schema result.""" schema_state: dict @dataclass -class CredDefResult(Minimal): +class CredDefResultAnoncreds(Minimal): """Credential definition result.""" credential_definition_state: dict +@dataclass +class V20CredExRecord(Minimal): + """V2.0 credential exchange record.""" + + state: str + cred_ex_id: str + connection_id: str + thread_id: str + + +@dataclass +class V20CredExRecordFormat(Minimal): + """V2.0 credential exchange record anoncreds.""" + + rev_reg_id: Optional[str] = None + cred_rev_id: Optional[str] = None + + +@dataclass +class V20CredExRecordDetail(Minimal): + """V2.0 credential exchange record detail.""" + + cred_ex_record: V20CredExRecord + details: Optional[V20CredExRecordFormat] = None + + +@dataclass +class ProofRequest(Minimal): + """Proof request.""" + + requested_attributes: Dict[str, Any] + requested_predicates: Dict[str, Any] + + +@dataclass +class PresSpec(Minimal): + """Presentation specification.""" + + requested_attributes: Dict[str, Any] + requested_predicates: Dict[str, Any] + self_attested_attributes: Dict[str, Any] + + +@dataclass +class CredInfo(Minimal): + """Credential information.""" + + referent: str + attrs: Dict[str, Any] + + +@dataclass +class CredPrecis(Minimal): + """Credential precis.""" + + cred_info: CredInfo + presentation_referents: List[str] + + @classmethod + def deserialize(cls: Type[MinType], value: Mapping[str, Any]) -> MinType: + """Deserialize the credential precis.""" + value = dict(value) + if cred_info := value.get("cred_info"): + value["cred_info"] = CredInfo.deserialize(cred_info) + return super().deserialize(value) + + +@dataclass +class Settings(Minimal): + """Settings information.""" + + +def auto_select_credentials_for_presentation_request( + presentation_request: Union[ProofRequest, dict], + relevant_creds: List[CredPrecis], +) -> PresSpec: + """Select credentials to use for presentation automatically.""" + if isinstance(presentation_request, dict): + presentation_request = ProofRequest.deserialize(presentation_request) + + requested_attributes = {} + for pres_referrent in presentation_request.requested_attributes.keys(): + for cred_precis in relevant_creds: + if pres_referrent in cred_precis.presentation_referents: + requested_attributes[pres_referrent] = { + "cred_id": cred_precis.cred_info.referent, + "revealed": True, + } + requested_predicates = {} + for pres_referrent in presentation_request.requested_predicates.keys(): + for cred_precis in relevant_creds: + if pres_referrent in cred_precis.presentation_referents: + requested_predicates[pres_referrent] = { + "cred_id": cred_precis.cred_info.referent, + } + + return PresSpec.deserialize( + { + "requested_attributes": requested_attributes, + "requested_predicates": requested_predicates, + "self_attested_attributes": {}, + } + ) + + +async def issue_credential_v2( + issuer: Controller, + holder: Controller, + issuer_connection_id: str, + holder_connection_id: str, + cred_def_id: str, + attributes: Mapping[str, str], +) -> Tuple[V20CredExRecordDetail, V20CredExRecordDetail]: + """Issue an credential using issue-credential/2.0. + + Issuer and holder should already be connected. + """ + + is_issuer_anoncreds = (await issuer.get("/settings", response=Settings)).get( + "wallet.type" + ) == "askar-anoncreds" + is_holder_anoncreds = (await holder.get("/settings", response=Settings)).get( + "wallet.type" + ) == "askar-anoncreds" + + if is_issuer_anoncreds: + _filter = {"anoncreds": {"cred_def_id": cred_def_id}} + else: + _filter = {"indy": {"cred_def_id": cred_def_id}} + issuer_cred_ex = await issuer.post( + "/issue-credential-2.0/send-offer", + json={ + "auto_issue": False, + "auto_remove": False, + "comment": "Credential from minimal example", + "trace": False, + "connection_id": issuer_connection_id, + "filter": _filter, + "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=V20CredExRecord, + ) + issuer_cred_ex_id = issuer_cred_ex.cred_ex_id + + holder_cred_ex = await holder.event_with_values( + topic="issue_credential_v2_0", + event_type=V20CredExRecord, + connection_id=holder_connection_id, + state="offer-received", + ) + holder_cred_ex_id = holder_cred_ex.cred_ex_id + + await holder.post( + f"/issue-credential-2.0/records/{holder_cred_ex_id}/send-request", + response=V20CredExRecord, + ) + + await issuer.event_with_values( + topic="issue_credential_v2_0", + cred_ex_id=issuer_cred_ex_id, + state="request-received", + ) + + await issuer.post( + f"/issue-credential-2.0/records/{issuer_cred_ex_id}/issue", + json={}, + response=V20CredExRecordDetail, + ) + + await holder.event_with_values( + topic="issue_credential_v2_0", + cred_ex_id=holder_cred_ex_id, + state="credential-received", + ) + + await holder.post( + f"/issue-credential-2.0/records/{holder_cred_ex_id}/store", + json={}, + response=V20CredExRecordDetail, + ) + issuer_cred_ex = await issuer.event_with_values( + topic="issue_credential_v2_0", + event_type=V20CredExRecord, + cred_ex_id=issuer_cred_ex_id, + state="done", + ) + issuer_indy_record = await issuer.event_with_values( + topic="issue_credential_v2_0_anoncreds" + if is_issuer_anoncreds + else "issue_credential_v2_0_indy", + event_type=V20CredExRecordIndy, + ) + + holder_cred_ex = await holder.event_with_values( + topic="issue_credential_v2_0", + event_type=V20CredExRecord, + cred_ex_id=holder_cred_ex_id, + state="done", + ) + holder_indy_record = await holder.event_with_values( + topic="issue_credential_v2_0_anoncreds" + if is_holder_anoncreds + else "issue_credential_v2_0_indy", + event_type=V20CredExRecordIndy, + ) + + return ( + V20CredExRecordDetail(cred_ex_record=issuer_cred_ex, details=issuer_indy_record), + V20CredExRecordDetail( + cred_ex_record=holder_cred_ex, + details=holder_indy_record, + ), + ) + + +async def present_proof_v2( + holder: Controller, + verifier: Controller, + holder_connection_id: str, + verifier_connection_id: str, + *, + name: Optional[str] = None, + version: Optional[str] = None, + comment: Optional[str] = None, + requested_attributes: Optional[List[Mapping[str, Any]]] = None, + requested_predicates: Optional[List[Mapping[str, Any]]] = None, + non_revoked: Optional[Mapping[str, int]] = None, +): + """Present an credential using present proof v2.""" + + is_verifier_anoncreds = (await verifier.get("/settings", response=Settings)).get( + "wallet.type" + ) == "askar-anoncreds" + + attrs = { + "name": name or "proof", + "version": version or "0.1.0", + "nonce": str(randbelow(10**10)), + "requested_attributes": { + str(uuid4()): attr for attr in requested_attributes or [] + }, + "requested_predicates": { + str(uuid4()): pred for pred in requested_predicates or [] + }, + "non_revoked": (non_revoked if non_revoked else None), + } + + if is_verifier_anoncreds: + presentation_request = { + "anoncreds": attrs, + } + else: + presentation_request = { + "indy": attrs, + } + verifier_pres_ex = await verifier.post( + "/present-proof-2.0/send-request", + json={ + "auto_verify": False, + "comment": comment or "Presentation request from minimal", + "connection_id": verifier_connection_id, + "presentation_request": presentation_request, + "trace": False, + }, + response=V20PresExRecord, + ) + verifier_pres_ex_id = verifier_pres_ex.pres_ex_id + + holder_pres_ex = await holder.event_with_values( + topic="present_proof_v2_0", + event_type=V20PresExRecord, + connection_id=holder_connection_id, + state="request-received", + ) + assert holder_pres_ex.pres_request + holder_pres_ex_id = holder_pres_ex.pres_ex_id + + relevant_creds = await holder.get( + f"/present-proof-2.0/records/{holder_pres_ex_id}/credentials", + response=List[CredPrecis], + ) + assert holder_pres_ex.by_format.pres_request + proof_request = holder_pres_ex.by_format.pres_request.get( + "anoncreds" + ) or holder_pres_ex.by_format.pres_request.get("indy") + pres_spec = auto_select_credentials_for_presentation_request( + proof_request, relevant_creds + ) + if is_verifier_anoncreds: + proof = {"anoncreds": pres_spec.serialize()} + else: + proof = {"indy": pres_spec.serialize()} + await holder.post( + f"/present-proof-2.0/records/{holder_pres_ex_id}/send-presentation", + json=proof, + response=V20PresExRecord, + ) + + await verifier.event_with_values( + topic="present_proof_v2_0", + event_type=V20PresExRecord, + pres_ex_id=verifier_pres_ex_id, + state="presentation-received", + ) + await verifier.post( + f"/present-proof-2.0/records/{verifier_pres_ex_id}/verify-presentation", + json={}, + response=V20PresExRecord, + ) + verifier_pres_ex = await verifier.event_with_values( + topic="present_proof_v2_0", + event_type=V20PresExRecord, + pres_ex_id=verifier_pres_ex_id, + state="done", + ) + + holder_pres_ex = await holder.event_with_values( + topic="present_proof_v2_0", + event_type=V20PresExRecord, + pres_ex_id=holder_pres_ex_id, + state="done", + ) + + return holder_pres_ex, verifier_pres_ex + + async def main(): """Test Controller protocols.""" - async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + issuer_name = "issuer" + token_hex(8) + async with Controller(base_url=AGENCY) as agency: + issuer = await agency.post( + "/multitenancy/wallet", + json={ + "label": issuer_name, + "wallet_name": issuer_name, + "wallet_type": "askar", + }, + response=CreateWalletResponse, + ) + + async with Controller( + base_url=AGENCY, + wallet_id=issuer.wallet_id, + subwallet_token=issuer.token, + ) as issuer, Controller(base_url=HOLDER_ANONCREDS) as holder_anoncreds, Controller( + base_url=HOLDER_INDY + ) as holder_indy: + """ + This section of the test script demonstrates the issuance, presentation and + revocation of a credential where both the issuer is not anoncreds capable + (wallet type askar) and the holder is anoncreds capable + (wallet type askar-anoncreds). + """ + # Connecting - alice_conn, bob_conn = await didexchange(alice, bob) + issuer_conn_with_anoncreds_holder, holder_anoncreds_conn = await didexchange( + issuer, holder_anoncreds + ) # Issuance prep - config = (await alice.get("/status/config"))["config"] + config = (await issuer.get("/status/config"))["config"] genesis_url = config.get("ledger.genesis_url") - public_did = (await alice.get("/wallet/did/public", response=DIDResult)).result + public_did = (await issuer.get("/wallet/did/public", response=DIDResult)).result if not public_did: public_did = ( - await alice.post( + await issuer.post( "/wallet/did/create", json={"method": "sov", "options": {"key_type": "ed25519"}}, response=DIDResult, @@ -87,21 +459,154 @@ async def main(): ) as resp: assert resp.ok - await alice.post("/wallet/did/public", params=params(did=public_did.did)) + await issuer.post("/wallet/did/public", params=params(did=public_did.did)) + + _, cred_def = await indy_anoncred_credential_artifacts( + issuer, + ["firstname", "lastname"], + support_revocation=True, + ) + + # Issue a credential + issuer_cred_ex, _ = await issue_credential_v2( + issuer, + holder_anoncreds, + issuer_conn_with_anoncreds_holder.connection_id, + holder_anoncreds_conn.connection_id, + cred_def.credential_definition_id, + {"firstname": "Anoncreds", "lastname": "Holder"}, + ) + + # Present the the credential's attributes + await present_proof_v2( + holder_anoncreds, + issuer, + holder_anoncreds_conn.connection_id, + issuer_conn_with_anoncreds_holder.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + + # Revoke credential + await issuer.post( + url="/revocation/revoke", + json={ + "connection_id": issuer_conn_with_anoncreds_holder.connection_id, + "rev_reg_id": issuer_cred_ex.details.rev_reg_id, + "cred_rev_id": issuer_cred_ex.details.cred_rev_id, + "publish": True, + "notify": True, + "notify_version": "v1_0", + }, + ) + + await holder_anoncreds.record(topic="revocation-notification") + + """ + This section of the test script demonstrates the issuance, presentation and + revocation of a credential where the issuer and holder are not anoncreds + capable. Both are askar wallet type. + """ + + # Connecting + issuer_conn_with_indy_holder, holder_indy_conn = await didexchange( + issuer, holder_indy + ) + + # Issue a credential + issuer_cred_ex, _ = await issue_credential_v2( + issuer, + holder_indy, + issuer_conn_with_indy_holder.connection_id, + holder_indy_conn.connection_id, + cred_def.credential_definition_id, + {"firstname": "Indy", "lastname": "Holder"}, + ) + + # Present the the credential's attributes + await present_proof_v2( + holder_indy, + issuer, + holder_indy_conn.connection_id, + issuer_conn_with_indy_holder.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + # Query presentations + presentations = await issuer.get( + "/present-proof-2.0/records", + response=V20PresExRecordList, + ) + + # Presentation summary + for _, pres in enumerate(presentations.results): + print(summary(pres)) + + # Revoke credential + await issuer.post( + url="/revocation/revoke", + json={ + "connection_id": issuer_conn_with_indy_holder.connection_id, + "rev_reg_id": issuer_cred_ex.details.rev_reg_id, + "cred_rev_id": issuer_cred_ex.details.cred_rev_id, + "publish": True, + "notify": True, + "notify_version": "v1_0", + }, + ) + + await holder_indy.record(topic="revocation-notification") - schema = await alice.post( + """ + Upgrade the issuer tenant to anoncreds capable wallet type. When upgrading a + tenant the agent doesn't require a restart. That is why the test is done + with multitenancy + """ + await issuer.post( + "/anoncreds/wallet/upgrade", + params={ + "wallet_name": issuer_name, + }, + ) + + # Wait for the upgrade to complete + await asyncio.sleep(2) + + """ + Do issuance and presentation again after the upgrade. This time the issuer is + an anoncreds capable wallet (wallet type askar-anoncreds). + """ + # Presentation for anoncreds capable holder on existing credential + await present_proof_v2( + holder_anoncreds, + issuer, + holder_anoncreds_conn.connection_id, + issuer_conn_with_anoncreds_holder.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + + # Presentation for indy capable holder on existing credential + await present_proof_v2( + holder_indy, + issuer, + holder_indy_conn.connection_id, + issuer_conn_with_indy_holder.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + + # Create a new schema and cred def with different attributes on new + # anoncreds endpoints + schema = await issuer.post( "/anoncreds/schema", json={ "schema": { "name": "anoncreds-test-" + token_hex(8), "version": "1.0", - "attrNames": ["firstname", "lastname"], + "attrNames": ["middlename"], "issuerId": public_did.did, } }, - response=SchemaResult, + response=SchemaResultAnoncreds, ) - cred_def = await alice.post( + cred_def = await issuer.post( "/anoncreds/credential-definition", json={ "credential_definition": { @@ -109,77 +614,73 @@ async def main(): "schemaId": schema.schema_state["schema_id"], "tag": token_hex(8), }, - "options": { - "revocation_registry_size": 2000, - "support_revocation": True, - }, + "options": {"support_revocation": True, "revocation_registry_size": 10}, }, - response=CredDefResult, + response=CredDefResultAnoncreds, ) - # Issue a credential - alice_cred_ex, _ = await indy_issue_credential_v2( - alice, - bob, - alice_conn.connection_id, - bob_conn.connection_id, + # Issue a new credential to anoncreds holder + issuer_cred_ex, _ = await issue_credential_v2( + issuer, + holder_anoncreds, + issuer_conn_with_anoncreds_holder.connection_id, + holder_anoncreds_conn.connection_id, cred_def.credential_definition_state["credential_definition_id"], - {"firstname": "Bob", "lastname": "Builder"}, + {"middlename": "Anoncreds"}, ) - - # 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"}], + # Presentation for anoncreds capable holder + await present_proof_v2( + holder_anoncreds, + issuer, + holder_anoncreds_conn.connection_id, + issuer_conn_with_anoncreds_holder.connection_id, + requested_attributes=[{"name": "middlename"}], ) - # Revoke credential - await alice.post( + await issuer.post( url="/anoncreds/revocation/revoke", json={ - "connection_id": alice_conn.connection_id, - "rev_reg_id": alice_cred_ex.indy.rev_reg_id, - "cred_rev_id": alice_cred_ex.indy.cred_rev_id, + "connection_id": issuer_conn_with_anoncreds_holder.connection_id, + "rev_reg_id": issuer_cred_ex.details.rev_reg_id, + "cred_rev_id": issuer_cred_ex.details.cred_rev_id, "publish": True, "notify": True, "notify_version": "v1_0", }, ) + await holder_anoncreds.record(topic="revocation-notification") - await bob.record(topic="revocation-notification") - - # 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_state[ - "credential_definition_id" - ] - } - ], - } - ], + # Issue a new credential to indy holder + issuer_cred_ex, _ = await issue_credential_v2( + issuer, + holder_indy, + issuer_conn_with_indy_holder.connection_id, + holder_indy_conn.connection_id, + cred_def.credential_definition_state["credential_definition_id"], + {"middlename": "Indy"}, ) - - # Query presentations - presentations = await alice.get( - "/present-proof-2.0/records", - response=V20PresExRecordList, + # Presentation for indy holder + await present_proof_v2( + holder_indy, + issuer, + holder_indy_conn.connection_id, + issuer_conn_with_indy_holder.connection_id, + requested_attributes=[{"name": "middlename"}], + ) + # Revoke credential + await issuer.post( + url="/anoncreds/revocation/revoke", + json={ + "connection_id": issuer_conn_with_indy_holder.connection_id, + "rev_reg_id": issuer_cred_ex.details.rev_reg_id, + "cred_rev_id": issuer_cred_ex.details.cred_rev_id, + "publish": True, + "notify": True, + "notify_version": "v1_0", + }, ) - # Presentation summary - for i, pres in enumerate(presentations.results): - print(summary(pres)) + await holder_indy.record(topic="revocation-notification") if __name__ == "__main__": diff --git a/scenarios/poetry.lock b/scenarios/poetry.lock index 512f6c51a0..87805a2cb5 100644 --- a/scenarios/poetry.lock +++ b/scenarios/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "acapy-controller" @@ -36,112 +36,112 @@ files = [ [[package]] name = "aiohttp" -version = "3.10.5" +version = "3.10.11" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:18a01eba2574fb9edd5f6e5fb25f66e6ce061da5dab5db75e13fe1558142e0a3"}, - {file = "aiohttp-3.10.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:94fac7c6e77ccb1ca91e9eb4cb0ac0270b9fb9b289738654120ba8cebb1189c6"}, - {file = "aiohttp-3.10.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2f1f1c75c395991ce9c94d3e4aa96e5c59c8356a15b1c9231e783865e2772699"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f7acae3cf1a2a2361ec4c8e787eaaa86a94171d2417aae53c0cca6ca3118ff6"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:94c4381ffba9cc508b37d2e536b418d5ea9cfdc2848b9a7fea6aebad4ec6aac1"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c31ad0c0c507894e3eaa843415841995bf8de4d6b2d24c6e33099f4bc9fc0d4f"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0912b8a8fadeb32ff67a3ed44249448c20148397c1ed905d5dac185b4ca547bb"}, - {file = "aiohttp-3.10.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0d93400c18596b7dc4794d48a63fb361b01a0d8eb39f28800dc900c8fbdaca91"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d00f3c5e0d764a5c9aa5a62d99728c56d455310bcc288a79cab10157b3af426f"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d742c36ed44f2798c8d3f4bc511f479b9ceef2b93f348671184139e7d708042c"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:814375093edae5f1cb31e3407997cf3eacefb9010f96df10d64829362ae2df69"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:8224f98be68a84b19f48e0bdc14224b5a71339aff3a27df69989fa47d01296f3"}, - {file = "aiohttp-3.10.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d9a487ef090aea982d748b1b0d74fe7c3950b109df967630a20584f9a99c0683"}, - {file = "aiohttp-3.10.5-cp310-cp310-win32.whl", hash = "sha256:d9ef084e3dc690ad50137cc05831c52b6ca428096e6deb3c43e95827f531d5ef"}, - {file = "aiohttp-3.10.5-cp310-cp310-win_amd64.whl", hash = "sha256:66bf9234e08fe561dccd62083bf67400bdbf1c67ba9efdc3dac03650e97c6088"}, - {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8c6a4e5e40156d72a40241a25cc226051c0a8d816610097a8e8f517aeacd59a2"}, - {file = "aiohttp-3.10.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c634a3207a5445be65536d38c13791904fda0748b9eabf908d3fe86a52941cf"}, - {file = "aiohttp-3.10.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4aff049b5e629ef9b3e9e617fa6e2dfeda1bf87e01bcfecaf3949af9e210105e"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1942244f00baaacaa8155eca94dbd9e8cc7017deb69b75ef67c78e89fdad3c77"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e04a1f2a65ad2f93aa20f9ff9f1b672bf912413e5547f60749fa2ef8a644e061"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7f2bfc0032a00405d4af2ba27f3c429e851d04fad1e5ceee4080a1c570476697"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:424ae21498790e12eb759040bbb504e5e280cab64693d14775c54269fd1d2bb7"}, - {file = "aiohttp-3.10.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:975218eee0e6d24eb336d0328c768ebc5d617609affaca5dbbd6dd1984f16ed0"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4120d7fefa1e2d8fb6f650b11489710091788de554e2b6f8347c7a20ceb003f5"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b90078989ef3fc45cf9221d3859acd1108af7560c52397ff4ace8ad7052a132e"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ba5a8b74c2a8af7d862399cdedce1533642fa727def0b8c3e3e02fcb52dca1b1"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:02594361128f780eecc2a29939d9dfc870e17b45178a867bf61a11b2a4367277"}, - {file = "aiohttp-3.10.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8fb4fc029e135859f533025bc82047334e24b0d489e75513144f25408ecaf058"}, - {file = "aiohttp-3.10.5-cp311-cp311-win32.whl", hash = "sha256:e1ca1ef5ba129718a8fc827b0867f6aa4e893c56eb00003b7367f8a733a9b072"}, - {file = "aiohttp-3.10.5-cp311-cp311-win_amd64.whl", hash = "sha256:349ef8a73a7c5665cca65c88ab24abe75447e28aa3bc4c93ea5093474dfdf0ff"}, - {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:305be5ff2081fa1d283a76113b8df7a14c10d75602a38d9f012935df20731487"}, - {file = "aiohttp-3.10.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3a1c32a19ee6bbde02f1cb189e13a71b321256cc1d431196a9f824050b160d5a"}, - {file = "aiohttp-3.10.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:61645818edd40cc6f455b851277a21bf420ce347baa0b86eaa41d51ef58ba23d"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c225286f2b13bab5987425558baa5cbdb2bc925b2998038fa028245ef421e75"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8ba01ebc6175e1e6b7275c907a3a36be48a2d487549b656aa90c8a910d9f3178"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8eaf44ccbc4e35762683078b72bf293f476561d8b68ec8a64f98cf32811c323e"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1c43eb1ab7cbf411b8e387dc169acb31f0ca0d8c09ba63f9eac67829585b44f"}, - {file = "aiohttp-3.10.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:de7a5299827253023c55ea549444e058c0eb496931fa05d693b95140a947cb73"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4790f0e15f00058f7599dab2b206d3049d7ac464dc2e5eae0e93fa18aee9e7bf"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44b324a6b8376a23e6ba25d368726ee3bc281e6ab306db80b5819999c737d820"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0d277cfb304118079e7044aad0b76685d30ecb86f83a0711fc5fb257ffe832ca"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:54d9ddea424cd19d3ff6128601a4a4d23d54a421f9b4c0fff740505813739a91"}, - {file = "aiohttp-3.10.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4f1c9866ccf48a6df2b06823e6ae80573529f2af3a0992ec4fe75b1a510df8a6"}, - {file = "aiohttp-3.10.5-cp312-cp312-win32.whl", hash = "sha256:dc4826823121783dccc0871e3f405417ac116055bf184ac04c36f98b75aacd12"}, - {file = "aiohttp-3.10.5-cp312-cp312-win_amd64.whl", hash = "sha256:22c0a23a3b3138a6bf76fc553789cb1a703836da86b0f306b6f0dc1617398abc"}, - {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:7f6b639c36734eaa80a6c152a238242bedcee9b953f23bb887e9102976343092"}, - {file = "aiohttp-3.10.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f29930bc2921cef955ba39a3ff87d2c4398a0394ae217f41cb02d5c26c8b1b77"}, - {file = "aiohttp-3.10.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f489a2c9e6455d87eabf907ac0b7d230a9786be43fbe884ad184ddf9e9c1e385"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:123dd5b16b75b2962d0fff566effb7a065e33cd4538c1692fb31c3bda2bfb972"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b98e698dc34966e5976e10bbca6d26d6724e6bdea853c7c10162a3235aba6e16"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3b9162bab7e42f21243effc822652dc5bb5e8ff42a4eb62fe7782bcbcdfacf6"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1923a5c44061bffd5eebeef58cecf68096e35003907d8201a4d0d6f6e387ccaa"}, - {file = "aiohttp-3.10.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d55f011da0a843c3d3df2c2cf4e537b8070a419f891c930245f05d329c4b0689"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:afe16a84498441d05e9189a15900640a2d2b5e76cf4efe8cbb088ab4f112ee57"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:f8112fb501b1e0567a1251a2fd0747baae60a4ab325a871e975b7bb67e59221f"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:1e72589da4c90337837fdfe2026ae1952c0f4a6e793adbbfbdd40efed7c63599"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4d46c7b4173415d8e583045fbc4daa48b40e31b19ce595b8d92cf639396c15d5"}, - {file = "aiohttp-3.10.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:33e6bc4bab477c772a541f76cd91e11ccb6d2efa2b8d7d7883591dfb523e5987"}, - {file = "aiohttp-3.10.5-cp313-cp313-win32.whl", hash = "sha256:c58c6837a2c2a7cf3133983e64173aec11f9c2cd8e87ec2fdc16ce727bcf1a04"}, - {file = "aiohttp-3.10.5-cp313-cp313-win_amd64.whl", hash = "sha256:38172a70005252b6893088c0f5e8a47d173df7cc2b2bd88650957eb84fcf5022"}, - {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:f6f18898ace4bcd2d41a122916475344a87f1dfdec626ecde9ee802a711bc569"}, - {file = "aiohttp-3.10.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5ede29d91a40ba22ac1b922ef510aab871652f6c88ef60b9dcdf773c6d32ad7a"}, - {file = "aiohttp-3.10.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:673f988370f5954df96cc31fd99c7312a3af0a97f09e407399f61583f30da9bc"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58718e181c56a3c02d25b09d4115eb02aafe1a732ce5714ab70326d9776457c3"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4b38b1570242fbab8d86a84128fb5b5234a2f70c2e32f3070143a6d94bc854cf"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:074d1bff0163e107e97bd48cad9f928fa5a3eb4b9d33366137ffce08a63e37fe"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd31f176429cecbc1ba499d4aba31aaccfea488f418d60376b911269d3b883c5"}, - {file = "aiohttp-3.10.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7384d0b87d4635ec38db9263e6a3f1eb609e2e06087f0aa7f63b76833737b471"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8989f46f3d7ef79585e98fa991e6ded55d2f48ae56d2c9fa5e491a6e4effb589"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:c83f7a107abb89a227d6c454c613e7606c12a42b9a4ca9c5d7dad25d47c776ae"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:cde98f323d6bf161041e7627a5fd763f9fd829bcfcd089804a5fdce7bb6e1b7d"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:676f94c5480d8eefd97c0c7e3953315e4d8c2b71f3b49539beb2aa676c58272f"}, - {file = "aiohttp-3.10.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:2d21ac12dc943c68135ff858c3a989f2194a709e6e10b4c8977d7fcd67dfd511"}, - {file = "aiohttp-3.10.5-cp38-cp38-win32.whl", hash = "sha256:17e997105bd1a260850272bfb50e2a328e029c941c2708170d9d978d5a30ad9a"}, - {file = "aiohttp-3.10.5-cp38-cp38-win_amd64.whl", hash = "sha256:1c19de68896747a2aa6257ae4cf6ef59d73917a36a35ee9d0a6f48cff0f94db8"}, - {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7e2fe37ac654032db1f3499fe56e77190282534810e2a8e833141a021faaab0e"}, - {file = "aiohttp-3.10.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5bf3ead3cb66ab990ee2561373b009db5bc0e857549b6c9ba84b20bc462e172"}, - {file = "aiohttp-3.10.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1b2c16a919d936ca87a3c5f0e43af12a89a3ce7ccbce59a2d6784caba945b68b"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad146dae5977c4dd435eb31373b3fe9b0b1bf26858c6fc452bf6af394067e10b"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c5c6fa16412b35999320f5c9690c0f554392dc222c04e559217e0f9ae244b92"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:95c4dc6f61d610bc0ee1edc6f29d993f10febfe5b76bb470b486d90bbece6b22"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da452c2c322e9ce0cfef392e469a26d63d42860f829026a63374fde6b5c5876f"}, - {file = "aiohttp-3.10.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:898715cf566ec2869d5cb4d5fb4be408964704c46c96b4be267442d265390f32"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:391cc3a9c1527e424c6865e087897e766a917f15dddb360174a70467572ac6ce"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:380f926b51b92d02a34119d072f178d80bbda334d1a7e10fa22d467a66e494db"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ce91db90dbf37bb6fa0997f26574107e1b9d5ff939315247b7e615baa8ec313b"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9093a81e18c45227eebe4c16124ebf3e0d893830c6aca7cc310bfca8fe59d857"}, - {file = "aiohttp-3.10.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ee40b40aa753d844162dcc80d0fe256b87cba48ca0054f64e68000453caead11"}, - {file = "aiohttp-3.10.5-cp39-cp39-win32.whl", hash = "sha256:03f2645adbe17f274444953bdea69f8327e9d278d961d85657cb0d06864814c1"}, - {file = "aiohttp-3.10.5-cp39-cp39-win_amd64.whl", hash = "sha256:d17920f18e6ee090bdd3d0bfffd769d9f2cb4c8ffde3eb203777a3895c128862"}, - {file = "aiohttp-3.10.5.tar.gz", hash = "sha256:f071854b47d39591ce9a17981c46790acb30518e2f83dfca8db2dfa091178691"}, + {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5077b1a5f40ffa3ba1f40d537d3bec4383988ee51fbba6b74aa8fb1bc466599e"}, + {file = "aiohttp-3.10.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d6a14a4d93b5b3c2891fca94fa9d41b2322a68194422bef0dd5ec1e57d7d298"}, + {file = "aiohttp-3.10.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ffbfde2443696345e23a3c597049b1dd43049bb65337837574205e7368472177"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b3d9e416774d41813bc02fdc0663379c01817b0874b932b81c7f777f67b217"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b943011b45ee6bf74b22245c6faab736363678e910504dd7531a58c76c9015a"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48bc1d924490f0d0b3658fe5c4b081a4d56ebb58af80a6729d4bd13ea569797a"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e12eb3f4b1f72aaaf6acd27d045753b18101524f72ae071ae1c91c1cd44ef115"}, + {file = "aiohttp-3.10.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f14ebc419a568c2eff3c1ed35f634435c24ead2fe19c07426af41e7adb68713a"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:72b191cdf35a518bfc7ca87d770d30941decc5aaf897ec8b484eb5cc8c7706f3"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ab2328a61fdc86424ee540d0aeb8b73bbcad7351fb7cf7a6546fc0bcffa0038"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:aa93063d4af05c49276cf14e419550a3f45258b6b9d1f16403e777f1addf4519"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:30283f9d0ce420363c24c5c2421e71a738a2155f10adbb1a11a4d4d6d2715cfc"}, + {file = "aiohttp-3.10.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e5358addc8044ee49143c546d2182c15b4ac3a60be01c3209374ace05af5733d"}, + {file = "aiohttp-3.10.11-cp310-cp310-win32.whl", hash = "sha256:e1ffa713d3ea7cdcd4aea9cddccab41edf6882fa9552940344c44e59652e1120"}, + {file = "aiohttp-3.10.11-cp310-cp310-win_amd64.whl", hash = "sha256:778cbd01f18ff78b5dd23c77eb82987ee4ba23408cbed233009fd570dda7e674"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:80ff08556c7f59a7972b1e8919f62e9c069c33566a6d28586771711e0eea4f07"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2c8f96e9ee19f04c4914e4e7a42a60861066d3e1abf05c726f38d9d0a466e695"}, + {file = "aiohttp-3.10.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fb8601394d537da9221947b5d6e62b064c9a43e88a1ecd7414d21a1a6fba9c24"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ea224cf7bc2d8856d6971cea73b1d50c9c51d36971faf1abc169a0d5f85a382"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db9503f79e12d5d80b3efd4d01312853565c05367493379df76d2674af881caa"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0f449a50cc33f0384f633894d8d3cd020e3ccef81879c6e6245c3c375c448625"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82052be3e6d9e0c123499127782a01a2b224b8af8c62ab46b3f6197035ad94e9"}, + {file = "aiohttp-3.10.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:20063c7acf1eec550c8eb098deb5ed9e1bb0521613b03bb93644b810986027ac"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:489cced07a4c11488f47aab1f00d0c572506883f877af100a38f1fedaa884c3a"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ea9b3bab329aeaa603ed3bf605f1e2a6f36496ad7e0e1aa42025f368ee2dc07b"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ca117819d8ad113413016cb29774b3f6d99ad23c220069789fc050267b786c16"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:2dfb612dcbe70fb7cdcf3499e8d483079b89749c857a8f6e80263b021745c730"}, + {file = "aiohttp-3.10.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f9b615d3da0d60e7d53c62e22b4fd1c70f4ae5993a44687b011ea3a2e49051b8"}, + {file = "aiohttp-3.10.11-cp311-cp311-win32.whl", hash = "sha256:29103f9099b6068bbdf44d6a3d090e0a0b2be6d3c9f16a070dd9d0d910ec08f9"}, + {file = "aiohttp-3.10.11-cp311-cp311-win_amd64.whl", hash = "sha256:236b28ceb79532da85d59aa9b9bf873b364e27a0acb2ceaba475dc61cffb6f3f"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:7480519f70e32bfb101d71fb9a1f330fbd291655a4c1c922232a48c458c52710"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f65267266c9aeb2287a6622ee2bb39490292552f9fbf851baabc04c9f84e048d"}, + {file = "aiohttp-3.10.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7400a93d629a0608dc1d6c55f1e3d6e07f7375745aaa8bd7f085571e4d1cee97"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f34b97e4b11b8d4eb2c3a4f975be626cc8af99ff479da7de49ac2c6d02d35725"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e7b825da878464a252ccff2958838f9caa82f32a8dbc334eb9b34a026e2c636"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9f92a344c50b9667827da308473005f34767b6a2a60d9acff56ae94f895f385"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f1ab987a27b83c5268a17218463c2ec08dbb754195113867a27b166cd6087"}, + {file = "aiohttp-3.10.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1dc0f4ca54842173d03322793ebcf2c8cc2d34ae91cc762478e295d8e361e03f"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7ce6a51469bfaacff146e59e7fb61c9c23006495d11cc24c514a455032bcfa03"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:aad3cd91d484d065ede16f3cf15408254e2469e3f613b241a1db552c5eb7ab7d"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f4df4b8ca97f658c880fb4b90b1d1ec528315d4030af1ec763247ebfd33d8b9a"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2e4e18a0a2d03531edbc06c366954e40a3f8d2a88d2b936bbe78a0c75a3aab3e"}, + {file = "aiohttp-3.10.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6ce66780fa1a20e45bc753cda2a149daa6dbf1561fc1289fa0c308391c7bc0a4"}, + {file = "aiohttp-3.10.11-cp312-cp312-win32.whl", hash = "sha256:a919c8957695ea4c0e7a3e8d16494e3477b86f33067478f43106921c2fef15bb"}, + {file = "aiohttp-3.10.11-cp312-cp312-win_amd64.whl", hash = "sha256:b5e29706e6389a2283a91611c91bf24f218962717c8f3b4e528ef529d112ee27"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:703938e22434d7d14ec22f9f310559331f455018389222eed132808cd8f44127"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9bc50b63648840854e00084c2b43035a62e033cb9b06d8c22b409d56eb098413"}, + {file = "aiohttp-3.10.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5f0463bf8b0754bc744e1feb61590706823795041e63edf30118a6f0bf577461"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6c6dec398ac5a87cb3a407b068e1106b20ef001c344e34154616183fe684288"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bcaf2d79104d53d4dcf934f7ce76d3d155302d07dae24dff6c9fffd217568067"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:25fd5470922091b5a9aeeb7e75be609e16b4fba81cdeaf12981393fb240dd10e"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbde2ca67230923a42161b1f408c3992ae6e0be782dca0c44cb3206bf330dee1"}, + {file = "aiohttp-3.10.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:249c8ff8d26a8b41a0f12f9df804e7c685ca35a207e2410adbd3e924217b9006"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878ca6a931ee8c486a8f7b432b65431d095c522cbeb34892bee5be97b3481d0f"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8663f7777ce775f0413324be0d96d9730959b2ca73d9b7e2c2c90539139cbdd6"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:6cd3f10b01f0c31481fba8d302b61603a2acb37b9d30e1d14e0f5a58b7b18a31"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:4e8d8aad9402d3aa02fdc5ca2fe68bcb9fdfe1f77b40b10410a94c7f408b664d"}, + {file = "aiohttp-3.10.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:38e3c4f80196b4f6c3a85d134a534a56f52da9cb8d8e7af1b79a32eefee73a00"}, + {file = "aiohttp-3.10.11-cp313-cp313-win32.whl", hash = "sha256:fc31820cfc3b2863c6e95e14fcf815dc7afe52480b4dc03393c4873bb5599f71"}, + {file = "aiohttp-3.10.11-cp313-cp313-win_amd64.whl", hash = "sha256:4996ff1345704ffdd6d75fb06ed175938c133425af616142e7187f28dc75f14e"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:74baf1a7d948b3d640badeac333af581a367ab916b37e44cf90a0334157cdfd2"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:473aebc3b871646e1940c05268d451f2543a1d209f47035b594b9d4e91ce8339"}, + {file = "aiohttp-3.10.11-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c2f746a6968c54ab2186574e15c3f14f3e7f67aef12b761e043b33b89c5b5f95"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d110cabad8360ffa0dec8f6ec60e43286e9d251e77db4763a87dcfe55b4adb92"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e0099c7d5d7afff4202a0c670e5b723f7718810000b4abcbc96b064129e64bc7"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0316e624b754dbbf8c872b62fe6dcb395ef20c70e59890dfa0de9eafccd2849d"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a5f7ab8baf13314e6b2485965cbacb94afff1e93466ac4d06a47a81c50f9cca"}, + {file = "aiohttp-3.10.11-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c891011e76041e6508cbfc469dd1a8ea09bc24e87e4c204e05f150c4c455a5fa"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9208299251370ee815473270c52cd3f7069ee9ed348d941d574d1457d2c73e8b"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:459f0f32c8356e8125f45eeff0ecf2b1cb6db1551304972702f34cd9e6c44658"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:14cdc8c1810bbd4b4b9f142eeee23cda528ae4e57ea0923551a9af4820980e39"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:971aa438a29701d4b34e4943e91b5e984c3ae6ccbf80dd9efaffb01bd0b243a9"}, + {file = "aiohttp-3.10.11-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9a309c5de392dfe0f32ee57fa43ed8fc6ddf9985425e84bd51ed66bb16bce3a7"}, + {file = "aiohttp-3.10.11-cp38-cp38-win32.whl", hash = "sha256:9ec1628180241d906a0840b38f162a3215114b14541f1a8711c368a8739a9be4"}, + {file = "aiohttp-3.10.11-cp38-cp38-win_amd64.whl", hash = "sha256:9c6e0ffd52c929f985c7258f83185d17c76d4275ad22e90aa29f38e211aacbec"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cdc493a2e5d8dc79b2df5bec9558425bcd39aff59fc949810cbd0832e294b106"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b3e70f24e7d0405be2348da9d5a7836936bf3a9b4fd210f8c37e8d48bc32eca6"}, + {file = "aiohttp-3.10.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968b8fb2a5eee2770eda9c7b5581587ef9b96fbdf8dcabc6b446d35ccc69df01"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:deef4362af9493d1382ef86732ee2e4cbc0d7c005947bd54ad1a9a16dd59298e"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:686b03196976e327412a1b094f4120778c7c4b9cff9bce8d2fdfeca386b89829"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3bf6d027d9d1d34e1c2e1645f18a6498c98d634f8e373395221121f1c258ace8"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:099fd126bf960f96d34a760e747a629c27fb3634da5d05c7ef4d35ef4ea519fc"}, + {file = "aiohttp-3.10.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c73c4d3dae0b4644bc21e3de546530531d6cdc88659cdeb6579cd627d3c206aa"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:0c5580f3c51eea91559db3facd45d72e7ec970b04528b4709b1f9c2555bd6d0b"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fdf6429f0caabfd8a30c4e2eaecb547b3c340e4730ebfe25139779b9815ba138"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d97187de3c276263db3564bb9d9fad9e15b51ea10a371ffa5947a5ba93ad6777"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0acafb350cfb2eba70eb5d271f55e08bd4502ec35e964e18ad3e7d34d71f7261"}, + {file = "aiohttp-3.10.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c13ed0c779911c7998a58e7848954bd4d63df3e3575f591e321b19a2aec8df9f"}, + {file = "aiohttp-3.10.11-cp39-cp39-win32.whl", hash = "sha256:22b7c540c55909140f63ab4f54ec2c20d2635c0289cdd8006da46f3327f971b9"}, + {file = "aiohttp-3.10.11-cp39-cp39-win_amd64.whl", hash = "sha256:7b26b1551e481012575dab8e3727b16fe7dd27eb2711d2e63ced7368756268fb"}, + {file = "aiohttp-3.10.11.tar.gz", hash = "sha256:9dc2b8f3dcab2e39e0fa309c8da50c3b55e6f34ab25f1a71d3288f24924d33a7"}, ] [package.dependencies] aiohappyeyeballs = ">=2.3.0" aiosignal = ">=1.1.2" -async-timeout = {version = ">=4.0,<5.0", markers = "python_version < \"3.11\""} +async-timeout = {version = ">=4.0,<6.0", markers = "python_version < \"3.11\""} attrs = ">=17.3.0" frozenlist = ">=1.1.1" multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" +yarl = ">=1.12.0,<2.0" [package.extras] speedups = ["Brotli", "aiodns (>=3.2.0)", "brotlicffi"] @@ -485,6 +485,113 @@ files = [ dev = ["pre-commit", "tox"] testing = ["pytest", "pytest-benchmark"] +[[package]] +name = "propcache" +version = "0.2.0" +description = "Accelerated property cache" +optional = false +python-versions = ">=3.8" +files = [ + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:c5869b8fd70b81835a6f187c5fdbe67917a04d7e52b6e7cc4e5fe39d55c39d58"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:952e0d9d07609d9c5be361f33b0d6d650cd2bae393aabb11d9b719364521984b"}, + {file = "propcache-0.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:33ac8f098df0585c0b53009f039dfd913b38c1d2edafed0cedcc0c32a05aa110"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:97e48e8875e6c13909c800fa344cd54cc4b2b0db1d5f911f840458a500fde2c2"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388f3217649d6d59292b722d940d4d2e1e6a7003259eb835724092a1cca0203a"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f571aea50ba5623c308aa146eb650eebf7dbe0fd8c5d946e28343cb3b5aad577"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3dfafb44f7bb35c0c06eda6b2ab4bfd58f02729e7c4045e179f9a861b07c9850"}, + {file = "propcache-0.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3ebe9a75be7ab0b7da2464a77bb27febcb4fab46a34f9288f39d74833db7f61"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d2f0d0f976985f85dfb5f3d685697ef769faa6b71993b46b295cdbbd6be8cc37"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a3dc1a4b165283bd865e8f8cb5f0c64c05001e0718ed06250d8cac9bec115b48"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9e0f07b42d2a50c7dd2d8675d50f7343d998c64008f1da5fef888396b7f84630"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:e63e3e1e0271f374ed489ff5ee73d4b6e7c60710e1f76af5f0e1a6117cd26394"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:56bb5c98f058a41bb58eead194b4db8c05b088c93d94d5161728515bd52b052b"}, + {file = "propcache-0.2.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7665f04d0c7f26ff8bb534e1c65068409bf4687aa2534faf7104d7182debb336"}, + {file = "propcache-0.2.0-cp310-cp310-win32.whl", hash = "sha256:7cf18abf9764746b9c8704774d8b06714bcb0a63641518a3a89c7f85cc02c2ad"}, + {file = "propcache-0.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:cfac69017ef97db2438efb854edf24f5a29fd09a536ff3a992b75990720cdc99"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:63f13bf09cc3336eb04a837490b8f332e0db41da66995c9fd1ba04552e516354"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:608cce1da6f2672a56b24a015b42db4ac612ee709f3d29f27a00c943d9e851de"}, + {file = "propcache-0.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:466c219deee4536fbc83c08d09115249db301550625c7fef1c5563a584c9bc87"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2db02409338bf36590aa985a461b2c96fce91f8e7e0f14c50c5fcc4f229016"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6ed8db0a556343d566a5c124ee483ae113acc9a557a807d439bcecc44e7dfbb"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:91997d9cb4a325b60d4e3f20967f8eb08dfcb32b22554d5ef78e6fd1dda743a2"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c7dde9e533c0a49d802b4f3f218fa9ad0a1ce21f2c2eb80d5216565202acab4"}, + {file = "propcache-0.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcad6c564fe6b9b8916c1aefbb37a362deebf9394bd2974e9d84232e3e08504"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:97a58a28bcf63284e8b4d7b460cbee1edaab24634e82059c7b8c09e65284f178"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:945db8ee295d3af9dbdbb698cce9bbc5c59b5c3fe328bbc4387f59a8a35f998d"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:39e104da444a34830751715f45ef9fc537475ba21b7f1f5b0f4d71a3b60d7fe2"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c5ecca8f9bab618340c8e848d340baf68bcd8ad90a8ecd7a4524a81c1764b3db"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:c436130cc779806bdf5d5fae0d848713105472b8566b75ff70048c47d3961c5b"}, + {file = "propcache-0.2.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:191db28dc6dcd29d1a3e063c3be0b40688ed76434622c53a284e5427565bbd9b"}, + {file = "propcache-0.2.0-cp311-cp311-win32.whl", hash = "sha256:5f2564ec89058ee7c7989a7b719115bdfe2a2fb8e7a4543b8d1c0cc4cf6478c1"}, + {file = "propcache-0.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:6e2e54267980349b723cff366d1e29b138b9a60fa376664a157a342689553f71"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2ee7606193fb267be4b2e3b32714f2d58cad27217638db98a60f9efb5efeccc2"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:91ee8fc02ca52e24bcb77b234f22afc03288e1dafbb1f88fe24db308910c4ac7"}, + {file = "propcache-0.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e900bad2a8456d00a113cad8c13343f3b1f327534e3589acc2219729237a2e8"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f52a68c21363c45297aca15561812d542f8fc683c85201df0bebe209e349f793"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1e41d67757ff4fbc8ef2af99b338bfb955010444b92929e9e55a6d4dcc3c4f09"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a64e32f8bd94c105cc27f42d3b658902b5bcc947ece3c8fe7bc1b05982f60e89"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:55346705687dbd7ef0d77883ab4f6fabc48232f587925bdaf95219bae072491e"}, + {file = "propcache-0.2.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00181262b17e517df2cd85656fcd6b4e70946fe62cd625b9d74ac9977b64d8d9"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6994984550eaf25dd7fc7bd1b700ff45c894149341725bb4edc67f0ffa94efa4"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:56295eb1e5f3aecd516d91b00cfd8bf3a13991de5a479df9e27dd569ea23959c"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:439e76255daa0f8151d3cb325f6dd4a3e93043e6403e6491813bcaaaa8733887"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f6475a1b2ecb310c98c28d271a30df74f9dd436ee46d09236a6b750a7599ce57"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:3444cdba6628accf384e349014084b1cacd866fbb88433cd9d279d90a54e0b23"}, + {file = "propcache-0.2.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4a9d9b4d0a9b38d1c391bb4ad24aa65f306c6f01b512e10a8a34a2dc5675d348"}, + {file = "propcache-0.2.0-cp312-cp312-win32.whl", hash = "sha256:69d3a98eebae99a420d4b28756c8ce6ea5a29291baf2dc9ff9414b42676f61d5"}, + {file = "propcache-0.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ad9c9b99b05f163109466638bd30ada1722abb01bbb85c739c50b6dc11f92dc3"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ecddc221a077a8132cf7c747d5352a15ed763b674c0448d811f408bf803d9ad7"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0e53cb83fdd61cbd67202735e6a6687a7b491c8742dfc39c9e01e80354956763"}, + {file = "propcache-0.2.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92fe151145a990c22cbccf9ae15cae8ae9eddabfc949a219c9f667877e40853d"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a21ef516d36909931a2967621eecb256018aeb11fc48656e3257e73e2e247a"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f88a4095e913f98988f5b338c1d4d5d07dbb0b6bad19892fd447484e483ba6b"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5a5b3bb545ead161be780ee85a2b54fdf7092815995661947812dde94a40f6fb"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67aeb72e0f482709991aa91345a831d0b707d16b0257e8ef88a2ad246a7280bf"}, + {file = "propcache-0.2.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c997f8c44ec9b9b0bcbf2d422cc00a1d9b9c681f56efa6ca149a941e5560da2"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2a66df3d4992bc1d725b9aa803e8c5a66c010c65c741ad901e260ece77f58d2f"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:3ebbcf2a07621f29638799828b8d8668c421bfb94c6cb04269130d8de4fb7136"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1235c01ddaa80da8235741e80815ce381c5267f96cc49b1477fdcf8c047ef325"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:3947483a381259c06921612550867b37d22e1df6d6d7e8361264b6d037595f44"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d5bed7f9805cc29c780f3aee05de3262ee7ce1f47083cfe9f77471e9d6777e83"}, + {file = "propcache-0.2.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4a91d44379f45f5e540971d41e4626dacd7f01004826a18cb048e7da7e96544"}, + {file = "propcache-0.2.0-cp313-cp313-win32.whl", hash = "sha256:f902804113e032e2cdf8c71015651c97af6418363bea8d78dc0911d56c335032"}, + {file = "propcache-0.2.0-cp313-cp313-win_amd64.whl", hash = "sha256:8f188cfcc64fb1266f4684206c9de0e80f54622c3f22a910cbd200478aeae61e"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:53d1bd3f979ed529f0805dd35ddaca330f80a9a6d90bc0121d2ff398f8ed8861"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:83928404adf8fb3d26793665633ea79b7361efa0287dfbd372a7e74311d51ee6"}, + {file = "propcache-0.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:77a86c261679ea5f3896ec060be9dc8e365788248cc1e049632a1be682442063"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:218db2a3c297a3768c11a34812e63b3ac1c3234c3a086def9c0fee50d35add1f"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7735e82e3498c27bcb2d17cb65d62c14f1100b71723b68362872bca7d0913d90"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:20a617c776f520c3875cf4511e0d1db847a076d720714ae35ffe0df3e440be68"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67b69535c870670c9f9b14a75d28baa32221d06f6b6fa6f77a0a13c5a7b0a5b9"}, + {file = "propcache-0.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4569158070180c3855e9c0791c56be3ceeb192defa2cdf6a3f39e54319e56b89"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:db47514ffdbd91ccdc7e6f8407aac4ee94cc871b15b577c1c324236b013ddd04"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_armv7l.whl", hash = "sha256:2a60ad3e2553a74168d275a0ef35e8c0a965448ffbc3b300ab3a5bb9956c2162"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:662dd62358bdeaca0aee5761de8727cfd6861432e3bb828dc2a693aa0471a563"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:25a1f88b471b3bc911d18b935ecb7115dff3a192b6fef46f0bfaf71ff4f12418"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:f60f0ac7005b9f5a6091009b09a419ace1610e163fa5deaba5ce3484341840e7"}, + {file = "propcache-0.2.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:74acd6e291f885678631b7ebc85d2d4aec458dd849b8c841b57ef04047833bed"}, + {file = "propcache-0.2.0-cp38-cp38-win32.whl", hash = "sha256:d9b6ddac6408194e934002a69bcaadbc88c10b5f38fb9307779d1c629181815d"}, + {file = "propcache-0.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:676135dcf3262c9c5081cc8f19ad55c8a64e3f7282a21266d05544450bffc3a5"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:25c8d773a62ce0451b020c7b29a35cfbc05de8b291163a7a0f3b7904f27253e6"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:375a12d7556d462dc64d70475a9ee5982465fbb3d2b364f16b86ba9135793638"}, + {file = "propcache-0.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1ec43d76b9677637a89d6ab86e1fef70d739217fefa208c65352ecf0282be957"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f45eec587dafd4b2d41ac189c2156461ebd0c1082d2fe7013571598abb8505d1"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc092ba439d91df90aea38168e11f75c655880c12782facf5cf9c00f3d42b562"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fa1076244f54bb76e65e22cb6910365779d5c3d71d1f18b275f1dfc7b0d71b4d"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:682a7c79a2fbf40f5dbb1eb6bfe2cd865376deeac65acf9beb607505dced9e12"}, + {file = "propcache-0.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e40876731f99b6f3c897b66b803c9e1c07a989b366c6b5b475fafd1f7ba3fb8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:363ea8cd3c5cb6679f1c2f5f1f9669587361c062e4899fce56758efa928728f8"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:140fbf08ab3588b3468932974a9331aff43c0ab8a2ec2c608b6d7d1756dbb6cb"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e70fac33e8b4ac63dfc4c956fd7d85a0b1139adcfc0d964ce288b7c527537fea"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:b33d7a286c0dc1a15f5fc864cc48ae92a846df287ceac2dd499926c3801054a6"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f6d5749fdd33d90e34c2efb174c7e236829147a2713334d708746e94c4bde40d"}, + {file = "propcache-0.2.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:22aa8f2272d81d9317ff5756bb108021a056805ce63dd3630e27d042c8092798"}, + {file = "propcache-0.2.0-cp39-cp39-win32.whl", hash = "sha256:73e4b40ea0eda421b115248d7e79b59214411109a5bc47d0d48e4c73e3b8fcf9"}, + {file = "propcache-0.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:9517d5e9e0731957468c29dbfd0f976736a0e55afaea843726e887f36fe017df"}, + {file = "propcache-0.2.0-py3-none-any.whl", hash = "sha256:2ccc28197af5313706511fab3a8b66dcd6da067a1331372c82ea1cb74285e036"}, + {file = "propcache-0.2.0.tar.gz", hash = "sha256:df81779732feb9d01e5d513fad0122efb3d53bbc75f61b2a4f29a020bc985e70"}, +] + [[package]] name = "pydantic" version = "2.8.2" @@ -683,106 +790,99 @@ files = [ [[package]] name = "yarl" -version = "1.9.4" +version = "1.17.2" description = "Yet another URL library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" files = [ - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, - {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, - {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, - {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, - {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, - {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, - {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, - {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, - {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, - {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, - {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, - {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, - {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, - {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, - {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, - {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, - {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, - {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, - {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, - {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, - {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, - {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, - {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, - {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, - {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, - {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, - {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, - {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, - {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, - {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, - {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, - {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, - {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, + {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:93771146ef048b34201bfa382c2bf74c524980870bb278e6df515efaf93699ff"}, + {file = "yarl-1.17.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8281db240a1616af2f9c5f71d355057e73a1409c4648c8949901396dc0a3c151"}, + {file = "yarl-1.17.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:170ed4971bf9058582b01a8338605f4d8c849bd88834061e60e83b52d0c76870"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc61b005f6521fcc00ca0d1243559a5850b9dd1e1fe07b891410ee8fe192d0c0"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:871e1b47eec7b6df76b23c642a81db5dd6536cbef26b7e80e7c56c2fd371382e"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3a58a2f2ca7aaf22b265388d40232f453f67a6def7355a840b98c2d547bd037f"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:736bb076f7299c5c55dfef3eb9e96071a795cb08052822c2bb349b06f4cb2e0a"}, + {file = "yarl-1.17.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8fd51299e21da709eabcd5b2dd60e39090804431292daacbee8d3dabe39a6bc0"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:358dc7ddf25e79e1cc8ee16d970c23faee84d532b873519c5036dbb858965795"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:50d866f7b1a3f16f98603e095f24c0eeba25eb508c85a2c5939c8b3870ba2df8"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8b9c4643e7d843a0dca9cd9d610a0876e90a1b2cbc4c5ba7930a0d90baf6903f"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d63123bfd0dce5f91101e77c8a5427c3872501acece8c90df457b486bc1acd47"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4e76381be3d8ff96a4e6c77815653063e87555981329cf8f85e5be5abf449021"}, + {file = "yarl-1.17.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:734144cd2bd633a1516948e477ff6c835041c0536cef1d5b9a823ae29899665b"}, + {file = "yarl-1.17.2-cp310-cp310-win32.whl", hash = "sha256:26bfb6226e0c157af5da16d2d62258f1ac578d2899130a50433ffee4a5dfa673"}, + {file = "yarl-1.17.2-cp310-cp310-win_amd64.whl", hash = "sha256:76499469dcc24759399accd85ec27f237d52dec300daaca46a5352fcbebb1071"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:792155279dc093839e43f85ff7b9b6493a8eaa0af1f94f1f9c6e8f4de8c63500"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:38bc4ed5cae853409cb193c87c86cd0bc8d3a70fd2268a9807217b9176093ac6"}, + {file = "yarl-1.17.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4a8c83f6fcdc327783bdc737e8e45b2e909b7bd108c4da1892d3bc59c04a6d84"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c6d5fed96f0646bfdf698b0a1cebf32b8aae6892d1bec0c5d2d6e2df44e1e2d"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:782ca9c58f5c491c7afa55518542b2b005caedaf4685ec814fadfcee51f02493"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ff6af03cac0d1a4c3c19e5dcc4c05252411bf44ccaa2485e20d0a7c77892ab6e"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a3f47930fbbed0f6377639503848134c4aa25426b08778d641491131351c2c8"}, + {file = "yarl-1.17.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1fa68a3c921365c5745b4bd3af6221ae1f0ea1bf04b69e94eda60e57958907f"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:187df91395c11e9f9dc69b38d12406df85aa5865f1766a47907b1cc9855b6303"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:93d1c8cc5bf5df401015c5e2a3ce75a5254a9839e5039c881365d2a9dcfc6dc2"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:11d86c6145ac5c706c53d484784cf504d7d10fa407cb73b9d20f09ff986059ef"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:c42774d1d1508ec48c3ed29e7b110e33f5e74a20957ea16197dbcce8be6b52ba"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:0c8e589379ef0407b10bed16cc26e7392ef8f86961a706ade0a22309a45414d7"}, + {file = "yarl-1.17.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1056cadd5e850a1c026f28e0704ab0a94daaa8f887ece8dfed30f88befb87bb0"}, + {file = "yarl-1.17.2-cp311-cp311-win32.whl", hash = "sha256:be4c7b1c49d9917c6e95258d3d07f43cfba2c69a6929816e77daf322aaba6628"}, + {file = "yarl-1.17.2-cp311-cp311-win_amd64.whl", hash = "sha256:ac8eda86cc75859093e9ce390d423aba968f50cf0e481e6c7d7d63f90bae5c9c"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dd90238d3a77a0e07d4d6ffdebc0c21a9787c5953a508a2231b5f191455f31e9"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c74f0b0472ac40b04e6d28532f55cac8090e34c3e81f118d12843e6df14d0909"}, + {file = "yarl-1.17.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4d486ddcaca8c68455aa01cf53d28d413fb41a35afc9f6594a730c9779545876"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25b7e93f5414b9a983e1a6c1820142c13e1782cc9ed354c25e933aebe97fcf2"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3a0baff7827a632204060f48dca9e63fbd6a5a0b8790c1a2adfb25dc2c9c0d50"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:460024cacfc3246cc4d9f47a7fc860e4fcea7d1dc651e1256510d8c3c9c7cde0"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5870d620b23b956f72bafed6a0ba9a62edb5f2ef78a8849b7615bd9433384171"}, + {file = "yarl-1.17.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2941756754a10e799e5b87e2319bbec481ed0957421fba0e7b9fb1c11e40509f"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9611b83810a74a46be88847e0ea616794c406dbcb4e25405e52bff8f4bee2d0a"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:cd7e35818d2328b679a13268d9ea505c85cd773572ebb7a0da7ccbca77b6a52e"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6b981316fcd940f085f646b822c2ff2b8b813cbd61281acad229ea3cbaabeb6b"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:688058e89f512fb7541cb85c2f149c292d3fa22f981d5a5453b40c5da49eb9e8"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:56afb44a12b0864d17b597210d63a5b88915d680f6484d8d202ed68ade38673d"}, + {file = "yarl-1.17.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:17931dfbb84ae18b287279c1f92b76a3abcd9a49cd69b92e946035cff06bcd20"}, + {file = "yarl-1.17.2-cp312-cp312-win32.whl", hash = "sha256:ff8d95e06546c3a8c188f68040e9d0360feb67ba8498baf018918f669f7bc39b"}, + {file = "yarl-1.17.2-cp312-cp312-win_amd64.whl", hash = "sha256:4c840cc11163d3c01a9d8aad227683c48cd3e5be5a785921bcc2a8b4b758c4f3"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:3294f787a437cb5d81846de3a6697f0c35ecff37a932d73b1fe62490bef69211"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f1e7fedb09c059efee2533119666ca7e1a2610072076926fa028c2ba5dfeb78c"}, + {file = "yarl-1.17.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:da9d3061e61e5ae3f753654813bc1cd1c70e02fb72cf871bd6daf78443e9e2b1"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:91c012dceadc695ccf69301bfdccd1fc4472ad714fe2dd3c5ab4d2046afddf29"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f11fd61d72d93ac23718d393d2a64469af40be2116b24da0a4ca6922df26807e"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:46c465ad06971abcf46dd532f77560181387b4eea59084434bdff97524444032"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef6eee1a61638d29cd7c85f7fd3ac7b22b4c0fabc8fd00a712b727a3e73b0685"}, + {file = "yarl-1.17.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4434b739a8a101a837caeaa0137e0e38cb4ea561f39cb8960f3b1e7f4967a3fc"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:752485cbbb50c1e20908450ff4f94217acba9358ebdce0d8106510859d6eb19a"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:17791acaa0c0f89323c57da7b9a79f2174e26d5debbc8c02d84ebd80c2b7bff8"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5c6ea72fe619fee5e6b5d4040a451d45d8175f560b11b3d3e044cd24b2720526"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:db5ac3871ed76340210fe028f535392f097fb31b875354bcb69162bba2632ef4"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7a1606ba68e311576bcb1672b2a1543417e7e0aa4c85e9e718ba6466952476c0"}, + {file = "yarl-1.17.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9bc27dd5cfdbe3dc7f381b05e6260ca6da41931a6e582267d5ca540270afeeb2"}, + {file = "yarl-1.17.2-cp313-cp313-win32.whl", hash = "sha256:52492b87d5877ec405542f43cd3da80bdcb2d0c2fbc73236526e5f2c28e6db28"}, + {file = "yarl-1.17.2-cp313-cp313-win_amd64.whl", hash = "sha256:8e1bf59e035534ba4077f5361d8d5d9194149f9ed4f823d1ee29ef3e8964ace3"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c556fbc6820b6e2cda1ca675c5fa5589cf188f8da6b33e9fc05b002e603e44fa"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f2f44a4247461965fed18b2573f3a9eb5e2c3cad225201ee858726cde610daca"}, + {file = "yarl-1.17.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3a3ede8c248f36b60227eb777eac1dbc2f1022dc4d741b177c4379ca8e75571a"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2654caaf5584449d49c94a6b382b3cb4a246c090e72453493ea168b931206a4d"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0d41c684f286ce41fa05ab6af70f32d6da1b6f0457459a56cf9e393c1c0b2217"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2270d590997445a0dc29afa92e5534bfea76ba3aea026289e811bf9ed4b65a7f"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18662443c6c3707e2fc7fad184b4dc32dd428710bbe72e1bce7fe1988d4aa654"}, + {file = "yarl-1.17.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:75ac158560dec3ed72f6d604c81090ec44529cfb8169b05ae6fcb3e986b325d9"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1fee66b32e79264f428dc8da18396ad59cc48eef3c9c13844adec890cd339db5"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:585ce7cd97be8f538345de47b279b879e091c8b86d9dbc6d98a96a7ad78876a3"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c019abc2eca67dfa4d8fb72ba924871d764ec3c92b86d5b53b405ad3d6aa56b0"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c6e659b9a24d145e271c2faf3fa6dd1fcb3e5d3f4e17273d9e0350b6ab0fe6e2"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:d17832ba39374134c10e82d137e372b5f7478c4cceeb19d02ae3e3d1daed8721"}, + {file = "yarl-1.17.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:bc3003710e335e3f842ae3fd78efa55f11a863a89a72e9a07da214db3bf7e1f8"}, + {file = "yarl-1.17.2-cp39-cp39-win32.whl", hash = "sha256:f5ffc6b7ace5b22d9e73b2a4c7305740a339fbd55301d52735f73e21d9eb3130"}, + {file = "yarl-1.17.2-cp39-cp39-win_amd64.whl", hash = "sha256:48e424347a45568413deec6f6ee2d720de2cc0385019bedf44cd93e8638aa0ed"}, + {file = "yarl-1.17.2-py3-none-any.whl", hash = "sha256:dd7abf4f717e33b7487121faf23560b3a50924f80e4bef62b22dab441ded8f3b"}, + {file = "yarl-1.17.2.tar.gz", hash = "sha256:753eaaa0c7195244c84b5cc159dc8204b7fd99f716f11198f999f2332a86b178"}, ] [package.dependencies] idna = ">=2.0" multidict = ">=4.0" +propcache = ">=0.2.0" [metadata] lock-version = "2.0"