diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index df92956262..911d874d9e 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -2,7 +2,7 @@ ARG VARIANT="3.12" FROM mcr.microsoft.com/devcontainers/python:${VARIANT} -ARG POETRY_VERSION="1.4" +ARG POETRY_VERSION="1.8.3" ENV POETRY_HOME="/opt/poetry" \ POETRY_VERSION=${POETRY_VERSION} @@ -17,5 +17,5 @@ RUN curl -sSL https://install.python-poetry.org | python3 - \ COPY pyproject.toml poetry.lock ./ RUN poetry config virtualenvs.create false \ - && poetry install --no-root --no-interaction -E "askar didcommv2" \ + && poetry install --no-root --no-interaction -E "didcommv2" \ && rm -rf /root/.cache/pypoetry diff --git a/.github/workflows/bdd-integration-tests.yml b/.github/workflows/bdd-integration-tests.yml index b880ebe58f..2df26f98b9 100644 --- a/.github/workflows/bdd-integration-tests.yml +++ b/.github/workflows/bdd-integration-tests.yml @@ -38,6 +38,7 @@ jobs: - acapy_agent/**/* - poetry.lock - pyproject.toml + - docker/* demo: "demo/**/*" - name: Check if demo or src files changed id: check-if-demo-or-src-changed diff --git a/.github/workflows/bdd-interop-tests.yml b/.github/workflows/bdd-interop-tests.yml index 98f3b04bdf..3991902945 100644 --- a/.github/workflows/bdd-interop-tests.yml +++ b/.github/workflows/bdd-interop-tests.yml @@ -38,6 +38,7 @@ jobs: - acapy_agent/**/* - poetry.lock - pyproject.toml + - docker/* - name: Check if src files changed id: check-if-src-changed run: | diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 1f7584e464..9970591437 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.8.0 + version: 0.9.2 args: "format --check" diff --git a/.github/workflows/snyk-lts.yml b/.github/workflows/snyk-lts.yml index 0853e1a61b..901a3aa185 100644 --- a/.github/workflows/snyk-lts.yml +++ b/.github/workflows/snyk-lts.yml @@ -5,8 +5,9 @@ on: # These branches represent the LTS releases branches: - 0.12.lts - - 0.11.lts + - 1.2.lts paths: + - aries_cloudagent/** - acapy_agent/** - docker/** diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2cc9bec01f..0dae0431dd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -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.8.1 + rev: v0.9.2 hooks: # Run the linter - id: ruff diff --git a/CHANGELOG.md b/CHANGELOG.md index a418c79077..73dad664e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,37 +1,108 @@ # Aries Cloud Agent Python Changelog -## 1.1.1rc0 +## 1.2.1 -### December 3, 2024 +### January 21, 2025 -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. +Release 1.2.1 is a patch to fix a couple of issues introduced in [Release 1.2.0](#120) that prevent the startup of multi-tenant/single database instances of ACA-Py. The release includes the fixes, plus a new test for testing ACA-Py upgrades -- a new test type introduced in [Release 1.2.0](#120). Given that there are no breaking changes in this release, we'll move the [1.2.lts branch](https://github.com/openwallet-foundation/acapy/tree/1.2.lts) to be based on this release. -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. +Enhancements in Release 1.2.1 are the addition of support for the Linked Data proof cryptosuite `EcdsaSecp256r1Signature2019`, and support for P256 keys generally and in `did:key` form. -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]. +### 1.2.1 Deprecation Notices -[GitHub Issue #3250]: https://github.com/hyperledger/aries-cloudagent-python/issues/3250 +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.2.1 release, but will be moved out of the core and into plugins soon. Please review these notifications carefully! + +### 1.2.1 Breaking Changes + +There are no breaking changes in this release, just fixes, new tests and minor updates. + +#### 1.2.1 Categorized List of Pull Requests + +- Linked Data Proof and Key Type Additions + - Support EcdsaSecp256r1Signature2019 linked data proof [\#3443](https://github.com/openwallet-foundation/acapy/pull/3443) [gmulhearn](https://github.com/gmulhearn) + - Support P256 keys & did:keys [\#3442](https://github.com/openwallet-foundation/acapy/pull/3442) [gmulhearn](https://github.com/gmulhearn) + +- Startup, Wallet Keys, and Upgrade Fixes + - Check admin wallet anoncreds upgrade on startup [\#3458](https://github.com/openwallet-foundation/acapy/pull/3458) [jamshale](https://github.com/jamshale) + - Add Multi-tenancy single wallet upgrade test [\#3457](https://github.com/openwallet-foundation/acapy/pull/3457) [jamshale](https://github.com/jamshale) + - Pass the correct key for multitenant single wallets [\#3450](https://github.com/openwallet-foundation/acapy/pull/3450) [jamshale](https://github.com/jamshale) + - Prevent dummy profiles on start up [\#3449](https://github.com/openwallet-foundation/acapy/pull/3449) [jamshale](https://github.com/jamshale) + - Fixed handling of base wallet routes in auth decorator [\#3448](https://github.com/openwallet-foundation/acapy/pull/3448) [esune](https://github.com/esune) + +- DID Registration and Resolution + - Change did:tdw resolver naming to did:webvh [\#3429](https://github.com/openwallet-foundation/acapy/pull/3429) [jamshale](https://github.com/jamshale) + +- Test Suite Updates and Artifact Publishing + - Only copy agent code in dockerfiles [\#3393](https://github.com/openwallet-foundation/acapy/pull/3393) [jamshale](https://github.com/jamshale) + +- Internal Improvements / Cleanups / Tech Debt Updates + - Update versions.json to correct the version drop down on aca-py.org [\#3434](https://github.com/openwallet-foundation/acapy/pull/3434) [swcurran](https://github.com/swcurran) + - Follow up from Release 1.2.0 -- including LTS change [\#3432](https://github.com/openwallet-foundation/acapy/pull/3432) [swcurran](https://github.com/swcurran) + +- Consolidate Dependabot updates and other library/dependency updates + - :arrow_up: Upgrade dev dependencies [\#3454](https://github.com/openwallet-foundation/acapy/pull/3454) [ff137](https://github.com/ff137) + - :recycle: Sync ruff version in workflows [\#3447](https://github.com/openwallet-foundation/acapy/pull/3447) [ff137](https://github.com/ff137) + +- Release management pull requests: + - 1.2.1 [\#3460](https://github.com/openwallet-foundation/acapy/pull/3460) [swcurran](https://github.com/swcurran) + - 1.2.1rc0 [\#3459](https://github.com/openwallet-foundation/acapy/pull/3459) [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%3A2025-01-08..2025-01-21+author%3Aapp%2Fdependabot+) + +## 1.2.0 + +### January 8, 2025 + +!!! warning "Multi-tenant, Single Database Deployments" -### 1.1.1 Deprecation Notices + A bug in Release 1.2.0 prevents using the release with existing multi-tenant, single wallet deployments. Those requiring such support **MUST** skip Release 1.2.0 and move to [Release 1.2.1](https://github.com/openwallet-foundation/acapy/releases/tag/1.2.1) or higher. -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! +Release 1.2.0 is a minor update to ACA-Py that contains an update to the AnonCreds implementation to make it easier to deploy on other than Hyperledger Indy, and a lengthy list of adjustments, improvements and fixes, with a focus on removing technical debt. In addition to the AnonCreds updates, 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. In removing the in-memory wallet, all of the unit and integration tests that used the in-memory wallet have been updated to use SQLite's in-memory wallet. -### 1.1.1 Breaking Changes +Release 1.2.x is the new current Long Term Support (LTS) for ACA-Py, as defined in the [LTS Strategy](./LTS-Strategy.md) document. With this release, the "end of life" for the previous "current LTS release" -- [0.12](#0123) -- is set for October 2025. -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. +The first step to full support of [did:webvh](https://identity.foundation/didwebvh/) ("`did:web` + Verifiable History"-- formerly `did:tdw`) has been added to ACA-Py -- a resolver. We're working on improving the new DID Registration mechanism for it, [Cheqd] and other DID Methods, enabling ACA-Py to be used easily with a variety of DID Methods. +[Cheqd]: https://cheqd.io/ -#### 1.1.1 Categorized List of Pull Requests +The move to the [OpenWallet Foundation](https://openwallet.foundation/) is now complete. If you haven't done so already, please update your ACA-Py deployment to use: + +- the [ACA-Py OWF repository](https://github.com/openwallet-foundation/acapy), +- the new [acapy-agent in PyPi](https://pypi.org/project/acapy-agent/), and +- the container images for ACA-Py hosted by the OpenWallet Foundation GitHub organization within the GitHub Container Repository (GHCR). + +A significant testing capability was added in this release -- the ability to run an integration test that includes an ACA-Py upgrade in the middle. This allows us to test, for example starting an agent on one release, doing an upgrade (possibly including running a migration script), and then completing the test on the upgraded release. This is enable by adding a capability to restart Docker containers in the middle of tests. Nice work, @ianco! + +### 1.2.0 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.2.0 release, but will be moved out of the core and into plugins soon. Please review these notifications carefully! + +### 1.2.0 Breaking Changes + +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 the Askar storage configuration in test environments and what is used in production. + +A fix for a multi-tenancy bug in the holding of VC-LD credentials that resulted in the storing of such credentials in the base wallet versus the intended tenant wallet in included in this release. As part of that fix, [PR #3391] impacts those using the GET /vc/credentials endpoint; the response is now an object with a single results attribute where it was previously a flat list. + +[PR #3391]: https://github.com/openwallet-foundation/acapy/pull/3391 + +#### 1.2.0 Categorized List of Pull Requests - AnonCreds VC Issuance and Presentation Enhancement / Fixes + - Fix indy fallback format in presentation from holder [\#3413](https://github.com/openwallet-foundation/acapy/pull/3413) [jamshale](https://github.com/jamshale) + - Anoncreds post api object handling [\#3411](https://github.com/openwallet-foundation/acapy/pull/3411) [jamshale](https://github.com/jamshale) + - fix: Anoncreds schemas and validation [\#3397](https://github.com/openwallet-foundation/acapy/pull/3397) [DaevMithran](https://github.com/DaevMithran) + - Update accumulator value in wallet on repair [\#3299](https://github.com/openwallet-foundation/acapy/pull/3299) [jamshale](https://github.com/jamshale) - Repair release bdd tests [\#3376](https://github.com/openwallet-foundation/acapy/pull/3376) [jamshale](https://github.com/jamshale) + - Update anoncreds format names [\#3374](https://github.com/openwallet-foundation/acapy/pull/3374) [jamshale](https://github.com/jamshale) + - Anoncreds create credential [\#3369](https://github.com/openwallet-foundation/acapy/pull/3369) [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 + - BREAKING: VCHolder multitenant binding [\#3391](https://github.com/openwallet-foundation/acapy/pull/3391) [jamshale](https://github.com/jamshale) - 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) @@ -39,6 +110,7 @@ While there are no breaking changes in this release that might impact production - 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 + - :bug: Ensure supported DID before calling Rotate [\#3380](https://github.com/openwallet-foundation/acapy/pull/3380) [ff137](https://github.com/ff137) - 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) @@ -49,11 +121,25 @@ While there are no breaking changes in this release that might impact production - :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 + - Scenario test with anoncreds wallet upgrade and restart [\#3410](https://github.com/openwallet-foundation/acapy/pull/3410) [ianco](https://github.com/ianco) + - Add legacy pypi token [\#3408](https://github.com/openwallet-foundation/acapy/pull/3408) [jamshale](https://github.com/jamshale) + - Aca-Py test scenario including a container restart (with aca-py version upgrade) [\#3400](https://github.com/openwallet-foundation/acapy/pull/3400) [ianco](https://github.com/ianco) + - Adjust coverage location for sonarcloud [\#3399](https://github.com/openwallet-foundation/acapy/pull/3399) [jamshale](https://github.com/jamshale) + - Remove sonar cov report move step [\#3398](https://github.com/openwallet-foundation/acapy/pull/3398) [jamshale](https://github.com/jamshale) + - Update Sonarcloud to new action [\#3390](https://github.com/openwallet-foundation/acapy/pull/3390) [ryjones](https://github.com/ryjones) + - Switch to COPY commands in dockerfiles [\#3389](https://github.com/openwallet-foundation/acapy/pull/3389) [jamshale](https://github.com/jamshale) + - Fix sonar coverage on merge main [\#3388](https://github.com/openwallet-foundation/acapy/pull/3388) [jamshale](https://github.com/jamshale) - 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 + - Fix devcontainer poetry install [\#3428](https://github.com/openwallet-foundation/acapy/pull/3428) [jamshale](https://github.com/jamshale) + - Pin poetry to 1.8.3 in dockerfiles [\#3427](https://github.com/openwallet-foundation/acapy/pull/3427) [jamshale](https://github.com/jamshale) + - Adds the OpenSSF to the readme [\#3412](https://github.com/openwallet-foundation/acapy/pull/3412) [swcurran](https://github.com/swcurran) + - The latest tag doesn't exist in git, just github [\#3392](https://github.com/openwallet-foundation/acapy/pull/3392) [ryjones](https://github.com/ryjones) + - :art: Fix model name for consistency [\#3382](https://github.com/openwallet-foundation/acapy/pull/3382) [ff137](https://github.com/ff137) + - Fix for demo initial cred_type override [\#3378](https://github.com/openwallet-foundation/acapy/pull/3378) [ianco](https://github.com/ianco) - :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) @@ -68,11 +154,34 @@ While there are no breaking changes in this release that might impact production - :arrow_up: Update lock file [\#3296](https://github.com/openwallet-foundation/acapy/pull/3296) [ff137](https://github.com/ff137) - Release management pull requests: + - 1.2.0 [\#3430](https://github.com/openwallet-foundation/acapy/pull/3430) [swcurran](https://github.com/swcurran) + - 1.2.0rc0 [\#3420](https://github.com/openwallet-foundation/acapy/pull/3420) [swcurran](https://github.com/swcurran) - 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+) + - [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..2025-01-08+author%3Aapp%2Fdependabot+) +## 1.1.1 + +ACA-Py Release 1.1.1 was a release candidate for 1.2.0. A mistake in the release PR meant the 1.1.1rc0 was tagged published to PyPi as Release 1.1.1. Since that was not intended to be a final release, the release changelog for 1.2.0 includes the Pull Requests that would have been in 1.1.1. + +## 0.12.3 + +### December 17, 2024 + +A patch release to add address a bug found in the Linked Data Verifiable Credential handling for multi-tenant holders. The bug was fixed in the main branch, [PR 3391 - BREAKING: VCHolder multitenant binding](https://github.com/openwallet-foundation/acapy/pull/3391), and with this release is backported to 0.12 Long Term Support branch. Prior to this release, holder credentials received into a tenant wallet were actually received into the multi-tenant admin wallet. + +### 0.12.3 Breaking Changes + +There are no breaking changes in this release. + +#### 0.12.3 Categorized List of Pull Requests + +- Multitenant LD-VC Holders + - Patch PR 3391 - 0.12.lts [\#3396](https://github.com/openwallet-foundation/acapy/pull/3396) +- Release management pull requests + - 0.12.3 [\#3408](https://github.com/hyperledger/aries-cloudagent-python/pull/3408) [swcurran](https://github.com/swcurran) + - 0.12.3rc0 [\#3406](https://github.com/hyperledger/aries-cloudagent-python/pull/3406) [swcurran](https://github.com/swcurran) ## 1.1.0 @@ -99,7 +208,7 @@ The only (but significant) breaking changes in 1.1.0 are related to the GitHub o - the renaming of the source code folder from `aries_cloudagent` to `acapy_agent`, - the publication of the [PyPi] project under the new `acapy_agent` name, and - the use of the OWF organizational GitHub Container Registry ([GHCR]) and `acapy_agent` as the name for release container image artifacts. - - The patterns for the image tags remain the same as before. So, for example, the new nightly artifact can be found here: [docker pull ghcr.io/openwallet-foundation/acapy-agent:py3.12-nightly](docker pull ghcr.io/openwallet-foundation/acapy-agent:py3.12-nightly). + - The patterns for the image tags remain the same as before. So, for example, the new nightly artifact can be found here: `docker pull ghcr.io/openwallet-foundation/acapy-agent:py3.12-nightly`. [PyPi]: https://pypi.org [GHCR]: https://ghcr.io diff --git a/Managing-ACA-Py-Doc-Site.md b/Managing-ACA-Py-Doc-Site.md index 5bafc5ad87..e4abbcf478 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.1`). +- Checks out the triggering branch, either `main` or `docs-v` (e.g `docs-v1.2.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,39 +97,10 @@ 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.1rc0` +- Remove the folder for the RC. For example `rm -rf 1.2.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 `main`!!). - Merge the PR and verify (after a few minutes) that the drop down no longer has the RC in it. - -## Adding new 0.11.x Releases - -The automatic generation process from ACA-Py started with release 0.12.0. -Unfortunately, we declared release 0.11.x to be an Long Term Support version and -so we still need to add 0.11.x version documentation to the generated site. -Here's the (lousy) process to do this. Typically, [swcurran] will do this and no -one else needs to worry about it. But for completeness, here is the process: - -- Follow the instructions in the [aries-acapy-docs] repository to generate and - publish the documentation site for the new 0.11.x version. -- Have a local copy of the [aries-acapy-docs] repository. In that repo, run `git - checkout -b gh-pages --track upstream/gh-pages` to checkout a local copy of - the generated pages from that repo. -- In ACA-Py, run `git checkout -b gh-pages --track upstream/gh-pages` to create - a local branch from which you will push a PR. -- Copy the v0.11.x folder from [aries-acapy-docs] local to a new 0.11.x folder - in the ACA-Py local. Note the "v" that is on the folder in [aries-acapy-docs], - but not in ACA-Py. -- Edit the `versions.json` file to add the 0.11.x reference into the file. -- Push the changes via a PR to the ACA-Py `gh-pages` branch (don't PR them into - `main`!!). -- Merge the PR and verify (after a few minutes) that the drop down includes the - 0.11.x version. - -Ugly! The LTS for 0.11 ends in January 2025 and this process can be dropped. - -[swcurran]: https://github.com/swcurran -[aries-acapy-docs]: https://github.com/hyperledger/aries-acapy-docs diff --git a/PUBLISHING.md b/PUBLISHING.md index e7bd48af07..89a213299c 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.1". +1. Create a local PR branch from an updated `main` branch, e.g. "1.2.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 @@ -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. -1. Check to see if there are any other PRs that should be included in the release. +5. Check to see if there are any other PRs that should be included in the release. -2. Update the ReadTheDocs in the `/docs` folder by following the instructions in +6. 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. -3. Search across the repository for the previous version number and update it +7. 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. -4. Regenerate openapi.json and swagger.json by running +8. 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. -5. Double check all of these steps above, and then submit a PR from the branch. +9. 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! -6. Immediately after it is merged, create a new GitHub tag representing the +10. 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. -7. New images for the release are automatically published by the GitHubAction +11. 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 @@ -139,8 +139,8 @@ Once you have the list of PRs: [publish.yml]: https://github.com/openwallet-foundation/acapy/blob/main/.github/workflows/publish.yml [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.1`. +12. 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.2.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/README.md b/README.md index 39c3ba75cd..a737fad8c8 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,17 @@ # ACA-Py -- A Cloud Agent - Python -🚨 **ACA-Py is transitioning to the [OpenWallet Foundation] (OWF)!** 🚨 +🚨 **ACA-Py is part of the [OpenWallet Foundation] (OWF)!** 🚨 [OpenWallet Foundation]: https://openwallet.foundation/ -We’re excited to announce that the ACA-Py project has moved to the OWF's GitHub organization as the [new "acapy" project](https://github.com/openwallet-foundation/project-proposals/blob/main/projects/aca-py.md). +The move of ACA-Py to the OWF is now complete. If you haven't done so already, please update your ACA-Py deployment to use: -For details on what this means for ACA-Py users, including steps for updating deployments, please follow the updates in [GitHub Issue #3250]. We'll keep you informed about how to update your deployment to reflect this change. Stay tuned! - -[GitHub Issue #3250]: https://github.com/openwallet-foundation/acapy/issues/3250 +- the [ACA-Py OWF repository](https://github.com/openwallet-foundation/acapy), +- the new [acapy-agent in PyPi](https://pypi.org/project/acapy-agent/), and +- the container images for ACA-Py hosted by the OpenWallet Foundation GitHub organization within the GitHub Container Repository (GHCR).

+ @@ -50,10 +51,14 @@ the active LTS releases. Each LTS release will be supported with patches for **9 months** following the designation of the **next** LTS Release. For more details see the [LTS strategy](./LTS-Strategy.md). -Current LTS releases are: +Current LTS releases: + +- Release [1.2](https://github.com/openwallet-foundation/acapy/releases/tag/1.2.1) **Current LTS Release** +- Release [0.12](https://github.com/openwallet-foundation/acapy/releases/tag/0.12.3) **End of Life: October 2025** + +Past LTS releases: -- [0.12](https://github.com/openwallet-foundation/acapy/releases/tag/0.12.1) **Current LTS Release** -- [0.11](https://github.com/openwallet-foundation/acapy/releases/tag/0.11.1) **End of Life: January 2025** +- Release [0.11](https://github.com/openwallet-foundation/acapy/releases/tag/0.11.3) **End of Life: January 2025** Unless specified in the **Breaking Changes** section of the ACA-Py [CHANGELOG](./CHANGELOG.md), all LTS patch releases will be able to be deployed diff --git a/acapy_agent/admin/decorators/auth.py b/acapy_agent/admin/decorators/auth.py index 3d1f209893..982a66872b 100644 --- a/acapy_agent/admin/decorators/auth.py +++ b/acapy_agent/admin/decorators/auth.py @@ -2,7 +2,7 @@ import functools import re -from typing import Optional, Pattern +from typing import List, Optional, Pattern from aiohttp import web @@ -65,8 +65,12 @@ async def tenant_auth(request): ) insecure_mode = bool(profile.settings.get("admin.admin_insecure_mode")) multitenant_enabled = profile.settings.get("multitenant.enabled") + base_wallet_routes = profile.settings.get("multitenant.base_wallet_routes") base_wallet_allowed_route = _base_wallet_route_access( - profile.settings.get("multitenant.base_wallet_routes"), request.path + [base_wallet_routes] + if isinstance(base_wallet_routes, str) + else base_wallet_routes, + request.path, ) # CORS fix: allow OPTIONS method access to paths without a token @@ -88,19 +92,22 @@ async def tenant_auth(request): return tenant_auth -def _base_wallet_route_access(additional_routes: str, request_path: str) -> bool: +def _base_wallet_route_access(additional_routes: List[str], request_path: str) -> bool: """Check if request path matches additional routes.""" - additional_routes_pattern = _build_additional_routes_pattern(additional_routes) + additional_routes_pattern = ( + _build_additional_routes_pattern(additional_routes) if additional_routes else None + ) return _matches_additional_routes(additional_routes_pattern, request_path) -def _build_additional_routes_pattern(pattern_string: str) -> Optional[Pattern]: +def _build_additional_routes_pattern(pattern_list: List[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 + all_paths = [] + for pattern in pattern_list: + paths = pattern.split(" ") + all_paths = all_paths + paths + return re.compile("^((?:)" + "|".join(all_paths) + ")$") def _matches_additional_routes(pattern: Pattern, path: str) -> bool: diff --git a/acapy_agent/admin/tests/test_auth.py b/acapy_agent/admin/tests/test_auth.py index 73680a1b00..ee5cdda150 100644 --- a/acapy_agent/admin/tests/test_auth.py +++ b/acapy_agent/admin/tests/test_auth.py @@ -134,8 +134,25 @@ async def test_multi_tenant_valid_auth_header(self): 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" + async def test_base_wallet_additional_route_allowed_string(self): + self.profile.settings["multitenant.base_wallet_routes"] = ( + "/not-this-route /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_allowed_list(self): + self.profile.settings["multitenant.base_wallet_routes"] = [ + "/extra-route", + "/not-this-route", + ] self.request = mock.MagicMock( __getitem__=lambda _, k: self.request_dict[k], headers={"x-api-key": "admin_api_key"}, diff --git a/acapy_agent/anoncreds/base.py b/acapy_agent/anoncreds/base.py index 32c0a1c1f1..4c5b79d345 100644 --- a/acapy_agent/anoncreds/base.py +++ b/acapy_agent/anoncreds/base.py @@ -16,6 +16,7 @@ RevRegDefResult, ) from .models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult +from .models.schema_info import AnoncredsSchemaInfo T = TypeVar("T") @@ -130,9 +131,15 @@ async def get_revocation_list( ) -> GetRevListResult: """Get a revocation list from the registry.""" + @abstractmethod + async def get_schema_info_by_id( + self, profile: Profile, schema_id: str + ) -> AnoncredsSchemaInfo: + """Get a schema info from the registry.""" + class BaseAnonCredsRegistrar(BaseAnonCredsHandler): - """Base Anon Creds Registrar.""" + """Base Anoncreds Registrar.""" @abstractmethod async def register_schema( diff --git a/acapy_agent/anoncreds/default/did_indy/registry.py b/acapy_agent/anoncreds/default/did_indy/registry.py index dcaafe4c06..6bd6cae693 100644 --- a/acapy_agent/anoncreds/default/did_indy/registry.py +++ b/acapy_agent/anoncreds/default/did_indy/registry.py @@ -17,6 +17,7 @@ RevRegDefResult, ) from ...models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult +from ...models.schema_info import AnoncredsSchemaInfo LOGGER = logging.getLogger(__name__) @@ -118,3 +119,9 @@ async def update_revocation_list( ) -> RevListResult: """Update a revocation list on the registry.""" raise NotImplementedError() + + async def get_schema_info_by_id( + self, profile: Profile, schema_id: str + ) -> AnoncredsSchemaInfo: + """Get a schema info from the registry.""" + return await super().get_schema_info_by_id(schema_id) diff --git a/acapy_agent/anoncreds/default/did_web/registry.py b/acapy_agent/anoncreds/default/did_web/registry.py index f97ba88fb8..718b624842 100644 --- a/acapy_agent/anoncreds/default/did_web/registry.py +++ b/acapy_agent/anoncreds/default/did_web/registry.py @@ -16,6 +16,7 @@ RevRegDefResult, ) from ...models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult +from ...models.schema_info import AnoncredsSchemaInfo class DIDWebRegistry(BaseAnonCredsResolver, BaseAnonCredsRegistrar): @@ -113,3 +114,9 @@ async def update_revocation_list( ) -> RevListResult: """Update a revocation list on the registry.""" raise NotImplementedError() + + async def get_schema_info_by_id( + self, profile: Profile, schema_id: str + ) -> AnoncredsSchemaInfo: + """Get a schema info from the registry.""" + return await super().get_schema_info_by_id(schema_id) diff --git a/acapy_agent/anoncreds/default/legacy_indy/registry.py b/acapy_agent/anoncreds/default/legacy_indy/registry.py index aff1040616..aad288d053 100644 --- a/acapy_agent/anoncreds/default/legacy_indy/registry.py +++ b/acapy_agent/anoncreds/default/legacy_indy/registry.py @@ -80,6 +80,7 @@ SchemaResult, SchemaState, ) +from ...models.schema_info import AnoncredsSchemaInfo from ...revocation import ( CATEGORY_REV_LIST, CATEGORY_REV_REG_DEF, @@ -1229,3 +1230,14 @@ async def txn_submit( ) except LedgerError as err: raise AnonCredsRegistrationError(err.roll_up) from err + + async def get_schema_info_by_id( + self, profile: Profile, schema_id: str + ) -> AnoncredsSchemaInfo: + """Get schema info by schema id.""" + schema_id_parts = re.match(r"^(\w+):2:([^:]+):([^:]+)$", schema_id) + return AnoncredsSchemaInfo( + issuer_id=schema_id_parts.group(1), + name=schema_id_parts.group(2), + version=schema_id_parts.group(3), + ) 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 c41eb80797..76ebbee7a2 100644 --- a/acapy_agent/anoncreds/default/legacy_indy/tests/test_registry.py +++ b/acapy_agent/anoncreds/default/legacy_indy/tests/test_registry.py @@ -1210,3 +1210,12 @@ async def test_sync_wallet_rev_list_with_issuer_cred_rev_records( ), ) assert isinstance(result, RevList) + + async def test_get_schem_info(self): + result = await self.registry.get_schema_info_by_id( + self.profile, + "XduBsoPyEA4szYMy3pZ8De:2:minimal-33279d005748b3cc:1.0", + ) + assert result.issuer_id == "XduBsoPyEA4szYMy3pZ8De" + assert result.name == "minimal-33279d005748b3cc" + assert result.version == "1.0" diff --git a/acapy_agent/anoncreds/holder.py b/acapy_agent/anoncreds/holder.py index f8dd4445f7..08006fe176 100644 --- a/acapy_agent/anoncreds/holder.py +++ b/acapy_agent/anoncreds/holder.py @@ -3,7 +3,6 @@ import asyncio import json import logging -import re from typing import Dict, Optional, Sequence, Tuple, Union from anoncreds import ( @@ -150,8 +149,8 @@ async def create_credential_request( ) = await asyncio.get_event_loop().run_in_executor( None, CredentialRequest.create, - None, holder_did, + None, credential_definition.to_native(), secret, AnonCredsHolder.MASTER_SECRET_ID, @@ -231,25 +230,19 @@ async def _finish_store_credential( rev_reg_def: Optional[dict] = None, ) -> str: credential_data = cred_recvd.to_dict() - schema_id = cred_recvd.schema_id - schema_id_parts = re.match(r"^(\w+):2:([^:]+):([^:]+)$", schema_id) - if not schema_id_parts: - raise AnonCredsHolderError(f"Error parsing credential schema ID: {schema_id}") - cred_def_id = cred_recvd.cred_def_id - cdef_id_parts = re.match(r"^(\w+):3:CL:([^:]+):([^:]+)$", cred_def_id) - if not cdef_id_parts: - raise AnonCredsHolderError( - f"Error parsing credential definition ID: {cred_def_id}" - ) + registry = self.profile.inject(AnonCredsRegistry) + schema_info = await registry.get_schema_info_by_id( + self.profile, credential_data["schema_id"] + ) credential_id = credential_id or str(uuid4()) tags = { - "schema_id": schema_id, - "schema_issuer_did": schema_id_parts[1], - "schema_name": schema_id_parts[2], - "schema_version": schema_id_parts[3], - "issuer_did": cdef_id_parts[1], - "cred_def_id": cred_def_id, + "schema_id": credential_data["schema_id"], + "schema_issuer_did": schema_info.issuer_id, + "schema_name": schema_info.name, + "schema_version": schema_info.version, + "issuer_did": credential_definition["issuerId"], + "cred_def_id": cred_recvd.cred_def_id, "rev_reg_id": cred_recvd.rev_reg_id or "None", } diff --git a/acapy_agent/anoncreds/issuer.py b/acapy_agent/anoncreds/issuer.py index 6dc3fababa..3d6948cf0e 100644 --- a/acapy_agent/anoncreds/issuer.py +++ b/acapy_agent/anoncreds/issuer.py @@ -196,7 +196,7 @@ async def create_and_register_schema( ) if schemas: raise AnonCredsSchemaAlreadyExists( - f"Schema with {name}: {version} " f"already exists for {issuer_id}", + f"Schema with {name}: {version} already exists for {issuer_id}", schemas[0].name, AnonCredsSchema.deserialize(schemas[0].value_json), ) diff --git a/acapy_agent/anoncreds/models/credential_request.py b/acapy_agent/anoncreds/models/credential_request.py index 49fd58e996..2d5147b4a6 100644 --- a/acapy_agent/anoncreds/models/credential_request.py +++ b/acapy_agent/anoncreds/models/credential_request.py @@ -24,6 +24,8 @@ class Meta: def __init__( self, + entropy: Optional[str] = None, + # For compatibility with credx agents, which uses `prover_did` instead of `entropy` # noqa prover_did: Optional[str] = None, cred_def_id: Optional[str] = None, blinded_ms: Optional[Mapping] = None, @@ -33,6 +35,7 @@ def __init__( ): """Initialize anoncreds credential request.""" super().__init__(**kwargs) + self.entropy = entropy self.prover_did = prover_did self.cred_def_id = cred_def_id self.blinded_ms = blinded_ms @@ -49,8 +52,16 @@ class Meta: model_class = AnoncredsCredRequest unknown = EXCLUDE + entropy = fields.Str( + required=False, + metadata={ + "description": "Prover DID/Random String/UUID", + "example": UUID4_EXAMPLE, + }, + ) + # For compatibility with credx agents, which uses `prover_did` instead of `entropy` prover_did = fields.Str( - required=True, + required=False, metadata={ "description": "Prover DID/Random String/UUID", "example": UUID4_EXAMPLE, diff --git a/acapy_agent/anoncreds/models/schema.py b/acapy_agent/anoncreds/models/schema.py index 6a3f56bc03..1a3e3152d2 100644 --- a/acapy_agent/anoncreds/models/schema.py +++ b/acapy_agent/anoncreds/models/schema.py @@ -64,6 +64,7 @@ class Meta: "example": ANONCREDS_DID_EXAMPLE, }, data_key="issuerId", + required=True, ) attr_names = fields.List( fields.Str( @@ -74,11 +75,15 @@ class Meta: ), metadata={"description": "Schema attribute names"}, data_key="attrNames", + required=True, ) name = fields.Str( - metadata={"description": "Schema name", "example": "Example schema"} + metadata={"description": "Schema name", "example": "Example schema"}, + required=True, + ) + version = fields.Str( + metadata={"description": "Schema version", "example": "1.0"}, required=True ) - version = fields.Str(metadata={"description": "Schema version", "example": "1.0"}) class GetSchemaResult(BaseModel): diff --git a/acapy_agent/anoncreds/models/schema_info.py b/acapy_agent/anoncreds/models/schema_info.py new file mode 100644 index 0000000000..e5cda7100d --- /dev/null +++ b/acapy_agent/anoncreds/models/schema_info.py @@ -0,0 +1,26 @@ +"""This class represents schema information for anoncreds.""" + +from typing import Optional + + +class AnoncredsSchemaInfo: + """Represents the schema information for anonymous credentials. + + Attributes: + issuer_id (str): The identifier of the issuer. + name (Optional[str]): The name of the schema. Defaults to None. + version (Optional[str]): The version of the schema. Defaults to None. + + Args: + issuer_id (str): The identifier of the issuer. + name (Optional[str], optional): The name of the schema. Defaults to None. + version (Optional[str], optional): The version of the schema. Defaults to None. + """ + + def __init__( + self, issuer_id: str, name: Optional[str] = None, version: Optional[str] = None + ): + """Initialize the schema information.""" + self.issuer_id = issuer_id + self.name = name + self.version = version diff --git a/acapy_agent/anoncreds/registry.py b/acapy_agent/anoncreds/registry.py index c355b447cd..92b70ac516 100644 --- a/acapy_agent/anoncreds/registry.py +++ b/acapy_agent/anoncreds/registry.py @@ -21,6 +21,7 @@ RevRegDefResult, ) from .models.schema import AnonCredsSchema, GetSchemaResult, SchemaResult +from .models.schema_info import AnoncredsSchemaInfo LOGGER = logging.getLogger(__name__) @@ -99,6 +100,13 @@ async def get_credential_definition( credential_definition_id, ) + async def get_schema_info_by_id( + self, profile: Profile, schema_id: str + ) -> AnoncredsSchemaInfo: + """Get a schema info from the registry.""" + resolver = await self._resolver_for_identifier(schema_id) + return await resolver.get_schema_info_by_id(profile, schema_id) + async def register_credential_definition( self, profile: Profile, diff --git a/acapy_agent/anoncreds/revocation.py b/acapy_agent/anoncreds/revocation.py index e9cc88293f..ad96dfe4cc 100644 --- a/acapy_agent/anoncreds/revocation.py +++ b/acapy_agent/anoncreds/revocation.py @@ -345,8 +345,7 @@ async def set_active_registry(self, rev_reg_def_id: str): ) if not entry: raise AnonCredsRevocationError( - f"{CATEGORY_REV_REG_DEF} with id " - f"{rev_reg_def_id} could not be found" + f"{CATEGORY_REV_REG_DEF} with id {rev_reg_def_id} could not be found" ) if entry.tags["active"] == json.dumps(True): diff --git a/acapy_agent/anoncreds/routes.py b/acapy_agent/anoncreds/routes.py index 9a8fe04669..2f877c5cc6 100644 --- a/acapy_agent/anoncreds/routes.py +++ b/acapy_agent/anoncreds/routes.py @@ -524,6 +524,7 @@ class InnerRevRegDefSchema(OpenAPISchema): "example": ANONCREDS_DID_EXAMPLE, }, data_key="issuerId", + required=True, ) cred_def_id = fields.Str( metadata={ @@ -531,9 +532,11 @@ class InnerRevRegDefSchema(OpenAPISchema): "example": ANONCREDS_SCHEMA_ID_EXAMPLE, }, data_key="credDefId", + required=True, ) tag = fields.Str( - metadata={"description": "tag for revocation registry", "example": "default"} + metadata={"description": "tag for revocation registry", "example": "default"}, + required=True, ) max_cred_num = fields.Int( metadata={ @@ -541,6 +544,7 @@ class InnerRevRegDefSchema(OpenAPISchema): "example": 777, }, data_key="maxCredNum", + required=True, ) @@ -649,7 +653,8 @@ class RevListCreateRequestSchema(OpenAPISchema): metadata={ "description": "Revocation registry definition identifier", "example": ANONCREDS_REV_REG_ID_EXAMPLE, - } + }, + required=True, ) options = fields.Nested(RevListOptionsSchema) diff --git a/acapy_agent/anoncreds/tests/test_holder.py b/acapy_agent/anoncreds/tests/test_holder.py index 34d23ef75f..9667fe76e5 100644 --- a/acapy_agent/anoncreds/tests/test_holder.py +++ b/acapy_agent/anoncreds/tests/test_holder.py @@ -55,11 +55,6 @@ def __init__(self, bad_schema=False, bad_cred_def=False): self.schema_id = "Sc886XPwD1gDcHwmmLDeR2:2:degree schema:45.101.94" self.cred_def_id = "Sc886XPwD1gDcHwmmLDeR2:3:CL:229975:faber.agent.degree_schema" - if bad_schema: - self.schema_id = "bad-schema-id" - if bad_cred_def: - self.cred_def_id = "bad-cred-def-id" - schema_id = "Sc886XPwD1gDcHwmmLDeR2:2:degree schema:45.101.94" cred_def_id = "Sc886XPwD1gDcHwmmLDeR2:3:CL:229975:faber.agent.degree_schema" rev_reg_id = None @@ -72,15 +67,10 @@ def to_dict(self): class MockCredReceivedW3C: - def __init__(self, bad_schema=False, bad_cred_def=False): + def __init__(self): self.schema_id = "Sc886XPwD1gDcHwmmLDeR2:2:degree schema:45.101.94" self.cred_def_id = "Sc886XPwD1gDcHwmmLDeR2:3:CL:229975:faber.agent.degree_schema" - if bad_schema: - self.schema_id = "bad-schema-id" - if bad_cred_def: - self.cred_def_id = "bad-cred-def-id" - def to_json_buffer(self): return b"credential" @@ -89,9 +79,7 @@ def to_dict(self): class MockCredential: - def __init__(self, bad_schema=False, bad_cred_def=False): - self.bad_schema = bad_schema - self.bad_cred_def = bad_cred_def + def __init__(self): self.rev_reg_id = "rev-reg-id" self.rev_reg_index = 0 @@ -101,21 +89,17 @@ def to_dict(self): return MOCK_CRED def process(self, *args, **kwargs): - return MockCredReceived(self.bad_schema, self.bad_cred_def) + return MockCredReceived() class MockW3Credential: - def __init__(self, bad_schema=False, bad_cred_def=False): - self.bad_schema = bad_schema - self.bad_cred_def = bad_cred_def - cred = mock.AsyncMock(auto_spec=W3cCredential) def to_dict(self): return MOCK_W3C_CRED def process(self, *args, **kwargs): - return MockCredReceivedW3C(self.bad_schema, self.bad_cred_def) + return MockCredReceivedW3C() class MockMasterSecret: @@ -285,8 +269,6 @@ async def test_store_credential_fails_to_load_raises_x(self, mock_master_secret) side_effect=[ MockCredential(), MockCredential(), - MockCredential(bad_schema=True), - MockCredential(bad_cred_def=True), ], ) async def test_store_credential(self, mock_load, mock_master_secret): @@ -296,6 +278,9 @@ async def test_store_credential(self, mock_load, mock_master_secret): commit=mock.CoroutineMock(return_value=None), ) ) + self.profile.context.injector.bind_instance( + AnonCredsRegistry, mock.MagicMock(AnonCredsRegistry, autospec=True) + ) # Valid result = await self.holder.store_credential( @@ -321,20 +306,6 @@ async def test_store_credential(self, mock_load, mock_master_secret): {"cred-req-meta": "cred-req-meta"}, ) - # Test bad id's - with self.assertRaises(AnonCredsHolderError): - await self.holder.store_credential( - MOCK_CRED_DEF, - MOCK_PRES, - {"cred-req-meta": "cred-req-meta"}, - ) - with self.assertRaises(AnonCredsHolderError): - await self.holder.store_credential( - MOCK_CRED_DEF, - MOCK_CRED, - {"cred-req-meta": "cred-req-meta"}, - ) - @mock.patch.object(AnonCredsHolder, "get_master_secret", return_value="master-secret") @mock.patch.object( W3cCredential, @@ -362,7 +333,9 @@ async def test_store_credential_w3c( commit=mock.CoroutineMock(return_value=None), ) ) - + self.profile.context.injector.bind_instance( + AnonCredsRegistry, mock.MagicMock(AnonCredsRegistry, autospec=True) + ) with mock.patch.object(jsonld, "expand", return_value=MagicMock()): with mock.patch.object(JsonLdProcessor, "get_values", return_value=["type1"]): result = await self.holder.store_credential_w3c( @@ -384,6 +357,9 @@ async def test_store_credential_failed_trx(self, *_): self.profile.transaction = mock.MagicMock( side_effect=[AskarError(AskarErrorCode.UNEXPECTED, "test")] ) + self.profile.context.injector.bind_instance( + AnonCredsRegistry, mock.MagicMock(AnonCredsRegistry, autospec=True) + ) with self.assertRaises(AnonCredsHolderError): await self.holder.store_credential( diff --git a/acapy_agent/anoncreds/tests/test_routes.py b/acapy_agent/anoncreds/tests/test_routes.py index 607b81f4ae..c59af1a662 100644 --- a/acapy_agent/anoncreds/tests/test_routes.py +++ b/acapy_agent/anoncreds/tests/test_routes.py @@ -97,6 +97,13 @@ async def test_schemas_post(self, mock_create_and_register_schema): }, {}, {"schema": {}}, + { + "schema": { + "attrNames": ["score"], + "name": "Example Schema", + "version": "0.0.1", + } + }, ] ) result = await test_module.schemas_post(self.request) @@ -105,9 +112,12 @@ async def test_schemas_post(self, mock_create_and_register_schema): assert mock_create_and_register_schema.call_count == 1 with self.assertRaises(web.HTTPBadRequest): + # Empty body + await test_module.schemas_post(self.request) + # Empty schema + await test_module.schemas_post(self.request) + # Missing issuerId await test_module.schemas_post(self.request) - - await test_module.schemas_post(self.request) async def test_get_schema(self): self.request.match_info = {"schema_id": "schema_id"} diff --git a/acapy_agent/anoncreds/verifier.py b/acapy_agent/anoncreds/verifier.py index 849c44ab5b..daeaeef7ce 100644 --- a/acapy_agent/anoncreds/verifier.py +++ b/acapy_agent/anoncreds/verifier.py @@ -205,9 +205,7 @@ async def check_timestamps( ) elif uuid in unrevealed_attrs: # nothing to do, attribute value is not revealed - msgs.append( - f"{PresVerifyMsg.CT_UNREVEALED_ATTRIBUTES.value}::" f"{uuid}" - ) + msgs.append(f"{PresVerifyMsg.CT_UNREVEALED_ATTRIBUTES.value}::{uuid}") elif uuid not in self_attested: raise ValueError( f"Presentation attributes mismatch requested attribute {uuid}" @@ -236,8 +234,7 @@ async def check_timestamps( < non_revoc_intervals[uuid].get("to", now) ): msgs.append( - f"{PresVerifyMsg.TSTMP_OUT_NON_REVOC_INTRVAL.value}::" - f"{uuid}" + f"{PresVerifyMsg.TSTMP_OUT_NON_REVOC_INTRVAL.value}::{uuid}" ) LOGGER.warning( f"Timestamp {timestamp} from ledger for item" @@ -266,7 +263,7 @@ async def check_timestamps( < non_revoc_intervals[uuid].get("to", now) ): msgs.append( - f"{PresVerifyMsg.TSTMP_OUT_NON_REVOC_INTRVAL.value}::" f"{uuid}" + f"{PresVerifyMsg.TSTMP_OUT_NON_REVOC_INTRVAL.value}::{uuid}" ) LOGGER.warning( f"Best-effort timestamp {timestamp} " @@ -333,9 +330,7 @@ async def pre_verify(self, pres_req: dict, pres: dict) -> list: elif uuid in unrevealed_attrs: # unrevealed attribute, nothing to do pres_req_attr_spec = {} - msgs.append( - f"{PresVerifyMsg.CT_UNREVEALED_ATTRIBUTES.value}::" f"{uuid}" - ) + msgs.append(f"{PresVerifyMsg.CT_UNREVEALED_ATTRIBUTES.value}::{uuid}") elif uuid in self_attested: if not req_attr.get("restrictions"): continue diff --git a/acapy_agent/config/argparse.py b/acapy_agent/config/argparse.py index 87a67aeaf7..bf911a2a5a 100644 --- a/acapy_agent/config/argparse.py +++ b/acapy_agent/config/argparse.py @@ -269,8 +269,7 @@ def add_arguments(self, parser: ArgumentParser): action="store_true", env_var="ACAPY_DEBUG_CREDENTIALS", help=( - "Enable additional logging around credential exchanges. " - "Default: false." + "Enable additional logging around credential exchanges. Default: false." ), ) parser.add_argument( @@ -278,15 +277,14 @@ def add_arguments(self, parser: ArgumentParser): action="store_true", env_var="ACAPY_DEBUG_PRESENTATIONS", help=( - "Enable additional logging around presentation exchanges. " - "Default: false." + "Enable additional logging around presentation exchanges. Default: false." ), ) parser.add_argument( "--debug-webhooks", action="store_true", env_var="ACAPY_DEBUG_WEBHOOKS", - help=("Emit protocol state object as webhook. " "Default: false."), + help=("Emit protocol state object as webhook. Default: false."), ) parser.add_argument( "--invite", @@ -416,8 +414,7 @@ def add_arguments(self, parser: ArgumentParser): action="store_true", env_var="ACAPY_AUTO_STORE_CREDENTIAL", help=( - "Automatically store an issued credential upon receipt. " - "Default: false." + "Automatically store an issued credential upon receipt. Default: false." ), ) parser.add_argument( @@ -425,8 +422,7 @@ def add_arguments(self, parser: ArgumentParser): action="store_true", env_var="ACAPY_AUTO_VERIFY_PRESENTATION", help=( - "Automatically verify a presentation when it is received. " - "Default: false." + "Automatically verify a presentation when it is received. Default: false." ), ) diff --git a/acapy_agent/config/ledger.py b/acapy_agent/config/ledger.py index 7d7acb1e7e..e8a4791e38 100644 --- a/acapy_agent/config/ledger.py +++ b/acapy_agent/config/ledger.py @@ -220,7 +220,7 @@ async def select_aml_tty(taa_info, provision: bool = False) -> Optional[str]: num_mechanisms = {} for idx, opt in enumerate(found): num_mechanisms[str(idx + 1)] = opt - opts.append(f" {idx+1}. {allow_opts[opt]}") + opts.append(f" {idx + 1}. {allow_opts[opt]}") opts.append(" X. Skip the transaction author agreement") opts_text = "\nPlease select an option:\n" + "\n".join(opts) + "\n[1]> " diff --git a/acapy_agent/connections/base_manager.py b/acapy_agent/connections/base_manager.py index fedd0b7242..549a394a19 100644 --- a/acapy_agent/connections/base_manager.py +++ b/acapy_agent/connections/base_manager.py @@ -1026,8 +1026,7 @@ async def resolve_inbound_connection( receipt.recipient_did_public = True except InjectionError: self._logger.warning( - "Cannot resolve recipient verkey, no wallet defined by " - "context: %s", + "Cannot resolve recipient verkey, no wallet defined by context: %s", receipt.recipient_verkey, ) except WalletNotFoundError: diff --git a/acapy_agent/core/conductor.py b/acapy_agent/core/conductor.py index 9935b6f745..ae62d3c94a 100644 --- a/acapy_agent/core/conductor.py +++ b/acapy_agent/core/conductor.py @@ -857,6 +857,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.""" if self.context.settings.get_value("multitenant.enabled"): + # Sub-wallets subwallet_profiles = await get_subwallet_profiles_from_storage( self.root_profile ) @@ -867,5 +868,5 @@ async def check_for_wallet_upgrades_in_progress(self): ] ) - else: - await upgrade_wallet_to_anoncreds_if_requested(self.root_profile) + # Stand-alone or admin wallet + await upgrade_wallet_to_anoncreds_if_requested(self.root_profile) diff --git a/acapy_agent/did/did_key.py b/acapy_agent/did/did_key.py index 2db750d139..2213e715a1 100644 --- a/acapy_agent/did/did_key.py +++ b/acapy_agent/did/did_key.py @@ -1,12 +1,14 @@ """DID Key class and resolver methods.""" -from ..vc.ld_proofs.constants import DID_V1_CONTEXT_URL +from typing import List, Optional +from ..vc.ld_proofs.constants import DID_V1_CONTEXT_URL, SECURITY_CONTEXT_MULTIKEY_URL from ..wallet.crypto import ed25519_pk_to_curve25519 from ..wallet.key_type import ( BLS12381G1, BLS12381G1G2, BLS12381G2, ED25519, + P256, X25519, KeyType, KeyTypes, @@ -276,7 +278,39 @@ def construct_did_key_ed25519(did_key: "DIDKey") -> dict: return did_doc -def construct_did_signature_key_base(*, id: str, key_id: str, verification_method: dict): +def construct_did_key_p256(did_key: "DIDKey") -> dict: + """Construct P256 did:key. + + Args: + did_key (DIDKey): did key instance to parse p256 did:key document from + + Returns: + dict: The p256 did:key did document + + """ + + did_doc = construct_did_signature_key_base( + id=did_key.did, + key_id=did_key.key_id, + verification_method={ + "id": did_key.key_id, + "type": "Multikey", + "controller": did_key.did, + "publicKeyMultibase": did_key.fingerprint, + }, + extra_context=[SECURITY_CONTEXT_MULTIKEY_URL], + ) + + return did_doc + + +def construct_did_signature_key_base( + *, + id: str, + key_id: str, + verification_method: dict, + extra_context: Optional[List[str]] = None, +): """Create base did key structure to use for most signature keys. May not be suitable for all did key types @@ -284,7 +318,7 @@ def construct_did_signature_key_base(*, id: str, key_id: str, verification_metho """ return { - "@context": DID_V1_CONTEXT_URL, + "@context": [DID_V1_CONTEXT_URL] + (extra_context or []), "id": id, "verificationMethod": [verification_method], "authentication": [key_id], @@ -298,6 +332,7 @@ def construct_did_signature_key_base(*, id: str, key_id: str, verification_metho DID_KEY_RESOLVERS = { ED25519: construct_did_key_ed25519, X25519: construct_did_key_x25519, + P256: construct_did_key_p256, BLS12381G2: construct_did_key_bls12381g2, BLS12381G1: construct_did_key_bls12381g1, BLS12381G1G2: construct_did_key_bls12381g1g2, diff --git a/acapy_agent/did/tests/test_did_key_p256.py b/acapy_agent/did/tests/test_did_key_p256.py new file mode 100644 index 0000000000..1cd6cdcb03 --- /dev/null +++ b/acapy_agent/did/tests/test_did_key_p256.py @@ -0,0 +1,61 @@ +from unittest import TestCase + +from ...wallet.key_type import P256 +from ...wallet.util import b58_to_bytes +from ..did_key import DID_KEY_RESOLVERS, DIDKey +from .test_dids import DID_P256_zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169 + +TEST_P256_BASE58_KEY = "23FF9c3MrW7NkEW6uNDvdSKQMJ4YFTBXNMEPytZfYeE33" +TEST_P256_FINGERPRINT = "zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" +TEST_P256_DID = f"did:key:{TEST_P256_FINGERPRINT}" +TEST_P256_KEY_ID = f"{TEST_P256_DID}#{TEST_P256_FINGERPRINT}" +TEST_P256_PREFIX_BYTES = b"".join([b"\x80\x24", b58_to_bytes(TEST_P256_BASE58_KEY)]) + + +class TestDIDKey(TestCase): + def test_p256_from_public_key(self): + key_bytes = b58_to_bytes(TEST_P256_BASE58_KEY) + did_key = DIDKey.from_public_key(key_bytes, P256) + + assert did_key.did == TEST_P256_DID + + def test_p256_from_public_key_b58(self): + did_key = DIDKey.from_public_key_b58(TEST_P256_BASE58_KEY, P256) + + assert did_key.did == TEST_P256_DID + + def test_p256_from_fingerprint(self): + did_key = DIDKey.from_fingerprint(TEST_P256_FINGERPRINT) + + assert did_key.did == TEST_P256_DID + assert did_key.public_key_b58 == TEST_P256_BASE58_KEY + + def test_p256_from_did(self): + did_key = DIDKey.from_did(TEST_P256_DID) + + assert did_key.public_key_b58 == TEST_P256_BASE58_KEY + + def test_p256_properties(self): + did_key = DIDKey.from_did(TEST_P256_DID) + + assert did_key.fingerprint == TEST_P256_FINGERPRINT + assert did_key.did == TEST_P256_DID + assert did_key.public_key_b58 == TEST_P256_BASE58_KEY + assert did_key.public_key == b58_to_bytes(TEST_P256_BASE58_KEY) + assert did_key.key_type == P256 + assert did_key.key_id == TEST_P256_KEY_ID + assert did_key.prefixed_public_key == TEST_P256_PREFIX_BYTES + + def test_p256_diddoc(self): + did_key = DIDKey.from_did(TEST_P256_DID) + + resolver = DID_KEY_RESOLVERS[P256] + + assert resolver(did_key) == did_key.did_doc + + def test_p256_resolver(self): + did_key = DIDKey.from_did(TEST_P256_DID) + resolver = DID_KEY_RESOLVERS[P256] + did_doc = resolver(did_key) + + assert did_doc == DID_P256_zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169 diff --git a/acapy_agent/did/tests/test_dids.py b/acapy_agent/did/tests/test_dids.py index 9a1e246564..7c97da9217 100644 --- a/acapy_agent/did/tests/test_dids.py +++ b/acapy_agent/did/tests/test_dids.py @@ -1,5 +1,5 @@ DID_ED25519_z6MkmjY8GnV5i9YTDtPETC2uUAW6ejw3nk5mXF5yci5ab7th = { - "@context": "https://www.w3.org/ns/did/v1", + "@context": ["https://www.w3.org/ns/did/v1"], "id": "did:key:z6MkmjY8GnV5i9YTDtPETC2uUAW6ejw3nk5mXF5yci5ab7th", "verificationMethod": [ { @@ -51,8 +51,34 @@ ], } +DID_P256_zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169 = { + "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], + "id": "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + "verificationMethod": [ + { + "id": "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + "type": "Multikey", + "controller": "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + "publicKeyMultibase": "zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169", + } + ], + "authentication": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ], + "assertionMethod": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ], + "capabilityDelegation": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ], + "capabilityInvocation": [ + "did:key:zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169#zDnaerDaTF5BXEavCrfRZEk316dpbLsfPDZ3WJ5hRTPFU2169" + ], + "keyAgreement": [], +} + DID_BLS12381G2_zUC71nmwvy83x1UzNKbZbS7N9QZx8rqpQx3Ee3jGfKiEkZngTKzsRoqobX6wZdZF5F93pSGYYco3gpK9tc53ruWUo2tkBB9bxPCFBUjq2th8FbtT4xih6y6Q1K9EL4Th86NiCGT = { - "@context": "https://www.w3.org/ns/did/v1", + "@context": ["https://www.w3.org/ns/did/v1"], "id": "did:key:zUC71nmwvy83x1UzNKbZbS7N9QZx8rqpQx3Ee3jGfKiEkZngTKzsRoqobX6wZdZF5F93pSGYYco3gpK9tc53ruWUo2tkBB9bxPCFBUjq2th8FbtT4xih6y6Q1K9EL4Th86NiCGT", "verificationMethod": [ { @@ -78,7 +104,7 @@ } DID_BLS12381G1_z3tEFALUKUzzCAvytMHX8X4SnsNsq6T5tC5Zb18oQEt1FqNcJXqJ3AA9umgzA9yoqPBeWA = { - "@context": "https://www.w3.org/ns/did/v1", + "@context": ["https://www.w3.org/ns/did/v1"], "id": "did:key:z3tEFALUKUzzCAvytMHX8X4SnsNsq6T5tC5Zb18oQEt1FqNcJXqJ3AA9umgzA9yoqPBeWA", "verificationMethod": [ { diff --git a/acapy_agent/indy/credx/issuer.py b/acapy_agent/indy/credx/issuer.py index 8cd857df9e..c67b4d911a 100644 --- a/acapy_agent/indy/credx/issuer.py +++ b/acapy_agent/indy/credx/issuer.py @@ -330,6 +330,11 @@ async def create_credential( revoc = None credential_revocation_id = None + # This is for compatibility with an anoncreds holder + if not credential_request.get("prover_did"): + credential_request["prover_did"] = credential_request["entropy"] + del credential_request["entropy"] + try: ( credential, diff --git a/acapy_agent/indy/models/tests/test_pres_preview.py b/acapy_agent/indy/models/tests/test_pres_preview.py index b616639845..2e7570a85f 100644 --- a/acapy_agent/indy/models/tests/test_pres_preview.py +++ b/acapy_agent/indy/models/tests/test_pres_preview.py @@ -88,7 +88,7 @@ "name": "player", "restrictions": [ {{ - "cred_def_id": "{CD_ID['score']}" + "cred_def_id": "{CD_ID["score"]}" }} ] }}, @@ -96,7 +96,7 @@ "name": "screenCapture", "restrictions": [ {{ - "cred_def_id": "{CD_ID['score']}" + "cred_def_id": "{CD_ID["score"]}" }} ] }} @@ -108,7 +108,7 @@ "p_value": 1000000, "restrictions": [ {{ - "cred_def_id": "{CD_ID['score']}" + "cred_def_id": "{CD_ID["score"]}" }} ] }} @@ -125,7 +125,7 @@ "names": ["player", "screenCapture"], "restrictions": [ {{ - "cred_def_id": "{CD_ID['score']}" + "cred_def_id": "{CD_ID["score"]}" }} ] }}, @@ -133,7 +133,7 @@ "names": ["member", "since"], "restrictions": [ {{ - "cred_def_id": "{CD_ID['membership']}" + "cred_def_id": "{CD_ID["membership"]}" }} ] }} diff --git a/acapy_agent/indy/verifier.py b/acapy_agent/indy/verifier.py index 2a2bb0f243..3bb790593f 100644 --- a/acapy_agent/indy/verifier.py +++ b/acapy_agent/indy/verifier.py @@ -211,9 +211,7 @@ async def check_timestamps( ) elif uuid in unrevealed_attrs: # nothing to do, attribute value is not revealed - msgs.append( - f"{PresVerifyMsg.CT_UNREVEALED_ATTRIBUTES.value}::" f"{uuid}" - ) + msgs.append(f"{PresVerifyMsg.CT_UNREVEALED_ATTRIBUTES.value}::{uuid}") elif uuid not in self_attested: raise ValueError( f"Presentation attributes mismatch requested attribute {uuid}" @@ -242,8 +240,7 @@ async def check_timestamps( < non_revoc_intervals[uuid].get("to", now) ): msgs.append( - f"{PresVerifyMsg.TSTMP_OUT_NON_REVOC_INTRVAL.value}::" - f"{uuid}" + f"{PresVerifyMsg.TSTMP_OUT_NON_REVOC_INTRVAL.value}::{uuid}" ) LOGGER.warning( f"Timestamp {timestamp} from ledger for item" @@ -272,7 +269,7 @@ async def check_timestamps( < non_revoc_intervals[uuid].get("to", now) ): msgs.append( - f"{PresVerifyMsg.TSTMP_OUT_NON_REVOC_INTRVAL.value}::" f"{uuid}" + f"{PresVerifyMsg.TSTMP_OUT_NON_REVOC_INTRVAL.value}::{uuid}" ) LOGGER.warning( f"Best-effort timestamp {timestamp} " @@ -339,9 +336,7 @@ async def pre_verify(self, pres_req: dict, pres: dict) -> list: elif uuid in unrevealed_attrs: # unrevealed attribute, nothing to do pres_req_attr_spec = {} - msgs.append( - f"{PresVerifyMsg.CT_UNREVEALED_ATTRIBUTES.value}::" f"{uuid}" - ) + msgs.append(f"{PresVerifyMsg.CT_UNREVEALED_ATTRIBUTES.value}::{uuid}") elif uuid in self_attested: if not req_attr.get("restrictions"): continue diff --git a/acapy_agent/ledger/base.py b/acapy_agent/ledger/base.py index ffafe3bb31..576d591a0a 100644 --- a/acapy_agent/ledger/base.py +++ b/acapy_agent/ledger/base.py @@ -700,8 +700,7 @@ async def send_schema_anoncreds( ) if schema_info: LOGGER.warning( - "Schema already exists on ledger. Returning details." - " Error: %s", + "Schema already exists on ledger. Returning details. Error: %s", e, ) raise LedgerObjectAlreadyExistsError( diff --git a/acapy_agent/messaging/decorators/signature_decorator.py b/acapy_agent/messaging/decorators/signature_decorator.py index ed7a217611..4d980d2f22 100644 --- a/acapy_agent/messaging/decorators/signature_decorator.py +++ b/acapy_agent/messaging/decorators/signature_decorator.py @@ -120,8 +120,8 @@ def __str__(self): """Get a string representation of this class.""" return ( f"{self.__class__.__name__}" - + f"(signature_type='{self.signature_type,}', " - + f"signature='{self.signature,}', " + + f"(signature_type='{(self.signature_type,)}', " + + f"signature='{(self.signature,)}', " + f"sig_data='{self.sig_data}', signer='{self.signer}')" ) diff --git a/acapy_agent/messaging/jsonld/create_verify_data.py b/acapy_agent/messaging/jsonld/create_verify_data.py index a2ed01712b..1ec1ef7502 100644 --- a/acapy_agent/messaging/jsonld/create_verify_data.py +++ b/acapy_agent/messaging/jsonld/create_verify_data.py @@ -94,7 +94,7 @@ def create_verify_data(data, signature_options, document_loader=None): ) dropped = set(data.keys()) - set(for_diff.keys()) raise DroppedAttributeError( - f"{dropped} attributes dropped. " "Provide definitions in context to correct." + f"{dropped} attributes dropped. Provide definitions in context to correct." ) # Check proof for dropped attributes attr = [ diff --git a/acapy_agent/messaging/jsonld/tests/__init__.py b/acapy_agent/messaging/jsonld/tests/__init__.py index caed66d51c..c231a33645 100644 --- a/acapy_agent/messaging/jsonld/tests/__init__.py +++ b/acapy_agent/messaging/jsonld/tests/__init__.py @@ -13,7 +13,7 @@ "issuer": ("did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), "issuanceDate": "2020-03-10T04:24:12.164Z", "credentialSubject": { - "id": ("did:key:" "z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), + "id": ("did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), "degree": { "type": "BachelorDegree", "name": "Bachelor of Science and Arts", @@ -244,7 +244,7 @@ "issuer": ("did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), "issuanceDate": "2020-03-10T04:24:12.164Z", "credentialSubject": { - "id": ("did:key:" "z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), + "id": ("did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), "degree": { "type": "BachelorDegree", "name": "Bachelor of Science and Arts", @@ -365,7 +365,7 @@ "issuer": ("did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), "issuanceDate": "2020-03-10T04:24:12.164Z", "credentialSubject": { - "id": ("did:key:" "z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), + "id": ("did:key:z6MkjRagNiMu91DduvCvgEsqLZDVzrJzFrwahc4tXLt9DoHd"), "degree": { "type": "BachelorDegree", "name": "Bachelor of Science and Arts", diff --git a/acapy_agent/messaging/tests/test_valid.py b/acapy_agent/messaging/tests/test_valid.py index b99737c4a8..65d8986e8a 100644 --- a/acapy_agent/messaging/tests/test_valid.py +++ b/acapy_agent/messaging/tests/test_valid.py @@ -12,7 +12,7 @@ CREDENTIAL_TYPE_VALIDATE, DID_KEY_VALIDATE, DID_POSTURE_VALIDATE, - DID_TDW_VALIDATE, + DID_WEBVH_VALIDATE, ENDPOINT_TYPE_VALIDATE, ENDPOINT_VALIDATE, INDY_CRED_DEF_ID_VALIDATE, @@ -115,23 +115,23 @@ def test_indy_did(self): INDY_DID_VALIDATE("Q4zqM7aXqm7gDQkUVLng9h") INDY_DID_VALIDATE("did:sov:Q4zqM7aXqm7gDQkUVLng9h") - def test_tdw_did(self): - valid_tdw_dids = [ - "did:tdw:QmUchSB5f5DJQks9CeyLJjhAy4iKJcYzRyiuYq3sjV13px:example.com", - "did:tdw:QmZiKXwQVfyZVuvCsuHpQh4arSUpEmeVVRvSfv3uiEycSr:example.com%3A5000", + def test_webvh_did(self): + valid_webvh_dids = [ + "did:webvh:QmUchSB5f5DJQks9CeyLJjhAy4iKJcYzRyiuYq3sjV13px:example.com", + "did:webvh:QmZiKXwQVfyZVuvCsuHpQh4arSUpEmeVVRvSfv3uiEycSr:example.com%3A5000", ] - for valid_tdw_did in valid_tdw_dids: - DID_TDW_VALIDATE(valid_tdw_did) + for valid_webvh_did in valid_webvh_dids: + DID_WEBVH_VALIDATE(valid_webvh_did) - non_valid_tdw_dids = [ + non_valid_webvh_dids = [ "did:web:QmUchSB5f5DJQks9CeyLJjhAy4iKJcYzRyiuYq3sjV13px", # Did urls are not allowed - "did:tdw:QmP9VWaTCHcyztDpRj9XSHvZbmYe3m9HZ61KoDtZgWaXVU:example.com%3A5000#z6MkkzY9skorPaoEbCJFKUo7thD8Yb8MBs28aJRopf1TUo9V", - "did:tdw:QmZiKXwQVfyZVuvCsuHpQh4arSUpEmeVVRvSfv3uiEycSr:example.com%3A5000/whois", + "did:webvh:QmP9VWaTCHcyztDpRj9XSHvZbmYe3m9HZ61KoDtZgWaXVU:example.com%3A5000#z6MkkzY9skorPaoEbCJFKUo7thD8Yb8MBs28aJRopf1TUo9V", + "did:webvh:QmZiKXwQVfyZVuvCsuHpQh4arSUpEmeVVRvSfv3uiEycSr:example.com%3A5000/whois", ] - for non_valid_tdw_did in non_valid_tdw_dids: + for non_valid_webvh_did in non_valid_webvh_dids: with self.assertRaises(ValidationError): - DID_TDW_VALIDATE(non_valid_tdw_did) + DID_WEBVH_VALIDATE(non_valid_webvh_did) def test_indy_raw_public_key(self): non_indy_raw_public_keys = [ diff --git a/acapy_agent/messaging/valid.py b/acapy_agent/messaging/valid.py index 3089fd25ff..cb706deab0 100644 --- a/acapy_agent/messaging/valid.py +++ b/acapy_agent/messaging/valid.py @@ -223,9 +223,7 @@ class JSONWebToken(Regexp): """Validate JSON Web Token.""" EXAMPLE = ( - "eyJhbGciOiJFZERTQSJ9." - "eyJhIjogIjAifQ." - "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" + "eyJhbGciOiJFZERTQSJ9.eyJhIjogIjAifQ.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk" ) PATTERN = r"^[a-zA-Z0-9_-]+\.[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]+$" @@ -319,17 +317,19 @@ def __init__(self): ) -class DIDTdw(Regexp): - """Validate value against did:tdw specification.""" +class DIDWebvh(Regexp): + """Validate value against did:webvh specification.""" - EXAMPLE = "did:tdw:QmP9VWaTCHcyztDpRj9XSHvZbmYe3m9HZ61KoDtZgWaXVU:example.com%3A5000" - PATTERN = re.compile(r"^(did:tdw:)([a-zA-Z0-9%._-]*:)*[a-zA-Z0-9%._-]+$") + EXAMPLE = ( + "did:webvh:QmP9VWaTCHcyztDpRj9XSHvZbmYe3m9HZ61KoDtZgWaXVU:example.com%3A5000" + ) + PATTERN = re.compile(r"^(did:webvh:)([a-zA-Z0-9%._-]*:)*[a-zA-Z0-9%._-]+$") def __init__(self): """Initialize the instance.""" super().__init__( - DIDTdw.PATTERN, error="Value {input} is not in W3C did:tdw format" + DIDWebvh.PATTERN, error="Value {input} is not in W3C did:webvh format" ) @@ -924,7 +924,7 @@ def __call__(self, value): uri_validator(subject["id"]) except ValidationError: raise ValidationError( - f'credential subject id {subject["id"]} must be URI' + f"credential subject id {subject['id']} must be URI" ) from None return value @@ -1017,8 +1017,8 @@ def __init__( DID_WEB_VALIDATE = DIDWeb() DID_WEB_EXAMPLE = DIDWeb.EXAMPLE -DID_TDW_VALIDATE = DIDTdw() -DID_TDW_EXAMPLE = DIDTdw.EXAMPLE +DID_WEBVH_VALIDATE = DIDWebvh() +DID_WEBVH_EXAMPLE = DIDWebvh.EXAMPLE ROUTING_KEY_VALIDATE = RoutingKey() ROUTING_KEY_EXAMPLE = RoutingKey.EXAMPLE diff --git a/acapy_agent/multitenant/admin/routes.py b/acapy_agent/multitenant/admin/routes.py index 8ebea184a7..c89b302914 100644 --- a/acapy_agent/multitenant/admin/routes.py +++ b/acapy_agent/multitenant/admin/routes.py @@ -314,8 +314,7 @@ class RemoveWalletRequestSchema(OpenAPISchema): wallet_key = fields.Str( metadata={ "description": ( - "Master key used for key derivation. Only required for" - " unmanaged wallets." + "Master key used for key derivation. Only required for unmanaged wallets." ), "example": "MySecretKey123", } @@ -328,8 +327,7 @@ class CreateWalletTokenRequestSchema(OpenAPISchema): wallet_key = fields.Str( metadata={ "description": ( - "Master key used for key derivation. Only required for" - " unmanaged wallets." + "Master key used for key derivation. Only required for unmanaged wallets." ), "example": "MySecretKey123", } diff --git a/acapy_agent/multitenant/single_wallet_askar_manager.py b/acapy_agent/multitenant/single_wallet_askar_manager.py index 4e39683247..56e9051a13 100644 --- a/acapy_agent/multitenant/single_wallet_askar_manager.py +++ b/acapy_agent/multitenant/single_wallet_askar_manager.py @@ -71,11 +71,12 @@ async def get_wallet_profile( "multitenant.wallet_name", self.DEFAULT_MULTITENANT_WALLET_NAME ) context = base_context.copy() + sub_wallet_settings = { "wallet.recreate": False, "wallet.seed": None, - "wallet.key": "", - "wallet.rekey": None, + "wallet.key": base_context.settings.get("wallet.key", ""), + "wallet.rekey": base_context.settings.get("wallet.rekey"), "wallet.id": None, "wallet.name": multitenant_wallet_name, "wallet.type": "askar", diff --git a/acapy_agent/protocols/connections/v1_0/manager.py b/acapy_agent/protocols/connections/v1_0/manager.py index 9d7c0bf86d..3767c76998 100644 --- a/acapy_agent/protocols/connections/v1_0/manager.py +++ b/acapy_agent/protocols/connections/v1_0/manager.py @@ -559,7 +559,7 @@ async def receive_request( if not connection: if not self.profile.settings.get("requests_through_public_did"): raise ConnectionManagerError( - "Unsolicited connection requests to " "public DID is not enabled" + "Unsolicited connection requests to public DID is not enabled" ) connection = ConnRecord() connection.invitation_key = connection_key diff --git a/acapy_agent/protocols/connections/v1_0/messages/connection_response.py b/acapy_agent/protocols/connections/v1_0/messages/connection_response.py index 8bf11eae21..aeb9512314 100644 --- a/acapy_agent/protocols/connections/v1_0/messages/connection_response.py +++ b/acapy_agent/protocols/connections/v1_0/messages/connection_response.py @@ -9,8 +9,7 @@ from ..models.connection_detail import ConnectionDetail, ConnectionDetailSchema HANDLER_CLASS = ( - f"{PROTOCOL_PACKAGE}.handlers." - "connection_response_handler.ConnectionResponseHandler" + f"{PROTOCOL_PACKAGE}.handlers.connection_response_handler.ConnectionResponseHandler" ) diff --git a/acapy_agent/protocols/coordinate_mediation/v1_0/message_types.py b/acapy_agent/protocols/coordinate_mediation/v1_0/message_types.py index c1b0596d7e..869116665f 100644 --- a/acapy_agent/protocols/coordinate_mediation/v1_0/message_types.py +++ b/acapy_agent/protocols/coordinate_mediation/v1_0/message_types.py @@ -29,8 +29,7 @@ KEYLIST_QUERY: f"{PROTOCOL_PACKAGE}.messages.keylist_query.KeylistQuery", KEYLIST_UPDATE: f"{PROTOCOL_PACKAGE}.messages.keylist_update.KeylistUpdate", KEYLIST_UPDATE_RESPONSE: ( - f"{PROTOCOL_PACKAGE}." - "messages.keylist_update_response.KeylistUpdateResponse" + f"{PROTOCOL_PACKAGE}.messages.keylist_update_response.KeylistUpdateResponse" ), MEDIATE_DENY: f"{PROTOCOL_PACKAGE}.messages.mediate_deny.MediationDeny", MEDIATE_GRANT: f"{PROTOCOL_PACKAGE}.messages.mediate_grant.MediationGrant", diff --git a/acapy_agent/protocols/coordinate_mediation/v1_0/messages/problem_report.py b/acapy_agent/protocols/coordinate_mediation/v1_0/messages/problem_report.py index f264b26e99..747b4a9f11 100644 --- a/acapy_agent/protocols/coordinate_mediation/v1_0/messages/problem_report.py +++ b/acapy_agent/protocols/coordinate_mediation/v1_0/messages/problem_report.py @@ -9,7 +9,7 @@ from ..message_types import PROBLEM_REPORT, PROTOCOL_PACKAGE HANDLER_CLASS = ( - f"{PROTOCOL_PACKAGE}.handlers" ".problem_report_handler.CMProblemReportHandler" + f"{PROTOCOL_PACKAGE}.handlers.problem_report_handler.CMProblemReportHandler" ) LOGGER = logging.getLogger(__name__) diff --git a/acapy_agent/protocols/didexchange/v1_0/messages/tests/test_request.py b/acapy_agent/protocols/didexchange/v1_0/messages/tests/test_request.py index 3cd83db2d7..ddfd731e13 100644 --- a/acapy_agent/protocols/didexchange/v1_0/messages/tests/test_request.py +++ b/acapy_agent/protocols/didexchange/v1_0/messages/tests/test_request.py @@ -82,8 +82,7 @@ def test_type(self): assert self.request._type == DIDCommPrefix.qualify_current(DIDX_REQUEST) @mock.patch( - "acapy_agent.protocols.didexchange.v1_0.messages." - "request.DIDXRequestSchema.load" + "acapy_agent.protocols.didexchange.v1_0.messages.request.DIDXRequestSchema.load" ) def test_deserialize(self, mock_request_schema_load): """ @@ -97,8 +96,7 @@ def test_deserialize(self, mock_request_schema_load): assert request is mock_request_schema_load.return_value @mock.patch( - "acapy_agent.protocols.didexchange.v1_0.messages." - "request.DIDXRequestSchema.dump" + "acapy_agent.protocols.didexchange.v1_0.messages.request.DIDXRequestSchema.dump" ) def test_serialize(self, mock_request_schema_dump): """ diff --git a/acapy_agent/protocols/didexchange/v1_0/messages/tests/test_response.py b/acapy_agent/protocols/didexchange/v1_0/messages/tests/test_response.py index 5743bb669f..3ebd0ec342 100644 --- a/acapy_agent/protocols/didexchange/v1_0/messages/tests/test_response.py +++ b/acapy_agent/protocols/didexchange/v1_0/messages/tests/test_response.py @@ -76,8 +76,7 @@ def test_type(self): assert self.response._type == DIDCommPrefix.qualify_current(DIDX_RESPONSE) @mock.patch( - "acapy_agent.protocols.didexchange.v1_0.messages." - "response.DIDXResponseSchema.load" + "acapy_agent.protocols.didexchange.v1_0.messages.response.DIDXResponseSchema.load" ) def test_deserialize(self, mock_response_schema_load): """ @@ -91,8 +90,7 @@ def test_deserialize(self, mock_response_schema_load): assert response is mock_response_schema_load.return_value @mock.patch( - "acapy_agent.protocols.didexchange.v1_0.messages." - "response.DIDXResponseSchema.dump" + "acapy_agent.protocols.didexchange.v1_0.messages.response.DIDXResponseSchema.dump" ) def test_serialize(self, mock_response_schema_dump): """ diff --git a/acapy_agent/protocols/endorse_transaction/v1_0/manager.py b/acapy_agent/protocols/endorse_transaction/v1_0/manager.py index 91597cfbbe..5e85ce6ce6 100644 --- a/acapy_agent/protocols/endorse_transaction/v1_0/manager.py +++ b/acapy_agent/protocols/endorse_transaction/v1_0/manager.py @@ -316,7 +316,7 @@ async def create_endorse_response( endorsed_msg = json.dumps(ledger_response) else: raise TransactionManagerError( - f"Invalid goal code for transaction record:" f" {txn_goal_code}" + f"Invalid goal code for transaction record: {txn_goal_code}" ) # need to return the endorsed msg or else the ledger will reject the diff --git a/acapy_agent/protocols/introduction/v0_1/messages/tests/test_forward_invitation.py b/acapy_agent/protocols/introduction/v0_1/messages/tests/test_forward_invitation.py index 65e999ee43..07a16ea3d4 100644 --- a/acapy_agent/protocols/introduction/v0_1/messages/tests/test_forward_invitation.py +++ b/acapy_agent/protocols/introduction/v0_1/messages/tests/test_forward_invitation.py @@ -34,7 +34,7 @@ def test_type(self): assert self.invitation._type == DIDCommPrefix.qualify_current(FORWARD_INVITATION) @mock.patch( - f"{PROTOCOL_PACKAGE}.messages." "forward_invitation.ForwardInvitationSchema.load" + f"{PROTOCOL_PACKAGE}.messages.forward_invitation.ForwardInvitationSchema.load" ) def test_deserialize(self, mock_invitation_schema_load): """ @@ -48,7 +48,7 @@ def test_deserialize(self, mock_invitation_schema_load): assert invitation is mock_invitation_schema_load.return_value @mock.patch( - f"{PROTOCOL_PACKAGE}.messages." "forward_invitation.ForwardInvitationSchema.dump" + f"{PROTOCOL_PACKAGE}.messages.forward_invitation.ForwardInvitationSchema.dump" ) def test_serialize(self, mock_invitation_schema_dump): """ diff --git a/acapy_agent/protocols/introduction/v0_1/messages/tests/test_invitation_request.py b/acapy_agent/protocols/introduction/v0_1/messages/tests/test_invitation_request.py index 306b45c99e..65e0dd57c9 100644 --- a/acapy_agent/protocols/introduction/v0_1/messages/tests/test_invitation_request.py +++ b/acapy_agent/protocols/introduction/v0_1/messages/tests/test_invitation_request.py @@ -26,7 +26,7 @@ def test_type(self): assert self.request._type == DIDCommPrefix.qualify_current(INVITATION_REQUEST) @mock.patch( - f"{PROTOCOL_PACKAGE}.messages." "invitation_request.InvitationRequestSchema.load" + f"{PROTOCOL_PACKAGE}.messages.invitation_request.InvitationRequestSchema.load" ) def test_deserialize(self, mock_invitation_schema_load): """ @@ -40,7 +40,7 @@ def test_deserialize(self, mock_invitation_schema_load): assert request is mock_invitation_schema_load.return_value @mock.patch( - f"{PROTOCOL_PACKAGE}.messages." "invitation_request.InvitationRequestSchema.dump" + f"{PROTOCOL_PACKAGE}.messages.invitation_request.InvitationRequestSchema.dump" ) def test_serialize(self, mock_invitation_schema_dump): """ diff --git a/acapy_agent/protocols/issue_credential/v1_0/messages/tests/test_credential_request.py b/acapy_agent/protocols/issue_credential/v1_0/messages/tests/test_credential_request.py index 4276d06480..c88ed6a561 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/messages/tests/test_credential_request.py +++ b/acapy_agent/protocols/issue_credential/v1_0/messages/tests/test_credential_request.py @@ -70,7 +70,7 @@ def test_type(self): ) @mock.patch( - f"{PROTOCOL_PACKAGE}.messages." "credential_request.CredentialRequestSchema.load" + f"{PROTOCOL_PACKAGE}.messages.credential_request.CredentialRequestSchema.load" ) def test_deserialize(self, mock_credential_request_schema_load): """ @@ -84,7 +84,7 @@ def test_deserialize(self, mock_credential_request_schema_load): assert credential_request is mock_credential_request_schema_load.return_value @mock.patch( - f"{PROTOCOL_PACKAGE}.messages." "credential_request.CredentialRequestSchema.dump" + f"{PROTOCOL_PACKAGE}.messages.credential_request.CredentialRequestSchema.dump" ) def test_serialize(self, mock_credential_request_schema_dump): """ diff --git a/acapy_agent/protocols/issue_credential/v1_0/routes.py b/acapy_agent/protocols/issue_credential/v1_0/routes.py index 1b5581a51b..8afe893a5f 100644 --- a/acapy_agent/protocols/issue_credential/v1_0/routes.py +++ b/acapy_agent/protocols/issue_credential/v1_0/routes.py @@ -477,8 +477,7 @@ async def credential_exchange_retrieve(request: web.BaseRequest): @docs( tags=["issue-credential v1.0"], summary=( - "Create a credential record without " - "sending (generally for use with Out-Of-Band)" + "Create a credential record without sending (generally for use with Out-Of-Band)" ), deprecated=True, ) 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 f795929e8b..07f2d948c4 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 @@ -132,7 +132,7 @@ "nonce": "1234567890", } ANONCREDS_CRED_REQ = { - "prover_did": TEST_DID, + "entropy": TEST_DID, "cred_def_id": CRED_DEF_ID, "blinded_ms": { "u": "12345", diff --git a/acapy_agent/protocols/issue_credential/v2_0/messages/tests/test_cred_problem_report.py b/acapy_agent/protocols/issue_credential/v2_0/messages/tests/test_cred_problem_report.py index a1b6bc31d1..47b91020da 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/messages/tests/test_cred_problem_report.py +++ b/acapy_agent/protocols/issue_credential/v2_0/messages/tests/test_cred_problem_report.py @@ -29,8 +29,7 @@ def test_init_type(self): assert prob._type == DIDCommPrefix.qualify_current(CRED_20_PROBLEM_REPORT) @mock.patch( - f"{PROTOCOL_PACKAGE}.messages.cred_problem_report." - "V20CredProblemReportSchema.load" + f"{PROTOCOL_PACKAGE}.messages.cred_problem_report.V20CredProblemReportSchema.load" ) def test_deserialize(self, mock_load): """Test deserialization.""" @@ -48,8 +47,7 @@ def test_deserialize(self, mock_load): assert prob is mock_load.return_value @mock.patch( - f"{PROTOCOL_PACKAGE}.messages.cred_problem_report." - "V20CredProblemReportSchema.dump" + f"{PROTOCOL_PACKAGE}.messages.cred_problem_report.V20CredProblemReportSchema.dump" ) def test_serialize(self, mock_dump): """Test serialization.""" diff --git a/acapy_agent/protocols/issue_credential/v2_0/routes.py b/acapy_agent/protocols/issue_credential/v2_0/routes.py index de7c61f2e0..f1517cc0ed 100644 --- a/acapy_agent/protocols/issue_credential/v2_0/routes.py +++ b/acapy_agent/protocols/issue_credential/v2_0/routes.py @@ -698,8 +698,7 @@ async def credential_exchange_retrieve(request: web.BaseRequest): @docs( tags=["issue-credential v2.0"], summary=( - "Create a credential record without " - "sending (generally for use with Out-Of-Band)" + "Create a credential record without sending (generally for use with Out-Of-Band)" ), ) @request_schema(V20IssueCredSchemaCore()) diff --git a/acapy_agent/protocols/out_of_band/v1_0/message_types.py b/acapy_agent/protocols/out_of_band/v1_0/message_types.py index 4160d99349..181bdff7e0 100644 --- a/acapy_agent/protocols/out_of_band/v1_0/message_types.py +++ b/acapy_agent/protocols/out_of_band/v1_0/message_types.py @@ -26,7 +26,7 @@ INVITATION: f"{PROTOCOL_PACKAGE}.messages.invitation.Invitation", MESSAGE_REUSE: f"{PROTOCOL_PACKAGE}.messages.reuse.HandshakeReuse", MESSAGE_REUSE_ACCEPT: ( - f"{PROTOCOL_PACKAGE}.messages" ".reuse_accept.HandshakeReuseAccept" + f"{PROTOCOL_PACKAGE}.messages.reuse_accept.HandshakeReuseAccept" ), PROBLEM_REPORT: f"{PROTOCOL_PACKAGE}.messages.problem_report.OOBProblemReport", } diff --git a/acapy_agent/protocols/out_of_band/v1_0/messages/reuse_accept.py b/acapy_agent/protocols/out_of_band/v1_0/messages/reuse_accept.py index def92b3c0b..9e44b41254 100644 --- a/acapy_agent/protocols/out_of_band/v1_0/messages/reuse_accept.py +++ b/acapy_agent/protocols/out_of_band/v1_0/messages/reuse_accept.py @@ -8,8 +8,7 @@ from ..message_types import DEFAULT_VERSION, MESSAGE_REUSE_ACCEPT, PROTOCOL_PACKAGE HANDLER_CLASS = ( - f"{PROTOCOL_PACKAGE}.handlers" - ".reuse_accept_handler.HandshakeReuseAcceptMessageHandler" + f"{PROTOCOL_PACKAGE}.handlers.reuse_accept_handler.HandshakeReuseAcceptMessageHandler" ) diff --git a/acapy_agent/protocols/present_proof/dif/pres_exch.py b/acapy_agent/protocols/present_proof/dif/pres_exch.py index 677151954d..33f39d71ac 100644 --- a/acapy_agent/protocols/present_proof/dif/pres_exch.py +++ b/acapy_agent/protocols/present_proof/dif/pres_exch.py @@ -595,8 +595,7 @@ class Meta: data_key="schema", metadata={ "description": ( - "Accepts a list of schema or a dict containing filters like" - " oneof_filter." + "Accepts a list of schema or a dict containing filters like oneof_filter." ), "example": { "oneof_filter": [ diff --git a/acapy_agent/protocols/present_proof/dif/pres_exch_handler.py b/acapy_agent/protocols/present_proof/dif/pres_exch_handler.py index 3eff6d28f9..5641aaefc9 100644 --- a/acapy_agent/protocols/present_proof/dif/pres_exch_handler.py +++ b/acapy_agent/protocols/present_proof/dif/pres_exch_handler.py @@ -31,6 +31,7 @@ DocumentLoader, Ed25519Signature2018, Ed25519Signature2020, + EcdsaSecp256r1Signature2019, WalletKeyPair, ) from ....vc.ld_proofs.constants import ( @@ -45,7 +46,7 @@ ProofPurposeStr, ) from ....wallet.error import WalletError, WalletNotFoundError -from ....wallet.key_type import BLS12381G2, ED25519 +from ....wallet.key_type import BLS12381G2, ED25519, P256 from .pres_exch import ( Constraints, DIFField, @@ -79,6 +80,7 @@ class DIFPresExchHandler: ISSUE_SIGNATURE_SUITE_KEY_TYPE_MAPPING = { Ed25519Signature2018: ED25519, Ed25519Signature2020: ED25519, + EcdsaSecp256r1Signature2019: P256, } if BbsBlsSignature2020.BBS_SUPPORTED: @@ -193,6 +195,8 @@ async def get_sign_key_credential_subject_id( filtered_creds_list = [] if self.proof_type == BbsBlsSignature2020.signature_type: reqd_key_type = BLS12381G2 + elif self.proof_type == EcdsaSecp256r1Signature2019.signature_type: + reqd_key_type = P256 else: reqd_key_type = ED25519 for cred in applicable_creds: 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 3af1efe80e..89cc85e99f 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 @@ -24,7 +24,7 @@ ) from .....wallet.did_method import KEY, SOV, DIDMethods from .....wallet.error import WalletNotFoundError -from .....wallet.key_type import BLS12381G2, ED25519, KeyTypes +from .....wallet.key_type import BLS12381G2, ED25519, P256, KeyTypes from .. import pres_exch_handler as test_module from ..pres_exch import ( Constraints, @@ -2070,6 +2070,70 @@ async def test_get_sign_key_credential_subject_id_error(self): VC_RECORDS ) + async def test_get_sign_key_credential_subject_id_secp256r1(self): + dif_pres_exch_handler = DIFPresExchHandler( + self.profile, proof_type="EcdsaSecp256r1Signature2019" + ) + + VC_RECORDS = [ + VCRecord( + contexts=[ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1", + ], + expanded_types=[ + "https://www.w3.org/2018/credentials#VerifiableCredential", + "https://example.org/examples#UniversityDegreeCredential", + ], + issuer_id="https://example.edu/issuers/565049", + subject_ids=["did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL"], + proof_types=["EcdsaSecp256r1Signature2019"], + schema_ids=["https://example.org/examples/degree.json"], + cred_value={"...": "..."}, + given_id="http://example.edu/credentials/3732", + cred_tags={"some": "tag"}, + ), + VCRecord( + contexts=[ + "https://www.w3.org/2018/credentials/v1", + "https://www.w3.org/2018/credentials/examples/v1", + ], + expanded_types=[ + "https://www.w3.org/2018/credentials#VerifiableCredential", + "https://example.org/examples#UniversityDegreeCredential", + ], + issuer_id="https://example.edu/issuers/565049", + subject_ids=[ + "did:sov:LjgpST2rjsoxYegQDRm7EL", + "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", + ], + proof_types=["EcdsaSecp256r1Signature2019"], + schema_ids=["https://example.org/examples/degree.json"], + cred_value={"...": "..."}, + given_id="http://example.edu/credentials/3732", + cred_tags={"some": "tag"}, + ), + ] + with mock.patch.object( + DIFPresExchHandler, + "_did_info_for_did", + mock.CoroutineMock(), + ) as mock_did_info: + did_info = DIDInfo( + did="did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", + verkey="verkey", + metadata={}, + method=KEY, + key_type=P256, + ) + mock_did_info.return_value = did_info + ( + issuer_id, + filtered_creds, + ) = await dif_pres_exch_handler.get_sign_key_credential_subject_id(VC_RECORDS) + assert issuer_id == "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + assert len(filtered_creds) == 2 + async def test_get_sign_key_credential_subject_id_bbsbls(self): dif_pres_exch_handler = DIFPresExchHandler( self.profile, proof_type="BbsBlsSignature2020" diff --git a/acapy_agent/protocols/present_proof/v1_0/messages/presentation_request.py b/acapy_agent/protocols/present_proof/v1_0/messages/presentation_request.py index 0eb44ca721..d639eb3caf 100644 --- a/acapy_agent/protocols/present_proof/v1_0/messages/presentation_request.py +++ b/acapy_agent/protocols/present_proof/v1_0/messages/presentation_request.py @@ -12,8 +12,7 @@ from ..message_types import PRESENTATION_REQUEST, PROTOCOL_PACKAGE HANDLER_CLASS = ( - f"{PROTOCOL_PACKAGE}.handlers." - "presentation_request_handler.PresentationRequestHandler" + f"{PROTOCOL_PACKAGE}.handlers.presentation_request_handler.PresentationRequestHandler" ) 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 2c19d13443..492d0f3c4b 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 @@ -11,6 +11,7 @@ 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.registry import AnonCredsRegistry from ......anoncreds.util import generate_pr_nonce from ......anoncreds.verifier import AnonCredsVerifier from ......messaging.decorators.attach_decorator import AttachDecorator @@ -170,12 +171,19 @@ async def create_pres( pres_ex_record=pres_ex_record, requested_credentials=requested_credentials, ) + + # This is used for the fallback to indy format. Should be removed when indy + # format retired + if request_data.get("indy"): + return IndyPresExchangeHandler(self.profile).get_format_data( + PRES_20, presentation_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(): + async def _check_proof_vs_proposal(): """Check for bait and switch in presented values vs. proposal request.""" from ..indy.handler import IndyPresExchangeHandler @@ -198,13 +206,18 @@ def _check_proof_vs_proposal(): sub_proof_index = attr_spec["sub_proof_index"] schema_id = proof["identifiers"][sub_proof_index]["schema_id"] cred_def_id = proof["identifiers"][sub_proof_index]["cred_def_id"] + registry = self.profile.inject(AnonCredsRegistry) + schema = await registry.get_schema(self.profile, schema_id) + cred_def = await registry.get_credential_definition( + self.profile, cred_def_id + ) criteria = { "schema_id": schema_id, - "schema_issuer_did": schema_id.split(":")[-4], - "schema_name": schema_id.split(":")[-2], - "schema_version": schema_id.split(":")[-1], + "schema_issuer_did": schema.schema_value.issuer_id, + "schema_name": schema.schema_value.name, + "schema_version": schema.schema_value.version, "cred_def_id": cred_def_id, - "issuer_did": cred_def_id.split(":")[-5], + "issuer_did": cred_def.credential_definition.issuer_id, f"attr::{name}::value": proof_value, } @@ -233,13 +246,18 @@ def _check_proof_vs_proposal(): sub_proof_index = attr_spec["sub_proof_index"] schema_id = proof["identifiers"][sub_proof_index]["schema_id"] cred_def_id = proof["identifiers"][sub_proof_index]["cred_def_id"] + registry = self.profile.inject(AnonCredsRegistry) + schema = await registry.get_schema(self.profile, schema_id) + cred_def = await registry.get_credential_definition( + self.profile, cred_def_id + ) criteria = { "schema_id": schema_id, - "schema_issuer_did": schema_id.split(":")[-4], - "schema_name": schema_id.split(":")[-2], - "schema_version": schema_id.split(":")[-1], + "schema_issuer_did": schema.schema_value.issuer_id, + "schema_name": schema.schema_value.name, + "schema_version": schema.schema_value.version, "cred_def_id": cred_def_id, - "issuer_did": cred_def_id.split(":")[-5], + "issuer_did": cred_def.credential_definition.issuer_id, **{ f"attr::{name}::value": value for name, value in proof_values.items() @@ -294,13 +312,18 @@ def _check_proof_vs_proposal(): schema_id = proof["identifiers"][sub_proof_index]["schema_id"] cred_def_id = proof["identifiers"][sub_proof_index]["cred_def_id"] + registry = self.profile.inject(AnonCredsRegistry) + schema = await registry.get_schema(self.profile, schema_id) + cred_def = await registry.get_credential_definition( + self.profile, cred_def_id + ) criteria = { "schema_id": schema_id, - "schema_issuer_did": schema_id.split(":")[-4], - "schema_name": schema_id.split(":")[-2], - "schema_version": schema_id.split(":")[-1], + "schema_issuer_did": schema.schema_value.issuer_id, + "schema_name": schema.schema_value.name, + "schema_version": schema.schema_value.version, "cred_def_id": cred_def_id, - "issuer_did": cred_def_id.split(":")[-5], + "issuer_did": cred_def.credential_definition.issuer_id, } if ( @@ -313,7 +336,7 @@ def _check_proof_vs_proposal(): ) proof = message.attachment(AnonCredsPresExchangeHandler.format) - _check_proof_vs_proposal() + await _check_proof_vs_proposal() async def verify_pres(self, pres_ex_record: V20PresExRecord) -> V20PresExRecord: """Verify a presentation. diff --git a/acapy_agent/protocols/present_proof/v2_0/formats/dif/handler.py b/acapy_agent/protocols/present_proof/v2_0/formats/dif/handler.py index 4d31edadfb..d0b60321bd 100644 --- a/acapy_agent/protocols/present_proof/v2_0/formats/dif/handler.py +++ b/acapy_agent/protocols/present_proof/v2_0/formats/dif/handler.py @@ -15,6 +15,7 @@ BbsBlsSignature2020, Ed25519Signature2018, Ed25519Signature2020, + EcdsaSecp256r1Signature2019, ) from ......vc.vc_di.manager import VcDiManager from ......vc.vc_ld.manager import VcLdpManager @@ -232,12 +233,16 @@ async def create_pres( and ( Ed25519Signature2020.signature_type not in proof_types ) + and ( + EcdsaSecp256r1Signature2019.signature_type + not in proof_types + ) ): raise V20PresFormatHandlerError( "Only BbsBlsSignature2020 and/or " "Ed25519Signature2018 and/or " - "Ed25519Signature2018 and/or " - "Ed25519Signature2020 signature types " + "Ed25519Signature2020 and/or " + "EcdsaSecp256r1Signature2019 signature types " "are supported" ) elif ( @@ -251,11 +256,16 @@ async def create_pres( and ( Ed25519Signature2020.signature_type not in proof_types ) + and ( + EcdsaSecp256r1Signature2019.signature_type + not in proof_types + ) ): raise V20PresFormatHandlerError( - "Only BbsBlsSignature2020, Ed25519Signature2018 and " - "Ed25519Signature2020 signature types " - "are supported" + "Only BbsBlsSignature2020, Ed25519Signature2018, " + "Ed25519Signature2020 and " + "EcdsaSecp256r1Signature2019 " + "signature types are supported" ) else: for proof_format in proof_types: @@ -268,6 +278,17 @@ async def create_pres( Ed25519Signature2018.signature_type ) break + if ( + proof_format + == EcdsaSecp256r1Signature2019.signature_type + ): + proof_type = [ + EcdsaSecp256r1Signature2019.signature_type + ] + dif_handler_proof_type = ( + EcdsaSecp256r1Signature2019.signature_type + ) + break elif ( proof_format == BbsBlsSignature2020.signature_type ): @@ -291,9 +312,10 @@ async def create_pres( # TODO di_vc allowed ... raise V20PresFormatHandlerError( "Currently, only: ldp_vp with " - "BbsBlsSignature2020, Ed25519Signature2018 and " - "Ed25519Signature2020 signature types; and " - "di_vc with anoncreds-2023 signatures are supported" + "BbsBlsSignature2020, Ed25519Signature2018, " + "Ed25519Signature2020 and EcdsaSecp256r1Signature2019 " + "signature types; and di_vc with anoncreds-2023 " + "signatures are supported" ) if one_of_uri_groups: 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 2d0f73d59d..a33748bf31 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 @@ -1042,6 +1042,52 @@ async def test_create_pres_pd_claim_format_ed255(self): ) assert output[1].data.json_ == DIF_PRES + async def test_create_pres_pd_claim_format_secp256r1(self): + test_pd = deepcopy(DIF_PRES_REQUEST_B) + test_pd["presentation_definition"]["format"] = { + "ldp_vp": {"proof_type": ["EcdsaSecp256r1Signature2019"]} + } + del test_pd["presentation_definition"]["input_descriptors"][0]["constraints"][ + "limit_disclosure" + ] + dif_pres_request = V20PresRequest( + formats=[ + V20PresFormat( + attach_id="dif", + format_=ATTACHMENT_FORMAT[PRES_20_REQUEST][ + V20PresFormat.Format.DIF.api + ], + ) + ], + request_presentations_attach=[ + AttachDecorator.data_json(test_pd, ident="dif") + ], + ) + record = V20PresExRecord( + pres_ex_id="pxid", + thread_id="thid", + connection_id="conn_id", + initiator="init", + role="role", + state="state", + pres_request=dif_pres_request, + verified="false", + auto_present=True, + error_msg="error", + ) + + with mock.patch.object( + DIFPresExchHandler, + "create_vp", + mock.CoroutineMock(), + ) as mock_create_vp: + mock_create_vp.return_value = DIF_PRES + output = await self.handler.create_pres(record, {}) + assert isinstance(output[0], V20PresFormat) and isinstance( + output[1], AttachDecorator + ) + assert output[1].data.json_ == DIF_PRES + async def test_create_pres_pd_claim_format_bls12381g2(self): test_pd = deepcopy(DIF_PRES_REQUEST_B) test_pd["presentation_definition"]["format"] = { diff --git a/acapy_agent/protocols/present_proof/v2_0/messages/pres_problem_report.py b/acapy_agent/protocols/present_proof/v2_0/messages/pres_problem_report.py index 1cdc6b2a30..61ae9a11e8 100644 --- a/acapy_agent/protocols/present_proof/v2_0/messages/pres_problem_report.py +++ b/acapy_agent/protocols/present_proof/v2_0/messages/pres_problem_report.py @@ -8,8 +8,7 @@ from ..message_types import PRES_20_PROBLEM_REPORT, PROTOCOL_PACKAGE HANDLER_CLASS = ( - f"{PROTOCOL_PACKAGE}.handlers.pres_problem_report_handler." - "V20PresProblemReportHandler" + f"{PROTOCOL_PACKAGE}.handlers.pres_problem_report_handler.V20PresProblemReportHandler" ) diff --git a/acapy_agent/protocols/present_proof/v2_0/messages/tests/test_pres_problem_report.py b/acapy_agent/protocols/present_proof/v2_0/messages/tests/test_pres_problem_report.py index 10b197b5e0..df8b1d581c 100644 --- a/acapy_agent/protocols/present_proof/v2_0/messages/tests/test_pres_problem_report.py +++ b/acapy_agent/protocols/present_proof/v2_0/messages/tests/test_pres_problem_report.py @@ -23,8 +23,7 @@ def test_init_type(self): assert prob._type == DIDCommPrefix.qualify_current(PRES_20_PROBLEM_REPORT) @mock.patch( - f"{PROTOCOL_PACKAGE}.messages.pres_problem_report." - "V20PresProblemReportSchema.load" + f"{PROTOCOL_PACKAGE}.messages.pres_problem_report.V20PresProblemReportSchema.load" ) def test_deserialize(self, mock_load): """Test deserialization.""" @@ -42,8 +41,7 @@ def test_deserialize(self, mock_load): assert prob is mock_load.return_value @mock.patch( - f"{PROTOCOL_PACKAGE}.messages.pres_problem_report." - "V20PresProblemReportSchema.dump" + f"{PROTOCOL_PACKAGE}.messages.pres_problem_report.V20PresProblemReportSchema.dump" ) def test_serialize(self, mock_dump): """Test serialization.""" diff --git a/acapy_agent/protocols/present_proof/v2_0/routes.py b/acapy_agent/protocols/present_proof/v2_0/routes.py index b53188f118..2401ee5c14 100644 --- a/acapy_agent/protocols/present_proof/v2_0/routes.py +++ b/acapy_agent/protocols/present_proof/v2_0/routes.py @@ -47,6 +47,7 @@ BbsBlsSignature2020, Ed25519Signature2018, Ed25519Signature2020, + EcdsaSecp256r1Signature2019, ) from ....wallet.error import WalletNotFoundError from ..dif.pres_exch import ClaimFormat, InputDescriptors, SchemaInputDescriptor @@ -685,12 +686,17 @@ async def present_proof_credentials_list(request: web.BaseRequest): and ( Ed25519Signature2020.signature_type not in proof_types ) + and ( + EcdsaSecp256r1Signature2019.signature_type + not in proof_types + ) ): raise web.HTTPBadRequest( reason=( "Only BbsBlsSignature2020 and/or " "Ed25519Signature2018 and/or " - "Ed25519Signature2020 signature types " + "Ed25519Signature2020 and/or " + "EcdsaSecp256r1Signature2019 signature types " "are supported" ) ) @@ -705,12 +711,17 @@ async def present_proof_credentials_list(request: web.BaseRequest): and ( Ed25519Signature2020.signature_type not in proof_types ) + and ( + EcdsaSecp256r1Signature2019.signature_type + not in proof_types + ) ): raise web.HTTPBadRequest( reason=( "Only BbsBlsSignature2020, Ed25519Signature2018" - " and Ed25519Signature2020 signature types are" - " supported" + " and Ed25519Signature2020," + " EcdsaSecp256r1Signature2019" + " signature types are supported" ) ) else: @@ -727,6 +738,14 @@ async def present_proof_credentials_list(request: web.BaseRequest): ): proof_type = [Ed25519Signature2020.signature_type] break + elif ( + proof_format + == EcdsaSecp256r1Signature2019.signature_type + ): + proof_type = [ + EcdsaSecp256r1Signature2019.signature_type + ] + break elif ( proof_format == BbsBlsSignature2020.signature_type ): @@ -746,7 +765,8 @@ async def present_proof_credentials_list(request: web.BaseRequest): reason=( "Currently, only ldp_vp with " "BbsBlsSignature2020, Ed25519Signature2018 and " - "Ed25519Signature2020 signature types are supported" + "Ed25519Signature2020, EcdsaSecp256r1Signature2019" + " signature types are supported" ) ) if one_of_uri_groups: 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 9f88377968..a836e55ab3 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 @@ -6,6 +6,14 @@ import pytest from .....anoncreds.holder import AnonCredsHolder +from .....anoncreds.models.credential_definition import ( + CredDef, + CredDefValue, + CredDefValuePrimary, + GetCredDefResult, +) +from .....anoncreds.models.schema import AnonCredsSchema, GetSchemaResult +from .....anoncreds.registry import AnonCredsRegistry from .....anoncreds.verifier import AnonCredsVerifier from .....indy.models.pres_preview import ( IndyPresAttrSpec, @@ -469,6 +477,37 @@ async def asyncSetUp(self): ) ) injector.bind_instance(AnonCredsHolder, self.holder) + registry = mock.MagicMock(AnonCredsRegistry, autospec=True) + registry.get_schema = mock.CoroutineMock( + return_value=GetSchemaResult( + schema=AnonCredsSchema( + issuer_id=ISSUER_DID, + name="vidya", + version="1.0", + attr_names=["player", "screenCapture", "highScore"], + ), + schema_id=S_ID, + resolution_metadata={}, + schema_metadata={}, + ) + ) + registry.get_credential_definition = mock.CoroutineMock( + return_value=GetCredDefResult( + credential_definition_id="TUku9MDGa7QALbAJX4oAww:3:CL:531757:MYCO_Consent_Enablement", + credential_definition=CredDef( + issuer_id=ISSUER_DID, + schema_id=S_ID, + tag="tag", + type="CL", + value=CredDefValue( + primary=CredDefValuePrimary("n", "s", {}, "rctxt", "z") + ), + ), + credential_definition_metadata={}, + resolution_metadata={}, + ) + ) + injector.bind_instance(AnonCredsRegistry, registry) self.verifier = mock.MagicMock(AnonCredsVerifier, autospec=True) self.verifier.verify_presentation = mock.CoroutineMock(return_value=("true", [])) diff --git a/acapy_agent/resolver/__init__.py b/acapy_agent/resolver/__init__.py index 3998b3da1c..8ebc39028b 100644 --- a/acapy_agent/resolver/__init__.py +++ b/acapy_agent/resolver/__init__.py @@ -49,11 +49,11 @@ async def setup(context: InjectionContext): await web_resolver.setup(context) registry.register_resolver(web_resolver) - tdw_resolver = ClassProvider( - "acapy_agent.resolver.default.tdw.TdwDIDResolver" + webvh_resolver = ClassProvider( + "acapy_agent.resolver.default.webvh.WebvhDIDResolver" ).provide(context.settings, context.injector) - await tdw_resolver.setup(context) - registry.register_resolver(tdw_resolver) + await webvh_resolver.setup(context) + registry.register_resolver(webvh_resolver) if context.settings.get("resolver.universal"): universal_resolver = ClassProvider( diff --git a/acapy_agent/resolver/default/tests/test_tdw.py b/acapy_agent/resolver/default/tests/test_webvh.py similarity index 56% rename from acapy_agent/resolver/default/tests/test_tdw.py rename to acapy_agent/resolver/default/tests/test_webvh.py index 8829b9f031..878843efc1 100644 --- a/acapy_agent/resolver/default/tests/test_tdw.py +++ b/acapy_agent/resolver/default/tests/test_webvh.py @@ -1,17 +1,17 @@ import pytest from ....core.profile import Profile -from ....messaging.valid import DIDTdw +from ....messaging.valid import DIDWebvh from ....utils.testing import create_test_profile -from ..tdw import TdwDIDResolver +from ..webvh import WebvhDIDResolver -TEST_DID = "did:tdw:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example" +TEST_DID = "did:webvh:Qma6mc1qZw3NqxwX6SB5GPQYzP4pGN2nXD15Jwi4bcDBKu:domain.example" @pytest.fixture def resolver(): """Resolver fixture.""" - yield TdwDIDResolver() + yield WebvhDIDResolver() @pytest.fixture @@ -21,9 +21,9 @@ async def profile(): @pytest.mark.asyncio -async def test_supported_did_regex(profile, resolver: TdwDIDResolver): +async def test_supported_did_regex(profile, resolver: WebvhDIDResolver): """Test the supported_did_regex.""" - assert resolver.supported_did_regex == DIDTdw.PATTERN + assert resolver.supported_did_regex == DIDWebvh.PATTERN assert await resolver.supports( profile, TEST_DID, @@ -31,6 +31,6 @@ async def test_supported_did_regex(profile, resolver: TdwDIDResolver): @pytest.mark.asyncio -async def test_resolve(resolver: TdwDIDResolver, profile: Profile): +async def test_resolve(resolver: WebvhDIDResolver, profile: Profile): """Test resolve method.""" assert await resolver.resolve(profile, TEST_DID) diff --git a/acapy_agent/resolver/default/tdw.py b/acapy_agent/resolver/default/webvh.py similarity index 60% rename from acapy_agent/resolver/default/tdw.py rename to acapy_agent/resolver/default/webvh.py index 4aabd198e8..de4f72e64b 100644 --- a/acapy_agent/resolver/default/tdw.py +++ b/acapy_agent/resolver/default/webvh.py @@ -1,38 +1,38 @@ -"""TDW DID Resolver. +"""WEBVH DID Resolver. -Resolution is performed by the did_tdw library. +Resolution is performed by the did_webvh library. """ from re import Pattern from typing import Optional, Sequence, Text -from did_tdw.resolver import ResolutionResult, resolve_did +from did_webvh.resolver import ResolutionResult, resolve_did from ...config.injection_context import InjectionContext from ...core.profile import Profile -from ...messaging.valid import DIDTdw +from ...messaging.valid import DIDWebvh from ..base import BaseDIDResolver, ResolverType -class TdwDIDResolver(BaseDIDResolver): - """TDW DID Resolver.""" +class WebvhDIDResolver(BaseDIDResolver): + """WEBVH DID Resolver.""" def __init__(self): - """Initialize the TDW DID Resolver.""" + """Initialize the WEBVH DID Resolver.""" super().__init__(ResolverType.NATIVE) async def setup(self, context: InjectionContext): - """Perform required setup for TDW DID resolution.""" + """Perform required setup for WEBVH DID resolution.""" @property def supported_did_regex(self) -> Pattern: - """Return supported DID regex of TDW DID Resolver.""" - return DIDTdw.PATTERN + """Return supported DID regex of WEBVH DID Resolver.""" + return DIDWebvh.PATTERN async def _resolve( self, profile: Profile, did: str, service_accept: Optional[Sequence[Text]] = None ) -> dict: - """Resolve DID using TDW.""" + """Resolve DID using WEBVH.""" response: ResolutionResult = await resolve_did(did) if response.resolution_metadata and response.resolution_metadata.get("error"): return response.resolution_metadata diff --git a/acapy_agent/revocation/manager.py b/acapy_agent/revocation/manager.py index b97731b369..880c51e840 100644 --- a/acapy_agent/revocation/manager.py +++ b/acapy_agent/revocation/manager.py @@ -148,7 +148,7 @@ async def _get_endorsement_txn_for_revocation( ) except StorageNotFoundError: raise RevocationManagerError( - "No endorser connection record found " f"for id: {endorser_conn_id}" + f"No endorser connection record found for id: {endorser_conn_id}" ) endorser_info = await connection_record.metadata_get(session, "endorser_info") endorser_did = endorser_info["endorser_did"] diff --git a/acapy_agent/revocation/models/issuer_rev_reg_record.py b/acapy_agent/revocation/models/issuer_rev_reg_record.py index bed21031a2..ae10137695 100644 --- a/acapy_agent/revocation/models/issuer_rev_reg_record.py +++ b/acapy_agent/revocation/models/issuer_rev_reg_record.py @@ -400,7 +400,7 @@ async def fix_ledger_entry( LOGGER.debug(f"Fixed entry recs count = {rec_count}") LOGGER.debug(f"Rev reg entry value: {self.revoc_reg_entry.value}") - LOGGER.debug(f'Rev reg delta: {rev_reg_delta.get("value")}') + LOGGER.debug(f"Rev reg delta: {rev_reg_delta.get('value')}") # No update required if no discrepancies if rec_count == 0: diff --git a/acapy_agent/transport/pack_format.py b/acapy_agent/transport/pack_format.py index a4400c0dfe..4c70143b1a 100644 --- a/acapy_agent/transport/pack_format.py +++ b/acapy_agent/transport/pack_format.py @@ -80,9 +80,9 @@ def get_for_packed_msg(self, packed_msg: Union[str, bytes]) -> BaseWireFormat: DIDCommVersion.v1: self.v1pack_format, DIDCommVersion.v2: self.v2pack_format, }[get_version_for_packed_msg(packed_msg)] - assert ( - format - ), "self.v2_pack_format will be set when --experimental-didcomm-v2 is set" + assert format, ( + "self.v2_pack_format will be set when --experimental-didcomm-v2 is set" + ) return pack_format async def parse_message( diff --git a/acapy_agent/utils/endorsement_setup.py b/acapy_agent/utils/endorsement_setup.py index 685cdda3e6..0b733a706b 100644 --- a/acapy_agent/utils/endorsement_setup.py +++ b/acapy_agent/utils/endorsement_setup.py @@ -76,8 +76,7 @@ async def attempt_auto_author_with_endorser_setup(profile: Profile): ) else: raise EndorsementSetupError( - "Failed to establish endorser connection, invalid " - "invitation format." + "Failed to establish endorser connection, invalid invitation format." ) # configure the connection role and info (don't need to wait for the connection) diff --git a/acapy_agent/utils/multiformats/multicodec.py b/acapy_agent/utils/multiformats/multicodec.py index 465d5b3ea2..7e2ed5da55 100644 --- a/acapy_agent/utils/multiformats/multicodec.py +++ b/acapy_agent/utils/multiformats/multicodec.py @@ -20,6 +20,7 @@ class SupportedCodecs(Enum): bls12381g2 = Multicodec("bls12_381-g2-pub", b"\xeb\x01") bls12381g1g2 = Multicodec("bls12_381-g1g2-pub", b"\xee\x01") secp256k1_pub = Multicodec("secp256k1-pub", b"\xe7\x01") + p256_pub = Multicodec("p256-pub", b"\x80\x24") @classmethod def by_name(cls, name: str) -> Multicodec: @@ -45,6 +46,7 @@ def for_data(cls, data: bytes) -> Multicodec: "bls12_381-g2-pub", "bls12_381-g1g2-pub", "secp256k1-pub", + "p256-pub", ] diff --git a/acapy_agent/utils/profiles.py b/acapy_agent/utils/profiles.py index 1e78314de7..9fd888c3e4 100644 --- a/acapy_agent/utils/profiles.py +++ b/acapy_agent/utils/profiles.py @@ -8,6 +8,7 @@ from ..askar.profile_anon import AskarAnoncredsProfile from ..core.profile import Profile from ..multitenant.manager import MultitenantManager +from ..multitenant.single_wallet_askar_manager import SingleWalletAskarMultitenantManager from ..storage.base import BaseStorageSearch from ..wallet.models.wallet_record import WalletRecord @@ -41,6 +42,13 @@ async def get_subwallet_profiles_from_storage(root_profile: Profile) -> list[Pro search_session = base_storage_search.search_records( type_filter=WalletRecord.RECORD_TYPE, page_size=10 ) + if ( + root_profile.context.settings.get("multitenant.wallet_type") + == "single-wallet-askar" + ): + manager = SingleWalletAskarMultitenantManager(root_profile) + else: + manager = MultitenantManager(root_profile) while search_session._done is False: wallet_storage_records = await search_session.fetch() for wallet_storage_record in wallet_storage_records: @@ -49,7 +57,7 @@ async def get_subwallet_profiles_from_storage(root_profile: Profile) -> list[Pro json.loads(wallet_storage_record.value), ) subwallet_profiles.append( - await MultitenantManager(root_profile).get_wallet_profile( + await manager.get_wallet_profile( base_context=root_profile.context, wallet_record=wallet_record, ) diff --git a/acapy_agent/vc/data_integrity/cryptosuites/eddsa_jcs_2022.py b/acapy_agent/vc/data_integrity/cryptosuites/eddsa_jcs_2022.py index 69daaa9334..b0520aa8be 100644 --- a/acapy_agent/vc/data_integrity/cryptosuites/eddsa_jcs_2022.py +++ b/acapy_agent/vc/data_integrity/cryptosuites/eddsa_jcs_2022.py @@ -71,12 +71,12 @@ def proof_configuration(self, options: DataIntegrityProofOptions): https://www.w3.org/TR/vc-di-eddsa/#proof-configuration-eddsa-jcs-2022. """ proof_config = options - assert ( - proof_config.type == "DataIntegrityProof" - ), 'Expected proof.type to be "DataIntegrityProof' - assert ( - proof_config.cryptosuite == "eddsa-jcs-2022" - ), 'Expected proof.cryptosuite to be "eddsa-jcs-2022' + assert proof_config.type == "DataIntegrityProof", ( + 'Expected proof.type to be "DataIntegrityProof' + ) + assert proof_config.cryptosuite == "eddsa-jcs-2022", ( + 'Expected proof.cryptosuite to be "eddsa-jcs-2022' + ) if proof_config.created: assert datetime.fromisoformat(proof_config.created) @@ -93,12 +93,12 @@ def transformation( https://www.w3.org/TR/vc-di-eddsa/#transformation-eddsa-jcs-2022. """ - assert ( - options.type == "DataIntegrityProof" - ), "Expected proof.type to be `DataIntegrityProof`" - assert ( - options.cryptosuite == "eddsa-jcs-2022" - ), "Expected proof.cryptosuite to be `eddsa-jcs-2022`" + assert options.type == "DataIntegrityProof", ( + "Expected proof.type to be `DataIntegrityProof`" + ) + assert options.cryptosuite == "eddsa-jcs-2022", ( + "Expected proof.cryptosuite to be `eddsa-jcs-2022`" + ) return self._canonicalize(unsecured_document) diff --git a/acapy_agent/vc/data_integrity/tests/test_cryptosuites.py b/acapy_agent/vc/data_integrity/tests/test_cryptosuites.py index 246693f29b..31e4090482 100644 --- a/acapy_agent/vc/data_integrity/tests/test_cryptosuites.py +++ b/acapy_agent/vc/data_integrity/tests/test_cryptosuites.py @@ -8,6 +8,7 @@ from acapy_agent.utils.testing import create_test_profile from acapy_agent.vc.data_integrity.cryptosuites import EddsaJcs2022 from acapy_agent.vc.data_integrity.models.options import DataIntegrityProofOptions +from acapy_agent.wallet.key_type import KeyTypes from acapy_agent.wallet.keys.manager import MultikeyManager @@ -34,6 +35,7 @@ async def asyncSetUp(self): self.resolver.register_resolver(WebDIDResolver()) self.profile = await create_test_profile() self.profile.context.injector.bind_instance(DIDResolver, self.resolver) + self.profile.context.injector.bind_instance(KeyTypes, KeyTypes()) try: async with self.profile.session() as session: await MultikeyManager(session=session).create(seed=self.seed) diff --git a/acapy_agent/vc/data_integrity/tests/test_manager.py b/acapy_agent/vc/data_integrity/tests/test_manager.py index c5b4d509ce..b47c1e5423 100644 --- a/acapy_agent/vc/data_integrity/tests/test_manager.py +++ b/acapy_agent/vc/data_integrity/tests/test_manager.py @@ -8,6 +8,7 @@ from acapy_agent.utils.testing import create_test_profile from acapy_agent.vc.data_integrity.manager import DataIntegrityManager from acapy_agent.vc.data_integrity.models.options import DataIntegrityProofOptions +from acapy_agent.wallet.key_type import KeyTypes from acapy_agent.wallet.keys.manager import MultikeyManager @@ -34,6 +35,7 @@ async def asyncSetUp(self): self.resolver.register_resolver(WebDIDResolver()) self.profile = await create_test_profile() self.profile.context.injector.bind_instance(DIDResolver, self.resolver) + self.profile.context.injector.bind_instance(KeyTypes, KeyTypes()) try: async with self.profile.session() as session: await MultikeyManager(session=session).create(seed=self.seed) diff --git a/acapy_agent/vc/ld_proofs/__init__.py b/acapy_agent/vc/ld_proofs/__init__.py index 64c84915e8..36c77f84f8 100644 --- a/acapy_agent/vc/ld_proofs/__init__.py +++ b/acapy_agent/vc/ld_proofs/__init__.py @@ -14,6 +14,7 @@ from .suites import _BbsBlsSignatureProof2020 as BbsBlsSignatureProof2020 from .suites import _Ed25519Signature2018 as Ed25519Signature2018 from .suites import _Ed25519Signature2020 as Ed25519Signature2020 +from .suites import _EcdsaSecp256r1Signature2019 as EcdsaSecp256r1Signature2019 from .suites import _JwsLinkedDataSignature as JwsLinkedDataSignature from .suites import _LinkedDataProof as LinkedDataProof from .suites import _LinkedDataSignature as LinkedDataSignature @@ -36,6 +37,7 @@ "JwsLinkedDataSignature", "Ed25519Signature2018", "Ed25519Signature2020", + "EcdsaSecp256r1Signature2019", "BbsBlsSignature2020", "BbsBlsSignatureProof2020", # Key pairs diff --git a/acapy_agent/vc/ld_proofs/constants.py b/acapy_agent/vc/ld_proofs/constants.py index 2a4780f484..03af17dfc9 100644 --- a/acapy_agent/vc/ld_proofs/constants.py +++ b/acapy_agent/vc/ld_proofs/constants.py @@ -8,6 +8,7 @@ CREDENTIALS_CONTEXT_V1_URL = "https://www.w3.org/2018/credentials/v1" SECURITY_CONTEXT_BBS_URL = "https://w3id.org/security/bbs/v1" SECURITY_CONTEXT_ED25519_2020_URL = "https://w3id.org/security/suites/ed25519-2020/v1" +SECURITY_CONTEXT_MULTIKEY_URL = "https://w3id.org/security/multikey/v1" CREDENTIALS_ISSUER_URL = "https://www.w3.org/2018/credentials#issuer" SECURITY_PROOF_URL = "https://w3id.org/security#proof" diff --git a/acapy_agent/vc/ld_proofs/document_loader.py b/acapy_agent/vc/ld_proofs/document_loader.py index 521de31036..c348228687 100644 --- a/acapy_agent/vc/ld_proofs/document_loader.py +++ b/acapy_agent/vc/ld_proofs/document_loader.py @@ -70,8 +70,7 @@ async def _load_async(self, url: str, options: dict): document = self._load_http_document(url, options) else: raise LinkedDataProofException( - "Unrecognized url format. Must start with " - "'did:', 'http://' or 'https://'" + "Unrecognized url format. Must start with 'did:', 'http://' or 'https://'" ) return document diff --git a/acapy_agent/vc/ld_proofs/purposes/authentication_proof_purpose.py b/acapy_agent/vc/ld_proofs/purposes/authentication_proof_purpose.py index ef6a24787a..7a107b6100 100644 --- a/acapy_agent/vc/ld_proofs/purposes/authentication_proof_purpose.py +++ b/acapy_agent/vc/ld_proofs/purposes/authentication_proof_purpose.py @@ -50,13 +50,13 @@ def validate( if proof.get("challenge") != self.challenge: raise LinkedDataProofException( f"The challenge is not as expected; challenge=" - f'{proof.get("challenge")}, expected={self.challenge}' + f"{proof.get('challenge')}, expected={self.challenge}" ) if self.domain and (proof.get("domain") != self.domain): raise LinkedDataProofException( f"The domain is not as expected; " - f'domain={proof.get("domain")}, expected={self.domain}' + f"domain={proof.get('domain')}, expected={self.domain}" ) return super().validate( diff --git a/acapy_agent/vc/ld_proofs/suites/__init__.py b/acapy_agent/vc/ld_proofs/suites/__init__.py index f70151f473..71456f6744 100644 --- a/acapy_agent/vc/ld_proofs/suites/__init__.py +++ b/acapy_agent/vc/ld_proofs/suites/__init__.py @@ -4,6 +4,9 @@ ) from .ed25519_signature_2018 import Ed25519Signature2018 as _Ed25519Signature2018 from .ed25519_signature_2020 import Ed25519Signature2020 as _Ed25519Signature2020 +from .ecdsa_secp256r1_signature_2019 import ( + EcdsaSecp256r1Signature2019 as _EcdsaSecp256r1Signature2019, +) from .jws_linked_data_signature import JwsLinkedDataSignature as _JwsLinkedDataSignature from .linked_data_proof import LinkedDataProof as _LinkedDataProof from .linked_data_signature import LinkedDataSignature as _LinkedDataSignature @@ -14,6 +17,7 @@ "_JwsLinkedDataSignature", "_Ed25519Signature2018", "_Ed25519Signature2020", + "_EcdsaSecp256r1Signature2019", "_BbsBlsSignature2020", "_BbsBlsSignatureProof2020", ] diff --git a/acapy_agent/vc/ld_proofs/suites/ecdsa_secp256r1_signature_2019.py b/acapy_agent/vc/ld_proofs/suites/ecdsa_secp256r1_signature_2019.py new file mode 100644 index 0000000000..27d4022089 --- /dev/null +++ b/acapy_agent/vc/ld_proofs/suites/ecdsa_secp256r1_signature_2019.py @@ -0,0 +1,97 @@ +"""EcdsaSecp256r1Signature2019 suite.""" + +from datetime import datetime +from typing import List, Optional, Union + +from ....utils.multiformats import multibase +from ..crypto import _KeyPair as KeyPair +from ..document_loader import DocumentLoaderMethod +from ..error import LinkedDataProofException +from .linked_data_signature import LinkedDataSignature + + +class EcdsaSecp256r1Signature2019(LinkedDataSignature): + """EcdsaSecp256r1Signature2019 suite.""" + + signature_type = "EcdsaSecp256r1Signature2019" + + def __init__( + self, + *, + key_pair: KeyPair, + proof: Optional[dict] = None, + verification_method: Optional[str] = None, + date: Union[datetime, str, None] = None, + ): + """Create new EcdsaSecp256r1Signature2019 instance. + + Args: + key_pair (KeyPair): Key pair to use. Must provide ES256 signatures (P256) + proof (dict, optional): A JSON-LD document with options to use for the + `proof` node (e.g. any other custom fields can be provided here + using a context different from security-v2). + verification_method (str, optional): A key id URL to the paired public key. + date (datetime, optional): Signing date to use. + """ + super().__init__( + verification_method=verification_method, + proof=proof, + date=date, + ) + self.key_pair = key_pair + + async def sign(self, *, verify_data: bytes, proof: dict) -> dict: + """Sign the data and add it to the proof. + + Args: + verify_data (List[bytes]): The data to sign. + proof (dict): The proof to add the signature to + + Returns: + dict: The proof object with the added signature + + """ + signature = await self.key_pair.sign(verify_data) + + proof["proofValue"] = multibase.encode(signature, "base58btc") + + return proof + + async def verify_signature( + self, + *, + verify_data: List[bytes], + verification_method: dict, + document: dict, + proof: dict, + document_loader: DocumentLoaderMethod, + ) -> bool: + """Verify the data against the proof. + + Args: + verify_data (bytes): The data to check + verification_method (dict): The verification method to use. + document (dict): The document the verify data is derived for as extra context + proof (dict): The proof to check + document_loader (DocumentLoader): Document loader used for resolving + + Returns: + bool: Whether the signature is valid for the data + + """ + + if not (isinstance(proof.get("proofValue"), str)): + raise LinkedDataProofException( + 'The proof does not contain a valid "proofValue" property.' + ) + + signature = multibase.decode(proof["proofValue"]) + + # If the key pair has no public key yet, create a new key pair + # from the verification method. We don't want to overwrite data + # on the original key pair + key_pair = self.key_pair + if not key_pair.has_public_key: + key_pair = key_pair.from_verification_method(verification_method) + + return await key_pair.verify(verify_data, signature) diff --git a/acapy_agent/vc/ld_proofs/suites/tests/test_ecdsa_secp256r1_signature_2019.py b/acapy_agent/vc/ld_proofs/suites/tests/test_ecdsa_secp256r1_signature_2019.py new file mode 100644 index 0000000000..c45eb7126c --- /dev/null +++ b/acapy_agent/vc/ld_proofs/suites/tests/test_ecdsa_secp256r1_signature_2019.py @@ -0,0 +1,127 @@ +from unittest import IsolatedAsyncioTestCase + +from .....did.did_key import DIDKey +from .....utils.testing import create_test_profile +from .....wallet.base import BaseWallet +from .....wallet.key_type import P256 +from ....tests.data import ( + TEST_LD_DOCUMENT, + TEST_LD_DOCUMENT_BAD_SIGNED_P256_2019, + TEST_LD_DOCUMENT_SIGNED_P256_2019, + TEST_VC_DOCUMENT, + TEST_VC_DOCUMENT_SIGNED_P256_2019, +) +from ....tests.document_loader import custom_document_loader +from ...crypto.wallet_key_pair import WalletKeyPair +from ...ld_proofs import sign, verify +from ...purposes.assertion_proof_purpose import AssertionProofPurpose +from ..ecdsa_secp256r1_signature_2019 import EcdsaSecp256r1Signature2019 + + +class TestEcdsaSecp256r1Signature2019(IsolatedAsyncioTestCase): + test_seed = "testseed000000000000000000000001" + + async def asyncSetUp(self): + self.profile = await create_test_profile() + async with self.profile.session() as session: + wallet = session.inject(BaseWallet) + self.key = await wallet.create_signing_key(key_type=P256, seed=self.test_seed) + self.verification_method = DIDKey.from_public_key_b58( + self.key.verkey, P256 + ).key_id + + self.sign_key_pair = WalletKeyPair( + profile=self.profile, + key_type=P256, + public_key_base58=self.key.verkey, + ) + self.verify_key_pair = WalletKeyPair(profile=self.profile, key_type=P256) + + async def test_sign_ld_proofs(self): + signed = await sign( + document=TEST_LD_DOCUMENT, + suite=EcdsaSecp256r1Signature2019( + key_pair=self.sign_key_pair, + verification_method=self.verification_method, + ), + document_loader=custom_document_loader, + purpose=AssertionProofPurpose(), + ) + + assert signed + + async def test_verify_ld_proofs(self): + result = await verify( + document=TEST_LD_DOCUMENT_SIGNED_P256_2019, + suites=[EcdsaSecp256r1Signature2019(key_pair=self.verify_key_pair)], + document_loader=custom_document_loader, + purpose=AssertionProofPurpose(), + ) + + assert result + assert result.verified + + async def test_verify_ld_proofs_not_verified_bad_signature(self): + result = await verify( + document=TEST_LD_DOCUMENT_BAD_SIGNED_P256_2019, + suites=[EcdsaSecp256r1Signature2019(key_pair=self.verify_key_pair)], + document_loader=custom_document_loader, + purpose=AssertionProofPurpose(), + ) + + assert result + assert not result.verified + + async def test_verify_ld_proofs_not_verified_unsigned_statement(self): + MODIFIED_DOCUMENT = { + **TEST_LD_DOCUMENT_SIGNED_P256_2019, + "unsigned_claim": "oops", + } + result = await verify( + document=MODIFIED_DOCUMENT, + suites=[EcdsaSecp256r1Signature2019(key_pair=self.verify_key_pair)], + document_loader=custom_document_loader, + purpose=AssertionProofPurpose(), + ) + + assert result + assert not result.verified + + async def test_verify_ld_proofs_not_verified_changed_statement(self): + MODIFIED_DOCUMENT = { + **TEST_LD_DOCUMENT_SIGNED_P256_2019, + "email": "someOtherEmail@example.com", + } + result = await verify( + document=MODIFIED_DOCUMENT, + suites=[EcdsaSecp256r1Signature2019(key_pair=self.verify_key_pair)], + document_loader=custom_document_loader, + purpose=AssertionProofPurpose(), + ) + + assert result + assert not result.verified + + async def test_sign_vc(self): + signed = await sign( + document=TEST_VC_DOCUMENT, + suite=EcdsaSecp256r1Signature2019( + key_pair=self.sign_key_pair, + verification_method=self.verification_method, + ), + document_loader=custom_document_loader, + purpose=AssertionProofPurpose(), + ) + + assert signed + + async def test_verify_vc(self): + result = await verify( + document=TEST_VC_DOCUMENT_SIGNED_P256_2019, + suites=[EcdsaSecp256r1Signature2019(key_pair=self.verify_key_pair)], + document_loader=custom_document_loader, + purpose=AssertionProofPurpose(), + ) + + assert result + assert result.verified diff --git a/acapy_agent/vc/routes.py b/acapy_agent/vc/routes.py index e2d14e80fe..1993fe4731 100644 --- a/acapy_agent/vc/routes.py +++ b/acapy_agent/vc/routes.py @@ -95,6 +95,8 @@ async def issue_credential_route(request: web.BaseRequest): options["proofType"] = "Ed25519Signature2020" elif key_type == "bls12381g2": options["proofType"] = "BbsBlsSignature2020" + elif key_type == "p256": + options["proofType"] = "EcdsaSecp256r1Signature2019" credential = VerifiableCredential.deserialize(credential) options = LDProofVCOptions.deserialize(options) @@ -205,6 +207,8 @@ async def prove_presentation_route(request: web.BaseRequest): options["proofType"] = "Ed25519Signature2020" elif key_type == "bls12381g2": options["proofType"] = "BbsBlsSignature2020" + elif key_type == "p256": + options["proofType"] = "EcdsaSecp256r1Signature2019" presentation = VerifiablePresentation.deserialize(presentation) options = LDProofVCOptions.deserialize(options) diff --git a/acapy_agent/vc/tests/contexts/__init__.py b/acapy_agent/vc/tests/contexts/__init__.py index c95ecdb8ab..7d6acb271e 100644 --- a/acapy_agent/vc/tests/contexts/__init__.py +++ b/acapy_agent/vc/tests/contexts/__init__.py @@ -4,6 +4,7 @@ from .did_v1 import DID_V1 from .dif_presentation_submission_v1 import DIF_PRESENTATION_SUBMISSION_V1 from .ed25519_2020_v1 import ED25519_2020_V1 +from .multikey_v1 import MULTIKEY_V1 from .examples_v1 import EXAMPLES_V1 from .odrl import ODRL from .schema_org import SCHEMA_ORG @@ -20,6 +21,7 @@ "SECURITY_V3_UNSTABLE", "BBS_V1", "ED25519_2020_V1", + "MULTIKEY_V1", "CREDENTIALS_V1", "CITIZENSHIP_V1", "VACCINATION_V1", diff --git a/acapy_agent/vc/tests/contexts/multikey_v1.py b/acapy_agent/vc/tests/contexts/multikey_v1.py new file mode 100644 index 0000000000..93f2023785 --- /dev/null +++ b/acapy_agent/vc/tests/contexts/multikey_v1.py @@ -0,0 +1,35 @@ +MULTIKEY_V1 = { + "@context": { + "id": "@id", + "type": "@type", + "@protected": True, + "Multikey": { + "@id": "https://w3id.org/security#Multikey", + "@context": { + "@protected": True, + "id": "@id", + "type": "@type", + "controller": { + "@id": "https://w3id.org/security#controller", + "@type": "@id", + }, + "revoked": { + "@id": "https://w3id.org/security#revoked", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + }, + "expires": { + "@id": "https://w3id.org/security#expiration", + "@type": "http://www.w3.org/2001/XMLSchema#dateTime", + }, + "publicKeyMultibase": { + "@id": "https://w3id.org/security#publicKeyMultibase", + "@type": "https://w3id.org/security#multibase", + }, + "secretKeyMultibase": { + "@id": "https://w3id.org/security#secretKeyMultibase", + "@type": "https://w3id.org/security#multibase", + }, + }, + }, + } +} diff --git a/acapy_agent/vc/tests/data/__init__.py b/acapy_agent/vc/tests/data/__init__.py index 58d8e40702..38bd5c7e1d 100644 --- a/acapy_agent/vc/tests/data/__init__.py +++ b/acapy_agent/vc/tests/data/__init__.py @@ -20,6 +20,9 @@ from .test_ld_document_bad_signed_ed25519_2020 import ( TEST_LD_DOCUMENT_BAD_SIGNED_ED25519_2020, ) +from .test_ld_document_bad_signed_secp256r1_2019 import ( + TEST_LD_DOCUMENT_BAD_SIGNED_P256_2019, +) from .test_ld_document_partial_proof_bbs import TEST_LD_DOCUMENT_PARTIAL_PROOF_BBS from .test_ld_document_proof_bbs import TEST_LD_DOCUMENT_PROOF_BBS from .test_ld_document_reveal import TEST_LD_DOCUMENT_REVEAL @@ -27,6 +30,7 @@ from .test_ld_document_signed_bbs import TEST_LD_DOCUMENT_SIGNED_BBS from .test_ld_document_signed_ed25519 import TEST_LD_DOCUMENT_SIGNED_ED25519 from .test_ld_document_signed_ed25519_2020 import TEST_LD_DOCUMENT_SIGNED_ED25519_2020 +from .test_ld_document_signed_secp256r1_2019 import TEST_LD_DOCUMENT_SIGNED_P256_2019 from .test_vc_document import TEST_VC_DOCUMENT from .test_vc_document_did_key_ed25519 import TEST_VC_DOCUMENT_DID_KEY_ED25519 from .test_vc_document_nested import TEST_VC_DOCUMENT_NESTED @@ -44,6 +48,7 @@ ) from .test_vc_document_signed_ed25519 import TEST_VC_DOCUMENT_SIGNED_ED25519 from .test_vc_document_signed_ed25519_2020 import TEST_VC_DOCUMENT_SIGNED_ED25519_2020 +from .test_vc_document_signed_secp256r1_2019 import TEST_VC_DOCUMENT_SIGNED_P256_2019 __all__ = [ "BBS_NESTED_VC_FULL_REVEAL_DOCUMENT_MATTR", @@ -61,8 +66,10 @@ "TEST_LD_DOCUMENT_SIGNED_BBS", "TEST_LD_DOCUMENT_BAD_SIGNED_ED25519", "TEST_LD_DOCUMENT_BAD_SIGNED_ED25519_2020", + "TEST_LD_DOCUMENT_BAD_SIGNED_P256_2019", "TEST_LD_DOCUMENT_SIGNED_ED25519", "TEST_LD_DOCUMENT_SIGNED_ED25519_2020", + "TEST_LD_DOCUMENT_SIGNED_P256_2019", "TEST_LD_DOCUMENT", "TEST_LD_DOCUMENT_REVEAL", "TEST_LD_DOCUMENT_REVEAL_ALL", @@ -78,6 +85,7 @@ "TEST_VC_DOCUMENT_SIGNED_BBS", "TEST_VC_DOCUMENT_SIGNED_ED25519", "TEST_VC_DOCUMENT_SIGNED_ED25519_2020", + "TEST_VC_DOCUMENT_SIGNED_P256_2019", "TEST_VC_DOCUMENT", "TEST_VC_DOCUMENT_SIGNED_DID_KEY_ED25519", "TEST_VC_DOCUMENT_DID_KEY_ED25519", diff --git a/acapy_agent/vc/tests/data/test_ld_document_bad_signed_secp256r1_2019.py b/acapy_agent/vc/tests/data/test_ld_document_bad_signed_secp256r1_2019.py new file mode 100644 index 0000000000..81f94728a0 --- /dev/null +++ b/acapy_agent/vc/tests/data/test_ld_document_bad_signed_secp256r1_2019.py @@ -0,0 +1,16 @@ +TEST_LD_DOCUMENT_BAD_SIGNED_P256_2019 = { + "@context": ["http://schema.org/", "https://w3id.org/security/bbs/v1"], + "@type": "Person", + "firstName": "Jane", + "lastName": "Does", + "jobTitle": "Professor", + "telephone": "(425) 123-4567", + "email": "jane.doe@example.com", + "proof": { + "type": "EcdsaSecp256r1Signature2019", + "verificationMethod": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "created": "2025-01-15T00:55:37+00:00", + "proofPurpose": "assertionMethod", + "proofValue": "z42hBVFNcjBLGpdMcDpA9YfPagJ9Ky5Fv8PQf7KoRt3S8tYJq61shtnsSszdLxQRpospia8CrM76rKE2MRRQimQKb", + }, +} diff --git a/acapy_agent/vc/tests/data/test_ld_document_signed_secp256r1_2019.py b/acapy_agent/vc/tests/data/test_ld_document_signed_secp256r1_2019.py new file mode 100644 index 0000000000..a762ce07a0 --- /dev/null +++ b/acapy_agent/vc/tests/data/test_ld_document_signed_secp256r1_2019.py @@ -0,0 +1,16 @@ +TEST_LD_DOCUMENT_SIGNED_P256_2019 = { + "@context": ["http://schema.org/", "https://w3id.org/security/bbs/v1"], + "@type": "Person", + "firstName": "Jane", + "lastName": "Does", + "jobTitle": "Professor", + "telephone": "(425) 123-4567", + "email": "jane.doe@example.com", + "proof": { + "type": "EcdsaSecp256r1Signature2019", + "verificationMethod": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "created": "2025-01-15T00:55:37+00:00", + "proofPurpose": "assertionMethod", + "proofValue": "z42hBVFNcjBLGpdMcDpA9YwPagJ9Ky5Fv8PQf7KoRt3S8tYJq61shtnsSszdLxQRpospia8CrM76rKE2MRRQimQKb", + }, +} diff --git a/acapy_agent/vc/tests/data/test_vc_document_signed_secp256r1_2019.py b/acapy_agent/vc/tests/data/test_vc_document_signed_secp256r1_2019.py new file mode 100644 index 0000000000..23088d62d8 --- /dev/null +++ b/acapy_agent/vc/tests/data/test_vc_document_signed_secp256r1_2019.py @@ -0,0 +1,37 @@ +TEST_VC_DOCUMENT_SIGNED_P256_2019 = { + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/citizenship/v1", + ], + "id": "https://issuer.oidp.uscis.gov/credentials/83627465", + "type": ["VerifiableCredential", "PermanentResidentCard"], + "issuer": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "issuanceDate": "2019-12-03T12:19:52Z", + "expirationDate": "2029-12-03T12:19:52Z", + "credentialSubject": { + "id": "did:example:b34ca6cd37bbf23", + "type": ["PermanentResident", "Person"], + "givenName": "JOHN", + "familyName": "SMITH", + "gender": "Male", + "image": "data:image/png;base64,iVBORw0KGgokJggg==", + "residentSince": "2015-01-01", + "lprCategory": "C09", + "lprNumber": "999-999-999", + "commuterClassification": "C1", + "birthCountry": "Bahamas", + "birthDate": "1958-07-17", + }, + "proof": { + "type": "EcdsaSecp256r1Signature2019", + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "created": "2021-12-31T23:59:59Z", + "domain": "example.com", + "challenge": "3fa85f64-5717-4562-b3fc-2c963f66afa6", + "proofValue": "z3bo3AAbrWWBbGnwb5xdK7fVgSwxbr3marh9oGttkNafheHEh8qzA1hGneYe1MPBBXNwd7wp2yyQ9E9im6vzDsuo5", + }, + "description": "Government of Example Permanent Resident Card.", + "identifier": "83627465", + "name": "Permanent Resident Card", +} diff --git a/acapy_agent/vc/tests/dids/__init__.py b/acapy_agent/vc/tests/dids/__init__.py index b2b3acff1a..37191e48c9 100644 --- a/acapy_agent/vc/tests/dids/__init__.py +++ b/acapy_agent/vc/tests/dids/__init__.py @@ -3,12 +3,16 @@ from .did_z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL import ( DID_z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL, ) +from .did_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq import ( + DID_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq, +) from .did_zUC72Q7XD4PE4CrMiDVXuvZng3sBvMmaGgNeTUJuzavH2BS7ThbHL9FhsZM9QYY5fqAQ4MB8M9oudz3tfuaX36Ajr97QRW7LBt6WWmrtESe6Bs5NYzFtLWEmeVtvRYVAgjFcJSa import ( DID_zUC72Q7XD4PE4CrMiDVXuvZng3sBvMmaGgNeTUJuzavH2BS7ThbHL9FhsZM9QYY5fqAQ4MB8M9oudz3tfuaX36Ajr97QRW7LBt6WWmrtESe6Bs5NYzFtLWEmeVtvRYVAgjFcJSa, ) __all__ = [ "DID_z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", + "DID_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", "DID_zUC72Q7XD4PE4CrMiDVXuvZng3sBvMmaGgNeTUJuzavH2BS7ThbHL9FhsZM9QYY5fqAQ4MB8M9oudz3tfuaX36Ajr97QRW7LBt6WWmrtESe6Bs5NYzFtLWEmeVtvRYVAgjFcJSa", "DID_EXAMPLE_48939859", "DID_SOV_QqEfJxe752NCmWqR5TssZ5", diff --git a/acapy_agent/vc/tests/dids/did_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq.py b/acapy_agent/vc/tests/dids/did_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq.py new file mode 100644 index 0000000000..17651045d9 --- /dev/null +++ b/acapy_agent/vc/tests/dids/did_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq.py @@ -0,0 +1,25 @@ +DID_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq = { + "@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/multikey/v1"], + "id": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "verificationMethod": [ + { + "id": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "type": "Multikey", + "controller": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "publicKeyMultibase": "zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + } + ], + "authentication": [ + "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + ], + "assertionMethod": [ + "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + ], + "capabilityDelegation": [ + "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + ], + "capabilityInvocation": [ + "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + ], + "keyAgreement": [], +} diff --git a/acapy_agent/vc/tests/document_loader.py b/acapy_agent/vc/tests/document_loader.py index e53c687310..7204f27c9d 100644 --- a/acapy_agent/vc/tests/document_loader.py +++ b/acapy_agent/vc/tests/document_loader.py @@ -6,6 +6,7 @@ SECURITY_CONTEXT_V1_URL, SECURITY_CONTEXT_V2_URL, SECURITY_CONTEXT_V3_URL, + SECURITY_CONTEXT_MULTIKEY_URL, ) from .contexts import ( BBS_V1, @@ -14,6 +15,7 @@ DID_V1, DIF_PRESENTATION_SUBMISSION_V1, ED25519_2020_V1, + MULTIKEY_V1, EXAMPLES_V1, ODRL, SCHEMA_ORG, @@ -26,6 +28,7 @@ DID_EXAMPLE_48939859, DID_SOV_QqEfJxe752NCmWqR5TssZ5, DID_z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL, + DID_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq, DID_zUC72Q7XD4PE4CrMiDVXuvZng3sBvMmaGgNeTUJuzavH2BS7ThbHL9FhsZM9QYY5fqAQ4MB8M9oudz3tfuaX36Ajr97QRW7LBt6WWmrtESe6Bs5NYzFtLWEmeVtvRYVAgjFcJSa, ) @@ -33,6 +36,9 @@ DID_z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL.get( "id" ): DID_z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL, + DID_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq.get( + "id" + ): DID_zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq, DID_zUC72Q7XD4PE4CrMiDVXuvZng3sBvMmaGgNeTUJuzavH2BS7ThbHL9FhsZM9QYY5fqAQ4MB8M9oudz3tfuaX36Ajr97QRW7LBt6WWmrtESe6Bs5NYzFtLWEmeVtvRYVAgjFcJSa.get( "id" ): DID_zUC72Q7XD4PE4CrMiDVXuvZng3sBvMmaGgNeTUJuzavH2BS7ThbHL9FhsZM9QYY5fqAQ4MB8M9oudz3tfuaX36Ajr97QRW7LBt6WWmrtESe6Bs5NYzFtLWEmeVtvRYVAgjFcJSa, @@ -45,6 +51,7 @@ CREDENTIALS_CONTEXT_V1_URL: CREDENTIALS_V1, SECURITY_CONTEXT_BBS_URL: BBS_V1, SECURITY_CONTEXT_ED25519_2020_URL: ED25519_2020_V1, + SECURITY_CONTEXT_MULTIKEY_URL: MULTIKEY_V1, "https://www.w3.org/2018/credentials/examples/v1": EXAMPLES_V1, "https://w3id.org/citizenship/v1": CITIZENSHIP_V1, "https://www.w3.org/ns/odrl.jsonld": ODRL, diff --git a/acapy_agent/vc/vc_ld/manager.py b/acapy_agent/vc/vc_ld/manager.py index bf3fa83bc4..9ade719e4c 100644 --- a/acapy_agent/vc/vc_ld/manager.py +++ b/acapy_agent/vc/vc_ld/manager.py @@ -5,6 +5,10 @@ from pyld import jsonld from pyld.jsonld import JsonLdProcessor +from acapy_agent.vc.ld_proofs.suites.ecdsa_secp256r1_signature_2019 import ( + EcdsaSecp256r1Signature2019, +) + from ...core.profile import Profile from ...storage.vc_holder.base import VCHolder from ...storage.vc_holder.vc_record import VCRecord @@ -12,7 +16,7 @@ from ...wallet.default_verification_key_strategy import BaseVerificationKeyStrategy from ...wallet.did_info import DIDInfo from ...wallet.error import WalletNotFoundError -from ...wallet.key_type import BLS12381G2, ED25519, KeyType +from ...wallet.key_type import BLS12381G2, ED25519, P256, KeyType from ..ld_proofs.constants import ( SECURITY_CONTEXT_BBS_URL, SECURITY_CONTEXT_ED25519_2020_URL, @@ -41,11 +45,13 @@ SignatureTypes = Union[ Type[Ed25519Signature2018], Type[Ed25519Signature2020], + Type[EcdsaSecp256r1Signature2019], Type[BbsBlsSignature2020], ] ProofTypes = Union[ Type[Ed25519Signature2018], Type[Ed25519Signature2020], + Type[EcdsaSecp256r1Signature2019], Type[BbsBlsSignature2020], Type[BbsBlsSignatureProof2020], ] @@ -56,6 +62,7 @@ SIGNATURE_SUITE_KEY_TYPE_MAPPING: Dict[SignatureTypes, KeyType] = { Ed25519Signature2018: ED25519, Ed25519Signature2020: ED25519, + EcdsaSecp256r1Signature2019: P256, } PROOF_KEY_TYPE_MAPPING = cast(Dict[ProofTypes, KeyType], SIGNATURE_SUITE_KEY_TYPE_MAPPING) diff --git a/acapy_agent/vc/vc_ld/tests/test_manager.py b/acapy_agent/vc/vc_ld/tests/test_manager.py index 24182f5eda..cdb327f0c5 100644 --- a/acapy_agent/vc/vc_ld/tests/test_manager.py +++ b/acapy_agent/vc/vc_ld/tests/test_manager.py @@ -34,6 +34,7 @@ from ...ld_proofs.suites.bbs_bls_signature_proof_2020 import BbsBlsSignatureProof2020 from ...ld_proofs.suites.ed25519_signature_2018 import Ed25519Signature2018 from ...ld_proofs.suites.ed25519_signature_2020 import Ed25519Signature2020 +from ...ld_proofs.suites.ecdsa_secp256r1_signature_2019 import EcdsaSecp256r1Signature2019 from ..manager import VcLdpManager, VcLdpManagerError from ..models.credential import VerifiableCredential from ..models.options import LDProofVCOptions @@ -309,10 +310,11 @@ async def test_issue_bbs(self): async def test_get_all_suites(self): suites = await self.manager._get_all_proof_suites() - assert len(suites) == 4 + assert len(suites) == 5 types = ( Ed25519Signature2018, Ed25519Signature2020, + EcdsaSecp256r1Signature2019, BbsBlsSignature2020, BbsBlsSignatureProof2020, ) diff --git a/acapy_agent/wallet/anoncreds_upgrade.py b/acapy_agent/wallet/anoncreds_upgrade.py index 4261acf0eb..f0d5c421dc 100644 --- a/acapy_agent/wallet/anoncreds_upgrade.py +++ b/acapy_agent/wallet/anoncreds_upgrade.py @@ -472,6 +472,7 @@ async def get_rev_reg_def_upgrade_objs( key=lambda x: json.loads(x.value)["created_at"], ) found_active = False + is_active = False for askar_issuer_rev_reg_def in askar_issuer_rev_reg_def_records: # active rev reg def is the oldest non-full and active rev reg def if ( @@ -674,7 +675,7 @@ async def finish_upgrade_by_updating_profile_or_shutting_down( 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 + f"""Upgrade of subwallet {profile.settings.get("wallet.name")} has completed. Profile is now askar-anoncreds""" # noqa: E501 ) else: await finish_upgrade(profile) @@ -701,7 +702,7 @@ async def check_upgrade_completion_loop(profile: Profile, is_subwallet=False): 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 + f"""Upgrade of subwallet {profile.settings.get("wallet.name")} has completed. Profile is now askar-anoncreds""" # noqa: E501 ) return LOGGER.info( diff --git a/acapy_agent/wallet/askar.py b/acapy_agent/wallet/askar.py index 69b5cb109e..4be4ce29e4 100644 --- a/acapy_agent/wallet/askar.py +++ b/acapy_agent/wallet/askar.py @@ -20,7 +20,7 @@ from .did_method import SOV, DIDMethod, DIDMethods from .did_parameters_validation import DIDParametersValidation from .error import WalletDuplicateError, WalletError, WalletNotFoundError -from .key_type import BLS12381G2, ED25519, X25519, KeyType, KeyTypes +from .key_type import BLS12381G2, ED25519, P256, X25519, KeyType, KeyTypes from .util import b58_to_bytes, bytes_to_b58 CATEGORY_DID = "did" @@ -185,18 +185,22 @@ async def get_signing_key(self, verkey: str) -> KeyInfo: if not verkey: raise WalletNotFoundError("No key identifier provided") - key = await self._session.handle.fetch_key(verkey) - if not key: + key_entry = await self._session.handle.fetch_key(verkey) + if not key_entry: raise WalletNotFoundError("Unknown key: {}".format(verkey)) - metadata = json.loads(key.metadata or "{}") + metadata = json.loads(key_entry.metadata or "{}") try: - kid = key.tags.get("kid") + kid = key_entry.tags.get("kid") except Exception: kid = None - # FIXME implement key types - return KeyInfo(verkey=verkey, metadata=metadata, key_type=ED25519, kid=kid) + key = cast(Key, key_entry.key) + key_types = self.session.inject(KeyTypes) + key_type = key_types.from_key_type(key.algorithm.value) + if not key_type: + raise WalletError(f"Unknown key type {key.algorithm.value}") + return KeyInfo(verkey=verkey, metadata=metadata, key_type=key_type, kid=kid) async def replace_signing_key_metadata(self, verkey: str, metadata: dict): """Replace the metadata associated with a signing keypair. @@ -775,6 +779,12 @@ async def verify_message( return pk.verify_signature(message, signature) except AskarError as err: raise WalletError("Exception when verifying message signature") from err + elif key_type == P256: + try: + pk = Key.from_public_bytes(KeyAlg.P256, verkey) + return pk.verify_signature(message, signature) + except AskarError as err: + raise WalletError("Exception when verifying message signature") from err # other key types are currently verified outside of Askar return verify_signed_message( @@ -869,6 +879,8 @@ def _create_keypair(key_type: KeyType, seed: Union[str, bytes, None] = None) -> elif key_type == X25519: alg = KeyAlg.X25519 method = None + elif key_type == P256: + alg = KeyAlg.P256 elif key_type == BLS12381G2: alg = KeyAlg.BLS12_381_G2 method = SeedMethod.BlsKeyGen @@ -878,7 +890,7 @@ def _create_keypair(key_type: KeyType, seed: Union[str, bytes, None] = None) -> raise WalletError(f"Unsupported key algorithm: {key_type}") if seed: try: - if key_type == ED25519: + if key_type in (ED25519, P256): # not a seed - it is the secret key seed = validate_seed(seed) return Key.from_secret_bytes(alg, seed) @@ -886,6 +898,9 @@ def _create_keypair(key_type: KeyType, seed: Union[str, bytes, None] = None) -> return Key.from_seed(alg, seed, method=method) except AskarError as err: if err.code == AskarErrorCode.INPUT: - raise WalletError("Invalid seed for key generation") from None + raise WalletError("Invalid seed for key generation") from err + else: + LOGGER.error(f"Unhandled Askar error code: {err.code}") + raise else: return Key.generate(alg) diff --git a/acapy_agent/wallet/did_method.py b/acapy_agent/wallet/did_method.py index 2acf670837..3123349945 100644 --- a/acapy_agent/wallet/did_method.py +++ b/acapy_agent/wallet/did_method.py @@ -4,7 +4,7 @@ from typing import Dict, List, Mapping, Optional from .error import BaseError -from .key_type import BLS12381G2, ED25519, X25519, KeyType +from .key_type import BLS12381G2, ED25519, P256, X25519, KeyType class HolderDefinedDid(Enum): @@ -67,7 +67,7 @@ def holder_defined_did(self) -> HolderDefinedDid: ) KEY = DIDMethod( name="key", - key_types=[ED25519, BLS12381G2], + key_types=[ED25519, P256, BLS12381G2], rotation=False, ) WEB = DIDMethod( @@ -90,8 +90,8 @@ def holder_defined_did(self) -> HolderDefinedDid: holder_defined_did=HolderDefinedDid.NO, ) -TDW = DIDMethod( - name="tdw", +WEBVH = DIDMethod( + name="webvh", key_types=[ED25519, X25519], rotation=False, holder_defined_did=HolderDefinedDid.NO, @@ -109,7 +109,7 @@ def __init__(self) -> None: WEB.method_name: WEB, PEER2.method_name: PEER2, PEER4.method_name: PEER4, - TDW.method_name: TDW, + WEBVH.method_name: WEBVH, } def registered(self, method: str) -> bool: diff --git a/acapy_agent/wallet/jwt.py b/acapy_agent/wallet/jwt.py index 33edd22593..c7f6cacbdb 100644 --- a/acapy_agent/wallet/jwt.py +++ b/acapy_agent/wallet/jwt.py @@ -2,22 +2,25 @@ import json import logging -from typing import Any, Mapping, Optional +from typing import Any, Mapping, Optional, Tuple from marshmallow import fields from pydid import DIDUrl, Resource, VerificationMethod +from pydid.verification_method import Ed25519VerificationKey2018, Multikey + +from acapy_agent.wallet.keys.manager import key_type_from_multikey, multikey_to_verkey from ..core.profile import Profile from ..messaging.jsonld.error import BadJWSHeaderError, InvalidVerificationMethod -from ..messaging.jsonld.routes import SUPPORTED_VERIFICATION_METHOD_TYPES from ..messaging.models.base import BaseModel, BaseModelSchema from ..resolver.did_resolver import DIDResolver from .base import BaseWallet from .default_verification_key_strategy import BaseVerificationKeyStrategy -from .key_type import ED25519 +from .key_type import ED25519, KeyType from .util import b64_to_bytes, bytes_to_b64 LOGGER = logging.getLogger(__name__) +SUPPORTED_JWT_ALGS = ("EdDSA", "ES256") def dict_to_b64(value: Mapping[str, Any]) -> str: @@ -67,20 +70,25 @@ async def jwt_sign( if not did: raise ValueError("DID URL must be absolute") - if not headers.get("typ", None): - headers["typ"] = "JWT" - headers = { - **headers, - "alg": "EdDSA", - "kid": verification_method, - } - encoded_headers = dict_to_b64(headers) - encoded_payload = dict_to_b64(payload) - async with profile.session() as session: wallet = session.inject(BaseWallet) - LOGGER.info(f"jwt sign: {did}") did_info = await wallet.get_local_did(did_lookup_name(did)) + + header_alg = did_info.key_type.jws_algorithm + if not header_alg: + raise ValueError(f"DID key type '{did_info.key_type}' cannot be used for JWS") + + if not headers.get("typ", None): + headers["typ"] = "JWT" + headers = { + **headers, + "alg": header_alg, + "kid": verification_method, + } + encoded_headers = dict_to_b64(headers) + encoded_payload = dict_to_b64(payload) + + LOGGER.info(f"jwt sign: {did}") sig_bytes = await wallet.sign_message( f"{encoded_headers}.{encoded_payload}".encode(), did_info.verkey ) @@ -130,8 +138,10 @@ class Meta: error = fields.Str(required=False, metadata={"description": "Error text"}) -async def resolve_public_key_by_kid_for_verify(profile: Profile, kid: str) -> str: - """Resolve public key material from a kid.""" +async def resolve_public_key_by_kid_for_verify( + profile: Profile, kid: str +) -> Tuple[str, KeyType]: + """Resolve public key verkey (base58 public key) and key type from a kid.""" resolver = profile.inject(DIDResolver) vmethod: Resource = await resolver.dereference( profile, @@ -143,33 +153,51 @@ async def resolve_public_key_by_kid_for_verify(profile: Profile, kid: str) -> st "Dereferenced resource is not a verification method" ) - if not isinstance(vmethod, SUPPORTED_VERIFICATION_METHOD_TYPES): - raise InvalidVerificationMethod( - f"Dereferenced method {type(vmethod).__name__} is not supported" - ) + if isinstance(vmethod, Ed25519VerificationKey2018): + verkey = vmethod.public_key_base58 + ktyp = ED25519 + return (verkey, ktyp) + + if isinstance(vmethod, Multikey): + multikey = vmethod.public_key_multibase + verkey = multikey_to_verkey(multikey) + ktyp = key_type_from_multikey(multikey=multikey) + return (verkey, ktyp) - return vmethod.material + # unsupported + raise InvalidVerificationMethod( + f"Dereferenced method {type(vmethod).__name__} is not supported" + ) async def jwt_verify(profile: Profile, jwt: str) -> JWTVerifyResult: """Verify a JWT and return the headers and payload.""" encoded_headers, encoded_payload, encoded_signature = jwt.split(".", 3) headers = b64_to_dict(encoded_headers) - if "alg" not in headers or headers["alg"] != "EdDSA" or "kid" not in headers: - raise BadJWSHeaderError("Invalid JWS header parameters for Ed25519Signature2018.") + if "alg" not in headers: + raise BadJWSHeaderError("Missing 'alg' parameter in JWS header") + if "kid" not in headers: + raise BadJWSHeaderError("Missing 'kid' parameter in JWS header") + if headers["alg"] not in SUPPORTED_JWT_ALGS: + raise BadJWSHeaderError( + f"Unsupported 'alg' value in JWS header: '{headers['alg']}'. " + f"Supported algorithms: {', '.join(SUPPORTED_JWT_ALGS)}" + ) payload = b64_to_dict(encoded_payload) verification_method = headers["kid"] decoded_signature = b64_to_bytes(encoded_signature, urlsafe=True) async with profile.session() as session: - verkey = await resolve_public_key_by_kid_for_verify(profile, verification_method) + (verkey, ktyp) = await resolve_public_key_by_kid_for_verify( + profile, verification_method + ) wallet = session.inject(BaseWallet) valid = await wallet.verify_message( f"{encoded_headers}.{encoded_payload}".encode(), decoded_signature, - verkey, - ED25519, + from_verkey=verkey, + key_type=ktyp, ) return JWTVerifyResult(headers, payload, valid, verification_method) diff --git a/acapy_agent/wallet/key_type.py b/acapy_agent/wallet/key_type.py index 9e16bb1dde..08ae92d336 100644 --- a/acapy_agent/wallet/key_type.py +++ b/acapy_agent/wallet/key_type.py @@ -6,11 +6,18 @@ class KeyType: """Key Type class.""" - def __init__(self, key_type: str, multicodec_name: str, multicodec_prefix: bytes): + def __init__( + self, + key_type: str, + multicodec_name: str, + multicodec_prefix: bytes, + jws_alg: Optional[str], + ): """Construct key type.""" self._type: str = key_type self._name: str = multicodec_name self._prefix: bytes = multicodec_prefix + self._jws_alg: bytes = jws_alg @property def key_type(self) -> str: @@ -27,15 +34,21 @@ def multicodec_prefix(self) -> bytes: """Get key type multicodec prefix.""" return self._prefix + @property + def jws_algorithm(self) -> Optional[str]: + """Get key type JWS Algorithm (used in the JOSE header).""" + return self._jws_alg + # NOTE: the py_multicodec library is outdated. We use hardcoded prefixes here # until this PR gets released: https://github.com/multiformats/py-multicodec/pull/14 # multicodec is also not used now, but may be used again if py_multicodec is updated -ED25519: KeyType = KeyType("ed25519", "ed25519-pub", b"\xed\x01") -X25519: KeyType = KeyType("x25519", "x25519-pub", b"\xec\x01") -BLS12381G1: KeyType = KeyType("bls12381g1", "bls12_381-g1-pub", b"\xea\x01") -BLS12381G2: KeyType = KeyType("bls12381g2", "bls12_381-g2-pub", b"\xeb\x01") -BLS12381G1G2: KeyType = KeyType("bls12381g1g2", "bls12_381-g1g2-pub", b"\xee\x01") +ED25519: KeyType = KeyType("ed25519", "ed25519-pub", b"\xed\x01", "EdDSA") +X25519: KeyType = KeyType("x25519", "x25519-pub", b"\xec\x01", None) +P256: KeyType = KeyType("p256", "p256-pub", b"\x80\x24", "ES256") +BLS12381G1: KeyType = KeyType("bls12381g1", "bls12_381-g1-pub", b"\xea\x01", None) +BLS12381G2: KeyType = KeyType("bls12381g2", "bls12_381-g2-pub", b"\xeb\x01", None) +BLS12381G1G2: KeyType = KeyType("bls12381g1g2", "bls12_381-g1g2-pub", b"\xee\x01", None) class KeyTypes: @@ -46,6 +59,7 @@ def __init__(self) -> None: self._type_registry: dict[str, KeyType] = { ED25519.key_type: ED25519, X25519.key_type: X25519, + P256.key_type: P256, BLS12381G1.key_type: BLS12381G1, BLS12381G2.key_type: BLS12381G2, BLS12381G1G2.key_type: BLS12381G1G2, @@ -53,6 +67,7 @@ def __init__(self) -> None: self._name_registry: dict[str, KeyType] = { ED25519.multicodec_name: ED25519, X25519.multicodec_name: X25519, + P256.multicodec_name: P256, BLS12381G1.multicodec_name: BLS12381G1, BLS12381G2.multicodec_name: BLS12381G2, BLS12381G1G2.multicodec_name: BLS12381G1G2, @@ -60,6 +75,7 @@ def __init__(self) -> None: self._prefix_registry: dict[bytes, KeyType] = { ED25519.multicodec_prefix: ED25519, X25519.multicodec_prefix: X25519, + P256.multicodec_prefix: P256, BLS12381G1.multicodec_prefix: BLS12381G1, BLS12381G2.multicodec_prefix: BLS12381G2, BLS12381G1G2.multicodec_prefix: BLS12381G1G2, diff --git a/acapy_agent/wallet/keys/manager.py b/acapy_agent/wallet/keys/manager.py index ba1094bf9f..bab88b3dcb 100644 --- a/acapy_agent/wallet/keys/manager.py +++ b/acapy_agent/wallet/keys/manager.py @@ -2,7 +2,7 @@ from ...core.profile import ProfileSession from ..base import BaseWallet -from ..key_type import ED25519 +from ..key_type import ED25519, P256, KeyType from ..util import b58_to_bytes, bytes_to_b58 from ...utils.multiformats import multibase from ...wallet.error import WalletNotFoundError @@ -15,20 +15,27 @@ "multikey_prefix": "z6Mk", "prefix_hex": "ed01", "prefix_length": 2, - } + }, + "p256": { + "key_type": P256, + "multikey_prefix": "zDn", + "prefix_hex": "8024", + "prefix_length": 2, + }, } -def multikey_to_verkey(multikey: str, alg: str = DEFAULT_ALG): +def multikey_to_verkey(multikey: str): """Transform multikey to verkey.""" + alg = key_type_from_multikey(multikey).key_type prefix_length = ALG_MAPPINGS[alg]["prefix_length"] public_bytes = bytes(bytearray(multibase.decode(multikey))[prefix_length:]) return bytes_to_b58(public_bytes) -def verkey_to_multikey(verkey: str, alg: str = DEFAULT_ALG): +def verkey_to_multikey(verkey: str, alg: str): """Transform verkey to multikey.""" prefix_hex = ALG_MAPPINGS[alg]["prefix_hex"] @@ -37,7 +44,7 @@ def verkey_to_multikey(verkey: str, alg: str = DEFAULT_ALG): return multibase.encode(bytes.fromhex(prefixed_key_hex), "base58btc") -def key_type_from_multikey(multikey: str): +def key_type_from_multikey(multikey: str) -> KeyType: """Derive key_type class from multikey prefix.""" for mapping in ALG_MAPPINGS: if multikey.startswith(ALG_MAPPINGS[mapping]["multikey_prefix"]): @@ -70,10 +77,12 @@ async def resolve_multikey_from_verification_method(self, kid: str): multikey = verification_method.public_key_multibase elif verification_method.type == "Ed25519VerificationKey2018": - multikey = verkey_to_multikey(verification_method.public_key_base58) + multikey = verkey_to_multikey( + verification_method.public_key_base58, alg="ed25519" + ) elif verification_method.type == "Ed25519VerificationKey2020": - multikey = verkey_to_multikey(verification_method.public_key_multibase) + multikey = verification_method.public_key_multibase else: raise MultikeyManagerError("Unknown verification method type.") @@ -107,7 +116,9 @@ async def from_kid(self, kid: str): return { "kid": key_info.kid, - "multikey": verkey_to_multikey(key_info.verkey), + "multikey": verkey_to_multikey( + key_info.verkey, alg=key_info.key_type.key_type + ), } async def from_multikey(self, multikey: str): @@ -117,7 +128,9 @@ async def from_multikey(self, multikey: str): return { "kid": key_info.kid, - "multikey": verkey_to_multikey(key_info.verkey), + "multikey": verkey_to_multikey( + key_info.verkey, alg=key_info.key_type.key_type + ), } async def create(self, seed: str = None, kid: str = None, alg: str = DEFAULT_ALG): @@ -136,7 +149,7 @@ async def create(self, seed: str = None, kid: str = None, alg: str = DEFAULT_ALG return { "kid": key_info.kid, - "multikey": verkey_to_multikey(key_info.verkey), + "multikey": verkey_to_multikey(key_info.verkey, alg=alg), } async def update(self, multikey: str, kid: str): @@ -151,5 +164,7 @@ async def update(self, multikey: str, kid: str): return { "kid": key_info.kid, - "multikey": verkey_to_multikey(key_info.verkey), + "multikey": verkey_to_multikey( + key_info.verkey, alg=key_info.key_type.key_type + ), } diff --git a/acapy_agent/wallet/keys/tests/test_key_operations.py b/acapy_agent/wallet/keys/tests/test_key_operations.py index 9bea8d54c2..6ec4264f66 100644 --- a/acapy_agent/wallet/keys/tests/test_key_operations.py +++ b/acapy_agent/wallet/keys/tests/test_key_operations.py @@ -13,9 +13,14 @@ class TestKeyOperations(IsolatedAsyncioTestCase): seed = "00000000000000000000000000000000" - multikey = "z6MkgKA7yrw5kYSiDuQFcye4bMaJpcfHFry3Bx45pdWh3s8i" - verkey = "2ru5PcgeQzxF7QZYwQgDkG2K13PRqyigVw99zMYg8eML" - kid = "did:web:example.com#key-01" + + ed25519_multikey = "z6MkgKA7yrw5kYSiDuQFcye4bMaJpcfHFry3Bx45pdWh3s8i" + ed25519_verkey = "2ru5PcgeQzxF7QZYwQgDkG2K13PRqyigVw99zMYg8eML" + ed25519_alg = "ed25519" + + p256_multikey = "zDnaeSd75MAwSRmem34MfZEzSMjQNcpWLmzkbF8Su49AuA9U2" + p256_verkey = "demmi97mhJ7JQu31git4hQz8a1PD1dETJH9TVKaynNQv" + p256_alg = "p256" async def asyncSetUp(self) -> None: self.profile = await create_test_profile() @@ -23,26 +28,40 @@ async def asyncSetUp(self) -> None: async def test_key_creation(self): async with self.profile.session() as session: - key_info = await MultikeyManager(session=session).create(seed=self.seed) - assert key_info["multikey"] == self.multikey - assert key_info["kid"] is None - - key_info = await MultikeyManager(session=session).from_multikey( - multikey=self.multikey - ) - assert key_info["multikey"] == self.multikey - assert key_info["kid"] is None - - key_info = await MultikeyManager(session=session).update( - multikey=self.multikey, kid=self.kid - ) - assert key_info["multikey"] == self.multikey - assert key_info["kid"] == self.kid - - key_info = await MultikeyManager(session=session).from_kid(kid=self.kid) - assert key_info["multikey"] == self.multikey - assert key_info["kid"] == self.kid + for i, (alg, expected_multikey) in enumerate( + [ + (self.ed25519_alg, self.ed25519_multikey), + (self.p256_alg, self.p256_multikey), + ] + ): + kid = f"did:web:example.com#key-0{i}" + + key_info = await MultikeyManager(session=session).create( + seed=self.seed, alg=alg + ) + assert key_info["multikey"] == expected_multikey + assert key_info["kid"] is None + + key_info = await MultikeyManager(session=session).from_multikey( + multikey=expected_multikey + ) + assert key_info["multikey"] == expected_multikey + assert key_info["kid"] is None + + key_info = await MultikeyManager(session=session).update( + multikey=expected_multikey, kid=kid + ) + assert key_info["multikey"] == expected_multikey + assert key_info["kid"] == kid + + key_info = await MultikeyManager(session=session).from_kid(kid=kid) + assert key_info["multikey"] == expected_multikey + assert key_info["kid"] == kid async def test_key_transformations(self): - assert multikey_to_verkey(self.multikey) == self.verkey - assert verkey_to_multikey(self.verkey) == self.multikey + for alg, multikey, verkey in [ + (self.ed25519_alg, self.ed25519_multikey, self.ed25519_verkey), + (self.p256_alg, self.p256_multikey, self.p256_verkey), + ]: + assert multikey_to_verkey(multikey) == verkey + assert verkey_to_multikey(verkey, alg=alg) == multikey diff --git a/acapy_agent/wallet/routes.py b/acapy_agent/wallet/routes.py index 0b33f1bd80..8009e13d30 100644 --- a/acapy_agent/wallet/routes.py +++ b/acapy_agent/wallet/routes.py @@ -81,7 +81,7 @@ ) from .did_posture import DIDPosture from .error import WalletError, WalletNotFoundError -from .key_type import BLS12381G2, ED25519, KeyTypes +from .key_type import BLS12381G2, ED25519, P256, KeyTypes from .singletons import UpgradeInProgressSingleton from .util import EVENT_LISTENER_PATTERN @@ -128,7 +128,7 @@ class DIDSchema(OpenAPISchema): ) key_type = fields.Str( required=True, - validate=validate.OneOf([ED25519.key_type, BLS12381G2.key_type]), + validate=validate.OneOf([ED25519.key_type, BLS12381G2.key_type, P256.key_type]), metadata={ "description": "Key type associated with the DID", "example": ED25519.key_type, @@ -328,7 +328,7 @@ class DIDListQueryStringSchema(OpenAPISchema): ) key_type = fields.Str( required=False, - validate=validate.OneOf([ED25519.key_type, BLS12381G2.key_type]), + validate=validate.OneOf([ED25519.key_type, BLS12381G2.key_type, P256.key_type]), metadata={"example": ED25519.key_type, "description": "Key type to query for."}, ) @@ -348,7 +348,7 @@ class DIDCreateOptionsSchema(OpenAPISchema): key_type = fields.Str( required=True, - validate=validate.OneOf([ED25519.key_type, BLS12381G2.key_type]), + validate=validate.OneOf([ED25519.key_type, BLS12381G2.key_type, P256.key_type]), metadata={ "example": ED25519.key_type, "description": ( @@ -1076,7 +1076,7 @@ async def wallet_set_did_endpoint(request: web.BaseRequest): return web.json_response({"txn": transaction.serialize()}) -@docs(tags=["wallet"], summary="Create a EdDSA jws using did keys with a given payload") +@docs(tags=["wallet"], summary="Create a jws using did keys with a given payload") @request_schema(JWSCreateSchema) @response_schema(WalletModuleResponseSchema(), description="") @tenant_authentication @@ -1114,9 +1114,7 @@ async def wallet_jwt_sign(request: web.BaseRequest): return web.json_response(jws) -@docs( - tags=["wallet"], summary="Create a EdDSA sd-jws using did keys with a given payload" -) +@docs(tags=["wallet"], summary="Create an sd-jws using did keys with a given payload") @request_schema(SDJWSCreateSchema) @response_schema(WalletModuleResponseSchema(), description="") @tenant_authentication @@ -1158,7 +1156,7 @@ async def wallet_sd_jwt_sign(request: web.BaseRequest): return web.json_response(sd_jws) -@docs(tags=["wallet"], summary="Verify a EdDSA jws using did keys with a given JWS") +@docs(tags=["wallet"], summary="Verify a jws using did keys with a given JWS") @request_schema(JWSVerifySchema()) @response_schema(JWSVerifyResponseSchema(), 200, description="") @tenant_authentication @@ -1200,7 +1198,7 @@ async def wallet_jwt_verify(request: web.BaseRequest): @docs( tags=["wallet"], - summary="Verify a EdDSA sd-jws using did keys with a given SD-JWS with " + summary="Verify an sd-jws using did keys with a given SD-JWS with " "optional key binding", ) @request_schema(SDJWSVerifySchema()) @@ -1412,8 +1410,7 @@ async def on_register_nym_event(profile: Profile, event: Event): except StorageError as err: # log the error, but continue LOGGER.exception( - "Error accepting endorser invitation/configuring endorser" - " connection: %s", + "Error accepting endorser invitation/configuring endorser connection: %s", err, ) return diff --git a/acapy_agent/wallet/tests/test_did_method.py b/acapy_agent/wallet/tests/test_did_method.py index 9777cef1dc..3e488ab29d 100644 --- a/acapy_agent/wallet/tests/test_did_method.py +++ b/acapy_agent/wallet/tests/test_did_method.py @@ -1,31 +1,50 @@ from unittest import TestCase -from ..key_type import BLS12381G1, BLS12381G1G2, BLS12381G2, ED25519, X25519, KeyTypes +from ..key_type import ( + BLS12381G1, + BLS12381G1G2, + BLS12381G2, + ED25519, + P256, + X25519, + KeyTypes, +) ED25519_PREFIX_BYTES = b"\xed\x01" BLS12381G1_PREFIX_BYTES = b"\xea\x01" BLS12381G1G2_PREFIX_BYTES = b"\xee\x01" BLS12381G2_PREFIX_BYTES = b"\xeb\x01" X25519_PREFIX_BYTES = b"\xec\x01" +P256_PREFIX_BYTES = b"\x80\x24" ED25519_KEY_NAME = "ed25519" X25519_KEY_NAME = "x25519" +P256_KEY_NAME = "p256" BLS12381G1_KEY_NAME = "bls12381g1" BLS12381G2_KEY_NAME = "bls12381g2" BLS12381G1G2_KEY_NAME = "bls12381g1g2" ED25519_MULTICODEC_NAME = "ed25519-pub" X25519_MULTICODEC_NAME = "x25519-pub" +P256_MULTICODEC_NAME = "p256-pub" BLS12381G1_MULTICODEC_NAME = "bls12_381-g1-pub" BLS12381G2_MULTICODEC_NAME = "bls12_381-g2-pub" BLS12381G1G2_MULTICODEC_NAME = "bls12_381-g1g2-pub" +ED25519_JWS_ALG = "EdDSA" +X25519_JWS_ALG = None +P256_JWS_ALG = "ES256" +BLS12381G1_JWS_ALG = None +BLS12381G2_JWS_ALG = None +BLS12381G1G2_JWS_ALG = None + class TestKeyType(TestCase): def test_from_multicodec_name(self): key_types = KeyTypes() assert key_types.from_multicodec_name(ED25519_MULTICODEC_NAME) == ED25519 assert key_types.from_multicodec_name(X25519_MULTICODEC_NAME) == X25519 + assert key_types.from_multicodec_name(P256_MULTICODEC_NAME) == P256 assert key_types.from_multicodec_name(BLS12381G1_MULTICODEC_NAME) == BLS12381G1 assert key_types.from_multicodec_name(BLS12381G2_MULTICODEC_NAME) == BLS12381G2 assert ( @@ -37,6 +56,7 @@ def test_from_key_type(self): key_types = KeyTypes() assert key_types.from_key_type(ED25519_KEY_NAME) == ED25519 assert key_types.from_key_type(X25519_KEY_NAME) == X25519 + assert key_types.from_key_type(P256_KEY_NAME) == P256 assert key_types.from_key_type(BLS12381G1_KEY_NAME) == BLS12381G1 assert key_types.from_key_type(BLS12381G2_KEY_NAME) == BLS12381G2 assert key_types.from_key_type(BLS12381G1G2_KEY_NAME) == BLS12381G1G2 @@ -46,6 +66,7 @@ def test_from_multicodec_prefix(self): key_types = KeyTypes() assert key_types.from_multicodec_prefix(ED25519_PREFIX_BYTES) == ED25519 assert key_types.from_multicodec_prefix(X25519_PREFIX_BYTES) == X25519 + assert key_types.from_multicodec_prefix(P256_PREFIX_BYTES) == P256 assert key_types.from_multicodec_prefix(BLS12381G1_PREFIX_BYTES) == BLS12381G1 assert key_types.from_multicodec_prefix(BLS12381G2_PREFIX_BYTES) == BLS12381G2 assert key_types.from_multicodec_prefix(BLS12381G1G2_PREFIX_BYTES) == BLS12381G1G2 @@ -65,6 +86,10 @@ def test_from_prefixed_bytes(self): ) == X25519 ) + assert ( + key_types.from_prefixed_bytes(b"".join([P256_PREFIX_BYTES, b"random-bytes"])) + == P256 + ) assert ( key_types.from_prefixed_bytes( b"".join([BLS12381G1_PREFIX_BYTES, b"random-bytes"]) @@ -94,3 +119,39 @@ def test_properties(self): assert key_type.key_type == ED25519_KEY_NAME assert key_type.multicodec_name == ED25519_MULTICODEC_NAME assert key_type.multicodec_prefix == ED25519_PREFIX_BYTES + assert key_type.jws_algorithm == ED25519_JWS_ALG + + key_type = X25519 + + assert key_type.key_type == X25519_KEY_NAME + assert key_type.multicodec_name == X25519_MULTICODEC_NAME + assert key_type.multicodec_prefix == X25519_PREFIX_BYTES + assert key_type.jws_algorithm == X25519_JWS_ALG + + key_type = P256 + + assert key_type.key_type == P256_KEY_NAME + assert key_type.multicodec_name == P256_MULTICODEC_NAME + assert key_type.multicodec_prefix == P256_PREFIX_BYTES + assert key_type.jws_algorithm == P256_JWS_ALG + + key_type = BLS12381G1 + + assert key_type.key_type == BLS12381G1_KEY_NAME + assert key_type.multicodec_name == BLS12381G1_MULTICODEC_NAME + assert key_type.multicodec_prefix == BLS12381G1_PREFIX_BYTES + assert key_type.jws_algorithm == BLS12381G1_JWS_ALG + + key_type = BLS12381G2 + + assert key_type.key_type == BLS12381G2_KEY_NAME + assert key_type.multicodec_name == BLS12381G2_MULTICODEC_NAME + assert key_type.multicodec_prefix == BLS12381G2_PREFIX_BYTES + assert key_type.jws_algorithm == BLS12381G2_JWS_ALG + + key_type = BLS12381G1G2 + + assert key_type.key_type == BLS12381G1G2_KEY_NAME + assert key_type.multicodec_name == BLS12381G1G2_MULTICODEC_NAME + assert key_type.multicodec_prefix == BLS12381G1G2_PREFIX_BYTES + assert key_type.jws_algorithm == BLS12381G1G2_JWS_ALG diff --git a/acapy_agent/wallet/tests/test_jwt.py b/acapy_agent/wallet/tests/test_jwt.py index 709477f88b..211acddaee 100644 --- a/acapy_agent/wallet/tests/test_jwt.py +++ b/acapy_agent/wallet/tests/test_jwt.py @@ -1,3 +1,4 @@ +from typing import Tuple from unittest import IsolatedAsyncioTestCase import pytest @@ -6,7 +7,7 @@ from ...resolver.tests.test_did_resolver import MockResolver from ...utils.testing import create_test_profile from ...wallet.did_method import KEY, DIDMethods -from ...wallet.key_type import ED25519, KeyTypes +from ...wallet.key_type import ED25519, P256, KeyType, KeyTypes from ..base import BaseWallet from ..default_verification_key_strategy import ( BaseVerificationKeyStrategy, @@ -19,85 +20,133 @@ class TestJWT(IsolatedAsyncioTestCase): """Tests for JWT sign and verify using dids.""" seed = "testseed000000000000000000000001" + did_key_ed25519_did = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + did_key_ed25519_verification_method = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + did_key_ed25519_doc = { + "@context": "https://www.w3.org/ns/did/v1", + "id": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", + "verificationMethod": [ + { + "id": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", + "type": "Ed25519VerificationKey2018", + "controller": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", + "publicKeyBase58": "3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx", + } + ], + "authentication": [ + "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + ], + "assertionMethod": [ + "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + ], + "capabilityDelegation": [ + "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + ], + "capabilityInvocation": [ + "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" + ], + "keyAgreement": [ + { + "id": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6LSbkodSr6SU2trs8VUgnrnWtSm7BAPG245ggrBmSrxbv1R", + "type": "X25519KeyAgreementKey2019", + "controller": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", + "publicKeyBase58": "5dTvYHaNaB7mk7iA9LqCJEHG2dGZQsvoi8WGzDRtYEf", + } + ], + } + did_key_p256_did = "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + did_key_p256_verification_method = "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + did_key_p256_doc = { + "@context": [ + "https://www.w3.org/ns/did/v1", + "https://w3id.org/security/multikey/v1", + ], + "id": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "verificationMethod": [ + { + "id": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "type": "Multikey", + "controller": "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + "publicKeyMultibase": "zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq", + } + ], + "authentication": [ + "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + ], + "assertionMethod": [ + "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + ], + "capabilityDelegation": [ + "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + ], + "capabilityInvocation": [ + "did:key:zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq#zDnaehWviigWQQD7bqF3btFquwA5w8DX2sQwkVxnAyJ7oxdjq" + ], + "keyAgreement": [], + } async def asyncSetUp(self): self.profile = await create_test_profile() - self.resolver = DIDResolver() - self.resolver.register_resolver( - MockResolver( - ["key"], - resolved={ - "@context": "https://www.w3.org/ns/did/v1", - "id": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", - "verificationMethod": [ - { - "id": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", - "type": "Ed25519VerificationKey2018", - "controller": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", - "publicKeyBase58": "3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx", - } - ], - "authentication": [ - "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" - ], - "assertionMethod": [ - "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" - ], - "capabilityDelegation": [ - "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" - ], - "capabilityInvocation": [ - "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" - ], - "keyAgreement": [ - { - "id": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6LSbkodSr6SU2trs8VUgnrnWtSm7BAPG245ggrBmSrxbv1R", - "type": "X25519KeyAgreementKey2019", - "controller": "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL", - "publicKeyBase58": "5dTvYHaNaB7mk7iA9LqCJEHG2dGZQsvoi8WGzDRtYEf", - } - ], - }, - native=True, - ) - ) self.profile.context.injector.bind_instance(DIDMethods, DIDMethods()) self.profile.context.injector.bind_instance( BaseVerificationKeyStrategy, DefaultVerificationKeyStrategy() ) - self.profile.context.injector.bind_instance(DIDResolver, self.resolver) self.profile.context.injector.bind_instance(KeyTypes, KeyTypes()) - async def test_sign_with_did_key_and_verify(self): + async def setUpTestingDid(self, key_type: KeyType) -> Tuple[str, str]: async with self.profile.session() as session: wallet = session.inject(BaseWallet) - did_info = await wallet.create_local_did(KEY, ED25519, self.seed) - did = did_info.did - verification_method = None + await wallet.create_local_did(KEY, key_type, self.seed) + + if key_type == P256: + did = self.did_key_p256_did + vm_id = self.did_key_p256_verification_method + did_doc = self.did_key_p256_doc + elif key_type == ED25519: + did = self.did_key_ed25519_did + vm_id = self.did_key_ed25519_verification_method + did_doc = self.did_key_ed25519_doc + + resolver = DIDResolver() + resolver.register_resolver( + MockResolver( + ["key"], + resolved=did_doc, + native=True, + ) + ) + self.profile.context.injector.bind_instance(DIDResolver, resolver) - headers = {} - payload = {} - signed = await jwt_sign(self.profile, headers, payload, did, verification_method) + return (did, vm_id) - assert signed + async def test_sign_with_did_key_and_verify(self): + for key_type in [ED25519, P256]: + (did, _) = await self.setUpTestingDid(key_type) + verification_method = None + + headers = {} + payload = {} + signed = await jwt_sign( + self.profile, headers, payload, did, verification_method + ) - assert await jwt_verify(self.profile, signed) + assert signed + + assert await jwt_verify(self.profile, signed) async def test_sign_with_verification_method_and_verify(self): - async with self.profile.session() as session: - wallet = session.inject(BaseWallet) - await wallet.create_local_did(KEY, ED25519, self.seed) - did = None - verification_method = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" - headers = {} - payload = {} - signed: str = await jwt_sign( - self.profile, headers, payload, did, verification_method - ) + for key_type in [ED25519, P256]: + (_, verification_method) = await self.setUpTestingDid(key_type) + did = None + headers = {} + payload = {} + signed: str = await jwt_sign( + self.profile, headers, payload, did, verification_method + ) - assert signed + assert signed - assert await jwt_verify(self.profile, signed) + assert await jwt_verify(self.profile, signed) async def test_sign_x_invalid_did(self): did = "did:key:zzzzgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" @@ -118,27 +167,36 @@ async def test_sign_x_invalid_verification_method(self): assert "Unknown DID" in str(e_info) async def test_verify_x_invalid_signed(self): - async with self.profile.session() as session: - wallet = session.inject(BaseWallet) - did_info = await wallet.create_local_did(KEY, ED25519, self.seed) - did = did_info.did - verification_method = None + for key_type in [ED25519, P256]: + (did, _) = await self.setUpTestingDid(key_type) + verification_method = None + + headers = {} + payload = {} + signed = await jwt_sign( + self.profile, headers, payload, did, verification_method + ) - headers = {} - payload = {} - signed = await jwt_sign(self.profile, headers, payload, did, verification_method) + assert signed + signed = f"{signed[:-2]}2" + + with pytest.raises(Exception): + await jwt_verify(self.profile, signed) - assert signed - signed = f"{signed[:-2]}2" + async def test_resolve_public_key_by_kid_for_verify_ed25519(self): + (_, kid) = await self.setUpTestingDid(ED25519) + (key_bs58, key_type) = await resolve_public_key_by_kid_for_verify( + self.profile, kid + ) - with pytest.raises(Exception): - await jwt_verify(self.profile, signed) + assert key_bs58 == "3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx" + assert key_type == ED25519 - async def test_resolve_public_key_by_kid_for_verify(self): - async with self.profile.session() as session: - wallet = session.inject(BaseWallet) - await wallet.create_local_did(KEY, ED25519, self.seed) - kid = "did:key:z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL#z6Mkgg342Ycpuk263R9d8Aq6MUaxPn1DDeHyGo38EefXmgDL" - key_material = await resolve_public_key_by_kid_for_verify(self.profile, kid) + async def test_resolve_public_key_by_kid_for_verify_p256(self): + (_, kid) = await self.setUpTestingDid(P256) + (key_bs58, key_type) = await resolve_public_key_by_kid_for_verify( + self.profile, kid + ) - assert key_material == "3Dn1SJNPaCXcvvJvSbsFWP2xaCjMom3can8CQNhWrTRx" + assert key_bs58 == "tYbR5egjfja9D5ix1jjYGqfh5QPu73RcZ7UjQUXtargj" + assert key_type == P256 diff --git a/acapy_agent/wallet/tests/test_sd_jwt.py b/acapy_agent/wallet/tests/test_sd_jwt.py index 1ee2040776..41d9ac2ff2 100644 --- a/acapy_agent/wallet/tests/test_sd_jwt.py +++ b/acapy_agent/wallet/tests/test_sd_jwt.py @@ -119,7 +119,7 @@ async def test_sign_with_did_key_and_verify(self): for disclosure in signed.split("~")[1:-1]: # Decode the disclosures - padded = f"{disclosure}{'=' * divmod(len(disclosure),4)[1]}" + padded = f"{disclosure}{'=' * divmod(len(disclosure), 4)[1]}" decoded = json.loads(urlsafe_b64decode(padded).decode("utf-8")) # Add the disclosures associated with the claims to be revealed if decoded[1] in revealed: diff --git a/demo/docker-agent/Dockerfile.acapy b/demo/docker-agent/Dockerfile.acapy index 80ee05b2cc..0fad59f419 100644 --- a/demo/docker-agent/Dockerfile.acapy +++ b/demo/docker-agent/Dockerfile.acapy @@ -1,4 +1,4 @@ -FROM ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.12.2 +FROM ghcr.io/openwallet-foundation/acapy-agent:py3.12-1.2.0 USER root diff --git a/demo/multi-demo/Dockerfile.acapy b/demo/multi-demo/Dockerfile.acapy index 80ee05b2cc..0fad59f419 100644 --- a/demo/multi-demo/Dockerfile.acapy +++ b/demo/multi-demo/Dockerfile.acapy @@ -1,4 +1,4 @@ -FROM ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.12.2 +FROM ghcr.io/openwallet-foundation/acapy-agent:py3.12-1.2.0 USER root diff --git a/demo/playground/Dockerfile.acapy b/demo/playground/Dockerfile.acapy index 35f60c563c..5dfa08027a 100644 --- a/demo/playground/Dockerfile.acapy +++ b/demo/playground/Dockerfile.acapy @@ -1,4 +1,4 @@ -FROM ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.12.2 +FROM ghcr.io/openwallet-foundation/acapy-agent:py3.12-1.2.0 USER root diff --git a/demo/playground/README.md b/demo/playground/README.md index 418a1ee188..6608418b4d 100644 --- a/demo/playground/README.md +++ b/demo/playground/README.md @@ -26,7 +26,7 @@ These configuration files are provided to the ACA-Py start command via the `AGEN ### Dockerfile and start.sh -[`Dockerfile.acapy`](./Dockerfile.acapy) assembles the image to run. Currently based on [Aries Cloudagent Python 0.21.1](ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.12.1), we need [jq](https://stedolan.github.io/jq/) to setup (or not) the ngrok tunnel and execute the Aca-py start command - see [`start.sh`](./start.sh). You may note that the start command is very sparse, additional configuration is done via environment variables in the [docker compose file](./docker-compose.yml). +[`Dockerfile.acapy`](./Dockerfile.acapy) assembles the image to run. Currently based on [ACA-Py 1.2.0](ghcr.io/openwallet-foundation/acapy-agent:py3.12-1.2.0), we need [jq](https://stedolan.github.io/jq/) to setup (or not) the ngrok tunnel and execute the Aca-py start command - see [`start.sh`](./start.sh). You may note that the start command is very sparse, additional configuration is done via environment variables in the [docker compose file](./docker-compose.yml). ### ngrok diff --git a/demo/requirements.txt b/demo/requirements.txt index 9d0644b239..64c93ba07b 100644 --- a/demo/requirements.txt +++ b/demo/requirements.txt @@ -1,5 +1,5 @@ asyncpg~=0.30.0 prompt_toolkit~=2.0.10 web.py~=0.62 -pygments~=2.18 +pygments~=2.19 qrcode[pil]~=8.0 diff --git a/docker/Dockerfile b/docker/Dockerfile index 89e2e3da54..101cffe8f5 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,16 +3,17 @@ FROM python:${python_version}-slim-bullseye AS build WORKDIR /src -COPY . . +COPY ./acapy_agent ./acapy_agent +COPY ./pyproject.toml ./poetry.lock ./README.md ./ -RUN pip install --no-cache-dir poetry +RUN pip install --no-cache-dir poetry==1.8.3 RUN poetry build FROM python:${python_version}-slim-bullseye AS main ARG uid=1001 ARG user=aries -ARG acapy_name="aries-cloudagent" +ARG acapy_name="acapy-agent" ARG acapy_version ARG acapy_reqs=[didcommv2] @@ -26,7 +27,7 @@ ENV HOME="/home/$user" \ RUST_LOG=warn \ SHELL=/bin/bash \ SUMMARY="$acapy_name image" \ - DESCRIPTION="$acapy_name provides a base image for running Hyperledger Aries agents in Docker. \ + DESCRIPTION="$acapy_name provides a base image for running acapy agents in Docker. \ This image layers the python implementation of $acapy_name $acapy_version. Based on Debian Buster." LABEL summary="$SUMMARY" \ @@ -100,7 +101,7 @@ RUN acapy_agent_package=$(find ./ -name "acapy_agent*.whl" | head -n 1) && \ rm acapy_agent*.whl && \ chmod +rx $(python -m site --user-site) $HOME/.local -# Clean-up unneccessary build dependencies and reduce final image size +# Clean-up unnecessary build dependencies and reduce final image size USER root RUN apt-get purge -y --auto-remove build-essential diff --git a/docker/Dockerfile.demo b/docker/Dockerfile.demo index 766dde0a64..dfbf170e55 100644 --- a/docker/Dockerfile.demo +++ b/docker/Dockerfile.demo @@ -1,4 +1,4 @@ -ARG from_image=ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.12.1 +ARG from_image=ghcr.io/openwallet-foundation/acapy-agent:py3.12-1.2.0 FROM ${from_image} ENV ENABLE_PTVSD 0 @@ -10,7 +10,7 @@ RUN mkdir -p bin && curl -L -o bin/jq \ chmod ug+x bin/jq # Copy and install Aries Agent code -RUN pip install --no-cache-dir poetry +RUN pip install --no-cache-dir poetry==1.8.3 COPY README.md pyproject.toml poetry.lock ./ diff --git a/docker/Dockerfile.run b/docker/Dockerfile.run index 706588d0b5..fe96405184 100644 --- a/docker/Dockerfile.run +++ b/docker/Dockerfile.run @@ -9,10 +9,10 @@ RUN apt-get update -y && \ WORKDIR /usr/src/app -# For consistency with base images, include curl for healthchecks +# For consistency with base images, include curl for health checks RUN apt-get update && apt-get install -y curl && apt-get clean -RUN pip install --no-cache-dir poetry +RUN pip install --no-cache-dir poetry==1.8.3 RUN mkdir -p acapy_agent && touch acapy_agent/__init__.py COPY pyproject.toml poetry.lock README.md ./ @@ -21,6 +21,6 @@ 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 "didcommv2"; fi -COPY . . +COPY ./acapy_agent ./acapy_agent ENTRYPOINT ["/bin/bash", "-c", "poetry run aca-py \"$@\"", "--"] diff --git a/docker/Dockerfile.test b/docker/Dockerfile.test index fb4e9e98f1..7b597c2785 100644 --- a/docker/Dockerfile.test +++ b/docker/Dockerfile.test @@ -9,7 +9,7 @@ RUN apt-get update -y && \ WORKDIR /usr/src/app -RUN pip install --no-cache-dir poetry +RUN pip install --no-cache-dir poetry==1.8.3 COPY ./README.md pyproject.toml ./poetry.lock ./ RUN mkdir acapy_agent && touch acapy_agent/__init__.py @@ -17,6 +17,7 @@ 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 "didcommv2" --with=dev; fi -COPY . . +COPY ./acapy_agent ./acapy_agent +COPY ./conftest.py ./ ENTRYPOINT ["/bin/bash", "-c", "poetry run pytest \"$@\"", "--"] diff --git a/docs/UpdateRTD.md b/docs/UpdateRTD.md index c9307936b2..ceabc1e7ac 100644 --- a/docs/UpdateRTD.md +++ b/docs/UpdateRTD.md @@ -35,6 +35,9 @@ cd docs; sphinx-build -b html -a -E -c ./ ./ ./_build; cd .. Once generated, go into the `docs/_build` folder and open `index.html` in a browser. Note that the `_build` is `.gitignore`'d and so will not be part of a git push. +If the script does not run at all, you may need to do a `pip install -r +docs/requirements.txt` to update the Sphinx dependencies. + ### Look for Errors This is the hard part; looking for errors in docstrings added by devs. Some tips: diff --git a/docs/features/DIDResolution.md b/docs/features/DIDResolution.md index 607d3f2dc3..e7da6ab1a0 100644 --- a/docs/features/DIDResolution.md +++ b/docs/features/DIDResolution.md @@ -176,7 +176,7 @@ plugin: The following is a fully functional Dockerfile encapsulating this setup: ```dockerfile= -FROM ghcr.io/openwallet-foundation/acapy:py3.9-0.12.1 +FROM ghcr.io/openwallet-foundation/acapy-agent:py3.12-1.2.0 RUN pip3 install git+https://github.com/dbluhm/acapy-resolver-github CMD ["aca-py", "start", "-it", "http", "0.0.0.0", "3000", "-ot", "http", "-e", "http://localhost:3000", "--admin", "0.0.0.0", "3001", "--admin-insecure-mode", "--no-ledger", "--plugin", "acapy_resolver_github"] diff --git a/docs/features/SupportedRFCs.md b/docs/features/SupportedRFCs.md index 8118b283c7..52358ee80c 100644 --- a/docs/features/SupportedRFCs.md +++ b/docs/features/SupportedRFCs.md @@ -1,4 +1,4 @@ -# Aries AIP, Protocols, Credential Formats, and Aries RFCs Supported in ACA-Py +# Aries AIP, Protocols, Credential Formats, and Other Capabilities Supported in ACA-Py This document provides a summary of the adherence of ACA-Py to the [Aries Interop Profiles](https://github.com/hyperledger/aries-rfcs/tree/main/concepts/0302-aries-interop-profile), @@ -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-12-02, Release 1.1.1 +**Last Update**: 2025-01-21, Release 1.2.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. @@ -56,7 +56,7 @@ A summary of the Aries Interop Profiles and Aries RFCs supported in ACA-Py can b | Credential Type | Supported | Notes | | --- | :--: | -- | | [Hyperledger AnonCreds] | :white_check_mark: | Includes full issue VC, present proof, and revoke VC support. | -| [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) | :white_check_mark: | Supports JSON-LD Data Integrity Proof Credentials using the `Ed25519Signature2018`, `BbsBlsSignature2020` and `BbsBlsSignatureProof2020` signature suites.

Supports the [DIF Presentation Exchange](https://identity.foundation/presentation-exchange/) data format for presentation requests and presentation submissions.

Work currently underway to add support for [Hyperledger AnonCreds] in W3C VC JSON-LD Format | +| [W3C Verifiable Credentials Data Model](https://www.w3.org/TR/vc-data-model/) | :white_check_mark: | Supports JSON-LD Data Integrity Proof Credentials using the `Ed25519Signature2018`, `EcdsaSecp256r1Signature2019`, `BbsBlsSignature2020` and `BbsBlsSignatureProof2020` signature suites.

Supports the [DIF Presentation Exchange](https://identity.foundation/presentation-exchange/) data format for presentation requests and presentation submissions.

Work currently underway to add support for [Hyperledger AnonCreds] in W3C VC JSON-LD Format | [Hyperledger AnonCreds]: https://www.hyperledger.org/projects/anoncreds diff --git a/docs/generated/acapy_agent.anoncreds.models.rst b/docs/generated/acapy_agent.anoncreds.models.rst index 58f7a28113..2d945f1b13 100644 --- a/docs/generated/acapy_agent.anoncreds.models.rst +++ b/docs/generated/acapy_agent.anoncreds.models.rst @@ -105,6 +105,14 @@ acapy\_agent.anoncreds.models.schema module :undoc-members: :show-inheritance: +acapy\_agent.anoncreds.models.schema\_info module +------------------------------------------------- + +.. automodule:: acapy_agent.anoncreds.models.schema_info + :members: + :undoc-members: + :show-inheritance: + acapy\_agent.anoncreds.models.utils module ------------------------------------------ diff --git a/docs/generated/acapy_agent.resolver.default.rst b/docs/generated/acapy_agent.resolver.default.rst index 32a0f44cc9..803b76d7f3 100644 --- a/docs/generated/acapy_agent.resolver.default.rst +++ b/docs/generated/acapy_agent.resolver.default.rst @@ -73,14 +73,6 @@ 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 ---------------------------------------------- @@ -96,3 +88,11 @@ acapy\_agent.resolver.default.web module :members: :undoc-members: :show-inheritance: + +acapy\_agent.resolver.default.webvh module +------------------------------------------ + +.. automodule:: acapy_agent.resolver.default.webvh + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/generated/acapy_agent.vc.ld_proofs.suites.rst b/docs/generated/acapy_agent.vc.ld_proofs.suites.rst index 1b9ead2996..92ee776688 100644 --- a/docs/generated/acapy_agent.vc.ld_proofs.suites.rst +++ b/docs/generated/acapy_agent.vc.ld_proofs.suites.rst @@ -33,6 +33,14 @@ acapy\_agent.vc.ld\_proofs.suites.bbs\_bls\_signature\_proof\_2020 module :undoc-members: :show-inheritance: +acapy\_agent.vc.ld\_proofs.suites.ecdsa\_secp256r1\_signature\_2019 module +-------------------------------------------------------------------------- + +.. automodule:: acapy_agent.vc.ld_proofs.suites.ecdsa_secp256r1_signature_2019 + :members: + :undoc-members: + :show-inheritance: + acapy\_agent.vc.ld\_proofs.suites.ed25519\_signature\_2018 module ----------------------------------------------------------------- diff --git a/docs/requirements.txt b/docs/requirements.txt index 87124ff7ab..06bebc1bbd 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,5 @@ # Defining the exact versions for ReadTheDocs that will make sure things don't break sphinx==5.3.0 sphinx_rtd_theme==1.3.0 -readthedocs-sphinx-search==0.3.2 \ No newline at end of file +readthedocs-sphinx-search==0.3.2 +sphinx-notfound-page==1.0.2 diff --git a/docs/testing/UnitTests.md b/docs/testing/UnitTests.md index 776611405d..e453255d9c 100644 --- a/docs/testing/UnitTests.md +++ b/docs/testing/UnitTests.md @@ -7,7 +7,7 @@ This [video](https://youtu.be/yJ6LpAiVNFM) is a presentation of the material cov ## Running unit tests in ACA-Py - `./scripts/run_tests` -- `./scripts/run_tests aries_cloudagent/protocols/out_of_band/v1_0/tests` +- `./scripts/run_tests acapy_agent/protocols/out_of_band/v1_0/tests` Note: The `bbs` library is not installed with ACA-Py by default, therefore unit tests involving BBS Signatures are disabled. To run BBS tests add the `--all-extras` flag: @@ -64,7 +64,7 @@ def test_sub_unsub(event_bus: EventBus, processor): assert not event_bus.topic_patterns_to_subscribers ``` -From aries_cloudagent/core/event_bus.py +From acapy_agent/core/event_bus.py ```python class EventBus: diff --git a/mkdocs-requirements.txt b/mkdocs-requirements.txt index f3ce31ab9c..c1104cc30b 100644 --- a/mkdocs-requirements.txt +++ b/mkdocs-requirements.txt @@ -1,3 +1,3 @@ -mkdocs-material==9.5.49 +mkdocs-material==9.5.50 mike==2.1.3 diff --git a/open-api/openapi.json b/open-api/openapi.json index 07c228d3a8..06966bba64 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.1" + "version" : "v1.2.1" }, "servers" : [ { "url" : "/" @@ -591,7 +591,7 @@ "name" : "cred_def_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+)):(.+)?$", + "pattern" : "^(.+$)", "type" : "string" } } ], @@ -619,7 +619,7 @@ "name" : "cred_def_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+)):(.+)?$", + "pattern" : "^(.+$)", "type" : "string" } } ], @@ -662,7 +662,7 @@ "in" : "query", "name" : "rev_reg_id", "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "pattern" : "^(.+$)", "type" : "string" } } ], @@ -718,7 +718,7 @@ "in" : "query", "name" : "cred_def_id", "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+)):(.+)?$", + "pattern" : "^(.+$)", "type" : "string" } }, { @@ -754,7 +754,7 @@ "name" : "rev_reg_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "pattern" : "^(.+$)", "type" : "string" } } ], @@ -782,7 +782,7 @@ "name" : "rev_reg_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "pattern" : "^(.+$)", "type" : "string" } }, { @@ -818,7 +818,7 @@ "name" : "rev_reg_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "pattern" : "^(.+$)", "type" : "string" } } ], @@ -846,7 +846,7 @@ "name" : "rev_reg_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "pattern" : "^(.+$)", "type" : "string" } } ], @@ -874,7 +874,7 @@ "name" : "rev_reg_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "pattern" : "^(.+$)", "type" : "string" } } ], @@ -902,7 +902,7 @@ "name" : "rev_reg_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "pattern" : "^(.+$)", "type" : "string" } }, { @@ -939,7 +939,7 @@ "name" : "rev_reg_id", "required" : true, "schema" : { - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "pattern" : "^(.+$)", "type" : "string" } } ], @@ -1156,7 +1156,7 @@ "in" : "query", "name" : "my_did", "schema" : { - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" } }, { @@ -1180,7 +1180,7 @@ "in" : "query", "name" : "their_did", "schema" : { - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" } }, { @@ -1188,7 +1188,7 @@ "in" : "query", "name" : "their_public_did", "schema" : { - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" } }, { @@ -2221,7 +2221,7 @@ "name" : "their_public_did", "required" : true, "schema" : { - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" } }, { @@ -6958,8 +6958,31 @@ }, "/vc/credentials/store" : { "post" : { + "requestBody" : { + "content" : { + "*/*" : { + "schema" : { + "$ref" : "#/components/schemas/StoreCredentialRequest" + } + } + }, + "required" : false + }, + "responses" : { + "200" : { + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/StoreCredentialResponse" + } + } + }, + "description" : "" + } + }, "summary" : "Store a credential", - "tags" : [ "vc-api" ] + "tags" : [ "vc-api" ], + "x-codegen-request-body-name" : "body" } }, "/vc/credentials/verify" : { @@ -7140,7 +7163,7 @@ "in" : "query", "name" : "did", "schema" : { - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" } }, { @@ -7148,7 +7171,7 @@ "in" : "query", "name" : "key_type", "schema" : { - "enum" : [ "ed25519", "bls12381g2" ], + "enum" : [ "ed25519", "bls12381g2", "p256" ], "type" : "string" } }, { @@ -7156,7 +7179,6 @@ "in" : "query", "name" : "method", "schema" : { - "enum" : [ "key", "sov", "did:peer:2", "did:peer:4" ], "type" : "string" } }, { @@ -7229,7 +7251,7 @@ "name" : "did", "required" : true, "schema" : { - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" } } ], @@ -7273,7 +7295,7 @@ "name" : "did", "required" : true, "schema" : { - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" } }, { @@ -7322,7 +7344,7 @@ "name" : "did", "required" : true, "schema" : { - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" } } ], @@ -7366,7 +7388,7 @@ "description" : "" } }, - "summary" : "Create a EdDSA jws using did keys with a given payload", + "summary" : "Create a jws using did keys with a given payload", "tags" : [ "wallet" ], "x-codegen-request-body-name" : "body" } @@ -7395,7 +7417,7 @@ "description" : "" } }, - "summary" : "Verify a EdDSA jws using did keys with a given JWS", + "summary" : "Verify a jws using did keys with a given JWS", "tags" : [ "wallet" ], "x-codegen-request-body-name" : "body" } @@ -7506,7 +7528,7 @@ "description" : "" } }, - "summary" : "Create a EdDSA sd-jws using did keys with a given payload", + "summary" : "Create an sd-jws using did keys with a given payload", "tags" : [ "wallet" ], "x-codegen-request-body-name" : "body" } @@ -7535,7 +7557,7 @@ "description" : "" } }, - "summary" : "Verify a EdDSA sd-jws using did keys with a given SD-JWS with optional key binding", + "summary" : "Verify an sd-jws using did keys with a given SD-JWS with optional key binding", "tags" : [ "wallet" ], "x-codegen-request-body-name" : "body" } @@ -7761,25 +7783,7 @@ "type" : "string" } }, - "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" - } - }, + "required" : [ "attrNames", "issuerId", "name", "version" ], "type" : "object" }, "AnoncredsPresentationReqAttrSpec" : { @@ -7927,6 +7931,25 @@ "required" : [ "requested_attributes", "requested_predicates" ], "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" + }, "AttachDecorator" : { "properties" : { "@id" : { @@ -8220,7 +8243,7 @@ "my_did" : { "description" : "Our DID for connection", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "request_id" : { @@ -8242,7 +8265,7 @@ "their_did" : { "description" : "Their DID for connection", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "their_label" : { @@ -8286,7 +8309,7 @@ "did" : { "description" : "DID for connection invitation", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "imageUrl" : { @@ -9372,12 +9395,12 @@ "did" : { "description" : "DID of interest", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "key_type" : { "description" : "Key type associated with the DID", - "enum" : [ "ed25519", "bls12381g2" ], + "enum" : [ "ed25519", "bls12381g2", "p256" ], "example" : "ed25519", "type" : "string" }, @@ -9434,12 +9457,12 @@ "did" : { "description" : "Specify final value of the did (including did:: prefix)if the method supports or requires so.", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "key_type" : { "description" : "Key type to use for the DID keypair. Validated with the chosen DID method's supported key types.", - "enum" : [ "ed25519", "bls12381g2" ], + "enum" : [ "ed25519", "bls12381g2", "p256" ], "example" : "ed25519", "type" : "string" } @@ -9551,7 +9574,7 @@ "did" : { "description" : "DID of exchange", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "did_doc~attach" : { @@ -11219,6 +11242,7 @@ "type" : "string" } }, + "required" : [ "credDefId", "issuerId", "maxCredNum", "tag" ], "type" : "object" }, "InputDescriptors" : { @@ -11736,7 +11760,7 @@ "did" : { "description" : "DID of interest", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "headers" : { @@ -12090,6 +12114,14 @@ "type" : "object" }, "ListCredentialsResponse" : { + "properties" : { + "results" : { + "items" : { + "$ref" : "#/components/schemas/VerifiableCredential" + }, + "type" : "array" + } + }, "type" : "object" }, "MediationCreateRequest" : { @@ -12899,7 +12931,7 @@ "did" : { "description" : "DID for connection invitation", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "imageUrl" : { @@ -13011,6 +13043,7 @@ "type" : "string" } }, + "required" : [ "rev_reg_def_id" ], "type" : "object" }, "RevListOptions" : { @@ -13304,8 +13337,8 @@ "rev_reg_ids" : { "items" : { "description" : "Revocation registry identifiers", - "example" : "WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "example" : "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0", + "pattern" : "^(.+$)", "type" : "string" }, "type" : "array" @@ -13408,8 +13441,8 @@ }, "rev_reg_id" : { "description" : "Revocation registry identifier", - "example" : "WgWxqztrNooG92RXvxSTWv:4:WgWxqztrNooG92RXvxSTWv:3:CL:20:tag:CL_ACCUM:0", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)", + "example" : "did:(method):4:did::3:CL:20:tag:CL_ACCUM:0", + "pattern" : "^(.+$)", "type" : "string" }, "thread_id" : { @@ -13483,7 +13516,7 @@ "did" : { "description" : "DID of interest", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$", "type" : "string" }, "headers" : { @@ -13881,6 +13914,22 @@ "required" : [ "proof" ], "type" : "object" }, + "StoreCredentialRequest" : { + "properties" : { + "verifiableCredential" : { + "$ref" : "#/components/schemas/VerifiableCredential" + } + }, + "type" : "object" + }, + "StoreCredentialResponse" : { + "properties" : { + "credentialId" : { + "type" : "string" + } + }, + "type" : "object" + }, "SubmissionRequirements" : { "properties" : { "count" : { @@ -15534,16 +15583,11 @@ "properties" : { "cred_def_id" : { "description" : "Credential definition identifier", - "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", - "type" : "string" - }, - "epoch" : { - "description" : "Credential epoch time", - "example" : "2021-08-24", + "example" : "did:(method):3:CL:20:tag", "type" : "string" }, "issuer_id" : { - "description" : "Credential issuer DID", + "description" : "Credential issuer ID", "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", "type" : "string" }, @@ -15551,6 +15595,21 @@ "description" : "Schema identifier", "example" : "did:(method):2:schema_name:1.0", "type" : "string" + }, + "schema_issuer_id" : { + "description" : "Schema issuer ID", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", + "type" : "string" + }, + "schema_name" : { + "description" : "Schema name", + "example" : "preferences", + "type" : "string" + }, + "schema_version" : { + "description" : "Schema version", + "example" : "1.0", + "type" : "string" } }, "type" : "object" diff --git a/open-api/swagger.json b/open-api/swagger.json index c49ae1134d..0ef90cd209 100644 --- a/open-api/swagger.json +++ b/open-api/swagger.json @@ -1,7 +1,7 @@ { "swagger" : "2.0", "info" : { - "version" : "v1.1.1", + "version" : "v1.2.1", "title" : "Aries Cloud Agent" }, "tags" : [ { @@ -518,7 +518,7 @@ "description" : "Credential definition identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+)):(.+)?$" + "pattern" : "^(.+$)" } ], "responses" : { "200" : { @@ -541,7 +541,7 @@ "description" : "Credential definition identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+)):(.+)?$" + "pattern" : "^(.+$)" } ], "responses" : { "200" : { @@ -578,7 +578,7 @@ "description" : "Revocation registry identifier", "required" : false, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" } ], "responses" : { "200" : { @@ -624,7 +624,7 @@ "description" : "Credential definition identifier", "required" : false, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+)):(.+)?$" + "pattern" : "^(.+$)" }, { "name" : "state", "in" : "query", @@ -654,7 +654,7 @@ "description" : "Revocation Registry identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" } ], "responses" : { "200" : { @@ -677,7 +677,7 @@ "description" : "Revocation Registry identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" }, { "name" : "apply_ledger_update", "in" : "query", @@ -706,7 +706,7 @@ "description" : "Revocation Registry identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" } ], "responses" : { "200" : { @@ -729,7 +729,7 @@ "description" : "Revocation Registry identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" } ], "responses" : { "200" : { @@ -752,7 +752,7 @@ "description" : "Revocation Registry identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" } ], "responses" : { "200" : { @@ -775,7 +775,7 @@ "description" : "Revocation Registry identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" }, { "name" : "state", "in" : "query", @@ -805,7 +805,7 @@ "description" : "Revocation Registry identifier", "required" : true, "type" : "string", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" } ], "responses" : { "200" : { @@ -985,7 +985,7 @@ "description" : "My DID", "required" : false, "type" : "string", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, { "name" : "offset", "in" : "query", @@ -1006,14 +1006,14 @@ "description" : "Their DID", "required" : false, "type" : "string", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, { "name" : "their_public_did", "in" : "query", "description" : "Their Public DID", "required" : false, "type" : "string", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, { "name" : "their_role", "in" : "query", @@ -1853,7 +1853,7 @@ "description" : "Qualified public DID to which to request connection", "required" : true, "type" : "string", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, { "name" : "alias", "in" : "query", @@ -5716,8 +5716,22 @@ "tags" : [ "vc-api" ], "summary" : "Store a credential", "produces" : [ "application/json" ], - "parameters" : [ ], - "responses" : { } + "parameters" : [ { + "in" : "body", + "name" : "body", + "required" : false, + "schema" : { + "$ref" : "#/definitions/StoreCredentialRequest" + } + } ], + "responses" : { + "200" : { + "description" : "", + "schema" : { + "$ref" : "#/definitions/StoreCredentialResponse" + } + } + } } }, "/vc/credentials/verify" : { @@ -5867,21 +5881,20 @@ "description" : "DID of interest", "required" : false, "type" : "string", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, { "name" : "key_type", "in" : "query", "description" : "Key type to query for.", "required" : false, "type" : "string", - "enum" : [ "ed25519", "bls12381g2" ] + "enum" : [ "ed25519", "bls12381g2", "p256" ] }, { "name" : "method", "in" : "query", "description" : "DID method to query for. e.g. sov to only fetch indy/sov DIDs", "required" : false, - "type" : "string", - "enum" : [ "key", "sov", "did:peer:2", "did:peer:4" ] + "type" : "string" }, { "name" : "posture", "in" : "query", @@ -5941,7 +5954,7 @@ "description" : "DID of interest", "required" : true, "type" : "string", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" } ], "responses" : { "200" : { @@ -5978,7 +5991,7 @@ "description" : "DID of interest", "required" : true, "type" : "string", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, { "name" : "conn_id", "in" : "query", @@ -6019,7 +6032,7 @@ "description" : "DID of interest", "required" : true, "type" : "string", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" } ], "responses" : { "200" : { @@ -6034,7 +6047,7 @@ "/wallet/jwt/sign" : { "post" : { "tags" : [ "wallet" ], - "summary" : "Create a EdDSA jws using did keys with a given payload", + "summary" : "Create a jws using did keys with a given payload", "produces" : [ "application/json" ], "parameters" : [ { "in" : "body", @@ -6057,7 +6070,7 @@ "/wallet/jwt/verify" : { "post" : { "tags" : [ "wallet" ], - "summary" : "Verify a EdDSA jws using did keys with a given JWS", + "summary" : "Verify a jws using did keys with a given JWS", "produces" : [ "application/json" ], "parameters" : [ { "in" : "body", @@ -6145,7 +6158,7 @@ "/wallet/sd-jwt/sign" : { "post" : { "tags" : [ "wallet" ], - "summary" : "Create a EdDSA sd-jws using did keys with a given payload", + "summary" : "Create an sd-jws using did keys with a given payload", "produces" : [ "application/json" ], "parameters" : [ { "in" : "body", @@ -6168,7 +6181,7 @@ "/wallet/sd-jwt/verify" : { "post" : { "tags" : [ "wallet" ], - "summary" : "Verify a EdDSA sd-jws using did keys with a given SD-JWS with optional key binding", + "summary" : "Verify an sd-jws using did keys with a given SD-JWS with optional key binding", "produces" : [ "application/json" ], "parameters" : [ { "in" : "body", @@ -6369,6 +6382,7 @@ }, "AnonCredsSchema" : { "type" : "object", + "required" : [ "attrNames", "issuerId", "name", "version" ], "properties" : { "attrNames" : { "type" : "array", @@ -6396,25 +6410,6 @@ } } }, - "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" : { @@ -6560,6 +6555,25 @@ } } }, + "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 + } + } + }, "AttachDecorator" : { "type" : "object", "required" : [ "data" ], @@ -6851,7 +6865,7 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "Our DID for connection", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "request_id" : { "type" : "string", @@ -6873,7 +6887,7 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "Their DID for connection", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "their_label" : { "type" : "string", @@ -6916,7 +6930,7 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "DID for connection invitation", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "imageUrl" : { "type" : "string", @@ -7962,13 +7976,13 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "DID of interest", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "key_type" : { "type" : "string", "example" : "ed25519", "description" : "Key type associated with the DID", - "enum" : [ "ed25519", "bls12381g2" ] + "enum" : [ "ed25519", "bls12381g2", "p256" ] }, "metadata" : { "type" : "object", @@ -8020,13 +8034,13 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "Specify final value of the did (including did:: prefix)if the method supports or requires so.", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "key_type" : { "type" : "string", "example" : "ed25519", "description" : "Key type to use for the DID keypair. Validated with the chosen DID method's supported key types.", - "enum" : [ "ed25519", "bls12381g2" ] + "enum" : [ "ed25519", "bls12381g2", "p256" ] } } }, @@ -8137,7 +8151,7 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "DID of exchange", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "did_doc~attach" : { "$ref" : "#/definitions/DIDXRequest_did_docattach" @@ -9711,6 +9725,7 @@ }, "InnerRevRegDef" : { "type" : "object", + "required" : [ "credDefId", "issuerId", "maxCredNum", "tag" ], "properties" : { "credDefId" : { "type" : "string", @@ -10222,7 +10237,7 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "DID of interest", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "headers" : { "type" : "object", @@ -10539,7 +10554,15 @@ "additionalProperties" : true }, "ListCredentialsResponse" : { - "type" : "object" + "type" : "object", + "properties" : { + "results" : { + "type" : "array", + "items" : { + "$ref" : "#/definitions/VerifiableCredential" + } + } + } }, "MediationCreateRequest" : { "type" : "object" @@ -11332,7 +11355,7 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "DID for connection invitation", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "imageUrl" : { "type" : "string", @@ -11434,6 +11457,7 @@ }, "RevListCreateRequest" : { "type" : "object", + "required" : [ "rev_reg_def_id" ], "properties" : { "options" : { "$ref" : "#/definitions/RevListOptions" @@ -11730,9 +11754,9 @@ "type" : "array", "items" : { "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 identifiers", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" } } } @@ -11833,9 +11857,9 @@ }, "rev_reg_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 identifier", - "pattern" : "^([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):4:([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}):3:CL:(([1-9][0-9]*)|([123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}:2:.+:[0-9.]+))(:.+)?:CL_ACCUM:(.+$)" + "pattern" : "^(.+$)" }, "thread_id" : { "type" : "string", @@ -11910,7 +11934,7 @@ "type" : "string", "example" : "did:peer:WgWxqztrNooG92RXvxSTWv", "description" : "DID of interest", - "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+):([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" + "pattern" : "^(did:sov:)?[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]{21,22}$|^did:([a-zA-Z0-9_]+)(:[a-zA-Z0-9_.%-]+)?:([a-zA-Z0-9_.%-]+(:[a-zA-Z0-9_.%-]+)*)((;[a-zA-Z0-9_.:%-]+=[a-zA-Z0-9_.:%-]*)*)(\\/[^#?]*)?([?][^#]*)?(\\#.*)?$$" }, "headers" : { "type" : "object", @@ -12291,6 +12315,22 @@ }, "additionalProperties" : true }, + "StoreCredentialRequest" : { + "type" : "object", + "properties" : { + "verifiableCredential" : { + "$ref" : "#/definitions/VerifiableCredential" + } + } + }, + "StoreCredentialResponse" : { + "type" : "object", + "properties" : { + "credentialId" : { + "type" : "string" + } + } + }, "SubmissionRequirements" : { "type" : "object", "properties" : { @@ -13817,23 +13857,33 @@ "properties" : { "cred_def_id" : { "type" : "string", - "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", + "example" : "did:(method):3:CL:20:tag", "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" + "description" : "Credential issuer ID" }, "schema_id" : { "type" : "string", "example" : "did:(method):2:schema_name:1.0", "description" : "Schema identifier" + }, + "schema_issuer_id" : { + "type" : "string", + "example" : "did:(method):WgWxqztrNooG92RXvxSTWv", + "description" : "Schema issuer ID" + }, + "schema_name" : { + "type" : "string", + "example" : "preferences", + "description" : "Schema name" + }, + "schema_version" : { + "type" : "string", + "example" : "1.0", + "description" : "Schema version" } } }, diff --git a/poetry.lock b/poetry.lock index 8ad4ac8838..65fc4b0e53 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. [[package]] name = "aiofiles" @@ -6,6 +6,7 @@ version = "24.1.0" description = "File support for asyncio." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"}, {file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"}, @@ -17,6 +18,7 @@ version = "2.4.4" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, @@ -24,87 +26,88 @@ files = [ [[package]] name = "aiohttp" -version = "3.11.10" +version = "3.11.11" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" -files = [ - {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cbad88a61fa743c5d283ad501b01c153820734118b65aee2bd7dbb735475ce0d"}, - {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80886dac673ceaef499de2f393fc80bb4481a129e6cb29e624a12e3296cc088f"}, - {file = "aiohttp-3.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61b9bae80ed1f338c42f57c16918853dc51775fb5cb61da70d590de14d8b5fb4"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e2e576caec5c6a6b93f41626c9c02fc87cd91538b81a3670b2e04452a63def6"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02c13415b5732fb6ee7ff64583a5e6ed1c57aa68f17d2bda79c04888dfdc2769"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfce37f31f20800a6a6620ce2cdd6737b82e42e06e6e9bd1b36f546feb3c44f"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bbbfff4c679c64e6e23cb213f57cc2c9165c9a65d63717108a644eb5a7398df"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49c7dbbc1a559ae14fc48387a115b7d4bbc84b4a2c3b9299c31696953c2a5219"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:68386d78743e6570f054fe7949d6cb37ef2b672b4d3405ce91fafa996f7d9b4d"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9ef405356ba989fb57f84cac66f7b0260772836191ccefbb987f414bcd2979d9"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5d6958671b296febe7f5f859bea581a21c1d05430d1bbdcf2b393599b1cdce77"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:99b7920e7165be5a9e9a3a7f1b680f06f68ff0d0328ff4079e5163990d046767"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0dc49f42422163efb7e6f1df2636fe3db72713f6cd94688e339dbe33fe06d61d"}, - {file = "aiohttp-3.11.10-cp310-cp310-win32.whl", hash = "sha256:40d1c7a7f750b5648642586ba7206999650208dbe5afbcc5284bcec6579c9b91"}, - {file = "aiohttp-3.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:68ff6f48b51bd78ea92b31079817aff539f6c8fc80b6b8d6ca347d7c02384e33"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:77c4aa15a89847b9891abf97f3d4048f3c2d667e00f8a623c89ad2dccee6771b"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:909af95a72cedbefe5596f0bdf3055740f96c1a4baa0dd11fd74ca4de0b4e3f1"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:386fbe79863eb564e9f3615b959e28b222259da0c48fd1be5929ac838bc65683"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3de34936eb1a647aa919655ff8d38b618e9f6b7f250cc19a57a4bf7fd2062b6d"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c9527819b29cd2b9f52033e7fb9ff08073df49b4799c89cb5754624ecd98299"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a96e3e03300b41f261bbfd40dfdbf1c301e87eab7cd61c054b1f2e7c89b9e8"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f5635f7b74bcd4f6f72fcd85bea2154b323a9f05226a80bc7398d0c90763b0"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03b6002e20938fc6ee0918c81d9e776bebccc84690e2b03ed132331cca065ee5"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6362cc6c23c08d18ddbf0e8c4d5159b5df74fea1a5278ff4f2c79aed3f4e9f46"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3691ed7726fef54e928fe26344d930c0c8575bc968c3e239c2e1a04bd8cf7838"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31d5093d3acd02b31c649d3a69bb072d539d4c7659b87caa4f6d2bcf57c2fa2b"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8b3cf2dc0f0690a33f2d2b2cb15db87a65f1c609f53c37e226f84edb08d10f52"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbbaea811a2bba171197b08eea288b9402faa2bab2ba0858eecdd0a4105753a3"}, - {file = "aiohttp-3.11.10-cp311-cp311-win32.whl", hash = "sha256:4b2c7ac59c5698a7a8207ba72d9e9c15b0fc484a560be0788b31312c2c5504e4"}, - {file = "aiohttp-3.11.10-cp311-cp311-win_amd64.whl", hash = "sha256:974d3a2cce5fcfa32f06b13ccc8f20c6ad9c51802bb7f829eae8a1845c4019ec"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b78f053a7ecfc35f0451d961dacdc671f4bcbc2f58241a7c820e9d82559844cf"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab7485222db0959a87fbe8125e233b5a6f01f4400785b36e8a7878170d8c3138"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cf14627232dfa8730453752e9cdc210966490992234d77ff90bc8dc0dce361d5"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:076bc454a7e6fd646bc82ea7f98296be0b1219b5e3ef8a488afbdd8e81fbac50"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:482cafb7dc886bebeb6c9ba7925e03591a62ab34298ee70d3dd47ba966370d2c"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf3d1a519a324af764a46da4115bdbd566b3c73fb793ffb97f9111dbc684fc4d"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24213ba85a419103e641e55c27dc7ff03536c4873470c2478cce3311ba1eee7b"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b99acd4730ad1b196bfb03ee0803e4adac371ae8efa7e1cbc820200fc5ded109"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:14cdb5a9570be5a04eec2ace174a48ae85833c2aadc86de68f55541f66ce42ab"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7e97d622cb083e86f18317282084bc9fbf261801b0192c34fe4b1febd9f7ae69"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:012f176945af138abc10c4a48743327a92b4ca9adc7a0e078077cdb5dbab7be0"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44224d815853962f48fe124748227773acd9686eba6dc102578defd6fc99e8d9"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c87bf31b7fdab94ae3adbe4a48e711bfc5f89d21cf4c197e75561def39e223bc"}, - {file = "aiohttp-3.11.10-cp312-cp312-win32.whl", hash = "sha256:06a8e2ee1cbac16fe61e51e0b0c269400e781b13bcfc33f5425912391a542985"}, - {file = "aiohttp-3.11.10-cp312-cp312-win_amd64.whl", hash = "sha256:be2b516f56ea883a3e14dda17059716593526e10fb6303189aaf5503937db408"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8cc5203b817b748adccb07f36390feb730b1bc5f56683445bfe924fc270b8816"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ef359ebc6949e3a34c65ce20230fae70920714367c63afd80ea0c2702902ccf"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9bca390cb247dbfaec3c664326e034ef23882c3f3bfa5fbf0b56cad0320aaca5"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811f23b3351ca532af598405db1093f018edf81368e689d1b508c57dcc6b6a32"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddf5f7d877615f6a1e75971bfa5ac88609af3b74796ff3e06879e8422729fd01"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ab29b8a0beb6f8eaf1e5049252cfe74adbaafd39ba91e10f18caeb0e99ffb34"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c49a76c1038c2dd116fa443eba26bbb8e6c37e924e2513574856de3b6516be99"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f3dc0e330575f5b134918976a645e79adf333c0a1439dcf6899a80776c9ab39"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:efb15a17a12497685304b2d976cb4939e55137df7b09fa53f1b6a023f01fcb4e"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db1d0b28fcb7f1d35600150c3e4b490775251dea70f894bf15c678fdd84eda6a"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:15fccaf62a4889527539ecb86834084ecf6e9ea70588efde86e8bc775e0e7542"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:593c114a2221444f30749cc5e5f4012488f56bd14de2af44fe23e1e9894a9c60"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7852bbcb4d0d2f0c4d583f40c3bc750ee033265d80598d0f9cb6f372baa6b836"}, - {file = "aiohttp-3.11.10-cp313-cp313-win32.whl", hash = "sha256:65e55ca7debae8faaffee0ebb4b47a51b4075f01e9b641c31e554fd376595c6c"}, - {file = "aiohttp-3.11.10-cp313-cp313-win_amd64.whl", hash = "sha256:beb39a6d60a709ae3fb3516a1581777e7e8b76933bb88c8f4420d875bb0267c6"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0580f2e12de2138f34debcd5d88894786453a76e98febaf3e8fe5db62d01c9bf"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a55d2ad345684e7c3dd2c20d2f9572e9e1d5446d57200ff630e6ede7612e307f"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04814571cb72d65a6899db6099e377ed00710bf2e3eafd2985166f2918beaf59"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e44a9a3c053b90c6f09b1bb4edd880959f5328cf63052503f892c41ea786d99f"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:502a1464ccbc800b4b1995b302efaf426e8763fadf185e933c2931df7db9a199"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:613e5169f8ae77b1933e42e418a95931fb4867b2991fc311430b15901ed67079"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cca22a61b7fe45da8fc73c3443150c3608750bbe27641fc7558ec5117b27fdf"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86a5dfcc39309470bd7b68c591d84056d195428d5d2e0b5ccadfbaf25b026ebc"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:77ae58586930ee6b2b6f696c82cf8e78c8016ec4795c53e36718365f6959dc82"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:78153314f26d5abef3239b4a9af20c229c6f3ecb97d4c1c01b22c4f87669820c"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:98283b94cc0e11c73acaf1c9698dea80c830ca476492c0fe2622bd931f34b487"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:53bf2097e05c2accc166c142a2090e4c6fd86581bde3fd9b2d3f9e93dda66ac1"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5532f0441fc09c119e1dca18fbc0687e64fbeb45aa4d6a87211ceaee50a74c4"}, - {file = "aiohttp-3.11.10-cp39-cp39-win32.whl", hash = "sha256:47ad15a65fb41c570cd0ad9a9ff8012489e68176e7207ec7b82a0940dddfd8be"}, - {file = "aiohttp-3.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:c6b9e6d7e41656d78e37ce754813fa44b455c3d0d0dced2a047def7dc5570b74"}, - {file = "aiohttp-3.11.10.tar.gz", hash = "sha256:b1fc6b45010a8d0ff9e88f9f2418c6fd408c99c211257334aff41597ebece42e"}, +groups = ["main"] +files = [ + {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8"}, + {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5"}, + {file = "aiohttp-3.11.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:731468f555656767cda219ab42e033355fe48c85fbe3ba83a349631541715ba2"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb23d8bb86282b342481cad4370ea0853a39e4a32a0042bb52ca6bdde132df43"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f047569d655f81cb70ea5be942ee5d4421b6219c3f05d131f64088c73bb0917f"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd7659baae9ccf94ae5fe8bfaa2c7bc2e94d24611528395ce88d009107e00c6d"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af01e42ad87ae24932138f154105e88da13ce7d202a6de93fafdafb2883a00ef"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5854be2f3e5a729800bac57a8d76af464e160f19676ab6aea74bde18ad19d438"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6526e5fb4e14f4bbf30411216780c9967c20c5a55f2f51d3abd6de68320cc2f3"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:85992ee30a31835fc482468637b3e5bd085fa8fe9392ba0bdcbdc1ef5e9e3c55"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:88a12ad8ccf325a8a5ed80e6d7c3bdc247d66175afedbe104ee2aaca72960d8e"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0a6d3fbf2232e3a08c41eca81ae4f1dff3d8f1a30bae415ebe0af2d2458b8a33"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84a585799c58b795573c7fa9b84c455adf3e1d72f19a2bf498b54a95ae0d194c"}, + {file = "aiohttp-3.11.11-cp310-cp310-win32.whl", hash = "sha256:bfde76a8f430cf5c5584553adf9926534352251d379dcb266ad2b93c54a29745"}, + {file = "aiohttp-3.11.11-cp310-cp310-win_amd64.whl", hash = "sha256:0fd82b8e9c383af11d2b26f27a478640b6b83d669440c0a71481f7c865a51da9"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773"}, + {file = "aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62"}, + {file = "aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e"}, + {file = "aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600"}, + {file = "aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5"}, + {file = "aiohttp-3.11.11-cp313-cp313-win32.whl", hash = "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d"}, + {file = "aiohttp-3.11.11-cp313-cp313-win_amd64.whl", hash = "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3e23419d832d969f659c208557de4a123e30a10d26e1e14b73431d3c13444c2e"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21fef42317cf02e05d3b09c028712e1d73a9606f02467fd803f7c1f39cc59add"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1f21bb8d0235fc10c09ce1d11ffbd40fc50d3f08a89e4cf3a0c503dc2562247a"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1642eceeaa5ab6c9b6dfeaaa626ae314d808188ab23ae196a34c9d97efb68350"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2170816e34e10f2fd120f603e951630f8a112e1be3b60963a1f159f5699059a6"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8be8508d110d93061197fd2d6a74f7401f73b6d12f8822bbcd6d74f2b55d71b1"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eed954b161e6b9b65f6be446ed448ed3921763cc432053ceb606f89d793927e"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6c9af134da4bc9b3bd3e6a70072509f295d10ee60c697826225b60b9959acdd"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:44167fc6a763d534a6908bdb2592269b4bf30a03239bcb1654781adf5e49caf1"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:479b8c6ebd12aedfe64563b85920525d05d394b85f166b7873c8bde6da612f9c"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:10b4ff0ad793d98605958089fabfa350e8e62bd5d40aa65cdc69d6785859f94e"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b540bd67cfb54e6f0865ceccd9979687210d7ed1a1cc8c01f8e67e2f1e883d28"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1dac54e8ce2ed83b1f6b1a54005c87dfed139cf3f777fdc8afc76e7841101226"}, + {file = "aiohttp-3.11.11-cp39-cp39-win32.whl", hash = "sha256:568c1236b2fde93b7720f95a890741854c1200fba4a3471ff48b2934d2d93fd3"}, + {file = "aiohttp-3.11.11-cp39-cp39-win_amd64.whl", hash = "sha256:943a8b052e54dfd6439fd7989f67fc6a7f2138d0a2cf0a7de5f18aa4fe7eb3b1"}, + {file = "aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e"}, ] [package.dependencies] @@ -125,6 +128,7 @@ version = "3.0.2" description = "Build and document REST APIs with aiohttp and apispec" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "aiohttp-apispec-acapy-3.0.2.tar.gz", hash = "sha256:9e6946a48cb70d3f7097f51e2ce7ba8bee32fce9d654454fe300930bfa8ce542"}, {file = "aiohttp_apispec_acapy-3.0.2-py3-none-any.whl", hash = "sha256:93ea532afb3876685d185cc1cfe51d6d08e597cf04f79d16898a23ac4842b742"}, @@ -142,6 +146,7 @@ version = "0.7.0" description = "CORS support for aiohttp" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "aiohttp-cors-0.7.0.tar.gz", hash = "sha256:4d39c6d7100fd9764ed1caf8cebf0eb01bf5e3f24e2e073fda6234bc48b19f5d"}, {file = "aiohttp_cors-0.7.0-py3-none-any.whl", hash = "sha256:0451ba59fdf6909d0e2cd21e4c0a43752bc0703d33fc78ae94d9d9321710193e"}, @@ -152,13 +157,14 @@ aiohttp = ">=1.1" [[package]] name = "aiosignal" -version = "1.3.1" +version = "1.3.2" description = "aiosignal: a list of registered asynchronous callbacks" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, + {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, + {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, ] [package.dependencies] @@ -166,13 +172,14 @@ frozenlist = ">=1.1.0" [[package]] name = "alabaster" -version = "0.7.16" +version = "1.0.0" description = "A light, configurable Sphinx theme" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "alabaster-0.7.16-py3-none-any.whl", hash = "sha256:b46733c07dce03ae4e150330b975c75737fa60f0a7c591b6c8bf4928a28e2c92"}, - {file = "alabaster-0.7.16.tar.gz", hash = "sha256:75a8b99c28a5dad50dd7f8ccdd447a121ddb3892da9e53d1ca5cca3106d58d65"}, + {file = "alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b"}, + {file = "alabaster-1.0.0.tar.gz", hash = "sha256:c00dca57bca26fa62a6d7d0a9fcce65f3e026e9bfe33e9c538fd3fbb2144fd9e"}, ] [[package]] @@ -181,6 +188,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -192,6 +200,7 @@ version = "0.2.0" description = "" optional = false python-versions = ">=3.6.3" +groups = ["main"] files = [ {file = "anoncreds-0.2.0-py3-none-macosx_10_9_universal2.whl", hash = "sha256:ec57e224d5f1b8749c3d6ff75bb61229a4f9c31df1ee863835f025c78ec10cd0"}, {file = "anoncreds-0.2.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:55dd0ad8c8611d2f6af158485dbd2f3c9524694ee4eaf1c5558973f1e436f943"}, @@ -205,6 +214,7 @@ version = "6.6.1" description = "A pluggable API specification generator. Currently supports the OpenAPI Specification (f.k.a. the Swagger specification)." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "apispec-6.6.1-py3-none-any.whl", hash = "sha256:6460315cb38ac6a2ff42d9e2b8dc0435c37d4428d3abeda96ff97b5dc8eb6b94"}, {file = "apispec-6.6.1.tar.gz", hash = "sha256:f5caa47cee75fe03b9c50b5594048b4c052eeca2c212e0dac12dbb6175d9a659"}, @@ -226,6 +236,7 @@ version = "0.3.2" description = "" optional = false python-versions = ">=3.6.3" +groups = ["main"] files = [ {file = "aries_askar-0.3.2-py3-none-macosx_10_9_universal2.whl", hash = "sha256:02ddbe1773ce72c57edafff5777a1337d4a678da7484596712949170fb3ca1dc"}, {file = "aries_askar-0.3.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:176eebcf833bb9974a162fd931c8d67669e4f0145b351ce9cb1289fd2d5a345c"}, @@ -242,6 +253,7 @@ version = "4.0.3" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "async-timeout-4.0.3.tar.gz", hash = "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f"}, {file = "async_timeout-4.0.3-py3-none-any.whl", hash = "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028"}, @@ -249,19 +261,20 @@ files = [ [[package]] name = "attrs" -version = "24.2.0" +version = "24.3.0" description = "Classes Without Boilerplate" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, + {file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"}, + {file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"}, ] [package.extras] benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] @@ -272,6 +285,7 @@ version = "2.16.0" description = "Internationalization utilities" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"}, {file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"}, @@ -286,6 +300,7 @@ version = "2.1.1" description = "Base58 and Base58Check implementation." optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "base58-2.1.1-py3-none-any.whl", hash = "sha256:11a36f4d3ce51dfc1043f3218591ac4eb1ceb172919cebe05b52a5bcc8d245c2"}, {file = "base58-2.1.1.tar.gz", hash = "sha256:c5d0cb3f5b6e81e8e35da5754388ddcc6d0d14b6c6a132cb93d69ed580a7278c"}, @@ -300,6 +315,7 @@ version = "0.3.0" description = "Python library for general Base-N encodings." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "bases-0.3.0-py3-none-any.whl", hash = "sha256:a2fef3366f3e522ff473d2e95c21523fe8e44251038d5c6150c01481585ebf5b"}, {file = "bases-0.3.0.tar.gz", hash = "sha256:70f04a4a45d63245787f9e89095ca11042685b6b64b542ad916575ba3ccd1570"}, @@ -318,6 +334,7 @@ version = "1.5.2" description = "A decorator for caching properties in classes." optional = false python-versions = "*" +groups = ["main"] files = [ {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, @@ -329,6 +346,7 @@ version = "5.5.0" description = "Extensible memoizing collections and decorators" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "cachetools-5.5.0-py3-none-any.whl", hash = "sha256:02134e8439cdc2ffb62023ce1debca2944c3f289d66bb17ead3ab3dede74b292"}, {file = "cachetools-5.5.0.tar.gz", hash = "sha256:2cc24fb4cbe39633fb7badd9db9ca6295d766d9c2995f245725a46715d050f2a"}, @@ -340,6 +358,7 @@ version = "2.0.0" description = "Canonical JSON" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "canonicaljson-2.0.0-py3-none-any.whl", hash = "sha256:c38a315de3b5a0532f1ec1f9153cd3d716abfc565a558d00a4835428a34fca5b"}, {file = "canonicaljson-2.0.0.tar.gz", hash = "sha256:e2fdaef1d7fadc5d9cb59bd3d0d41b064ddda697809ac4325dced721d12f113f"}, @@ -347,13 +366,14 @@ files = [ [[package]] name = "certifi" -version = "2024.8.30" +version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ - {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, - {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, + {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, + {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, ] [[package]] @@ -362,6 +382,7 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -441,6 +462,7 @@ version = "3.4.0" description = "Validate configuration and produce human readable error messages." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"}, {file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"}, @@ -448,116 +470,104 @@ files = [ [[package]] name = "charset-normalizer" -version = "3.4.0" +version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:4f9fc98dad6c2eaa32fc3af1417d95b5e3d08aff968df0cd320066def971f9a6"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0de7b687289d3c1b3e8660d0741874abe7888100efe14bd0f9fd7141bcbda92b"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5ed2e36c3e9b4f21dd9422f6893dec0abf2cca553af509b10cd630f878d3eb99"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:40d3ff7fc90b98c637bda91c89d51264a3dcf210cade3a2c6f838c7268d7a4ca"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1110e22af8ca26b90bd6364fe4c763329b0ebf1ee213ba32b68c73de5752323d"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:86f4e8cca779080f66ff4f191a685ced73d2f72d50216f7112185dc02b90b9b7"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f683ddc7eedd742e2889d2bfb96d69573fde1d92fcb811979cdb7165bb9c7d3"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:27623ba66c183eca01bf9ff833875b459cad267aeeb044477fedac35e19ba907"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f606a1881d2663630ea5b8ce2efe2111740df4b687bd78b34a8131baa007f79b"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0b309d1747110feb25d7ed6b01afdec269c647d382c857ef4663bbe6ad95a912"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:136815f06a3ae311fae551c3df1f998a1ebd01ddd424aa5603a4336997629e95"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:14215b71a762336254351b00ec720a8e85cada43b987da5a042e4ce3e82bd68e"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:79983512b108e4a164b9c8d34de3992f76d48cadc9554c9e60b43f308988aabe"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-win32.whl", hash = "sha256:c94057af19bc953643a33581844649a7fdab902624d2eb739738a30e2b3e60fc"}, - {file = "charset_normalizer-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:55f56e2ebd4e3bc50442fbc0888c9d8c94e4e06a933804e2af3e89e2f9c1c749"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0d99dd8ff461990f12d6e42c7347fd9ab2532fb70e9621ba520f9e8637161d7c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c57516e58fd17d03ebe67e181a4e4e2ccab1168f8c2976c6a334d4f819fe5944"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:6dba5d19c4dfab08e58d5b36304b3f92f3bd5d42c1a3fa37b5ba5cdf6dfcbcee"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf4475b82be41b07cc5e5ff94810e6a01f276e37c2d55571e3fe175e467a1a1c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce031db0408e487fd2775d745ce30a7cd2923667cf3b69d48d219f1d8f5ddeb6"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ff4e7cdfdb1ab5698e675ca622e72d58a6fa2a8aa58195de0c0061288e6e3ea"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3710a9751938947e6327ea9f3ea6332a09bf0ba0c09cae9cb1f250bd1f1549bc"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82357d85de703176b5587dbe6ade8ff67f9f69a41c0733cf2425378b49954de5"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47334db71978b23ebcf3c0f9f5ee98b8d65992b65c9c4f2d34c2eaf5bcaf0594"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8ce7fd6767a1cc5a92a639b391891bf1c268b03ec7e021c7d6d902285259685c"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:f1a2f519ae173b5b6a2c9d5fa3116ce16e48b3462c8b96dfdded11055e3d6365"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:63bc5c4ae26e4bc6be6469943b8253c0fd4e4186c43ad46e713ea61a0ba49129"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bcb4f8ea87d03bc51ad04add8ceaf9b0f085ac045ab4d74e73bbc2dc033f0236"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-win32.whl", hash = "sha256:9ae4ef0b3f6b41bad6366fb0ea4fc1d7ed051528e113a60fa2a65a9abb5b1d99"}, - {file = "charset_normalizer-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:cee4373f4d3ad28f1ab6290684d8e2ebdb9e7a1b74fdc39e4c211995f77bec27"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0713f3adb9d03d49d365b70b84775d0a0d18e4ab08d12bc46baa6132ba78aaf6"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:de7376c29d95d6719048c194a9cf1a1b0393fbe8488a22008610b0361d834ecf"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4a51b48f42d9358460b78725283f04bddaf44a9358197b889657deba38f329db"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b295729485b06c1a0683af02a9e42d2caa9db04a373dc38a6a58cdd1e8abddf1"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee803480535c44e7f5ad00788526da7d85525cfefaf8acf8ab9a310000be4b03"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d59d125ffbd6d552765510e3f31ed75ebac2c7470c7274195b9161a32350284"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8cda06946eac330cbe6598f77bb54e690b4ca93f593dee1568ad22b04f347c15"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07afec21bbbbf8a5cc3651aa96b980afe2526e7f048fdfb7f1014d84acc8b6d8"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6b40e8d38afe634559e398cc32b1472f376a4099c75fe6299ae607e404c033b2"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b8dcd239c743aa2f9c22ce674a145e0a25cb1566c495928440a181ca1ccf6719"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:84450ba661fb96e9fd67629b93d2941c871ca86fc38d835d19d4225ff946a631"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44aeb140295a2f0659e113b31cfe92c9061622cadbc9e2a2f7b8ef6b1e29ef4b"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1db4e7fefefd0f548d73e2e2e041f9df5c59e178b4c72fbac4cc6f535cfb1565"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-win32.whl", hash = "sha256:5726cf76c982532c1863fb64d8c6dd0e4c90b6ece9feb06c9f202417a31f7dd7"}, - {file = "charset_normalizer-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:b197e7094f232959f8f20541ead1d9862ac5ebea1d58e9849c1bf979255dfac9"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:dd4eda173a9fcccb5f2e2bd2a9f423d180194b1bf17cf59e3269899235b2a114"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e9e3c4c9e1ed40ea53acf11e2a386383c3304212c965773704e4603d589343ed"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:92a7e36b000bf022ef3dbb9c46bfe2d52c047d5e3f3343f43204263c5addc250"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:54b6a92d009cbe2fb11054ba694bc9e284dad30a26757b1e372a1fdddaf21920"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ffd9493de4c922f2a38c2bf62b831dcec90ac673ed1ca182fe11b4d8e9f2a64"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:35c404d74c2926d0287fbd63ed5d27eb911eb9e4a3bb2c6d294f3cfd4a9e0c23"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4796efc4faf6b53a18e3d46343535caed491776a22af773f366534056c4e1fbc"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e7fdd52961feb4c96507aa649550ec2a0d527c086d284749b2f582f2d40a2e0d"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:92db3c28b5b2a273346bebb24857fda45601aef6ae1c011c0a997106581e8a88"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:ab973df98fc99ab39080bfb0eb3a925181454d7c3ac8a1e695fddfae696d9e90"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:4b67fdab07fdd3c10bb21edab3cbfe8cf5696f453afce75d815d9d7223fbe88b"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:aa41e526a5d4a9dfcfbab0716c7e8a1b215abd3f3df5a45cf18a12721d31cb5d"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ffc519621dce0c767e96b9c53f09c5d215578e10b02c285809f76509a3931482"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-win32.whl", hash = "sha256:f19c1585933c82098c2a520f8ec1227f20e339e33aca8fa6f956f6691b784e67"}, - {file = "charset_normalizer-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:707b82d19e65c9bd28b81dde95249b07bf9f5b90ebe1ef17d9b57473f8a64b7b"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:dbe03226baf438ac4fda9e2d0715022fd579cb641c4cf639fa40d53b2fe6f3e2"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd9a8bd8900e65504a305bf8ae6fa9fbc66de94178c420791d0293702fce2df7"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8831399554b92b72af5932cdbbd4ddc55c55f631bb13ff8fe4e6536a06c5c51"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a14969b8691f7998e74663b77b4c36c0337cb1df552da83d5c9004a93afdb574"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcaf7c1524c0542ee2fc82cc8ec337f7a9f7edee2532421ab200d2b920fc97cf"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425c5f215d0eecee9a56cdb703203dda90423247421bf0d67125add85d0c4455"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:d5b054862739d276e09928de37c79ddeec42a6e1bfc55863be96a36ba22926f6"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:f3e73a4255342d4eb26ef6df01e3962e73aa29baa3124a8e824c5d3364a65748"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:2f6c34da58ea9c1a9515621f4d9ac379871a8f21168ba1b5e09d74250de5ad62"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:f09cb5a7bbe1ecae6e87901a2eb23e0256bb524a79ccc53eb0b7629fbe7677c4"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0099d79bdfcf5c1f0c2c72f91516702ebf8b0b8ddd8905f97a8aecf49712c621"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-win32.whl", hash = "sha256:9c98230f5042f4945f957d006edccc2af1e03ed5e37ce7c373f00a5a4daa6149"}, - {file = "charset_normalizer-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:62f60aebecfc7f4b82e3f639a7d1433a20ec32824db2199a11ad4f5e146ef5ee"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:af73657b7a68211996527dbfeffbb0864e043d270580c5aef06dc4b659a4b578"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cab5d0b79d987c67f3b9e9c53f54a61360422a5a0bc075f43cab5621d530c3b6"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:9289fd5dddcf57bab41d044f1756550f9e7cf0c8e373b8cdf0ce8773dc4bd417"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b493a043635eb376e50eedf7818f2f322eabbaa974e948bd8bdd29eb7ef2a51"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fa2566ca27d67c86569e8c85297aaf413ffab85a8960500f12ea34ff98e4c41"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a8e538f46104c815be19c975572d74afb53f29650ea2025bbfaef359d2de2f7f"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fd30dc99682dc2c603c2b315bded2799019cea829f8bf57dc6b61efde6611c8"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2006769bd1640bdf4d5641c69a3d63b71b81445473cac5ded39740a226fa88ab"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:dc15e99b2d8a656f8e666854404f1ba54765871104e50c8e9813af8a7db07f12"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ab2e5bef076f5a235c3774b4f4028a680432cded7cad37bba0fd90d64b187d19"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:4ec9dd88a5b71abfc74e9df5ebe7921c35cbb3b641181a531ca65cdb5e8e4dea"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:43193c5cda5d612f247172016c4bb71251c784d7a4d9314677186a838ad34858"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:aa693779a8b50cd97570e5a0f343538a8dbd3e496fa5dcb87e29406ad0299654"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-win32.whl", hash = "sha256:7706f5850360ac01d80c89bcef1640683cc12ed87f42579dab6c5d3ed6888613"}, - {file = "charset_normalizer-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:c3e446d253bd88f6377260d07c895816ebf33ffffd56c1c792b13bff9c3e1ade"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:980b4f289d1d90ca5efcf07958d3eb38ed9c0b7676bf2831a54d4f66f9c27dfa"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f28f891ccd15c514a0981f3b9db9aa23d62fe1a99997512b0491d2ed323d229a"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8aacce6e2e1edcb6ac625fb0f8c3a9570ccc7bfba1f63419b3769ccf6a00ed0"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7af3717683bea4c87acd8c0d3d5b44d56120b26fd3f8a692bdd2d5260c620a"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ff2ed8194587faf56555927b3aa10e6fb69d931e33953943bc4f837dfee2242"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e91f541a85298cf35433bf66f3fab2a4a2cff05c127eeca4af174f6d497f0d4b"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:309a7de0a0ff3040acaebb35ec45d18db4b28232f21998851cfa709eeff49d62"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:285e96d9d53422efc0d7a17c60e59f37fbf3dfa942073f666db4ac71e8d726d0"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5d447056e2ca60382d460a604b6302d8db69476fd2015c81e7c35417cfabe4cd"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:20587d20f557fe189b7947d8e7ec5afa110ccf72a3128d61a2a387c3313f46be"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:130272c698667a982a5d0e626851ceff662565379baf0ff2cc58067b81d4f11d"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:ab22fbd9765e6954bc0bcff24c25ff71dcbfdb185fcdaca49e81bac68fe724d3"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7782afc9b6b42200f7362858f9e73b1f8316afb276d316336c0ec3bd73312742"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-win32.whl", hash = "sha256:2de62e8801ddfff069cd5c504ce3bc9672b23266597d4e4f50eda28846c322f2"}, - {file = "charset_normalizer-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:95c3c157765b031331dd4db3c775e58deaee050a3042fcad72cbc4189d7c8dca"}, - {file = "charset_normalizer-3.4.0-py3-none-any.whl", hash = "sha256:fe9f97feb71aa9896b81973a7bbada8c49501dc73e58a10fcef6663af95e5079"}, - {file = "charset_normalizer-3.4.0.tar.gz", hash = "sha256:223217c3d4f82c3ac5e29032b3f1c2eb0fb591b72161f86d93f5719079dae93e"}, +python-versions = ">=3.7" +groups = ["main", "dev"] +files = [ + {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win32.whl", hash = "sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f"}, + {file = "charset_normalizer-3.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win32.whl", hash = "sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b"}, + {file = "charset_normalizer-3.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win32.whl", hash = "sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35"}, + {file = "charset_normalizer-3.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win32.whl", hash = "sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407"}, + {file = "charset_normalizer-3.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_i686.whl", hash = "sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_ppc64le.whl", hash = "sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_s390x.whl", hash = "sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win32.whl", hash = "sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487"}, + {file = "charset_normalizer-3.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win32.whl", hash = "sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e"}, + {file = "charset_normalizer-3.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win32.whl", hash = "sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5"}, + {file = "charset_normalizer-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765"}, + {file = "charset_normalizer-3.4.1-py3-none-any.whl", hash = "sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85"}, + {file = "charset_normalizer-3.4.1.tar.gz", hash = "sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3"}, ] [[package]] @@ -566,10 +576,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "dev"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "platform_system == \"Windows\"", dev = "sys_platform == \"win32\""} [[package]] name = "configargparse" @@ -577,6 +589,7 @@ version = "1.7" description = "A drop-in replacement for argparse that allows options to also be set via config files and/or environment variables." optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "ConfigArgParse-1.7-py3-none-any.whl", hash = "sha256:d249da6591465c6c26df64a9f73d2536e743be2f244eb3ebe61114af2f94f86b"}, {file = "ConfigArgParse-1.7.tar.gz", hash = "sha256:e7067471884de5478c58a511e529f0f9bd1c66bfef1dea90935438d6c23306d1"}, @@ -588,73 +601,74 @@ yaml = ["PyYAML"] [[package]] name = "coverage" -version = "7.6.8" +version = "7.6.10" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" -files = [ - {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"}, +groups = ["dev"] +files = [ + {file = "coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78"}, + {file = "coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c"}, + {file = "coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a"}, + {file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165"}, + {file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988"}, + {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5"}, + {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3"}, + {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5"}, + {file = "coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244"}, + {file = "coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e"}, + {file = "coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3"}, + {file = "coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43"}, + {file = "coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132"}, + {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f"}, + {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994"}, + {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99"}, + {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd"}, + {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377"}, + {file = "coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8"}, + {file = "coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609"}, + {file = "coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853"}, + {file = "coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078"}, + {file = "coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0"}, + {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50"}, + {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022"}, + {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b"}, + {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0"}, + {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852"}, + {file = "coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359"}, + {file = "coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247"}, + {file = "coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9"}, + {file = "coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b"}, + {file = "coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690"}, + {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18"}, + {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c"}, + {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd"}, + {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e"}, + {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694"}, + {file = "coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6"}, + {file = "coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e"}, + {file = "coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe"}, + {file = "coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273"}, + {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8"}, + {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098"}, + {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb"}, + {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0"}, + {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf"}, + {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2"}, + {file = "coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312"}, + {file = "coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d"}, + {file = "coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a"}, + {file = "coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27"}, + {file = "coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4"}, + {file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f"}, + {file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25"}, + {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315"}, + {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90"}, + {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d"}, + {file = "coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18"}, + {file = "coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59"}, + {file = "coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f"}, + {file = "coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23"}, ] [package.extras] @@ -666,6 +680,7 @@ version = "44.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.7" +groups = ["main"] 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"}, @@ -711,97 +726,113 @@ test-randomorder = ["pytest-randomly"] [[package]] name = "cytoolz" -version = "1.0.0" +version = "1.0.1" description = "Cython implementation of Toolz: High performance functional utilities" optional = false python-versions = ">=3.8" -files = [ - {file = "cytoolz-1.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ecf5a887acb8f079ab1b81612b1c889bcbe6611aa7804fd2df46ed310aa5a345"}, - {file = "cytoolz-1.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0ef30c1e091d4d59d14d8108a16d50bd227be5d52a47da891da5019ac2f8e4"}, - {file = "cytoolz-1.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7df2dfd679f0517a96ced1cdd22f5c6c6aeeed28d928a82a02bf4c3fd6fd7ac4"}, - {file = "cytoolz-1.0.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c51452c938e610f57551aa96e34924169c9100c0448bac88c2fb395cbd3538c"}, - {file = "cytoolz-1.0.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6433f03910c5e5345d82d6299457c26bf33821224ebb837c6b09d9cdbc414a6c"}, - {file = "cytoolz-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:389ec328bb535f09e71dfe658bf0041f17194ca4cedaacd39bafe7893497a819"}, - {file = "cytoolz-1.0.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c64658e1209517ce4b54c1c9269a508b289d8d55fc742760e4b8579eacf09a33"}, - {file = "cytoolz-1.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f6039a9bd5bb988762458b9ca82b39e60ca5e5baae2ba93913990dcc5d19fa88"}, - {file = "cytoolz-1.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:85c9c8c4465ed1b2c8d67003809aec9627b129cb531d2f6cf0bbfe39952e7e4d"}, - {file = "cytoolz-1.0.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:49375aad431d76650f94877afb92f09f58b6ff9055079ef4f2cd55313f5a1b39"}, - {file = "cytoolz-1.0.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:4c45106171c824a61e755355520b646cb35a1987b34bbf5789443823ee137f63"}, - {file = "cytoolz-1.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3b319a7f0fed5db07d189db4046162ebc183c108df3562a65ba6ebe862d1f634"}, - {file = "cytoolz-1.0.0-cp310-cp310-win32.whl", hash = "sha256:9770e1b09748ad0d751853d994991e2592a9f8c464a87014365f80dac2e83faa"}, - {file = "cytoolz-1.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:20194dd02954c00c1f0755e636be75a20781f91a4ac9270c7f747e82d3c7f5a5"}, - {file = "cytoolz-1.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dffc22fd2c91be64dbdbc462d0786f8e8ac9a275cfa1869a1084d1867d4f67e0"}, - {file = "cytoolz-1.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a99e7e29274e293f4ffe20e07f76c2ac753a78f1b40c1828dfc54b2981b2f6c4"}, - {file = "cytoolz-1.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c507a3e0a45c41d66b43f96797290d75d1e7a8549aa03a4a6b8854fdf3f7b8d8"}, - {file = "cytoolz-1.0.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:643a593ec272ef7429099e1182a22f64ec2696c00d295d2a5be390db1b7ff176"}, - {file = "cytoolz-1.0.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ce38e2e42cbae30446190c59b92a8a9029e1806fd79eaf88f48b0fe33003893"}, - {file = "cytoolz-1.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:810a6a168b8c5ecb412fbae3dd6f7ed6c6253a63caf4174ee9794ebd29b2224f"}, - {file = "cytoolz-1.0.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ce8a2a85c0741c1b19b16e6782c4a5abc54c3caecda66793447112ab2fa9884"}, - {file = "cytoolz-1.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ea4ac72e6b830861035c4c7999af8e55813f57c6d1913a3d93cc4a6babc27bf7"}, - {file = "cytoolz-1.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:a09cdfb21dfb38aa04df43e7546a41f673377eb5485da88ceb784e327ec7603b"}, - {file = "cytoolz-1.0.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:658dd85deb375ff7af990a674e5c9058cef1c9d1f5dc89bc87b77be499348144"}, - {file = "cytoolz-1.0.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:9715d1ff5576919d10b68f17241375f6a1eec8961c25b78a83e6ef1487053f39"}, - {file = "cytoolz-1.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f370a1f1f1afc5c1c8cc5edc1cfe0ba444263a0772af7ce094be8e734f41769d"}, - {file = "cytoolz-1.0.0-cp311-cp311-win32.whl", hash = "sha256:dbb2ec1177dca700f3db2127e572da20de280c214fc587b2a11c717fc421af56"}, - {file = "cytoolz-1.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:0983eee73df86e54bb4a79fcc4996aa8b8368fdbf43897f02f9c3bf39c4dc4fb"}, - {file = "cytoolz-1.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:10e3986066dc379e30e225b230754d9f5996aa8d84c2accc69c473c21d261e46"}, - {file = "cytoolz-1.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:16576f1bb143ee2cb9f719fcc4b845879fb121f9075c7c5e8a5ff4854bd02fc6"}, - {file = "cytoolz-1.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3faa25a1840b984315e8b3ae517312375f4273ffc9a2f035f548b7f916884f37"}, - {file = "cytoolz-1.0.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:781fce70a277b20fd95dc66811d1a97bb07b611ceea9bda8b7dd3c6a4b05d59a"}, - {file = "cytoolz-1.0.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7a562c25338eb24d419d1e80a7ae12133844ce6fdeb4ab54459daf250088a1b2"}, - {file = "cytoolz-1.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f29d8330aaf070304f7cd5cb7e73e198753624eb0aec278557cccd460c699b5b"}, - {file = "cytoolz-1.0.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:98a96c54aa55ed9c7cdb23c2f0df39a7b4ee518ac54888480b5bdb5ef69c7ef0"}, - {file = "cytoolz-1.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:287d6d7f475882c2ddcbedf8da9a9b37d85b77690779a2d1cdceb5ae3998d52e"}, - {file = "cytoolz-1.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:05a871688df749b982839239fcd3f8ec3b3b4853775d575ff9cd335fa7c75035"}, - {file = "cytoolz-1.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:28bb88e1e2f7d6d4b8e0890b06d292c568984d717de3e8381f2ca1dd12af6470"}, - {file = "cytoolz-1.0.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:576a4f1fc73d8836b10458b583f915849da6e4f7914f4ecb623ad95c2508cad5"}, - {file = "cytoolz-1.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:509ed3799c47e4ada14f63e41e8f540ac6e2dab97d5d7298934e6abb9d3830ec"}, - {file = "cytoolz-1.0.0-cp312-cp312-win32.whl", hash = "sha256:9ce25f02b910630f6dc2540dd1e26c9326027ddde6c59f8cab07c56acc70714c"}, - {file = "cytoolz-1.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:7e53cfcce87e05b7f0ae2fb2b3e5820048cd0bb7b701e92bd8f75c9fbb7c9ae9"}, - {file = "cytoolz-1.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7d56569dfe67a39ce74ffff0dc12cf0a3d1aae709667a303fe8f2dd5fd004fdf"}, - {file = "cytoolz-1.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:035c8bb4706dcf93a89fb35feadff67e9301935bf6bb864cd2366923b69d9a29"}, - {file = "cytoolz-1.0.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:27c684799708bdc7ee7acfaf464836e1b4dec0996815c1d5efd6a92a4356a562"}, - {file = "cytoolz-1.0.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:44ab57cfc922b15d94899f980d76759ef9e0256912dfab70bf2561bea9cd5b19"}, - {file = "cytoolz-1.0.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:478af5ecc066da093d7660b23d0b465a7f44179739937afbded8af00af412eb6"}, - {file = "cytoolz-1.0.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:da1f82a7828a42468ea2820a25b6e56461361390c29dcd4d68beccfa1b71066b"}, - {file = "cytoolz-1.0.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c371b3114d38ee717780b239179e88d5d358fe759a00dcf07691b8922bbc762"}, - {file = "cytoolz-1.0.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:90b343b2f3b3e77c3832ba19b0b17e95412a5b2e715b05c23a55ba525d1fca49"}, - {file = "cytoolz-1.0.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:89a554a9ba112403232a54e15e46ff218b33020f3f45c4baf6520ab198b7ad93"}, - {file = "cytoolz-1.0.0-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:0d603f5e2b1072166745ecdd81384a75757a96a704a5642231eb51969f919d5f"}, - {file = "cytoolz-1.0.0-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:122ef2425bd3c0419e6e5260d0b18cd25cf74de589cd0184e4a63b24a4641e2e"}, - {file = "cytoolz-1.0.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8819f1f97ebe36efcaf4b550e21677c46ac8a41bed482cf66845f377dd20700d"}, - {file = "cytoolz-1.0.0-cp38-cp38-win32.whl", hash = "sha256:fcddbb853770dd6e270d89ea8742f0aa42c255a274b9e1620eb04e019b79785e"}, - {file = "cytoolz-1.0.0-cp38-cp38-win_amd64.whl", hash = "sha256:ca526905a014a38cc23ae78635dc51d0462c5c24425b22c08beed9ff2ee03845"}, - {file = "cytoolz-1.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:05df5ff1cdd198fb57e7368623662578c950be0b14883cadfb9ee4098415e1e5"}, - {file = "cytoolz-1.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04a84778f48ebddb26948971dc60948907c876ba33b13f9cbb014fe65b341fc2"}, - {file = "cytoolz-1.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f65283b618b4c4df759f57bcf8483865a73f7f268e6d76886c743407c8d26c1c"}, - {file = "cytoolz-1.0.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388cd07ee9a9e504c735a0a933e53c98586a1c301a64af81f7aa7ff40c747520"}, - {file = "cytoolz-1.0.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:06d09e9569cfdfc5c082806d4b4582db8023a3ce034097008622bcbac7236f38"}, - {file = "cytoolz-1.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9502bd9e37779cc9893cbab515a474c2ab6af61ed22ac2f7e16033db18fcaa85"}, - {file = "cytoolz-1.0.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:364c2fda148def38003b2c86e8adde1d2aab12411dd50872c244a815262e2fda"}, - {file = "cytoolz-1.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9b2e945617325242687189966335e785dc0fae316f4c1825baacf56e5a97e65f"}, - {file = "cytoolz-1.0.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0f16907fdc724c55b16776bdb7e629deae81d500fe48cfc3861231753b271355"}, - {file = "cytoolz-1.0.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:d3206c81ca3ba2d7b8fe78f2e116e3028e721148be753308e88dcbbc370bca52"}, - {file = "cytoolz-1.0.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:becce4b13e110b5ac6b23753dcd0c977f4fdccffa31898296e13fd1109e517e3"}, - {file = "cytoolz-1.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:69a7e5e98fd446079b8b8ec5987aec9a31ec3570a6f494baefa6800b783eaf22"}, - {file = "cytoolz-1.0.0-cp39-cp39-win32.whl", hash = "sha256:b1707b6c3a91676ac83a28a231a14b337dbb4436b937e6b3e4fd44209852a48b"}, - {file = "cytoolz-1.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:11d48b8521ef5fe92e099f4fc00717b5d0789c3c90d5d84031b6d3b17dee1700"}, - {file = "cytoolz-1.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:e672712d5dc3094afc6fb346dd4e9c18c1f3c69608ddb8cf3b9f8428f9c26a5c"}, - {file = "cytoolz-1.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86fb208bfb7420e1d0d20065d661310e4a8a6884851d4044f47d37ed4cd7410e"}, - {file = "cytoolz-1.0.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6dbe5fe3b835859fc559eb59bf2775b5a108f7f2cfab0966f3202859d787d8fd"}, - {file = "cytoolz-1.0.0-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cace092dfda174eed09ed871793beb5b65633963bcda5b1632c73a5aceea1ce"}, - {file = "cytoolz-1.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f7a9d816af3be9725c70efe0a6e4352a45d3877751b395014b8eb2f79d7d8d9d"}, - {file = "cytoolz-1.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:caa7ef840847a23b379e6146760e3a22f15f445656af97e55a435c592125cfa5"}, - {file = "cytoolz-1.0.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:921082fff09ff6e40c12c87b49be044492b2d6bb01d47783995813b76680c7b2"}, - {file = "cytoolz-1.0.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a32f1356f3b64dda883583383966948604ac69ca0b7fbcf5f28856e5f9133b4e"}, - {file = "cytoolz-1.0.0-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9af793b1738e4191d15a92e1793f1ffea9f6461022c7b2442f3cb1ea0a4f758a"}, - {file = "cytoolz-1.0.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:51dfda3983fcc59075c534ce54ca041bb3c80e827ada5d4f25ff7b4049777f94"}, - {file = "cytoolz-1.0.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:acfb8780c04d29423d14aaab74cd1b7b4beaba32f676e7ace02c9acfbf532aba"}, - {file = "cytoolz-1.0.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99f39dcc46416dca3eb23664b73187b77fb52cd8ba2ddd8020a292d8f449db67"}, - {file = "cytoolz-1.0.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c0d56b3721977806dcf1a68b0ecd56feb382fdb0f632af1a9fc5ab9b662b32c6"}, - {file = "cytoolz-1.0.0-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45d346620abc8c83ae634136e700432ad6202faffcc24c5ab70b87392dcda8a1"}, - {file = "cytoolz-1.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:df0c81197fc130de94c09fc6f024a6a19c98ba8fe55c17f1e45ebba2e9229079"}, - {file = "cytoolz-1.0.0.tar.gz", hash = "sha256:eb453b30182152f9917a5189b7d99046b6ce90cdf8aeb0feff4b2683e600defd"}, +groups = ["main"] +markers = "implementation_name == \"cpython\"" +files = [ + {file = "cytoolz-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:cec9af61f71fc3853eb5dca3d42eb07d1f48a4599fa502cbe92adde85f74b042"}, + {file = "cytoolz-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:140bbd649dbda01e91add7642149a5987a7c3ccc251f2263de894b89f50b6608"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e90124bdc42ff58b88cdea1d24a6bc5f776414a314cc4d94f25c88badb3a16d1"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e74801b751e28f7c5cc3ad264c123954a051f546f2fdfe089f5aa7a12ccfa6da"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:582dad4545ddfb5127494ef23f3fa4855f1673a35d50c66f7638e9fb49805089"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd7bd0618e16efe03bd12f19c2a26a27e6e6b75d7105adb7be1cd2a53fa755d8"}, + {file = "cytoolz-1.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d74cca6acf1c4af58b2e4a89cc565ed61c5e201de2e434748c93e5a0f5c541a5"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:823a3763828d8d457f542b2a45d75d6b4ced5e470b5c7cf2ed66a02f508ed442"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:51633a14e6844c61db1d68c1ffd077cf949f5c99c60ed5f1e265b9e2966f1b52"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:f3ec9b01c45348f1d0d712507d54c2bfd69c62fbd7c9ef555c9d8298693c2432"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1855022b712a9c7a5bce354517ab4727a38095f81e2d23d3eabaf1daeb6a3b3c"}, + {file = "cytoolz-1.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:9930f7288c4866a1dc1cc87174f0c6ff4cad1671eb1f6306808aa6c445857d78"}, + {file = "cytoolz-1.0.1-cp310-cp310-win32.whl", hash = "sha256:a9baad795d72fadc3445ccd0f122abfdbdf94269157e6d6d4835636dad318804"}, + {file = "cytoolz-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:ad95b386a84e18e1f6136f6d343d2509d4c3aae9f5a536f3dc96808fcc56a8cf"}, + {file = "cytoolz-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2d958d4f04d9d7018e5c1850790d9d8e68b31c9a2deebca74b903706fdddd2b6"}, + {file = "cytoolz-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0f445b8b731fc0ecb1865b8e68a070084eb95d735d04f5b6c851db2daf3048ab"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f546a96460a7e28eb2ec439f4664fa646c9b3e51c6ebad9a59d3922bbe65e30"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0317681dd065532d21836f860b0563b199ee716f55d0c1f10de3ce7100c78a3b"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0c0ef52febd5a7821a3fd8d10f21d460d1a3d2992f724ba9c91fbd7a96745d41"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5ebaf419acf2de73b643cf96108702b8aef8e825cf4f63209ceb078d5fbbbfd"}, + {file = "cytoolz-1.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f7f04eeb4088947585c92d6185a618b25ad4a0f8f66ea30c8db83cf94a425e3"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f61928803bb501c17914b82d457c6f50fe838b173fb40d39c38d5961185bd6c7"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:d2960cb4fa01ccb985ad1280db41f90dc97a80b397af970a15d5a5de403c8c61"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b2b407cc3e9defa8df5eb46644f6f136586f70ba49eba96f43de67b9a0984fd3"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8245f929144d4d3bd7b972c9593300195c6cea246b81b4c46053c48b3f044580"}, + {file = "cytoolz-1.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e37385db03af65763933befe89fa70faf25301effc3b0485fec1c15d4ce4f052"}, + {file = "cytoolz-1.0.1-cp311-cp311-win32.whl", hash = "sha256:50f9c530f83e3e574fc95c264c3350adde8145f4f8fc8099f65f00cc595e5ead"}, + {file = "cytoolz-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:b7f6b617454b4326af7bd3c7c49b0fc80767f134eb9fd6449917a058d17a0e3c"}, + {file = "cytoolz-1.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fcb8f7d0d65db1269022e7e0428471edee8c937bc288ebdcb72f13eaa67c2fe4"}, + {file = "cytoolz-1.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:207d4e4b445e087e65556196ff472ff134370d9a275d591724142e255f384662"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:21cdf6bac6fd843f3b20280a66fd8df20dea4c58eb7214a2cd8957ec176f0bb3"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a55ec098036c0dea9f3bdc021f8acd9d105a945227d0811589f0573f21c9ce1"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a13ab79ff4ce202e03ab646a2134696988b554b6dc4b71451e948403db1331d8"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e2d944799026e1ff08a83241f1027a2d9276c41f7a74224cd98b7df6e03957d"}, + {file = "cytoolz-1.0.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88ba85834cd523b91fdf10325e1e6d71c798de36ea9bdc187ca7bd146420de6f"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5a750b1af7e8bf6727f588940b690d69e25dc47cce5ce467925a76561317eaf7"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:44a71870f7eae31d263d08b87da7c2bf1176f78892ed8bdade2c2850478cb126"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:c8231b9abbd8e368e036f4cc2e16902c9482d4cf9e02a6147ed0e9a3cd4a9ab0"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:aa87599ccc755de5a096a4d6c34984de6cd9dc928a0c5eaa7607457317aeaf9b"}, + {file = "cytoolz-1.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:67cd16537df51baabde3baa770ab7b8d16839c4d21219d5b96ac59fb012ebd2d"}, + {file = "cytoolz-1.0.1-cp312-cp312-win32.whl", hash = "sha256:fb988c333f05ee30ad4693fe4da55d95ec0bb05775d2b60191236493ea2e01f9"}, + {file = "cytoolz-1.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:8f89c48d8e5aec55ffd566a8ec858706d70ed0c6a50228eca30986bfa5b4da8b"}, + {file = "cytoolz-1.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6944bb93b287032a4c5ca6879b69bcd07df46f3079cf8393958cf0b0454f50c0"}, + {file = "cytoolz-1.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e027260fd2fc5cb041277158ac294fc13dca640714527219f702fb459a59823a"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88662c0e07250d26f5af9bc95911e6137e124a5c1ec2ce4a5d74de96718ab242"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:309dffa78b0961b4c0cf55674b828fbbc793cf2d816277a5c8293c0c16155296"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:edb34246e6eb40343c5860fc51b24937698e4fa1ee415917a73ad772a9a1746b"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a54da7a8e4348a18d45d4d5bc84af6c716d7f131113a4f1cc45569d37edff1b"}, + {file = "cytoolz-1.0.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:241c679c3b1913c0f7259cf1d9639bed5084c86d0051641d537a0980548aa266"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5bfc860251a8f280ac79696fc3343cfc3a7c30b94199e0240b6c9e5b6b01a2a5"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c8edd1547014050c1bdad3ff85d25c82bd1c2a3c96830c6181521eb78b9a42b3"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b349bf6162e8de215403d7f35f8a9b4b1853dc2a48e6e1a609a5b1a16868b296"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:1b18b35256219b6c3dd0fa037741b85d0bea39c552eab0775816e85a52834140"}, + {file = "cytoolz-1.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:738b2350f340ff8af883eb301054eb724997f795d20d90daec7911c389d61581"}, + {file = "cytoolz-1.0.1-cp313-cp313-win32.whl", hash = "sha256:9cbd9c103df54fcca42be55ef40e7baea624ac30ee0b8bf1149f21146d1078d9"}, + {file = "cytoolz-1.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:90e577e08d3a4308186d9e1ec06876d4756b1e8164b92971c69739ea17e15297"}, + {file = "cytoolz-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f3a509e4ac8e711703c368476b9bbce921fcef6ebb87fa3501525f7000e44185"}, + {file = "cytoolz-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a7eecab6373e933dfbf4fdc0601d8fd7614f8de76793912a103b5fccf98170cd"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e55ed62087f6e3e30917b5f55350c3b6be6470b849c6566018419cd159d2cebc"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:43de33d99a4ccc07234cecd81f385456b55b0ea9c39c9eebf42f024c313728a5"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:139bed875828e1727018aa0982aa140e055cbafccb7fd89faf45cbb4f2a21514"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22c12671194b518aa8ce2f4422bd5064f25ab57f410ba0b78705d0a219f4a97a"}, + {file = "cytoolz-1.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:79888f2f7dc25709cd5d37b032a8833741e6a3692c8823be181d542b5999128e"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:51628b4eb41fa25bd428f8f7b5b74fbb05f3ae65fbd265019a0dd1ded4fdf12a"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:1db9eb7179285403d2fb56ba1ff6ec35a44921b5e2fa5ca19d69f3f9f0285ea5"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:08ab7efae08e55812340bfd1b3f09f63848fe291675e2105eab1aa5327d3a16e"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:e5fdc5264f884e7c0a1711a81dff112708a64b9c8561654ee578bfdccec6be09"}, + {file = "cytoolz-1.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:90d6a2e6ab891043ee655ec99d5e77455a9bee9e1131bdfcfb745edde81200dd"}, + {file = "cytoolz-1.0.1-cp38-cp38-win32.whl", hash = "sha256:08946e083faa5147751b34fbf78ab931f149ef758af5c1092932b459e18dcf5c"}, + {file = "cytoolz-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:a91b4e10a9c03796c0dc93e47ebe25bb41ecc6fafc3cf5197c603cf767a3d44d"}, + {file = "cytoolz-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:980c323e626ba298b77ae62871b2de7c50b9d7219e2ddf706f52dd34b8be7349"}, + {file = "cytoolz-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:45f6fa1b512bc2a0f2de5123db932df06c7f69d12874fe06d67772b2828e2c8b"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f93f42d9100c415155ad1f71b0de362541afd4ac95e3153467c4c79972521b6b"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a76d20dec9c090cdf4746255bbf06a762e8cc29b5c9c1d138c380bbdb3122ade"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:239039585487c69aa50c5b78f6a422016297e9dea39755761202fb9f0530fe87"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28307640ca2ab57b9fbf0a834b9bf563958cd9e038378c3a559f45f13c3c541"}, + {file = "cytoolz-1.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:454880477bb901cee3a60f6324ec48c95d45acc7fecbaa9d49a5af737ded0595"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:902115d1b1f360fd81e44def30ac309b8641661150fcbdde18ead446982ada6a"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:e68e6b38473a3a79cee431baa22be31cac39f7df1bf23eaa737eaff42e213883"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:32fba3f63fcb76095b0a22f4bdcc22bc62a2bd2d28d58bf02fd21754c155a3ec"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:0724ba4cf41eb40b6cf75250820ab069e44bdf4183ff78857aaf4f0061551075"}, + {file = "cytoolz-1.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c42420e0686f887040d5230420ed44f0e960ccbfa29a0d65a3acd9ca52459209"}, + {file = "cytoolz-1.0.1-cp39-cp39-win32.whl", hash = "sha256:4ba8b16358ea56b1fe8e637ec421e36580866f2e787910bac1cf0a6997424a34"}, + {file = "cytoolz-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:92d27f84bf44586853d9562bfa3610ecec000149d030f793b4cb614fd9da1813"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:83d19d55738ad9c60763b94f3f6d3c6e4de979aeb8d76841c1401081e0e58d96"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f112a71fad6ea824578e6393765ce5c054603afe1471a5c753ff6c67fd872d10"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a515df8f8aa6e1eaaf397761a6e4aff2eef73b5f920aedf271416d5471ae5ee"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:92c398e7b7023460bea2edffe5fcd0a76029580f06c3f6938ac3d198b47156f3"}, + {file = "cytoolz-1.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3237e56211e03b13df47435b2369f5df281e02b04ad80a948ebd199b7bc10a47"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ba0d1da50aab1909b165f615ba1125c8b01fcc30d606c42a61c42ea0269b5e2c"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25b6e8dec29aa5a390092d193abd673e027d2c0b50774ae816a31454286c45c7"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36cd6989ebb2f18fe9af8f13e3c61064b9f741a40d83dc5afeb0322338ad25f2"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47394f8ab7fca3201f40de61fdeea20a2baffb101485ae14901ea89c3f6c95d"}, + {file = "cytoolz-1.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d00ac423542af944302e034e618fb055a0c4e87ba704cd6a79eacfa6ac83a3c9"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:a5ca923d1fa632f7a4fb33c0766c6fba7f87141a055c305c3e47e256fb99c413"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:058bf996bcae9aad3acaeeb937d42e0c77c081081e67e24e9578a6a353cb7fb2"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69e2a1f41a3dad94a17aef4a5cc003323359b9f0a9d63d4cc867cb5690a2551d"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:67daeeeadb012ec2b59d63cb29c4f2a2023b0c4957c3342d354b8bb44b209e9a"}, + {file = "cytoolz-1.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:54d3d36bbf0d4344d1afa22c58725d1668e30ff9de3a8f56b03db1a6da0acb11"}, + {file = "cytoolz-1.0.1.tar.gz", hash = "sha256:89cc3161b89e1bb3ed7636f74ed2e55984fd35516904fc878cae216e42b2c7d6"}, ] [package.dependencies] @@ -812,37 +843,38 @@ cython = ["cython"] [[package]] name = "debugpy" -version = "1.8.11" +version = "1.8.12" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" -files = [ - {file = "debugpy-1.8.11-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:2b26fefc4e31ff85593d68b9022e35e8925714a10ab4858fb1b577a8a48cb8cd"}, - {file = "debugpy-1.8.11-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61bc8b3b265e6949855300e84dc93d02d7a3a637f2aec6d382afd4ceb9120c9f"}, - {file = "debugpy-1.8.11-cp310-cp310-win32.whl", hash = "sha256:c928bbf47f65288574b78518449edaa46c82572d340e2750889bbf8cd92f3737"}, - {file = "debugpy-1.8.11-cp310-cp310-win_amd64.whl", hash = "sha256:8da1db4ca4f22583e834dcabdc7832e56fe16275253ee53ba66627b86e304da1"}, - {file = "debugpy-1.8.11-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:85de8474ad53ad546ff1c7c7c89230db215b9b8a02754d41cb5a76f70d0be296"}, - {file = "debugpy-1.8.11-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ffc382e4afa4aee367bf413f55ed17bd91b191dcaf979890af239dda435f2a1"}, - {file = "debugpy-1.8.11-cp311-cp311-win32.whl", hash = "sha256:40499a9979c55f72f4eb2fc38695419546b62594f8af194b879d2a18439c97a9"}, - {file = "debugpy-1.8.11-cp311-cp311-win_amd64.whl", hash = "sha256:987bce16e86efa86f747d5151c54e91b3c1e36acc03ce1ddb50f9d09d16ded0e"}, - {file = "debugpy-1.8.11-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:84e511a7545d11683d32cdb8f809ef63fc17ea2a00455cc62d0a4dbb4ed1c308"}, - {file = "debugpy-1.8.11-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce291a5aca4985d82875d6779f61375e959208cdf09fcec40001e65fb0a54768"}, - {file = "debugpy-1.8.11-cp312-cp312-win32.whl", hash = "sha256:28e45b3f827d3bf2592f3cf7ae63282e859f3259db44ed2b129093ca0ac7940b"}, - {file = "debugpy-1.8.11-cp312-cp312-win_amd64.whl", hash = "sha256:44b1b8e6253bceada11f714acf4309ffb98bfa9ac55e4fce14f9e5d4484287a1"}, - {file = "debugpy-1.8.11-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:8988f7163e4381b0da7696f37eec7aca19deb02e500245df68a7159739bbd0d3"}, - {file = "debugpy-1.8.11-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c1f6a173d1140e557347419767d2b14ac1c9cd847e0b4c5444c7f3144697e4e"}, - {file = "debugpy-1.8.11-cp313-cp313-win32.whl", hash = "sha256:bb3b15e25891f38da3ca0740271e63ab9db61f41d4d8541745cfc1824252cb28"}, - {file = "debugpy-1.8.11-cp313-cp313-win_amd64.whl", hash = "sha256:d8768edcbeb34da9e11bcb8b5c2e0958d25218df7a6e56adf415ef262cd7b6d1"}, - {file = "debugpy-1.8.11-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:ad7efe588c8f5cf940f40c3de0cd683cc5b76819446abaa50dc0829a30c094db"}, - {file = "debugpy-1.8.11-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:189058d03a40103a57144752652b3ab08ff02b7595d0ce1f651b9acc3a3a35a0"}, - {file = "debugpy-1.8.11-cp38-cp38-win32.whl", hash = "sha256:32db46ba45849daed7ccf3f2e26f7a386867b077f39b2a974bb5c4c2c3b0a280"}, - {file = "debugpy-1.8.11-cp38-cp38-win_amd64.whl", hash = "sha256:116bf8342062246ca749013df4f6ea106f23bc159305843491f64672a55af2e5"}, - {file = "debugpy-1.8.11-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:654130ca6ad5de73d978057eaf9e582244ff72d4574b3e106fb8d3d2a0d32458"}, - {file = "debugpy-1.8.11-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23dc34c5e03b0212fa3c49a874df2b8b1b8fda95160bd79c01eb3ab51ea8d851"}, - {file = "debugpy-1.8.11-cp39-cp39-win32.whl", hash = "sha256:52d8a3166c9f2815bfae05f386114b0b2d274456980d41f320299a8d9a5615a7"}, - {file = "debugpy-1.8.11-cp39-cp39-win_amd64.whl", hash = "sha256:52c3cf9ecda273a19cc092961ee34eb9ba8687d67ba34cc7b79a521c1c64c4c0"}, - {file = "debugpy-1.8.11-py2.py3-none-any.whl", hash = "sha256:0e22f846f4211383e6a416d04b4c13ed174d24cc5d43f5fd52e7821d0ebc8920"}, - {file = "debugpy-1.8.11.tar.gz", hash = "sha256:6ad2688b69235c43b020e04fecccdf6a96c8943ca9c2fb340b8adc103c655e57"}, +groups = ["dev"] +files = [ + {file = "debugpy-1.8.12-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:a2ba7ffe58efeae5b8fad1165357edfe01464f9aef25e814e891ec690e7dd82a"}, + {file = "debugpy-1.8.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbbd4149c4fc5e7d508ece083e78c17442ee13b0e69bfa6bd63003e486770f45"}, + {file = "debugpy-1.8.12-cp310-cp310-win32.whl", hash = "sha256:b202f591204023b3ce62ff9a47baa555dc00bb092219abf5caf0e3718ac20e7c"}, + {file = "debugpy-1.8.12-cp310-cp310-win_amd64.whl", hash = "sha256:9649eced17a98ce816756ce50433b2dd85dfa7bc92ceb60579d68c053f98dff9"}, + {file = "debugpy-1.8.12-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:36f4829839ef0afdfdd208bb54f4c3d0eea86106d719811681a8627ae2e53dd5"}, + {file = "debugpy-1.8.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a28ed481d530e3138553be60991d2d61103ce6da254e51547b79549675f539b7"}, + {file = "debugpy-1.8.12-cp311-cp311-win32.whl", hash = "sha256:4ad9a94d8f5c9b954e0e3b137cc64ef3f579d0df3c3698fe9c3734ee397e4abb"}, + {file = "debugpy-1.8.12-cp311-cp311-win_amd64.whl", hash = "sha256:4703575b78dd697b294f8c65588dc86874ed787b7348c65da70cfc885efdf1e1"}, + {file = "debugpy-1.8.12-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498"}, + {file = "debugpy-1.8.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06"}, + {file = "debugpy-1.8.12-cp312-cp312-win32.whl", hash = "sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d"}, + {file = "debugpy-1.8.12-cp312-cp312-win_amd64.whl", hash = "sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969"}, + {file = "debugpy-1.8.12-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f"}, + {file = "debugpy-1.8.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9"}, + {file = "debugpy-1.8.12-cp313-cp313-win32.whl", hash = "sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180"}, + {file = "debugpy-1.8.12-cp313-cp313-win_amd64.whl", hash = "sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c"}, + {file = "debugpy-1.8.12-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:b0232cd42506d0c94f9328aaf0d1d0785f90f87ae72d9759df7e5051be039738"}, + {file = "debugpy-1.8.12-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9af40506a59450f1315168d47a970db1a65aaab5df3833ac389d2899a5d63b3f"}, + {file = "debugpy-1.8.12-cp38-cp38-win32.whl", hash = "sha256:5cc45235fefac57f52680902b7d197fb2f3650112379a6fa9aa1b1c1d3ed3f02"}, + {file = "debugpy-1.8.12-cp38-cp38-win_amd64.whl", hash = "sha256:557cc55b51ab2f3371e238804ffc8510b6ef087673303890f57a24195d096e61"}, + {file = "debugpy-1.8.12-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:b5c6c967d02fee30e157ab5227706f965d5c37679c687b1e7bbc5d9e7128bd41"}, + {file = "debugpy-1.8.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a77f422f31f170c4b7e9ca58eae2a6c8e04da54121900651dfa8e66c29901a"}, + {file = "debugpy-1.8.12-cp39-cp39-win32.whl", hash = "sha256:a4042edef80364239f5b7b5764e55fd3ffd40c32cf6753da9bda4ff0ac466018"}, + {file = "debugpy-1.8.12-cp39-cp39-win_amd64.whl", hash = "sha256:f30b03b0f27608a0b26c75f0bb8a880c752c0e0b01090551b9d87c7d783e2069"}, + {file = "debugpy-1.8.12-py2.py3-none-any.whl", hash = "sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6"}, + {file = "debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce"}, ] [[package]] @@ -851,6 +883,7 @@ version = "0.3.0" description = "a toolset to deeply merge python dictionaries." optional = false python-versions = ">=3" +groups = ["main"] files = [ {file = "deepmerge-0.3.0-py2.py3-none-any.whl", hash = "sha256:87166dbe9ba1a3348a45c9d4ada6778f518d41afc0b85aa017ea3041facc3f9c"}, {file = "deepmerge-0.3.0.tar.gz", hash = "sha256:f6fd7f1293c535fb599e197e750dbe8674503c5d2a89759b3c72a3c46746d4fd"}, @@ -862,6 +895,7 @@ version = "0.1.2" description = "An implementation of did:peer:2" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "did_peer_2-0.1.2-py3-none-any.whl", hash = "sha256:d5908cda2d52b7c34428a421044507d7847fd79b78dc8360441c408f4507d612"}, {file = "did_peer_2-0.1.2.tar.gz", hash = "sha256:af8623f62022732e9fadc0289dfb886fd8267767251c4fa0b63694ecd29a7086"}, @@ -876,6 +910,7 @@ version = "0.1.4" description = "An implementation of did:peer:4" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "did_peer_4-0.1.4-py3-none-any.whl", hash = "sha256:4c2bb42a55e4fec08fe008a1585db2f11fe19e36121f8919991add027d7c816f"}, {file = "did_peer_4-0.1.4.tar.gz", hash = "sha256:b367922067b428d33458ca36158eaed40c863cde2fbab6a18a523dccad533c8e"}, @@ -885,14 +920,15 @@ files = [ base58 = ">=2.1.1" [[package]] -name = "did-tdw" +name = "did-webvh" version = "0.2.1" -description = "This repository includes Python libraries for working with `did:tdw` (Trust DID Web) DID documents and the underlying log format." +description = "This repository includes Python libraries for working with `did:webvh` (did:web + Verified History) DID documents and the underlying log format." optional = false python-versions = "<4.0,>=3.10" +groups = ["main"] files = [ - {file = "did_tdw-0.2.1-py3-none-any.whl", hash = "sha256:80c727d0bef37e2211d3caddb97ba3c4aa508c67d4ef502da5f326d9bf4c3ffb"}, - {file = "did_tdw-0.2.1.tar.gz", hash = "sha256:a61ed9f49369ea4c365e5e380431feae8cb3988375de37f73be2abe15d0bfde6"}, + {file = "did_webvh-0.2.1-py3-none-any.whl", hash = "sha256:4c4a84d3c7bda8d82eed1cb181dea1fc0fe4c23d6fe65e3622ff7f61dd7688a3"}, + {file = "did_webvh-0.2.1.tar.gz", hash = "sha256:2e731a594d9b7ff509f70d2595f1435873985b29ce2a489e98ead1a872264892"}, ] [package.dependencies] @@ -909,6 +945,8 @@ version = "0.1.1" description = "DIDComm Messaging implemented with swappable backends." optional = true python-versions = ">=3.9" +groups = ["main"] +markers = "extra == \"didcommv2\"" files = [ {file = "didcomm_messaging-0.1.1-py3-none-any.whl", hash = "sha256:5350006d3a92e085dd208add738d6439c2b0a950c1fe19011ece71de0574cc1a"}, {file = "didcomm_messaging-0.1.1.tar.gz", hash = "sha256:e3c7c7612b8f9710ccd221b2f5e8456cbf868600f7cc10474fcc98be325702eb"}, @@ -930,6 +968,7 @@ version = "0.3.9" description = "Distribution utilities" optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "distlib-0.3.9-py2.py3-none-any.whl", hash = "sha256:47f8c22fd27c27e25a65601af709b38e4f0a45ea4fc2e710f65755fa8caaaf87"}, {file = "distlib-0.3.9.tar.gz", hash = "sha256:a60f20dea646b8a33f3e7772f74dc0b2d0772d2837ee1342a00645c81edf9403"}, @@ -937,13 +976,14 @@ files = [ [[package]] name = "docutils" -version = "0.19" +version = "0.21.2" description = "Docutils -- Python Documentation Utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, - {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, + {file = "docutils-0.21.2-py3-none-any.whl", hash = "sha256:dafca5b9e384f0e419294eb4d2ff9fa826435bf15f15b7bd45723e8ad76811b2"}, + {file = "docutils-0.21.2.tar.gz", hash = "sha256:3a6b18732edf182daa3cd12775bbb338cf5691468f91eeeb109deff6ebfa986f"}, ] [[package]] @@ -952,6 +992,7 @@ version = "0.19.0" description = "ECDSA cryptographic signature library (pure python)" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.6" +groups = ["main"] files = [ {file = "ecdsa-0.19.0-py2.py3-none-any.whl", hash = "sha256:2cea9b88407fdac7bbeca0833b189e4c9c53f2ef1e1eaa29f6224dbc809b707a"}, {file = "ecdsa-0.19.0.tar.gz", hash = "sha256:60eaad1199659900dd0af521ed462b793bbdf867432b3948e87416ae4caf6bf8"}, @@ -966,39 +1007,41 @@ gmpy2 = ["gmpy2"] [[package]] name = "eth-hash" -version = "0.7.0" +version = "0.7.1" description = "eth-hash: The Ethereum hashing function, keccak256, sometimes (erroneously) called sha3" optional = false -python-versions = ">=3.8, <4" +python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth-hash-0.7.0.tar.gz", hash = "sha256:bacdc705bfd85dadd055ecd35fd1b4f846b671add101427e089a4ca2e8db310a"}, - {file = "eth_hash-0.7.0-py3-none-any.whl", hash = "sha256:b8d5a230a2b251f4a291e3164a23a14057c4a6de4b0aa4a16fa4dc9161b57e2f"}, + {file = "eth_hash-0.7.1-py3-none-any.whl", hash = "sha256:0fb1add2adf99ef28883fd6228eb447ef519ea72933535ad1a0b28c6f65f868a"}, + {file = "eth_hash-0.7.1.tar.gz", hash = "sha256:d2411a403a0b0a62e8247b4117932d900ffb4c8c64b15f92620547ca5ce46be5"}, ] [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] pycryptodome = ["pycryptodome (>=3.6.6,<4)"] pysha3 = ["pysha3 (>=1.0.0,<2.0.0)", "safe-pysha3 (>=1.0.0)"] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "eth-typing" -version = "5.0.1" +version = "5.1.0" description = "eth-typing: Common type annotations for ethereum python packages" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ - {file = "eth_typing-5.0.1-py3-none-any.whl", hash = "sha256:f30d1af16aac598f216748a952eeb64fbcb6e73efa691d2de31148138afe96de"}, - {file = "eth_typing-5.0.1.tar.gz", hash = "sha256:83debf88c9df286db43bb7374974681ebcc9f048fac81be2548dbc549a3203c0"}, + {file = "eth_typing-5.1.0-py3-none-any.whl", hash = "sha256:c0d6b93f5385aa84efc4b47ae2bd478da069bc0ffda8b67e0ccb573f43defd29"}, + {file = "eth_typing-5.1.0.tar.gz", hash = "sha256:8581f212ee6252aaa285377a77620f6e5f6e16ac3f144c61f098fafd47967b1a"}, ] [package.dependencies] -typing-extensions = ">=4.5.0" +typing_extensions = ">=4.5.0" [package.extras] -dev = ["build (>=0.9.0)", "bumpversion (>=0.5.3)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)", "tox (>=4.0.0)", "twine", "wheel"] -docs = ["sphinx (>=6.0.0)", "sphinx-rtd-theme (>=1.0.0)", "towncrier (>=21,<22)"] +dev = ["build (>=0.9.0)", "bump_my_version (>=0.19.0)", "ipython", "mypy (==1.10.0)", "pre-commit (>=3.4.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)", "sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)", "tox (>=4.0.0)", "twine", "wheel"] +docs = ["sphinx (>=6.0.0)", "sphinx-autobuild (>=2021.3.14)", "sphinx_rtd_theme (>=1.0.0)", "towncrier (>=24,<25)"] test = ["pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] @@ -1007,6 +1050,7 @@ version = "5.1.0" description = "eth-utils: Common utility functions for python code that interacts with Ethereum" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ {file = "eth_utils-5.1.0-py3-none-any.whl", hash = "sha256:a99f1f01b51206620904c5af47fac65abc143aebd0a76bdec860381c5a3230f8"}, {file = "eth_utils-5.1.0.tar.gz", hash = "sha256:84c6314b9cf1fcd526107464bbf487e3f87097a2e753360d5ed319f7d42e3f20"}, @@ -1029,6 +1073,7 @@ version = "2.1.1" description = "execnet: rapid multi-Python deployment" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "execnet-2.1.1-py3-none-any.whl", hash = "sha256:26dee51f1b80cebd6d0ca8e74dd8745419761d3bef34163928cbebbdc4749fdc"}, {file = "execnet-2.1.1.tar.gz", hash = "sha256:5189b52c6121c24feae288166ab41b32549c7e2348652736540b9e6e7d4e72e3"}, @@ -1043,6 +1088,7 @@ version = "3.16.1" description = "A platform independent file lock." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, @@ -1059,6 +1105,7 @@ version = "2.4.6" description = "A simple immutable dictionary" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "frozendict-2.4.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c3a05c0a50cab96b4bb0ea25aa752efbfceed5ccb24c007612bc63e51299336f"}, {file = "frozendict-2.4.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f5b94d5b07c00986f9e37a38dd83c13f5fe3bf3f1ccc8e88edea8fe15d6cd88c"}, @@ -1107,6 +1154,7 @@ version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, @@ -1204,13 +1252,14 @@ files = [ [[package]] name = "identify" -version = "2.6.3" +version = "2.6.5" description = "File identification library for Python" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "identify-2.6.3-py2.py3-none-any.whl", hash = "sha256:9edba65473324c2ea9684b1f944fe3191db3345e50b6d04571d10ed164f8d7bd"}, - {file = "identify-2.6.3.tar.gz", hash = "sha256:62f5dae9b5fef52c84cc188514e9ea4f3f636b1d8799ab5ebc475471f9e47a02"}, + {file = "identify-2.6.5-py2.py3-none-any.whl", hash = "sha256:14181a47091eb75b337af4c23078c9d09225cd4c48929f521f3bf16b09d02566"}, + {file = "identify-2.6.5.tar.gz", hash = "sha256:c10b33f250e5bba374fae86fb57f3adcebf1161bce7cdf92031915fd480c13bc"}, ] [package.extras] @@ -1222,6 +1271,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main", "dev"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -1236,6 +1286,7 @@ version = "1.4.1" description = "Getting image size from png/jpeg/jpeg2000/gif file" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] files = [ {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, @@ -1247,6 +1298,7 @@ version = "1.1.1" description = "" optional = false python-versions = ">=3.6.3" +groups = ["main"] files = [ {file = "indy_credx-1.1.1-py3-none-macosx_10_9_universal2.whl", hash = "sha256:522b90a2362de681e8224b7e5173a9a6093dc48b2ed13599c9eca3df36e29128"}, {file = "indy_credx-1.1.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:05f9a96166f79799c39c62723d78c5480fe9a872dd9dee9fbff1f79d0484c893"}, @@ -1260,6 +1312,7 @@ version = "0.4.2" description = "" optional = false python-versions = ">=3.6.3" +groups = ["main"] files = [ {file = "indy_vdr-0.4.2-py3-none-macosx_10_9_universal2.whl", hash = "sha256:21e4cc22bdb1de581e4abe00e2201d970f46e05d2420437fe023052614867553"}, {file = "indy_vdr-0.4.2-py3-none-manylinux2014_aarch64.whl", hash = "sha256:9dc8e16e8a0c4666c1a9f0a3e9967cb3dace92975b8dbb9b0aa2c7785ac5e12b"}, @@ -1273,6 +1326,7 @@ version = "0.5.1" description = "A port of Ruby on Rails inflector to Python" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, @@ -1284,6 +1338,7 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" +groups = ["dev"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -1291,13 +1346,14 @@ files = [ [[package]] name = "jinja2" -version = "3.1.4" +version = "3.1.5" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ - {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, - {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, + {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"}, + {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"}, ] [package.dependencies] @@ -1312,6 +1368,7 @@ version = "0.2.3" description = "Typed Python implementation of JSON Canonicalization Scheme as described in RFC 8785. Currently lacks full floating point support" optional = false python-versions = ">=3.8,<4.0" +groups = ["main"] files = [ {file = "jsoncanon-0.2.3-py3-none-any.whl", hash = "sha256:adb35dac2d0c5dd56f1cb374f1ea6f1fff2ebbb4e844b06d9c96b9ccadf12bf0"}, {file = "jsoncanon-0.2.3.tar.gz", hash = "sha256:483c1ef14e6c8151ba69c0bf646551f249698dd523e9c6da1339a688c5f96d6d"}, @@ -1323,6 +1380,7 @@ version = "1.7.0" description = "A final implementation of JSONPath for Python that aims to be standard compliant, including arithmetic and binary comparison operators and providing clear AST for metaprogramming." optional = false python-versions = "*" +groups = ["main"] files = [ {file = "jsonpath-ng-1.7.0.tar.gz", hash = "sha256:f6f5f7fd4e5ff79c785f1573b394043b39849fb2bb47bcead935d12b00beab3c"}, {file = "jsonpath_ng-1.7.0-py2-none-any.whl", hash = "sha256:898c93fc173f0c336784a3fa63d7434297544b7198124a68f9a3ef9597b0ae6e"}, @@ -1338,6 +1396,7 @@ version = "1.5.6" description = "Implementation of JOSE Web standards" optional = false python-versions = ">= 3.8" +groups = ["main"] files = [ {file = "jwcrypto-1.5.6-py3-none-any.whl", hash = "sha256:150d2b0ebbdb8f40b77f543fb44ffd2baeff48788be71f67f03566692fd55789"}, {file = "jwcrypto-1.5.6.tar.gz", hash = "sha256:771a87762a0c081ae6166958a954f80848820b2ab066937dc8b8379d65b1b039"}, @@ -1353,6 +1412,7 @@ version = "5.3.0" description = "Powerful and Pythonic XML processing library combining libxml2/libxslt with the ElementTree API." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:dd36439be765e2dde7660212b5275641edbc813e7b24668831a5c8ac91180656"}, {file = "lxml-5.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ae5fe5c4b525aa82b8076c1a59d642c17b6e8739ecf852522c6321852178119d"}, @@ -1507,6 +1567,7 @@ version = "3.7" description = "Python implementation of John Gruber's Markdown." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "Markdown-3.7-py3-none-any.whl", hash = "sha256:7eb6df5690b81a1d7942992c97fad2938e956e79df20cbc6186e9c3a77b1c803"}, {file = "markdown-3.7.tar.gz", hash = "sha256:2ae2471477cfd02dbbf038d5d9bc226d40def84b4fe2986e49b59b6b472bbed2"}, @@ -1522,6 +1583,7 @@ version = "2.1.5" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, @@ -1587,13 +1649,14 @@ files = [ [[package]] name = "marshmallow" -version = "3.23.1" +version = "3.25.1" description = "A lightweight library for converting complex datatypes to and from native Python datatypes." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "marshmallow-3.23.1-py3-none-any.whl", hash = "sha256:fece2eb2c941180ea1b7fcbd4a83c51bfdd50093fdd3ad2585ee5e1df2508491"}, - {file = "marshmallow-3.23.1.tar.gz", hash = "sha256:3a8dfda6edd8dcdbf216c0ede1d1e78d230a6dc9c5a088f58c4083b974a0d468"}, + {file = "marshmallow-3.25.1-py3-none-any.whl", hash = "sha256:ec5d00d873ce473b7f2ffcb7104286a376c354cab0c2fa12f5573dab03e87210"}, + {file = "marshmallow-3.25.1.tar.gz", hash = "sha256:f4debda3bb11153d81ac34b0d582bf23053055ee11e791b54b4b35493468040a"}, ] [package.dependencies] @@ -1601,7 +1664,7 @@ packaging = ">=17.0" [package.extras] dev = ["marshmallow[tests]", "pre-commit (>=3.5,<5.0)", "tox"] -docs = ["alabaster (==1.0.0)", "autodocsumm (==0.2.14)", "sphinx (==8.1.3)", "sphinx-issues (==5.0.0)", "sphinx-version-warning (==1.1.2)"] +docs = ["autodocsumm (==0.2.14)", "furo (==2024.8.6)", "sphinx (==8.1.3)", "sphinx-copybutton (==0.5.2)", "sphinx-issues (==5.0.0)", "sphinxext-opengraph (==0.9.1)"] tests = ["pytest", "simplejson"] [[package]] @@ -1610,6 +1673,7 @@ version = "6.1.0" description = "multidict implementation" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, @@ -1711,6 +1775,7 @@ version = "0.3.1.post4" description = "Python implementation of multiformats protocols." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "multiformats-0.3.1.post4-py3-none-any.whl", hash = "sha256:5b1d61bd8275c9e817bdbee38dbd501b26629011962ee3c86c46e7ccd0b14129"}, {file = "multiformats-0.3.1.post4.tar.gz", hash = "sha256:d00074fdbc7d603c2084b4c38fa17bbc28173cf2750f51f46fbbc5c4d5605fbb"}, @@ -1732,6 +1797,7 @@ version = "0.3.1" description = "Pre-loading configuration module for the 'multiformats' package." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "multiformats-config-0.3.1.tar.gz", hash = "sha256:7eaa80ef5d9c5ee9b86612d21f93a087c4a655cbcb68960457e61adbc62b47a7"}, {file = "multiformats_config-0.3.1-py3-none-any.whl", hash = "sha256:dec4c9d42ed0d9305889b67440f72e8e8d74b82b80abd7219667764b5b0a8e1d"}, @@ -1749,6 +1815,7 @@ version = "1.6.0" description = "Patch asyncio to allow nested event loops" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, @@ -1760,6 +1827,7 @@ version = "1.9.1" description = "Node.js virtual environment builder" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, @@ -1771,6 +1839,7 @@ version = "23.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.7" +groups = ["main", "dev"] files = [ {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, @@ -1778,93 +1847,90 @@ files = [ [[package]] name = "pillow" -version = "11.0.0" +version = "11.1.0" description = "Python Imaging Library (Fork)" optional = false python-versions = ">=3.9" -files = [ - {file = "pillow-11.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947"}, - {file = "pillow-11.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba"}, - {file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086"}, - {file = "pillow-11.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9"}, - {file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488"}, - {file = "pillow-11.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f"}, - {file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb"}, - {file = "pillow-11.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97"}, - {file = "pillow-11.0.0-cp310-cp310-win32.whl", hash = "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50"}, - {file = "pillow-11.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c"}, - {file = "pillow-11.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1"}, - {file = "pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc"}, - {file = "pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a"}, - {file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3"}, - {file = "pillow-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5"}, - {file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b"}, - {file = "pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa"}, - {file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306"}, - {file = "pillow-11.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9"}, - {file = "pillow-11.0.0-cp311-cp311-win32.whl", hash = "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5"}, - {file = "pillow-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291"}, - {file = "pillow-11.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9"}, - {file = "pillow-11.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923"}, - {file = "pillow-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903"}, - {file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4"}, - {file = "pillow-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f"}, - {file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9"}, - {file = "pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7"}, - {file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6"}, - {file = "pillow-11.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc"}, - {file = "pillow-11.0.0-cp312-cp312-win32.whl", hash = "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6"}, - {file = "pillow-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47"}, - {file = "pillow-11.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25"}, - {file = "pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699"}, - {file = "pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38"}, - {file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2"}, - {file = "pillow-11.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2"}, - {file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527"}, - {file = "pillow-11.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa"}, - {file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f"}, - {file = "pillow-11.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb"}, - {file = "pillow-11.0.0-cp313-cp313-win32.whl", hash = "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798"}, - {file = "pillow-11.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de"}, - {file = "pillow-11.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84"}, - {file = "pillow-11.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b"}, - {file = "pillow-11.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003"}, - {file = "pillow-11.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2"}, - {file = "pillow-11.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a"}, - {file = "pillow-11.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8"}, - {file = "pillow-11.0.0-cp313-cp313t-win32.whl", hash = "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8"}, - {file = "pillow-11.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904"}, - {file = "pillow-11.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3"}, - {file = "pillow-11.0.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:2e46773dc9f35a1dd28bd6981332fd7f27bec001a918a72a79b4133cf5291dba"}, - {file = "pillow-11.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2679d2258b7f1192b378e2893a8a0a0ca472234d4c2c0e6bdd3380e8dfa21b6a"}, - {file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eda2616eb2313cbb3eebbe51f19362eb434b18e3bb599466a1ffa76a033fb916"}, - {file = "pillow-11.0.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ec184af98a121fb2da42642dea8a29ec80fc3efbaefb86d8fdd2606619045d"}, - {file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:8594f42df584e5b4bb9281799698403f7af489fba84c34d53d1c4bfb71b7c4e7"}, - {file = "pillow-11.0.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:c12b5ae868897c7338519c03049a806af85b9b8c237b7d675b8c5e089e4a618e"}, - {file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:70fbbdacd1d271b77b7721fe3cdd2d537bbbd75d29e6300c672ec6bb38d9672f"}, - {file = "pillow-11.0.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5178952973e588b3f1360868847334e9e3bf49d19e169bbbdfaf8398002419ae"}, - {file = "pillow-11.0.0-cp39-cp39-win32.whl", hash = "sha256:8c676b587da5673d3c75bd67dd2a8cdfeb282ca38a30f37950511766b26858c4"}, - {file = "pillow-11.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:94f3e1780abb45062287b4614a5bc0874519c86a777d4a7ad34978e86428b8dd"}, - {file = "pillow-11.0.0-cp39-cp39-win_arm64.whl", hash = "sha256:290f2cc809f9da7d6d622550bbf4c1e57518212da51b6a30fe8e0a270a5b78bd"}, - {file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2"}, - {file = "pillow-11.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2"}, - {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b"}, - {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2"}, - {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830"}, - {file = "pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734"}, - {file = "pillow-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316"}, - {file = "pillow-11.0.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5bd2d3bdb846d757055910f0a59792d33b555800813c3b39ada1829c372ccb06"}, - {file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:375b8dd15a1f5d2feafff536d47e22f69625c1aa92f12b339ec0b2ca40263273"}, - {file = "pillow-11.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:daffdf51ee5db69a82dd127eabecce20729e21f7a3680cf7cbb23f0829189790"}, - {file = "pillow-11.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7326a1787e3c7b0429659e0a944725e1b03eeaa10edd945a86dead1913383944"}, - {file = "pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739"}, +groups = ["main"] +files = [ + {file = "pillow-11.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:e1abe69aca89514737465752b4bcaf8016de61b3be1397a8fc260ba33321b3a8"}, + {file = "pillow-11.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c640e5a06869c75994624551f45e5506e4256562ead981cce820d5ab39ae2192"}, + {file = "pillow-11.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a07dba04c5e22824816b2615ad7a7484432d7f540e6fa86af60d2de57b0fcee2"}, + {file = "pillow-11.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e267b0ed063341f3e60acd25c05200df4193e15a4a5807075cd71225a2386e26"}, + {file = "pillow-11.1.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:bd165131fd51697e22421d0e467997ad31621b74bfc0b75956608cb2906dda07"}, + {file = "pillow-11.1.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:abc56501c3fd148d60659aae0af6ddc149660469082859fa7b066a298bde9482"}, + {file = "pillow-11.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:54ce1c9a16a9561b6d6d8cb30089ab1e5eb66918cb47d457bd996ef34182922e"}, + {file = "pillow-11.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:73ddde795ee9b06257dac5ad42fcb07f3b9b813f8c1f7f870f402f4dc54b5269"}, + {file = "pillow-11.1.0-cp310-cp310-win32.whl", hash = "sha256:3a5fe20a7b66e8135d7fd617b13272626a28278d0e578c98720d9ba4b2439d49"}, + {file = "pillow-11.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:b6123aa4a59d75f06e9dd3dac5bf8bc9aa383121bb3dd9a7a612e05eabc9961a"}, + {file = "pillow-11.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:a76da0a31da6fcae4210aa94fd779c65c75786bc9af06289cd1c184451ef7a65"}, + {file = "pillow-11.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:e06695e0326d05b06833b40b7ef477e475d0b1ba3a6d27da1bb48c23209bf457"}, + {file = "pillow-11.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96f82000e12f23e4f29346e42702b6ed9a2f2fea34a740dd5ffffcc8c539eb35"}, + {file = "pillow-11.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3cd561ded2cf2bbae44d4605837221b987c216cff94f49dfeed63488bb228d2"}, + {file = "pillow-11.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f189805c8be5ca5add39e6f899e6ce2ed824e65fb45f3c28cb2841911da19070"}, + {file = "pillow-11.1.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:dd0052e9db3474df30433f83a71b9b23bd9e4ef1de13d92df21a52c0303b8ab6"}, + {file = "pillow-11.1.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:837060a8599b8f5d402e97197d4924f05a2e0d68756998345c829c33186217b1"}, + {file = "pillow-11.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:aa8dd43daa836b9a8128dbe7d923423e5ad86f50a7a14dc688194b7be5c0dea2"}, + {file = "pillow-11.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0a2f91f8a8b367e7a57c6e91cd25af510168091fb89ec5146003e424e1558a96"}, + {file = "pillow-11.1.0-cp311-cp311-win32.whl", hash = "sha256:c12fc111ef090845de2bb15009372175d76ac99969bdf31e2ce9b42e4b8cd88f"}, + {file = "pillow-11.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:fbd43429d0d7ed6533b25fc993861b8fd512c42d04514a0dd6337fb3ccf22761"}, + {file = "pillow-11.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:f7955ecf5609dee9442cbface754f2c6e541d9e6eda87fad7f7a989b0bdb9d71"}, + {file = "pillow-11.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2062ffb1d36544d42fcaa277b069c88b01bb7298f4efa06731a7fd6cc290b81a"}, + {file = "pillow-11.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a85b653980faad27e88b141348707ceeef8a1186f75ecc600c395dcac19f385b"}, + {file = "pillow-11.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9409c080586d1f683df3f184f20e36fb647f2e0bc3988094d4fd8c9f4eb1b3b3"}, + {file = "pillow-11.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7fdadc077553621911f27ce206ffcbec7d3f8d7b50e0da39f10997e8e2bb7f6a"}, + {file = "pillow-11.1.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:93a18841d09bcdd774dcdc308e4537e1f867b3dec059c131fde0327899734aa1"}, + {file = "pillow-11.1.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:9aa9aeddeed452b2f616ff5507459e7bab436916ccb10961c4a382cd3e03f47f"}, + {file = "pillow-11.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3cdcdb0b896e981678eee140d882b70092dac83ac1cdf6b3a60e2216a73f2b91"}, + {file = "pillow-11.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:36ba10b9cb413e7c7dfa3e189aba252deee0602c86c309799da5a74009ac7a1c"}, + {file = "pillow-11.1.0-cp312-cp312-win32.whl", hash = "sha256:cfd5cd998c2e36a862d0e27b2df63237e67273f2fc78f47445b14e73a810e7e6"}, + {file = "pillow-11.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a697cd8ba0383bba3d2d3ada02b34ed268cb548b369943cd349007730c92bddf"}, + {file = "pillow-11.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:4dd43a78897793f60766563969442020e90eb7847463eca901e41ba186a7d4a5"}, + {file = "pillow-11.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ae98e14432d458fc3de11a77ccb3ae65ddce70f730e7c76140653048c71bfcbc"}, + {file = "pillow-11.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cc1331b6d5a6e144aeb5e626f4375f5b7ae9934ba620c0ac6b3e43d5e683a0f0"}, + {file = "pillow-11.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:758e9d4ef15d3560214cddbc97b8ef3ef86ce04d62ddac17ad39ba87e89bd3b1"}, + {file = "pillow-11.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b523466b1a31d0dcef7c5be1f20b942919b62fd6e9a9be199d035509cbefc0ec"}, + {file = "pillow-11.1.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:9044b5e4f7083f209c4e35aa5dd54b1dd5b112b108648f5c902ad586d4f945c5"}, + {file = "pillow-11.1.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:3764d53e09cdedd91bee65c2527815d315c6b90d7b8b79759cc48d7bf5d4f114"}, + {file = "pillow-11.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:31eba6bbdd27dde97b0174ddf0297d7a9c3a507a8a1480e1e60ef914fe23d352"}, + {file = "pillow-11.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b5d658fbd9f0d6eea113aea286b21d3cd4d3fd978157cbf2447a6035916506d3"}, + {file = "pillow-11.1.0-cp313-cp313-win32.whl", hash = "sha256:f86d3a7a9af5d826744fabf4afd15b9dfef44fe69a98541f666f66fbb8d3fef9"}, + {file = "pillow-11.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:593c5fd6be85da83656b93ffcccc2312d2d149d251e98588b14fbc288fd8909c"}, + {file = "pillow-11.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:11633d58b6ee5733bde153a8dafd25e505ea3d32e261accd388827ee987baf65"}, + {file = "pillow-11.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70ca5ef3b3b1c4a0812b5c63c57c23b63e53bc38e758b37a951e5bc466449861"}, + {file = "pillow-11.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8000376f139d4d38d6851eb149b321a52bb8893a88dae8ee7d95840431977081"}, + {file = "pillow-11.1.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ee85f0696a17dd28fbcfceb59f9510aa71934b483d1f5601d1030c3c8304f3c"}, + {file = "pillow-11.1.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:dd0e081319328928531df7a0e63621caf67652c8464303fd102141b785ef9547"}, + {file = "pillow-11.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e63e4e5081de46517099dc30abe418122f54531a6ae2ebc8680bcd7096860eab"}, + {file = "pillow-11.1.0-cp313-cp313t-win32.whl", hash = "sha256:dda60aa465b861324e65a78c9f5cf0f4bc713e4309f83bc387be158b077963d9"}, + {file = "pillow-11.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ad5db5781c774ab9a9b2c4302bbf0c1014960a0a7be63278d13ae6fdf88126fe"}, + {file = "pillow-11.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:67cd427c68926108778a9005f2a04adbd5e67c442ed21d95389fe1d595458756"}, + {file = "pillow-11.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:bf902d7413c82a1bfa08b06a070876132a5ae6b2388e2712aab3a7cbc02205c6"}, + {file = "pillow-11.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c1eec9d950b6fe688edee07138993e54ee4ae634c51443cfb7c1e7613322718e"}, + {file = "pillow-11.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e275ee4cb11c262bd108ab2081f750db2a1c0b8c12c1897f27b160c8bd57bbc"}, + {file = "pillow-11.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4db853948ce4e718f2fc775b75c37ba2efb6aaea41a1a5fc57f0af59eee774b2"}, + {file = "pillow-11.1.0-cp39-cp39-manylinux_2_28_aarch64.whl", hash = "sha256:ab8a209b8485d3db694fa97a896d96dd6533d63c22829043fd9de627060beade"}, + {file = "pillow-11.1.0-cp39-cp39-manylinux_2_28_x86_64.whl", hash = "sha256:54251ef02a2309b5eec99d151ebf5c9904b77976c8abdcbce7891ed22df53884"}, + {file = "pillow-11.1.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:5bb94705aea800051a743aa4874bb1397d4695fb0583ba5e425ee0328757f196"}, + {file = "pillow-11.1.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:89dbdb3e6e9594d512780a5a1c42801879628b38e3efc7038094430844e271d8"}, + {file = "pillow-11.1.0-cp39-cp39-win32.whl", hash = "sha256:e5449ca63da169a2e6068dd0e2fcc8d91f9558aba89ff6d02121ca8ab11e79e5"}, + {file = "pillow-11.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:3362c6ca227e65c54bf71a5f88b3d4565ff1bcbc63ae72c34b07bbb1cc59a43f"}, + {file = "pillow-11.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:b20be51b37a75cc54c2c55def3fa2c65bb94ba859dde241cd0a4fd302de5ae0a"}, + {file = "pillow-11.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:8c730dc3a83e5ac137fbc92dfcfe1511ce3b2b5d7578315b63dbbb76f7f51d90"}, + {file = "pillow-11.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:7d33d2fae0e8b170b6a6c57400e077412240f6f5bb2a342cf1ee512a787942bb"}, + {file = "pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a8d65b38173085f24bc07f8b6c505cbb7418009fa1a1fcb111b1f4961814a442"}, + {file = "pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:015c6e863faa4779251436db398ae75051469f7c903b043a48f078e437656f83"}, + {file = "pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d44ff19eea13ae4acdaaab0179fa68c0c6f2f45d66a4d8ec1eda7d6cecbcc15f"}, + {file = "pillow-11.1.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:d3d8da4a631471dfaf94c10c85f5277b1f8e42ac42bade1ac67da4b4a7359b73"}, + {file = "pillow-11.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:4637b88343166249fe8aa94e7c4a62a180c4b3898283bb5d3d2fd5fe10d8e4e0"}, + {file = "pillow-11.1.0.tar.gz", hash = "sha256:368da70808b36d73b4b390a8ffac11069f8a5c85f29eff1f1b01bcf3ef5b2a20"}, ] [package.extras] docs = ["furo", "olefile", "sphinx (>=8.1)", "sphinx-copybutton", "sphinx-inline-tabs", "sphinxext-opengraph"] fpx = ["olefile"] mic = ["olefile"] -tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout"] +tests = ["check-manifest", "coverage (>=7.4.2)", "defusedxml", "markdown2", "olefile", "packaging", "pyroma", "pytest", "pytest-cov", "pytest-timeout", "trove-classifiers (>=2024.10.12)"] typing = ["typing-extensions"] xmp = ["defusedxml"] @@ -1874,6 +1940,7 @@ version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -1890,6 +1957,7 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -1905,6 +1973,7 @@ version = "3.11" description = "Python Lex & Yacc" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "ply-3.11-py2.py3-none-any.whl", hash = "sha256:096f9b8350b65ebd2fd1346b12452efe5b9607f7482813ffca50c22722a807ce"}, {file = "ply-3.11.tar.gz", hash = "sha256:00c7c1aaa88358b9c765b6d3000c6eec0ba42abca5351b095321aef446081da3"}, @@ -1916,6 +1985,7 @@ version = "2.10.1" description = "Wraps the portalocker recipe for easy usage" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "portalocker-2.10.1-py3-none-any.whl", hash = "sha256:53a5984ebc86a025552264b459b46a2086e269b21823cb572f8f28ee759e45bf"}, {file = "portalocker-2.10.1.tar.gz", hash = "sha256:ef1bf844e878ab08aee7e40184156e1151f228f103aa5c6bd0724cc330960f8f"}, @@ -1931,13 +2001,14 @@ tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "p [[package]] name = "pre-commit" -version = "3.8.0" +version = "4.0.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pre_commit-3.8.0-py2.py3-none-any.whl", hash = "sha256:9a90a53bf82fdd8778d58085faf8d83df56e40dfe18f45b19446e26bf1b3a63f"}, - {file = "pre_commit-3.8.0.tar.gz", hash = "sha256:8bb6494d4a20423842e198980c9ecf9f96607a07ea29549e180eef9ae80fe7af"}, + {file = "pre_commit-4.0.1-py2.py3-none-any.whl", hash = "sha256:efde913840816312445dc98787724647c65473daefe420785f885e8ed9a06878"}, + {file = "pre_commit-4.0.1.tar.gz", hash = "sha256:80905ac375958c0444c65e9cebebd948b3cdb518f335a091a670a89d652139d2"}, ] [package.dependencies] @@ -1953,6 +2024,7 @@ version = "2.0.10" description = "Library for building powerful interactive command lines in Python" optional = false python-versions = ">=2.6,<3.0.dev0 || >=3.3.dev0" +groups = ["main"] files = [ {file = "prompt_toolkit-2.0.10-py2-none-any.whl", hash = "sha256:e7f8af9e3d70f514373bf41aa51bc33af12a6db3f71461ea47fea985defb2c31"}, {file = "prompt_toolkit-2.0.10-py3-none-any.whl", hash = "sha256:46642344ce457641f28fc9d1c9ca939b63dadf8df128b86f1b9860e59c73a5e4"}, @@ -1969,6 +2041,7 @@ version = "0.2.1" description = "Accelerated property cache" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {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"}, @@ -2060,6 +2133,7 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -2067,18 +2141,19 @@ files = [ [[package]] name = "pydantic" -version = "2.10.3" +version = "2.10.5" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "pydantic-2.10.3-py3-none-any.whl", hash = "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d"}, - {file = "pydantic-2.10.3.tar.gz", hash = "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"}, + {file = "pydantic-2.10.5-py3-none-any.whl", hash = "sha256:4dd4e322dbe55472cb7ca7e73f4b63574eecccf2835ffa2af9021ce113c83c53"}, + {file = "pydantic-2.10.5.tar.gz", hash = "sha256:278b38dbbaec562011d659ee05f63346951b3a248a6f3642e1bc68894ea2b4ff"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.27.1" +pydantic-core = "2.27.2" typing-extensions = ">=4.12.2" [package.extras] @@ -2087,111 +2162,112 @@ timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.27.1" +version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" -files = [ - {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"}, +groups = ["main"] +files = [ + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, + {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, ] [package.dependencies] @@ -2199,32 +2275,60 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydevd" -version = "1.5.1" +version = "3.2.3" description = "PyDev.Debugger (used in PyDev, PyCharm and VSCode Python)" optional = false python-versions = "*" -files = [ - {file = "pydevd-1.5.1-cp27-cp27m-win32.whl", hash = "sha256:9598dae25ea4e63077cf486329fd3822199b24bd39938870085c4b77e02d89ee"}, - {file = "pydevd-1.5.1-cp27-cp27m-win_amd64.whl", hash = "sha256:98807fecfed90f19bff3abe7341bebbf084970da36161c74409401c2d583e187"}, - {file = "pydevd-1.5.1-cp34-cp34m-win32.whl", hash = "sha256:aae284bf83110bc7650b84860bdd4997bf731468fa9a87737ba688b3ca49ddf7"}, - {file = "pydevd-1.5.1-cp34-cp34m-win_amd64.whl", hash = "sha256:f787d4a143a138944e34429d3928d713fe5688d54762d771d0581055a4b4b670"}, - {file = "pydevd-1.5.1-cp35-cp35m-win32.whl", hash = "sha256:8dfdcc2b811256e10320f4c8daf0181d7f775fce6bca02198b86ff046016e44f"}, - {file = "pydevd-1.5.1-cp35-cp35m-win_amd64.whl", hash = "sha256:c23b5dd0123d7341412ff3c20a978009bdfa0aa7d42cc6a6be3bdb1efcc2a651"}, - {file = "pydevd-1.5.1-cp36-cp36m-win32.whl", hash = "sha256:80f142eaedd6e5783e1ee658e4716b75d8eaced1358d5f63272c208a2d8de40a"}, - {file = "pydevd-1.5.1-cp36-cp36m-win_amd64.whl", hash = "sha256:be03afbc9bfb696dfce6317ad358d3971a3ba2dbd6486fbf1c3f2aaa0b95d13f"}, - {file = "pydevd-1.5.1-cp37-cp37m-win32.whl", hash = "sha256:eb3db3d4f279cf0447a3c0e617841a4a8d1c65051d049c49c11daa225bad3701"}, - {file = "pydevd-1.5.1-cp37-cp37m-win_amd64.whl", hash = "sha256:eee943317d92dda45494698af3e9aa8133646a1e19ab6e151cc21e04592ea3a4"}, - {file = "pydevd-1.5.1.tar.gz", hash = "sha256:4310c0b1ba39b415335e92d2986eff4273904427634d5e5b38e59c63a93bffd7"}, +groups = ["dev"] +files = [ + {file = "pydevd-3.2.3-cp310-cp310-macosx_14_0_universal2.whl", hash = "sha256:49ab46adb65e7816db387a836e6d761b2d091489f43376770942b048bf470568"}, + {file = "pydevd-3.2.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:541093ec04b4e2733003f508959014e20d9825eac68aa3b78337f1e16c0cefc9"}, + {file = "pydevd-3.2.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b93cf2ef02c26540a65b6b06d7630f5059278aab06156fb54d17b44a873605bb"}, + {file = "pydevd-3.2.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:7c048d5dd4956dfb97c37b9720723ab92bd414e5beb8246d6248c8ec1da8465d"}, + {file = "pydevd-3.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7e1ae249a5fe7457c8e46a40156303646e1150c68e70beffa42211abb853ce8a"}, + {file = "pydevd-3.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:520c0308d65585e8ea66091d0a7a1a1dfdfc22462c370f83f659797c19af5e64"}, + {file = "pydevd-3.2.3-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:7e564123669ea71f6c145f69f3e5dc42bc879125dd4446e3d2ec8414ff00c417"}, + {file = "pydevd-3.2.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ccbf10e2ced035b35cf91457fefb1c9d323a8e81695bec3e0eb769940fd19c7"}, + {file = "pydevd-3.2.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9b4859ece94e950d577e293935ce44dbf85df067a4c9f7f3b3f0144479f70a0"}, + {file = "pydevd-3.2.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:eede0158b0b0527fa149a733ecbe3a947e3505b603f8935edc4981d3184e07f8"}, + {file = "pydevd-3.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f1faf1dacde1a7057da7347a8ae00ce9db20cf70bb87fa38f1fa951424e10b31"}, + {file = "pydevd-3.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:824b389e38192143c84cc7f9aedb62712f0f4a4a839c8561d88462c2b1606417"}, + {file = "pydevd-3.2.3-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:07f78aec74b0b579dbfb404c89908c36f5f6f78f759f5e86fb2d7afbdeb5dd2c"}, + {file = "pydevd-3.2.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7836088dc66117607e776c4ec74793f129e823eae83a3f92ec2f129dc4ad0d70"}, + {file = "pydevd-3.2.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8bb6115db22af8c4b416b119f230222eabfa2913971de7a1e8a31003e09366a5"}, + {file = "pydevd-3.2.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a3824bf0014ced5c9449564740916073320995347ea78265c2b398e8b5ad96b0"}, + {file = "pydevd-3.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f6edf3145ff45edfd08a24f6784021b38db782be150ea39f74830242845d66d4"}, + {file = "pydevd-3.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:798f2bb77c28ba7828bcd1d08cc3ce7ba5a038397b9fc96ea66d8edf4f806577"}, + {file = "pydevd-3.2.3-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:bb7493e091ca12cffed93f16723701d12790c29000c9ec9a1f9aa6823ac964e2"}, + {file = "pydevd-3.2.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8950c70e61ff2e3305d4b6fa0442eb7bc9714d6c9abbb365fb0bba872631cc84"}, + {file = "pydevd-3.2.3-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc0fb536f71352814c7ab34a4cf4683c509d7a462f70b3b630b85b82ba9210d6"}, + {file = "pydevd-3.2.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:84ae4c25d600a328e7a2ca2e5e0246bd61137698e39bd285cfcb9fb0c35223d3"}, + {file = "pydevd-3.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:96d3cd3eaa601aa74dada5134e7679f678b25b8645cc3c182cbb253cc43d3b90"}, + {file = "pydevd-3.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:98400c90e39468f49d27426bf85a7549b432ca893ec8f9b67bca9f1952408a05"}, + {file = "pydevd-3.2.3-cp38-cp38-macosx_14_0_universal2.whl", hash = "sha256:fdea5d87436d6788edec901af84623e080861fe89f366d2d989a293ed2c7d569"}, + {file = "pydevd-3.2.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9513697241b6700e149270eba07ca5f7acef57cfd01fe8422596db3516d3441b"}, + {file = "pydevd-3.2.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c61db6f7286a5ceba661a557a51d76fa90cd224cd958c8a740ee001bc71cc51b"}, + {file = "pydevd-3.2.3-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:8527e6691e5abf14a7f789f22dddd150e7bd32eecc79c2b2a2871dfa7469bc9d"}, + {file = "pydevd-3.2.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:8bd64d485dbed999ebf1747c7fc0507519eca1ac14aa348b34e4dd81b4f98fa4"}, + {file = "pydevd-3.2.3-cp38-cp38-win_amd64.whl", hash = "sha256:ddbd6d237f515b97ad4a14ea811ffe66f17103054309c0618332c75098880659"}, + {file = "pydevd-3.2.3-cp39-cp39-macosx_14_0_universal2.whl", hash = "sha256:8f0497bd4a40c06117fabb7a0f21c181940a8622ccc4c4a4880bbe329ee285ba"}, + {file = "pydevd-3.2.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa19f2bb245c87cd96b767135f888dc68cf0defb19d769c20190d401a5c05cb5"}, + {file = "pydevd-3.2.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eadb278d173876644751079777efb13606be9d9b7f154c13338883c1be2e7182"}, + {file = "pydevd-3.2.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c00df573cca0e87a19995fc277693dd76cae969db8a2ec9e9077d5fe86837645"}, + {file = "pydevd-3.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:d65d02e39fd1fd4a2303d309eba379f49ac16470f83b7a92385d6be0b415e796"}, + {file = "pydevd-3.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:f65fcf9cc4faeac445c9c52948efbe2fafe45a9d800fb28e01f8f05958e5c0e2"}, + {file = "pydevd-3.2.3.tar.gz", hash = "sha256:54adc689a6bfb3508472b3517ee3e763da2774d6c554b8628ff208183d4c96a2"}, ] [[package]] name = "pydevd-pycharm" -version = "193.7288.30" +version = "243.23654.74" description = "PyCharm Debugger (used in PyCharm and PyDev)" optional = false python-versions = "*" +groups = ["dev"] files = [ - {file = "pydevd-pycharm-193.7288.30.tar.gz", hash = "sha256:159c5d4ec7bb285acd9b600c7056ff6515c92fda5ae704d370be827e423018af"}, + {file = "pydevd_pycharm-243.23654.74.tar.gz", hash = "sha256:1a988533ddd617da8d3dd032c49e0234860abab04fa589a92fd2b14e4092b591"}, ] [[package]] @@ -2233,6 +2337,7 @@ version = "0.5.1" description = "Python library for validating, constructing, and representing DIDs and DID Documents" optional = false python-versions = "<4.0.0,>=3.9.0" +groups = ["main"] files = [ {file = "pydid-0.5.1-py3-none-any.whl", hash = "sha256:be89df79b6267ec1814d49cdd240262c8bbddbfcee9e3aad97a97d521620d6c4"}, {file = "pydid-0.5.1.tar.gz", hash = "sha256:9489a5fbfbecc8dc864c461bb5a0c664895726ab3ca83daf389d91a10146d5e2"}, @@ -2245,13 +2350,14 @@ typing-extensions = ">=4.7.0,<5.0.0" [[package]] name = "pygments" -version = "2.18.0" +version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, - {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, + {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, + {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, ] [package.extras] @@ -2263,6 +2369,7 @@ version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, @@ -2280,6 +2387,7 @@ version = "2.0.4" description = "Python implementation of the JSON-LD API" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "PyLD-2.0.4-py3-none-any.whl", hash = "sha256:6dab9905644616df33f8755489fc9b354ed7d832d387b7d1974b4fbd3b8d2a89"}, {file = "PyLD-2.0.4.tar.gz", hash = "sha256:311e350f0dbc964311c79c28e86f84e195a81d06fef5a6f6ac2a4f6391ceeacc"}, @@ -2302,6 +2410,7 @@ version = "1.5.0" description = "Python binding to the Networking and Cryptography (NaCl) library" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, @@ -2328,6 +2437,7 @@ version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, @@ -2344,13 +2454,14 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments [[package]] name = "pytest-asyncio" -version = "0.25.0" +version = "0.25.2" description = "Pytest support for asyncio" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pytest_asyncio-0.25.0-py3-none-any.whl", hash = "sha256:db5432d18eac6b7e28b46dcd9b69921b55c3b1086e85febfe04e70b18d9e81b3"}, - {file = "pytest_asyncio-0.25.0.tar.gz", hash = "sha256:8c0610303c9e0442a5db8604505fc0f545456ba1528824842b37b4a626cbf609"}, + {file = "pytest_asyncio-0.25.2-py3-none-any.whl", hash = "sha256:0d0bb693f7b99da304a0634afc0a4b19e49d5e0de2d670f38dc4bfa5727c5075"}, + {file = "pytest_asyncio-0.25.2.tar.gz", hash = "sha256:3f8ef9a98f45948ea91a0ed3dc4268b5326c0e7bce73892acc654df4262ad45f"}, ] [package.dependencies] @@ -2362,17 +2473,18 @@ testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"] [[package]] name = "pytest-cov" -version = "5.0.0" +version = "6.0.0" description = "Pytest plugin for measuring coverage." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["dev"] files = [ - {file = "pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857"}, - {file = "pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652"}, + {file = "pytest-cov-6.0.0.tar.gz", hash = "sha256:fde0b595ca248bb8e2d76f020b465f3b107c9632e6a1d1705f17834c89dcadc0"}, + {file = "pytest_cov-6.0.0-py3-none-any.whl", hash = "sha256:eee6f1b9e61008bd34975a4d5bab25801eb31898b032dd55addc93e96fcaaa35"}, ] [package.dependencies] -coverage = {version = ">=5.2.1", extras = ["toml"]} +coverage = {version = ">=7.5", extras = ["toml"]} pytest = ">=4.6" [package.extras] @@ -2384,6 +2496,7 @@ version = "0.4.1" description = "pytest plugin to check ruff requirements." optional = false python-versions = "<4.0,>=3.8" +groups = ["dev"] files = [ {file = "pytest_ruff-0.4.1-py3-none-any.whl", hash = "sha256:69acd5b2ba68d65998c730b5b4d656788193190e45f61a53aa66ef8b390634a4"}, {file = "pytest_ruff-0.4.1.tar.gz", hash = "sha256:2c9a30f15f384c229c881b52ec86cfaf1e79d39530dd7dd5f2d6aebe278f7eb7"}, @@ -2399,6 +2512,7 @@ version = "3.6.1" description = "pytest xdist plugin for distributed testing, most importantly across multiple CPUs" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ {file = "pytest_xdist-3.6.1-py3-none-any.whl", hash = "sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7"}, {file = "pytest_xdist-3.6.1.tar.gz", hash = "sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"}, @@ -2419,6 +2533,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -2433,6 +2548,7 @@ version = "2.0.7" description = "A python library adding a json log formatter" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "python-json-logger-2.0.7.tar.gz", hash = "sha256:23e7ec02d34237c5aa1e29a070193a4ea87583bb4e7f8fd06d3de8264c4b2e1c"}, {file = "python_json_logger-2.0.7-py3-none-any.whl", hash = "sha256:f380b826a991ebbe3de4d897aeec42760035ac760345e57b812938dc8b35e2bd"}, @@ -2444,6 +2560,8 @@ version = "308" description = "Python for Window Extensions" optional = false python-versions = "*" +groups = ["main"] +markers = "platform_system == \"Windows\"" files = [ {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, @@ -2471,6 +2589,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -2533,6 +2652,7 @@ version = "6.1" description = "QR Code image generator" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "qrcode-6.1-py2.py3-none-any.whl", hash = "sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5"}, {file = "qrcode-6.1.tar.gz", hash = "sha256:505253854f607f2abf4d16092c61d4e9d511a3b4392e60bff957a68592b04369"}, @@ -2555,6 +2675,7 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main", "dev"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -2576,6 +2697,7 @@ version = "4.0.1" description = "rlp: A package for Recursive Length Prefix encoding and decoding" optional = false python-versions = "<4,>=3.8" +groups = ["main"] files = [ {file = "rlp-4.0.1-py3-none-any.whl", hash = "sha256:ff6846c3c27b97ee0492373aa074a7c3046aadd973320f4fffa7ac45564b0258"}, {file = "rlp-4.0.1.tar.gz", hash = "sha256:bcefb11013dfadf8902642337923bd0c786dc8a27cb4c21da6e154e52869ecb1"}, @@ -2592,29 +2714,30 @@ test = ["hypothesis (==5.19.0)", "pytest (>=7.0.0)", "pytest-xdist (>=2.4.0)"] [[package]] name = "ruff" -version = "0.8.3" +version = "0.9.2" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" -files = [ - {file = "ruff-0.8.3-py3-none-linux_armv6l.whl", hash = "sha256:8d5d273ffffff0acd3db5bf626d4b131aa5a5ada1276126231c4174543ce20d6"}, - {file = "ruff-0.8.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e4d66a21de39f15c9757d00c50c8cdd20ac84f55684ca56def7891a025d7e939"}, - {file = "ruff-0.8.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c356e770811858bd20832af696ff6c7e884701115094f427b64b25093d6d932d"}, - {file = "ruff-0.8.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c0a60a825e3e177116c84009d5ebaa90cf40dfab56e1358d1df4e29a9a14b13"}, - {file = "ruff-0.8.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:75fb782f4db39501210ac093c79c3de581d306624575eddd7e4e13747e61ba18"}, - {file = "ruff-0.8.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f26bc76a133ecb09a38b7868737eded6941b70a6d34ef53a4027e83913b6502"}, - {file = "ruff-0.8.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:01b14b2f72a37390c1b13477c1c02d53184f728be2f3ffc3ace5b44e9e87b90d"}, - {file = "ruff-0.8.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53babd6e63e31f4e96ec95ea0d962298f9f0d9cc5990a1bbb023a6baf2503a82"}, - {file = "ruff-0.8.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1ae441ce4cf925b7f363d33cd6570c51435972d697e3e58928973994e56e1452"}, - {file = "ruff-0.8.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7c65bc0cadce32255e93c57d57ecc2cca23149edd52714c0c5d6fa11ec328cd"}, - {file = "ruff-0.8.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5be450bb18f23f0edc5a4e5585c17a56ba88920d598f04a06bd9fd76d324cb20"}, - {file = "ruff-0.8.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8faeae3827eaa77f5721f09b9472a18c749139c891dbc17f45e72d8f2ca1f8fc"}, - {file = "ruff-0.8.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:db503486e1cf074b9808403991663e4277f5c664d3fe237ee0d994d1305bb060"}, - {file = "ruff-0.8.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:6567be9fb62fbd7a099209257fef4ad2c3153b60579818b31a23c886ed4147ea"}, - {file = "ruff-0.8.3-py3-none-win32.whl", hash = "sha256:19048f2f878f3ee4583fc6cb23fb636e48c2635e30fb2022b3a1cd293402f964"}, - {file = "ruff-0.8.3-py3-none-win_amd64.whl", hash = "sha256:f7df94f57d7418fa7c3ffb650757e0c2b96cf2501a0b192c18e4fb5571dfada9"}, - {file = "ruff-0.8.3-py3-none-win_arm64.whl", hash = "sha256:fe2756edf68ea79707c8d68b78ca9a58ed9af22e430430491ee03e718b5e4936"}, - {file = "ruff-0.8.3.tar.gz", hash = "sha256:5e7558304353b84279042fc584a4f4cb8a07ae79b2bf3da1a7551d960b5626d3"}, +groups = ["dev"] +files = [ + {file = "ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347"}, + {file = "ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00"}, + {file = "ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4"}, + {file = "ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d"}, + {file = "ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c"}, + {file = "ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f"}, + {file = "ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684"}, + {file = "ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d"}, + {file = "ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df"}, + {file = "ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247"}, + {file = "ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e"}, + {file = "ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe"}, + {file = "ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb"}, + {file = "ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a"}, + {file = "ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145"}, + {file = "ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5"}, + {file = "ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6"}, + {file = "ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0"}, ] [[package]] @@ -2623,6 +2746,7 @@ version = "0.10.4" description = "The reference implementation of the IETF SD-JWT specification." optional = false python-versions = ">=3.8,<4.0" +groups = ["main"] files = [ {file = "sd_jwt-0.10.4-py3-none-any.whl", hash = "sha256:d7ae669eb5d51bceeb38e0df8ab2faddd12e3b21ab64d831b6d048fc1e00ce75"}, {file = "sd_jwt-0.10.4.tar.gz", hash = "sha256:82f93e2f570cfd31fab124e301febb81f3bcad70b10e38f5f9cff70ad659c2ce"}, @@ -2634,13 +2758,14 @@ 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" +groups = ["main"] 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]] @@ -2649,6 +2774,7 @@ version = "2.2.0" description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." optional = false python-versions = "*" +groups = ["dev"] files = [ {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, @@ -2656,56 +2782,58 @@ files = [ [[package]] name = "sphinx" -version = "5.3.0" +version = "8.1.3" description = "Python documentation generator" optional = false -python-versions = ">=3.6" +python-versions = ">=3.10" +groups = ["dev"] files = [ - {file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"}, - {file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"}, + {file = "sphinx-8.1.3-py3-none-any.whl", hash = "sha256:09719015511837b76bf6e03e42eb7595ac8c2e41eeb9c29c5b755c6b677992a2"}, + {file = "sphinx-8.1.3.tar.gz", hash = "sha256:43c1911eecb0d3e161ad78611bc905d1ad0e523e4ddc202a58a821773dc4c927"}, ] [package.dependencies] -alabaster = ">=0.7,<0.8" -babel = ">=2.9" -colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} -docutils = ">=0.14,<0.20" +alabaster = ">=0.7.14" +babel = ">=2.13" +colorama = {version = ">=0.4.6", markers = "sys_platform == \"win32\""} +docutils = ">=0.20,<0.22" imagesize = ">=1.3" -Jinja2 = ">=3.0" -packaging = ">=21.0" -Pygments = ">=2.12" -requests = ">=2.5.0" -snowballstemmer = ">=2.0" -sphinxcontrib-applehelp = "*" -sphinxcontrib-devhelp = "*" -sphinxcontrib-htmlhelp = ">=2.0.0" -sphinxcontrib-jsmath = "*" -sphinxcontrib-qthelp = "*" -sphinxcontrib-serializinghtml = ">=1.1.5" +Jinja2 = ">=3.1" +packaging = ">=23.0" +Pygments = ">=2.17" +requests = ">=2.30.0" +snowballstemmer = ">=2.2" +sphinxcontrib-applehelp = ">=1.0.7" +sphinxcontrib-devhelp = ">=1.0.6" +sphinxcontrib-htmlhelp = ">=2.0.6" +sphinxcontrib-jsmath = ">=1.0.1" +sphinxcontrib-qthelp = ">=1.0.6" +sphinxcontrib-serializinghtml = ">=1.1.9" [package.extras] docs = ["sphinxcontrib-websupport"] -lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"] -test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] +lint = ["flake8 (>=6.0)", "mypy (==1.11.1)", "pyright (==1.1.384)", "pytest (>=6.0)", "ruff (==0.6.9)", "sphinx-lint (>=0.9)", "tomli (>=2)", "types-Pillow (==10.2.0.20240822)", "types-Pygments (==2.18.0.20240506)", "types-colorama (==0.4.15.20240311)", "types-defusedxml (==0.7.0.20240218)", "types-docutils (==0.21.0.20241005)", "types-requests (==2.32.0.20240914)", "types-urllib3 (==1.26.25.14)"] +test = ["cython (>=3.0)", "defusedxml (>=0.7.1)", "pytest (>=8.0)", "setuptools (>=70.0)", "typing_extensions (>=4.9)"] [[package]] name = "sphinx-rtd-theme" -version = "2.0.0" +version = "3.0.2" description = "Read the Docs theme for Sphinx" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "sphinx_rtd_theme-2.0.0-py2.py3-none-any.whl", hash = "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586"}, - {file = "sphinx_rtd_theme-2.0.0.tar.gz", hash = "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b"}, + {file = "sphinx_rtd_theme-3.0.2-py2.py3-none-any.whl", hash = "sha256:422ccc750c3a3a311de4ae327e82affdaf59eb695ba4936538552f3b00f4ee13"}, + {file = "sphinx_rtd_theme-3.0.2.tar.gz", hash = "sha256:b7457bc25dda723b20b086a670b9953c859eab60a2a03ee8eb2bb23e176e5f85"}, ] [package.dependencies] -docutils = "<0.21" -sphinx = ">=5,<8" +docutils = ">0.18,<0.22" +sphinx = ">=6,<9" sphinxcontrib-jquery = ">=4,<5" [package.extras] -dev = ["bump2version", "sphinxcontrib-httpdomain", "transifex-client", "wheel"] +dev = ["bump2version", "transifex-client", "twine", "wheel"] [[package]] name = "sphinxcontrib-applehelp" @@ -2713,6 +2841,7 @@ version = "2.0.0" description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"}, {file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"}, @@ -2729,6 +2858,7 @@ version = "2.0.0" description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"}, {file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"}, @@ -2745,6 +2875,7 @@ version = "2.1.0" description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"}, {file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"}, @@ -2761,6 +2892,7 @@ version = "4.1" description = "Extension to include jQuery on newer Sphinx releases" optional = false python-versions = ">=2.7" +groups = ["dev"] files = [ {file = "sphinxcontrib-jquery-4.1.tar.gz", hash = "sha256:1620739f04e36a2c779f1a131a2dfd49b2fd07351bf1968ced074365933abc7a"}, {file = "sphinxcontrib_jquery-4.1-py2.py3-none-any.whl", hash = "sha256:f936030d7d0147dd026a4f2b5a57343d233f1fc7b363f68b3d4f1cb0993878ae"}, @@ -2775,6 +2907,7 @@ version = "1.0.1" description = "A sphinx extension which renders display math in HTML via JavaScript" optional = false python-versions = ">=3.5" +groups = ["dev"] files = [ {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, @@ -2789,6 +2922,7 @@ version = "2.0.0" description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"}, {file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"}, @@ -2805,6 +2939,7 @@ version = "2.0.0" description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)" optional = false python-versions = ">=3.9" +groups = ["dev"] files = [ {file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"}, {file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"}, @@ -2821,6 +2956,8 @@ version = "1.0.0" description = "List processing tools and functional utilities" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "implementation_name == \"cpython\" or implementation_name == \"pypy\"" files = [ {file = "toolz-1.0.0-py3-none-any.whl", hash = "sha256:292c8f1c4e7516bf9086f8850935c799a874039c8bcf959d47b600e4c44a6236"}, {file = "toolz-1.0.0.tar.gz", hash = "sha256:2c86e3d9a04798ac556793bced838816296a2f085017664e4995cb40a1047a02"}, @@ -2832,6 +2969,7 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -2843,6 +2981,7 @@ version = "1.2.11.post4" description = "A simple library for runtime type-checking." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "typing_validation-1.2.11.post4-py3-none-any.whl", hash = "sha256:73dd504ddebf5210e80d5f65ba9b30efbd0fa42f266728fda7c4f0ba335c699c"}, {file = "typing_validation-1.2.11.post4.tar.gz", hash = "sha256:7aed04ecfbda07e63b7266f90e5d096f96344f7facfe04bb081b21e4a9781670"}, @@ -2857,6 +2996,7 @@ version = "0.2.0" description = "Unflatten dict to dict with nested dict/arrays" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "unflatten-0.2.0-py2.py3-none-any.whl", hash = "sha256:a0afa7ff22313dcc60ff45110b796ed5b4e908614826e8672a9f76d3a20c1f54"}, {file = "unflatten-0.2.0.tar.gz", hash = "sha256:9710bc558882f697bc36a95a97614be296f07c8f8df1bc2b4ef96c189ce5cf84"}, @@ -2864,13 +3004,14 @@ files = [ [[package]] name = "urllib3" -version = "2.2.3" +version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main", "dev"] files = [ - {file = "urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac"}, - {file = "urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9"}, + {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, + {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, ] [package.extras] @@ -2885,6 +3026,8 @@ version = "1.0.1" description = "" optional = true python-versions = ">=3.6.3" +groups = ["main"] +markers = "extra == \"bbs\"" files = [ {file = "ursa_bbs_signatures-1.0.1-py3-none-macosx_10_9_x86_64.whl", hash = "sha256:245701789df0d6cda09faa6194b590c0ce6513b39d80fe8f1fe2a52b69a4b520"}, {file = "ursa_bbs_signatures-1.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:79f410a1f89855a4149af7adecaa22a5f427640f5d093f53670657394a9f9ef4"}, @@ -2897,6 +3040,7 @@ version = "0.10.0" description = "Drop-in replacement for Python UUID in Rust" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {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"}, @@ -2929,13 +3073,14 @@ files = [ [[package]] name = "virtualenv" -version = "20.28.0" +version = "20.29.1" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.8" +groups = ["dev"] files = [ - {file = "virtualenv-20.28.0-py3-none-any.whl", hash = "sha256:23eae1b4516ecd610481eda647f3a7c09aea295055337331bb4e6892ecce47b0"}, - {file = "virtualenv-20.28.0.tar.gz", hash = "sha256:2c9c3262bb8e7b87ea801d715fae4495e6032450c71d2309be9550e7364049aa"}, + {file = "virtualenv-20.29.1-py3-none-any.whl", hash = "sha256:4e4cb403c0b0da39e13b46b1b2476e505cb0046b25f242bee80f62bf990b2779"}, + {file = "virtualenv-20.29.1.tar.gz", hash = "sha256:b8b8970138d32fb606192cb97f6cd4bb644fa486be9308fb9b63f81091b5dc35"}, ] [package.dependencies] @@ -2953,6 +3098,7 @@ version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -2964,6 +3110,7 @@ version = "8.4.0" description = "Declarative parsing and validation of HTTP request objects, with built-in support for popular web frameworks, including Flask, Django, Bottle, Tornado, Pyramid, Falcon, and aiohttp." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "webargs-8.4.0-py3-none-any.whl", hash = "sha256:22324305fbca6a2c4cce1235280e8b56372fb3211a8dac2ac8ed1948315a6f53"}, {file = "webargs-8.4.0.tar.gz", hash = "sha256:ea99368214a4ce613924be99d71db58c269631e95eff4fa09b7354e52dc006a5"}, @@ -2986,6 +3133,7 @@ version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {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"}, @@ -3081,6 +3229,6 @@ bbs = ["ursa-bbs-signatures"] didcommv2 = ["didcomm-messaging"] [metadata] -lock-version = "2.0" +lock-version = "2.1" python-versions = "^3.12" -content-hash = "0875982ff941354828c286c60d60e5dfc3cd51553751868dd95ac4293ec8b18f" +content-hash = "6746da380149ae13b17400170c5a84a7481fe66bc809ae8edb075eddd1723abb" diff --git a/pyproject.toml b/pyproject.toml index 7cb2cfd39c..5b10c80fc2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "acapy_agent" -version = "1.1.1" +version = "1.2.1" 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.10" +aiohttp = "~3.11.11" aiohttp-apispec-acapy = "~3.0.2" aiohttp-cors = "~0.7.0" apispec = "^6.6.0" @@ -28,7 +28,7 @@ ecdsa = "~0.19.0" jsonpath-ng = "1.7.0" Markdown = "~3.7" markupsafe = "2.1.5" -marshmallow = "~3.23.1" +marshmallow = "~3.25.1" nest_asyncio = "~1.6.0" packaging = "~23.2" portalocker = "~2.10.1" @@ -50,7 +50,7 @@ uuid_utils = "^0.10.0" # did libraries did-peer-2 = "^0.1.2" did-peer-4 = "^0.1.4" -did-tdw = "^0.2.1" +did-webvh = "^0.2.1" # Verifiable Credentials indy-credx = "~1.1.1" @@ -70,21 +70,22 @@ didcomm-messaging = { version = "^0.1.1a0", optional = true } canonicaljson = "^2.0.0" [tool.poetry.group.dev.dependencies] -pre-commit = "~3.8.0" -# Sync with version in .pre-commit-config.yaml -ruff = "0.8.3" +# Sync with version in .pre-commit-config.yaml and .github/workflows/format.yml +ruff = "0.9.2" -sphinx = "^5.3.0" -sphinx-rtd-theme = ">=0.4.3" +pre-commit = "~4.0.1" -pydevd = "1.5.1" +sphinx = "^8.1.3" +sphinx-rtd-theme = "^3.0.2" -pydevd-pycharm = "~193.7288.30" +pydevd = "~3.2.3" + +pydevd-pycharm = "~243.23654.74" # testing pytest = "^8.3.4" -pytest-asyncio = "^0.25.0" -pytest-cov = "^5.0.0" +pytest-asyncio = "^0.25.2" +pytest-cov = "^6.0.0" pytest-ruff = "^0.4.1" pytest-xdist = "^3.6.1" debugpy = "^1.8.11" diff --git a/scenarios/examples/anoncreds_issuance_and_revocation/example.py b/scenarios/examples/anoncreds_issuance_and_revocation/example.py index 05a68c395a..4489435c4c 100644 --- a/scenarios/examples/anoncreds_issuance_and_revocation/example.py +++ b/scenarios/examples/anoncreds_issuance_and_revocation/example.py @@ -4,20 +4,13 @@ """ import asyncio -import json -from dataclasses import dataclass from os import getenv -from secrets import randbelow, token_hex -from typing import Any, Dict, List, Mapping, Optional, Tuple, Type, Union -from uuid import uuid4 +from secrets import token_hex from acapy_controller import Controller -from acapy_controller.controller import Minimal, MinType from acapy_controller.logging import logging_to_stdout from acapy_controller.models import ( CreateWalletResponse, - V20CredExRecordIndy, - V20PresExRecord, V20PresExRecordList, ) from acapy_controller.protocols import ( @@ -27,378 +20,19 @@ params, ) from aiohttp import ClientSession +from examples.util import ( + CredDefResultAnoncreds, + SchemaResultAnoncreds, + anoncreds_issue_credential_v2, + anoncreds_present_proof_v2, + anoncreds_presentation_summary, +) 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: - """Summarize a presentation exchange record.""" - request = presentation.pres_request - return "Summary: " + json.dumps( - { - "state": presentation.state, - "verified": presentation.verified, - "presentation_request": request.model_dump(by_alias=True) - if request - else None, - }, - indent=2, - sort_keys=True, - ) - - -@dataclass -class SchemaResultAnoncreds(Minimal): - """Schema result.""" - - schema_state: dict - - -@dataclass -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.""" issuer_name = "issuer" + token_hex(8) @@ -413,13 +47,15 @@ async def main(): 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: + 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 @@ -468,7 +104,7 @@ async def main(): ) # Issue a credential - issuer_cred_ex, _ = await issue_credential_v2( + issuer_cred_ex, _ = await anoncreds_issue_credential_v2( issuer, holder_anoncreds, issuer_conn_with_anoncreds_holder.connection_id, @@ -478,7 +114,7 @@ async def main(): ) # Present the the credential's attributes - await present_proof_v2( + await anoncreds_present_proof_v2( holder_anoncreds, issuer, holder_anoncreds_conn.connection_id, @@ -513,7 +149,7 @@ async def main(): ) # Issue a credential - issuer_cred_ex, _ = await issue_credential_v2( + issuer_cred_ex, _ = await anoncreds_issue_credential_v2( issuer, holder_indy, issuer_conn_with_indy_holder.connection_id, @@ -523,7 +159,7 @@ async def main(): ) # Present the the credential's attributes - await present_proof_v2( + await anoncreds_present_proof_v2( holder_indy, issuer, holder_indy_conn.connection_id, @@ -538,7 +174,7 @@ async def main(): # Presentation summary for _, pres in enumerate(presentations.results): - print(summary(pres)) + print(anoncreds_presentation_summary(pres)) # Revoke credential await issuer.post( @@ -575,7 +211,7 @@ async def main(): an anoncreds capable wallet (wallet type askar-anoncreds). """ # Presentation for anoncreds capable holder on existing credential - await present_proof_v2( + await anoncreds_present_proof_v2( holder_anoncreds, issuer, holder_anoncreds_conn.connection_id, @@ -584,7 +220,7 @@ async def main(): ) # Presentation for indy capable holder on existing credential - await present_proof_v2( + await anoncreds_present_proof_v2( holder_indy, issuer, holder_indy_conn.connection_id, @@ -620,7 +256,7 @@ async def main(): ) # Issue a new credential to anoncreds holder - issuer_cred_ex, _ = await issue_credential_v2( + issuer_cred_ex, _ = await anoncreds_issue_credential_v2( issuer, holder_anoncreds, issuer_conn_with_anoncreds_holder.connection_id, @@ -629,7 +265,7 @@ async def main(): {"middlename": "Anoncreds"}, ) # Presentation for anoncreds capable holder - await present_proof_v2( + await anoncreds_present_proof_v2( holder_anoncreds, issuer, holder_anoncreds_conn.connection_id, @@ -651,7 +287,7 @@ async def main(): await holder_anoncreds.record(topic="revocation-notification") # Issue a new credential to indy holder - issuer_cred_ex, _ = await issue_credential_v2( + issuer_cred_ex, _ = await anoncreds_issue_credential_v2( issuer, holder_indy, issuer_conn_with_indy_holder.connection_id, @@ -660,7 +296,7 @@ async def main(): {"middlename": "Indy"}, ) # Presentation for indy holder - await present_proof_v2( + await anoncreds_present_proof_v2( holder_indy, issuer, holder_indy_conn.connection_id, diff --git a/scenarios/examples/json_ld/example.py b/scenarios/examples/json_ld/example.py index e1496256fd..7fa8bf3705 100644 --- a/scenarios/examples/json_ld/example.py +++ b/scenarios/examples/json_ld/example.py @@ -83,6 +83,15 @@ async def main(): "/wallet/did/public", params=params(did=public_did.did) ) + p256_alice_did_res = ( + await alice.post( + "/wallet/did/create", + json={"method": "key", "options": {"key_type": "p256"}}, + ) + )["result"] + assert p256_alice_did_res + p256_alice_did = p256_alice_did_res["did"] + bls_alice_did_res = ( await alice.post( "/wallet/did/create", @@ -93,14 +102,22 @@ async def main(): bls_alice_did = bls_alice_did_res["did"] with section("Recipient prepares subject DIDs", character="-"): - bob_did = ( + ed25519_bob_did = ( await bob.post( "/wallet/did/create", json={"method": "key", "options": {"key_type": "ed25519"}}, response=DIDResult, ) ).result - assert bob_did + assert ed25519_bob_did + p256_bob_did_res = ( + await bob.post( + "/wallet/did/create", + json={"method": "key", "options": {"key_type": "p256"}}, + ) + )["result"] + assert p256_bob_did_res + p256_bob_did = p256_bob_did_res["did"] bls_bob_did_res = ( await bob.post( "/wallet/did/create", @@ -112,7 +129,7 @@ async def main(): pause_for_input() - with section("Issue example credential using ED25519 Signature"): + with section("Issue example credential using Public Issuer ED25519 Signature"): issuer_cred_ex, holder_cred_ex = await jsonld_issue_credential( alice, bob, @@ -128,7 +145,7 @@ async def main(): "issuanceDate": str(date.today()), "credentialSubject": { "type": ["PermanentResident"], - "id": bob_did.did, + "id": ed25519_bob_did.did, "givenName": "Bob", "familyName": "Builder", "gender": "Male", @@ -141,7 +158,7 @@ async def main(): pause_for_input() - with section("Present example credential"): + with section("Present example ED25519 credential"): alice_pres_ex, bob_pres_ex = await jsonld_present_proof( alice, bob, @@ -194,7 +211,96 @@ async def main(): pause_for_input() - with section("Issue Credential with quick context"): + with section("Issue example credential using P256 Signature"): + issuer_cred_ex, holder_cred_ex = await jsonld_issue_credential( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + credential={ + "@context": [ + "https://www.w3.org/2018/credentials/v1", + "https://w3id.org/citizenship/v1", + ], + "type": ["VerifiableCredential", "PermanentResident"], + "issuer": p256_alice_did, + "issuanceDate": str(date.today()), + "credentialSubject": { + "type": ["PermanentResident"], + "id": p256_bob_did, + "givenName": "Bob", + "familyName": "Builder", + "gender": "Male", + "birthCountry": "Bahamas", + "birthDate": "1958-07-17", + }, + }, + options={"proofType": "EcdsaSecp256r1Signature2019"}, + ) + + pause_for_input() + + with section("Present example P256 credential"): + alice_pres_ex, bob_pres_ex = await jsonld_present_proof( + alice, + bob, + alice_conn.connection_id, + bob_conn.connection_id, + presentation_definition={ + "input_descriptors": [ + { + "id": "citizenship_input_1", + "name": "EU Driver's License", + "schema": [ + { + "uri": "https://www.w3.org/2018/credentials#VerifiableCredential" # noqa: E501 + }, + { + "uri": "https://w3id.org/citizenship#PermanentResident" # noqa: E501 + }, + ], + "constraints": { + "is_holder": [ + { + "directive": "required", + "field_id": [ + "1f44d55f-f161-4938-a659-f8026467f126" + ], + } + ], + "fields": [ + { + "id": "1f44d55f-f161-4938-a659-f8026467f126", + "path": ["$.credentialSubject.familyName"], + "purpose": "The claim must be from one of the specified issuers", # noqa: E501 + "filter": {"const": "Builder"}, + }, + { + "path": ["$.issuer"], + "purpose": "The claim must be from one of the specified issuers", # noqa: E501 + "filter": {"const": p256_alice_did} + }, + { + "path": ["$.credentialSubject.givenName"], + "purpose": "The claim must be from one of the specified issuers", # noqa: E501 + }, + ], + }, + } + ], + "id": str(uuid4()), + "format": { + "ldp_vp": {"proof_type": ["EcdsaSecp256r1Signature2019"]} + }, + }, + domain="test-degree", + ) + with section("Presentation summary", character="-"): + print(presentation_summary(alice_pres_ex.into(V20PresExRecord))) + + pause_for_input() + + with section("Issue ED25519 Credential with quick context"): issuer_cred_ex, holder_cred_ex = await jsonld_issue_credential( alice, bob, @@ -213,7 +319,7 @@ async def main(): "issuer": "did:sov:" + public_did.did, "issuanceDate": str(date.today()), "credentialSubject": { - "id": bob_did.did, + "id": ed25519_bob_did.did, "dateWon": str(date.today()), }, }, @@ -222,7 +328,7 @@ async def main(): pause_for_input() - with section("Present quick context credential"): + with section("Present ED25519 quick context credential"): alice_pres_ex, bob_pres_ex = await jsonld_present_proof( alice, bob, diff --git a/scenarios/examples/restart_anoncreds_upgrade/docker-compose.yml b/scenarios/examples/restart_anoncreds_upgrade/docker-compose.yml new file mode 100644 index 0000000000..caddadc8be --- /dev/null +++ b/scenarios/examples/restart_anoncreds_upgrade/docker-compose.yml @@ -0,0 +1,208 @@ +services: + wallet-db: + image: postgres:12 + environment: + - POSTGRES_USER=DB_USER + - POSTGRES_PASSWORD=DB_PASSWORD + ports: + - 5433:5432 + healthcheck: + test: ["CMD-SHELL", "pg_isready -U DB_USER"] + interval: 10s + retries: 5 + start_period: 30s + timeout: 10s + + alice: + image: acapy-test + ports: + - "3001:3001" + environment: + RUST_LOG: 'aries-askar::log::target=error' + command: > + start + --label Alice + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://alice:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url http://test.bcovrin.vonx.io/genesis + --wallet-type askar + --wallet-name alice + --wallet-key insecure + --wallet-storage-type "postgres_storage" + --wallet-storage-config "{\"url\":\"wallet-db:5432\",\"max_connections\":5}" + --wallet-storage-creds "{\"account\":\"DB_USER\",\"password\":\"DB_PASSWORD\",\"admin_account\":\"DB_USER\",\"admin_password\":\"DB_PASSWORD\"}" + --auto-provision + --log-level debug + --debug-webhooks + --notify-revocation + --preserve-exchange-records + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + wallet-db: + condition: service_healthy + + bob-askar: + image: acapy-test + ports: + - "3002:3001" + environment: + RUST_LOG: 'aries-askar::log::target=error' + command: > + start + --label bob-askar + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob-askar: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 bob-askar + --wallet-key insecure + --wallet-storage-type "postgres_storage" + --wallet-storage-config "{\"url\":\"wallet-db:5432\",\"max_connections\":5}" + --wallet-storage-creds "{\"account\":\"DB_USER\",\"password\":\"DB_PASSWORD\",\"admin_account\":\"DB_USER\",\"admin_password\":\"DB_PASSWORD\"}" + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + --preserve-exchange-records + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + wallet-db: + condition: service_healthy + + bob-anoncreds: + image: acapy-test + ports: + - "3003:3001" + environment: + RUST_LOG: 'aries-askar::log::target=error' + command: > + start + --label bob-anoncreds + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob-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-anoncreds + --wallet-key insecure + --wallet-storage-type "postgres_storage" + --wallet-storage-config "{\"url\":\"wallet-db:5432\",\"max_connections\":5}" + --wallet-storage-creds "{\"account\":\"DB_USER\",\"password\":\"DB_PASSWORD\",\"admin_account\":\"DB_USER\",\"admin_password\":\"DB_PASSWORD\"}" + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + --preserve-exchange-records + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + wallet-db: + condition: service_healthy + + bob-askar-anon: + image: acapy-test + ports: + - "3004:3001" + environment: + RUST_LOG: 'aries-askar::log::target=error' + command: > + start + --label bob-askar-anon + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://bob-askar-anon: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 bob-askar-anon + --wallet-key insecure + --wallet-storage-type "postgres_storage" + --wallet-storage-config "{\"url\":\"wallet-db:5432\",\"max_connections\":5}" + --wallet-storage-creds "{\"account\":\"DB_USER\",\"password\":\"DB_PASSWORD\",\"admin_account\":\"DB_USER\",\"admin_password\":\"DB_PASSWORD\"}" + --auto-provision + --log-level debug + --debug-webhooks + --monitor-revocation-notification + --preserve-exchange-records + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + wallet-db: + condition: service_healthy + + tails: + image: ghcr.io/bcgov/tails-server:latest + ports: + - 6543:6543 + environment: + - GENESIS_URL=http://test.bcovrin.vonx.io/genesis + command: > + tails-server + --host 0.0.0.0 + --port 6543 + --storage-path /tmp/tails-files + --log-level INFO + + example: + container_name: controller + privileged: true + build: + context: ../.. + environment: + - DOCKER_HOST=unix:///var/run/docker.sock + - ALICE=http://alice:3001 + - BOB_ASKAR=http://bob-askar:3001 + - BOB_ANONCREDS=http://bob-anoncreds:3001 + - BOB_ASKAR_ANON=http://bob-askar-anon:3001 + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ./example.py:/usr/src/app/example.py:ro,z + command: python -m example + depends_on: + alice: + condition: service_healthy + bob-askar: + condition: service_healthy + bob-anoncreds: + condition: service_healthy + bob-askar-anon: + condition: service_healthy diff --git a/scenarios/examples/restart_anoncreds_upgrade/example.py b/scenarios/examples/restart_anoncreds_upgrade/example.py new file mode 100644 index 0000000000..b73b46e5d8 --- /dev/null +++ b/scenarios/examples/restart_anoncreds_upgrade/example.py @@ -0,0 +1,500 @@ +"""Minimal reproducible example script. + +This script is for you to use to reproduce a bug or demonstrate a feature. +""" + +import asyncio +import json +from os import getenv + +from acapy_controller import Controller +from acapy_controller.logging import logging_to_stdout +from acapy_controller.protocols import ( + didexchange, + indy_anoncred_credential_artifacts, + indy_anoncred_onboard, +) +from examples.util import ( + Settings, + anoncreds_issue_credential_v2, + anoncreds_present_proof_v2, + get_wallet_name, + update_wallet_type, + wait_until_healthy, +) + +import docker + +ALICE = getenv("ALICE", "http://alice:3001") +BOB_ASKAR = getenv("BOB_ASKAR", "http://bob-askar:3001") +BOB_ANONCREDS = getenv("BOB_ANONCREDS", "http://bob-anoncreds:3001") +BOB_ASKAR_ANON = getenv("BOB_ASKAR_ANON", "http://bob-askar-anon:3001") + + +async def connect_agents_and_issue_credentials( + inviter: Controller, + invitee: Controller, + inviter_cred_def, + fname: str, + lname: str, + inviter_conn=None, + invitee_conn=None, +): + is_inviter_anoncreds = (await inviter.get("/settings", response=Settings)).get( + "wallet.type" + ) == "askar-anoncreds" + + # connect the 2 agents + if (not inviter_conn) or (not invitee_conn): + print(">>> connecting agents ...") + (inviter_conn, invitee_conn) = await didexchange(inviter, invitee) + + # Issue a credential + print(">>> issue credential ...") + inviter_cred_ex, _ = await anoncreds_issue_credential_v2( + inviter, + invitee, + inviter_conn.connection_id, + invitee_conn.connection_id, + inviter_cred_def.credential_definition_id, + {"firstname": fname, "lastname": lname}, + ) + + # Present the the credential's attributes + print(">>> present proof ...") + await anoncreds_present_proof_v2( + invitee, + inviter, + invitee_conn.connection_id, + inviter_conn.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + + # Revoke credential + if is_inviter_anoncreds: + await inviter.post( + url="/anoncreds/revocation/revoke", # TODO need to check agent type (askar vs anoncreds) + json={ + "connection_id": inviter_conn.connection_id, + "rev_reg_id": inviter_cred_ex.details.rev_reg_id, + "cred_rev_id": inviter_cred_ex.details.cred_rev_id, + "publish": True, + "notify": True, + "notify_version": "v1_0", + }, + ) + await invitee.record(topic="revocation-notification") + else: + await inviter.post( + url="/revocation/revoke", # TODO need to check agent type (askar vs anoncreds) + json={ + "connection_id": inviter_conn.connection_id, + "rev_reg_id": inviter_cred_ex.details.rev_reg_id, + "cred_rev_id": inviter_cred_ex.details.cred_rev_id, + "publish": True, + "notify": True, + "notify_version": "v1_0", + }, + ) + await invitee.record(topic="revocation-notification") + + # Issue a second credential + print(">>> issue credential ...") + inviter_cred_ex, _ = await anoncreds_issue_credential_v2( + inviter, + invitee, + inviter_conn.connection_id, + invitee_conn.connection_id, + inviter_cred_def.credential_definition_id, + {"firstname": f"{fname}2", "lastname": f"{lname}2"}, + ) + print(">>> Done!") + + return (inviter_conn, invitee_conn) + + +async def verify_schema_cred_def(issuer, schema_count, cred_def_count): + is_issuer_anoncreds = (await issuer.get("/settings", response=Settings)).get( + "wallet.type" + ) == "askar-anoncreds" + + if is_issuer_anoncreds: + schemas = await issuer.get("/anoncreds/schemas") + assert schema_count == len(schemas["schema_ids"]) + + cred_defs = await issuer.get("/anoncreds/credential-definitions") + assert cred_def_count == len(cred_defs["credential_definition_ids"]) + else: + schemas = await issuer.get("/schemas/created") + assert schema_count == len(schemas["schema_ids"]) + + cred_defs = await issuer.get("/credential-definitions/created") + assert cred_def_count == len(cred_defs["credential_definition_ids"]) + + +async def verify_issued_credentials(issuer, issued_cred_count, revoked_cred_count): + is_issuer_anoncreds = (await issuer.get("/settings", response=Settings)).get( + "wallet.type" + ) == "askar-anoncreds" + + cred_exch_recs = await issuer.get("/issue-credential-2.0/records") + cred_exch_recs = cred_exch_recs["results"] + assert len(cred_exch_recs) == issued_cred_count + registries = {} + active_creds = 0 + revoked_creds = 0 + for cred_exch in cred_exch_recs: + cred_type = ( + "indy" + if "indy" in cred_exch + and cred_exch["indy"] + and "rev_reg_id" in cred_exch["indy"] + else "anoncreds" + ) + rev_reg_id = cred_exch[cred_type]["rev_reg_id"] + cred_rev_id = cred_exch[cred_type]["cred_rev_id"] + cred_rev_id = int(cred_rev_id) + if not rev_reg_id in registries: + if is_issuer_anoncreds: + registries[rev_reg_id] = await issuer.get( + f"/anoncreds/revocation/registry/{rev_reg_id}/issued/indy_recs", + ) + else: + registries[rev_reg_id] = await issuer.get( + f"/revocation/registry/{rev_reg_id}/issued/indy_recs", + ) + registry = registries[rev_reg_id] + if cred_rev_id in registry["rev_reg_delta"]["value"]["revoked"]: + revoked_creds = revoked_creds + 1 + else: + active_creds = active_creds + 1 + assert revoked_creds == revoked_cred_count + assert (revoked_creds + active_creds) == issued_cred_count + + +async def verify_recd_credentials(holder, active_cred_count, revoked_cred_count): + is_holder_anoncreds = (await holder.get("/settings", response=Settings)).get( + "wallet.type" + ) == "askar-anoncreds" + + credentials = await holder.get(f"/credentials") + credentials = credentials["results"] + assert len(credentials) == (active_cred_count + revoked_cred_count) + registries = {} + active_creds = 0 + revoked_creds = 0 + for credential in credentials: + rev_reg_id = credential["rev_reg_id"] + cred_rev_id = int(credential["cred_rev_id"]) + if not rev_reg_id in registries: + if is_holder_anoncreds: + registries[rev_reg_id] = await holder.get( + f"/anoncreds/revocation/registry/{rev_reg_id}/issued/indy_recs", + ) + else: + registries[rev_reg_id] = await holder.get( + f"/revocation/registry/{rev_reg_id}/issued/indy_recs", + ) + registry = registries[rev_reg_id] + if cred_rev_id in registry["rev_reg_delta"]["value"]["revoked"]: + revoked_creds = revoked_creds + 1 + else: + active_creds = active_creds + 1 + assert revoked_creds == revoked_cred_count + assert active_creds == active_cred_count + + +async def verify_recd_presentations(verifier, recd_pres_count): + presentations = await verifier.get(f"/present-proof-2.0/records") + presentations = presentations["results"] + + assert recd_pres_count == len(presentations) + + +async def upgrade_wallet_and_shutdown_container( + client, + agent_controller, + agent_container, +): + agent_command = agent_container.attrs["Config"]["Cmd"] + + # command is a List, find the wallet type and replace "askar" with "askar-anoncreds" + correct_wallet_type = update_wallet_type(agent_command, "askar-anoncreds") + wallet_name = get_wallet_name(agent_command) + + # call the wallet upgrade endpoint to upgrade to askar-anoncreds + await agent_controller.post( + "/anoncreds/wallet/upgrade", + params={ + "wallet_name": wallet_name, + }, + ) + + # Wait for the upgrade ... + await asyncio.sleep(2) + + print(">>> waiting for container to exit ...") + agent_id = agent_container.attrs["Id"] + wait_until_healthy(client, agent_id, is_healthy=False) + agent_container.remove() + + return agent_command + + +def start_new_container( + client, + agent_command, + agent_container, + agent_label, +): + print(">>> start new container ...") + new_agent_container = client.containers.run( + "acapy-test", + command=agent_command, + detach=True, + environment={"RUST_LOG": "aries-askar::log::target=error"}, + healthcheck=agent_container.attrs["Config"]["Healthcheck"], + name=agent_label, + network=agent_container.attrs["HostConfig"]["NetworkMode"], + ports=agent_container.attrs["NetworkSettings"]["Ports"], + ) + print(">>> new container:", agent_label, json.dumps(new_agent_container.attrs)) + new_agent_id = new_agent_container.attrs["Id"] + + wait_until_healthy(client, new_agent_id) + print(">>> new container is healthy") + + return (new_agent_container, new_agent_id) + + +def stop_and_remove_container(client, agent_id): + # cleanup - shut down agent (not part of docker compose) + print(">>> shut down agent ...") + agent_container = client.containers.get(agent_id) + agent_container.stop() + wait_until_healthy(client, agent_id, is_healthy=False) + agent_container.remove() + + +async def main(): + """Test Controller protocols.""" + async with Controller(base_url=ALICE) as alice: + # setup alice as an issuer + print(">>> setting up alice as issuer ...") + await indy_anoncred_onboard(alice) + schema, cred_def = await indy_anoncred_credential_artifacts( + alice, + ["firstname", "lastname"], + support_revocation=True, + revocation_registry_size=5, + ) + + # confirm alice has 1 schema and 1 cred def + await verify_schema_cred_def(alice, 1, 1) + + alice_conns = {} + bob_conns = {} + async with ( + Controller(base_url=ALICE) as alice, + Controller(base_url=BOB_ASKAR) as bob, + ): + # connect to Bob (Askar wallet) and issue (and revoke) some credentials + (alice_conn, bob_conn) = await connect_agents_and_issue_credentials( + alice, + bob, + cred_def, + "Bob", + "Askar", + ) + alice_conns["askar"] = alice_conn + bob_conns["askar"] = bob_conn + await verify_recd_credentials(bob, 1, 1) + + async with ( + Controller(base_url=ALICE) as alice, + Controller(base_url=BOB_ANONCREDS) as bob, + ): + # connect to Bob (Anoncreds wallet) and issue (and revoke) some credentials + (alice_conn, bob_conn) = await connect_agents_and_issue_credentials( + alice, + bob, + cred_def, + "Bob", + "Anoncreds", + ) + alice_conns["anoncreds"] = alice_conn + bob_conns["anoncreds"] = bob_conn + await verify_recd_credentials(bob, 1, 1) + + async with ( + Controller(base_url=ALICE) as alice, + Controller(base_url=BOB_ASKAR_ANON) as bob, + ): + # connect to Bob (Askar wallet which will be upgraded) and issue (and revoke) some credentials + (alice_conn, bob_conn) = await connect_agents_and_issue_credentials( + alice, + bob, + cred_def, + "Bob", + "Askar_Anon", + ) + alice_conns["askar-anon"] = alice_conn + bob_conns["askar-anon"] = bob_conn + await verify_recd_credentials(bob, 1, 1) + await verify_issued_credentials(alice, 6, 3) + await verify_recd_presentations(alice, 3) + + # at this point alice has issued 6 credentials (revocation registry size is 5) and revoked 3 + # TODO verify counts of credentials, revocations etc for each agent + + # play with docker - get a list of all our running containers + client = docker.from_env() + containers = client.containers.list(all=True) + docker_containers = {} + for container in containers: + if "com.docker.compose.service" in container.attrs["Config"]["Labels"]: + container_name = container.attrs["Config"]["Labels"][ + "com.docker.compose.service" + ] + container_id = container.attrs["Id"] + container_is_running = container.attrs["State"]["Running"] + docker_containers[container_name] = { + "Id": container_id, + "Running": container_is_running, + } + print(">>> container:", container_name, docker_containers[container_name]) + + alice_docker_container = docker_containers["alice"] + alice_container = client.containers.get(alice_docker_container["Id"]) + async with Controller(base_url=ALICE) as alice: + alice_command = await upgrade_wallet_and_shutdown_container( + client, + alice, + alice_container, + ) + + bob_docker_container = docker_containers["bob-askar-anon"] + bob_container = client.containers.get(bob_docker_container["Id"]) + async with Controller(base_url=BOB_ASKAR_ANON) as bob: + bob_command = await upgrade_wallet_and_shutdown_container( + client, + bob, + bob_container, + ) + + new_alice_container = None + alice_id = None + new_bob_container = None + bob_id = None + try: + (new_alice_container, alice_id) = start_new_container( + client, + alice_command, + alice_container, + "alice", + ) + + (new_bob_container, bob_id) = start_new_container( + client, + bob_command, + bob_container, + "bob-askar-anon", + ) + + # TODO verify counts of credentials, revocations etc for each upgraded agent + async with ( + Controller(base_url=ALICE) as alice, + Controller(base_url=BOB_ASKAR_ANON) as bob, + ): + await verify_schema_cred_def(alice, 1, 1) + + # run some more tests ... alice should still be connected to bob for example ... + async with ( + Controller(base_url=ALICE) as alice, + Controller(base_url=BOB_ANONCREDS) as bob, + ): + # Present the the credential's attributes + print(">>> present proof ... again ...") + await anoncreds_present_proof_v2( + bob, + alice, + bob_conns["anoncreds"].connection_id, + alice_conns["anoncreds"].connection_id, + requested_attributes=[{"name": "firstname"}], + ) + await connect_agents_and_issue_credentials( + alice, + bob, + cred_def, + "Bob", + "Anoncreds", + inviter_conn=alice_conns["anoncreds"], + invitee_conn=bob_conns["anoncreds"], + ) + await verify_recd_credentials(bob, 2, 2) + print(">>> Done! (again)") + + async with ( + Controller(base_url=ALICE) as alice, + Controller(base_url=BOB_ASKAR_ANON) as bob, + ): + # Present the the credential's attributes + print(">>> present proof ... again ...") + await anoncreds_present_proof_v2( + bob, + alice, + bob_conns["askar-anon"].connection_id, + alice_conns["askar-anon"].connection_id, + requested_attributes=[{"name": "firstname"}], + ) + await connect_agents_and_issue_credentials( + alice, + bob, + cred_def, + "Bob", + "Askar_Anon", + inviter_conn=alice_conns["askar-anon"], + invitee_conn=bob_conns["askar-anon"], + ) + await verify_recd_credentials(bob, 2, 2) + print(">>> Done! (again)") + + async with ( + Controller(base_url=ALICE) as alice, + Controller(base_url=BOB_ASKAR) as bob, + ): + # Present the the credential's attributes + print(">>> present proof ... again ...") + await anoncreds_present_proof_v2( + bob, + alice, + bob_conns["askar"].connection_id, + alice_conns["askar"].connection_id, + requested_attributes=[{"name": "firstname"}], + ) + await connect_agents_and_issue_credentials( + alice, + bob, + cred_def, + "Bob", + "Askar", + inviter_conn=alice_conns["askar"], + invitee_conn=bob_conns["askar"], + ) + await verify_recd_credentials(bob, 2, 2) + await verify_issued_credentials(alice, 12, 6) + await verify_recd_presentations(alice, 9) + print(">>> Done! (again)") + + finally: + if alice_id and new_alice_container: + # cleanup - shut down alice agent (not part of docker compose) + stop_and_remove_container(client, alice_id) + if bob_id and new_bob_container: + # cleanup - shut down bob agent (not part of docker compose) + stop_and_remove_container(client, bob_id) + + +if __name__ == "__main__": + logging_to_stdout() + asyncio.run(main()) diff --git a/scenarios/examples/simple_restart/docker-compose.yml b/scenarios/examples/simple_restart/docker-compose.yml index c3c589c42d..59a7ed2d28 100644 --- a/scenarios/examples/simple_restart/docker-compose.yml +++ b/scenarios/examples/simple_restart/docker-compose.yml @@ -90,6 +90,43 @@ services: wallet-db: condition: service_healthy + agency: + image: bcgovimages/aries-cloudagent:py3.12_1.0.1 + ports: + - "3003:3001" + command: > + start + --label Agency + --inbound-transport http 0.0.0.0 3000 + --outbound-transport http + --endpoint http://agency:3000 + --admin 0.0.0.0 3001 + --admin-insecure-mode + --tails-server-base-url http://tails:6543 + --genesis-url http://test.bcovrin.vonx.io/genesis + --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 + --wallet-storage-type "postgres_storage" + --wallet-storage-config "{\"url\":\"wallet-db:5432\",\"max_connections\":5}" + --wallet-storage-creds "{\"account\":\"DB_USER\",\"password\":\"DB_PASSWORD\",\"admin_account\":\"DB_USER\",\"admin_password\":\"DB_PASSWORD\"}" + --log-level info + --debug-webhooks + healthcheck: + test: curl -s -o /dev/null -w '%{http_code}' "http://localhost:3001/status/live" | grep "200" > /dev/null + start_period: 30s + interval: 7s + timeout: 5s + retries: 5 + depends_on: + tails: + condition: service_started + tails: image: ghcr.io/bcgov/tails-server:latest ports: @@ -112,6 +149,7 @@ services: - DOCKER_HOST=unix:///var/run/docker.sock - ALICE=http://alice:3001 - BOB=http://bob:3001 + - AGENCY=http://agency:3001 volumes: - /var/run/docker.sock:/var/run/docker.sock - ./example.py:/usr/src/app/example.py:ro,z @@ -121,3 +159,5 @@ services: condition: service_healthy bob: condition: service_healthy + agency: + condition: service_healthy diff --git a/scenarios/examples/simple_restart/example.py b/scenarios/examples/simple_restart/example.py index 558d94285b..17597dce6b 100644 --- a/scenarios/examples/simple_restart/example.py +++ b/scenarios/examples/simple_restart/example.py @@ -5,59 +5,50 @@ import asyncio from os import getenv -import json -import time - -import docker -from docker.errors import NotFound -from docker.models.containers import Container -from docker.models.networks import Network from acapy_controller import Controller from acapy_controller.logging import logging_to_stdout +from acapy_controller.models import CreateWalletResponse from acapy_controller.protocols import ( - connection, didexchange, indy_anoncred_credential_artifacts, indy_anoncred_onboard, - indy_anoncreds_publish_revocation, - indy_anoncreds_revoke, indy_issue_credential_v2, indy_present_proof_v2, ) +from examples.util import ( + wait_until_healthy, +) + +import docker ALICE = getenv("ALICE", "http://alice:3001") BOB = getenv("BOB", "http://bob:3001") - - -def healthy(container: Container) -> bool: - """Check if container is healthy.""" - inspect_results = container.attrs - return inspect_results["State"]["Running"] and inspect_results["State"]["Health"]["Status"] == "healthy" - - -def unhealthy(container: Container) -> bool: - """Check if container is unhealthy.""" - inspect_results = container.attrs - return not inspect_results["State"]["Running"] - - -def wait_until_healthy(client, container_id: str, attempts: int = 350, is_healthy=True): - """Wait until container is healthy.""" - container = client.containers.get(container_id) - print((container.name, container.status)) - for _ in range(attempts): - if (is_healthy and healthy(container)) or unhealthy(container): - return - else: - time.sleep(1) - container = client.containers.get(container_id) - raise TimeoutError("Timed out waiting for container") +AGENCY = getenv("AGENCY", "http://agency:3001") async def main(): """Test Controller protocols.""" - async with Controller(base_url=ALICE) as alice, Controller(base_url=BOB) as bob: + # create multitenant issuer tenant + async with Controller(base_url=AGENCY) as agency: + multitenant_issuer_tenant = await agency.post( + "/multitenancy/wallet", + json={ + "label": "MultitenantIssuer", + "wallet_type": "askar", + }, + response=CreateWalletResponse, + ) + + async with ( + Controller(base_url=ALICE) as alice, + Controller(base_url=BOB) as bob, + Controller( + base_url=AGENCY, + wallet_id=multitenant_issuer_tenant.wallet_id, + subwallet_token=multitenant_issuer_tenant.token, + ) as multitenant_issuer, + ): # connect the 2 agents print(">>> connecting agents ...") (alice_conn, bob_conn) = await didexchange(alice, bob) @@ -93,45 +84,101 @@ async def main(): ) print(">>> Done!") + # connect multitenant issuer to bob + print(">>> connecting agents ...") + (multitenant_issuer_conn, bob_to_mt_conn) = await didexchange( + multitenant_issuer, bob + ) + + # setup multitenant issuer as an issuer + print(">>> setting up multitenant issuer as issuer ...") + await indy_anoncred_onboard(multitenant_issuer) + schema, cred_def = await indy_anoncred_credential_artifacts( + multitenant_issuer, + ["firstname", "lastname"], + support_revocation=True, + ) + + # Issue a credential + print(">>> issue credential ...") + multitenant_issuer_cred_ex, _ = await indy_issue_credential_v2( + multitenant_issuer, + bob, + multitenant_issuer_conn.connection_id, + bob_to_mt_conn.connection_id, + cred_def.credential_definition_id, + {"firstname": "Bob", "lastname": "Builder"}, + ) + + # Present the the credential's attributes + print(">>> present proof ...") + await indy_present_proof_v2( + bob, + multitenant_issuer, + bob_to_mt_conn.connection_id, + multitenant_issuer_conn.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + print(">>> Done!") + # play with docker client = docker.from_env() containers = client.containers.list(all=True) docker_containers = {} for container in containers: - if 'com.docker.compose.service' in container.attrs['Config']['Labels']: - container_name = container.attrs['Config']['Labels']['com.docker.compose.service'] - container_id = container.attrs['Id'] - container_is_running = container.attrs['State']['Running'] - docker_containers[container_name] = {'Id': container_id, 'Running': container_is_running} + if "com.docker.compose.service" in container.attrs["Config"]["Labels"]: + container_name = container.attrs["Config"]["Labels"][ + "com.docker.compose.service" + ] + container_id = container.attrs["Id"] + container_is_running = container.attrs["State"]["Running"] + docker_containers[container_name] = { + "Id": container_id, + "Running": container_is_running, + } print(">>> container:", container_name, docker_containers[container_name]) # try to restart a container (stop alice and start alice-upgrade) - alice_docker_container = docker_containers['alice'] - alice_container = client.containers.get(alice_docker_container['Id']) + alice_docker_container = docker_containers["alice"] + alice_container = client.containers.get(alice_docker_container["Id"]) + + # try to restart agency container (stop agency and start agency-upgrade) + agency_docker_container = docker_containers["agency"] + agency_container = client.containers.get(agency_docker_container["Id"]) print(">>> shut down alice ...") alice_container.stop() + print(">>> shut down agency ...") + agency_container.stop() + print(">>> waiting for alice container to exit ...") - alice_id = alice_container.attrs['Id'] + alice_id = agency_container.attrs["Id"] wait_until_healthy(client, alice_id, is_healthy=False) alice_container.remove() - print(">>> start new alice container ...") - new_alice_container = client.containers.run( - 'acapy-test', - command=alice_container.attrs['Config']['Cmd'], - detach=True, - environment={'RUST_LOG': 'aries-askar::log::target=error'}, - healthcheck=alice_container.attrs['Config']['Healthcheck'], - name='alice', - network=alice_container.attrs['HostConfig']['NetworkMode'], - ports=alice_container.attrs['NetworkSettings']['Ports'], - ) - print(">>> new container:", 'alice', json.dumps(new_alice_container.attrs)) - alice_id = new_alice_container.attrs['Id'] + print(">>> waiting for agency container to exit ...") + agency_id = agency_container.attrs["Id"] + wait_until_healthy(client, agency_id, is_healthy=False) + agency_container.remove() + # Upgrade alice and perform some tests + new_alice_container = None + alice_id = None try: + print(">>> start new alice container ...") + new_alice_container = client.containers.run( + "acapy-test", + command=alice_container.attrs["Config"]["Cmd"], + detach=True, + environment={"RUST_LOG": "aries-askar::log::target=error"}, + healthcheck=alice_container.attrs["Config"]["Healthcheck"], + name="alice", + network=alice_container.attrs["HostConfig"]["NetworkMode"], + ports=alice_container.attrs["NetworkSettings"]["Ports"], + ) + alice_id = new_alice_container.attrs["Id"] + wait_until_healthy(client, alice_id) print(">>> new alice container is healthy") @@ -148,12 +195,61 @@ async def main(): ) print(">>> Done! (again)") finally: - # cleanup - shut down alice agent (not part of docker compose) - print(">>> shut down alice ...") - alice_container = client.containers.get(alice_id) - alice_container.stop() - wait_until_healthy(client, alice_id, is_healthy=False) - alice_container.remove() + if alice_id and new_alice_container: + # cleanup - shut down alice agent (not part of docker compose) + print(">>> shut down alice ...") + alice_container = client.containers.get(alice_id) + alice_container.stop() + wait_until_healthy(client, alice_id, is_healthy=False) + alice_container.remove() + + # Upgrade agency and perform some tests + new_agency_container = None + agency_id = None + try: + print(">>> start new agency container ...") + new_agency_container = client.containers.run( + "acapy-test", + command=agency_container.attrs["Config"]["Cmd"], + detach=True, + environment={"RUST_LOG": "aries-askar::log::target=error"}, + healthcheck=agency_container.attrs["Config"]["Healthcheck"], + name="agency", + network=agency_container.attrs["HostConfig"]["NetworkMode"], + ports=agency_container.attrs["NetworkSettings"]["Ports"], + ) + agency_id = new_agency_container.attrs["Id"] + + wait_until_healthy(client, agency_id) + print(">>> new agency container is healthy") + + # run some more tests ... agency tenant should still be connected to bob ... + async with ( + Controller(base_url=BOB) as bob, + Controller( + base_url=AGENCY, + wallet_id=multitenant_issuer_tenant.wallet_id, + subwallet_token=multitenant_issuer_tenant.token, + ) as multitenant_issuer, + ): + # Present the the credential's attributes + print(">>> present proof ... again ...") + await indy_present_proof_v2( + bob, + multitenant_issuer, + bob_to_mt_conn.connection_id, + multitenant_issuer_conn.connection_id, + requested_attributes=[{"name": "firstname"}], + ) + print(">>> Done! (again)") + finally: + if agency_id and new_agency_container: + # cleanup - shut down agency agent (not part of docker compose) + print(">>> shut down agency ...") + agency_container = client.containers.get(agency_id) + agency_container.stop() + wait_until_healthy(client, agency_id, is_healthy=False) + agency_container.remove() if __name__ == "__main__": diff --git a/scenarios/examples/util.py b/scenarios/examples/util.py new file mode 100644 index 0000000000..d4f128d972 --- /dev/null +++ b/scenarios/examples/util.py @@ -0,0 +1,432 @@ +import json +import time +from dataclasses import dataclass +from secrets import randbelow +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, MinType +from acapy_controller.models import ( + V20CredExRecordIndy, + V20PresExRecord, +) + +from docker.models.containers import Container + + +# docker utilities: +def healthy(container: Container) -> bool: + """Check if container is healthy.""" + inspect_results = container.attrs + return ( + inspect_results["State"]["Running"] + and inspect_results["State"]["Health"]["Status"] == "healthy" + ) + + +def unhealthy(container: Container) -> bool: + """Check if container is unhealthy.""" + inspect_results = container.attrs + return not inspect_results["State"]["Running"] + + +def wait_until_healthy(client, container_id: str, attempts: int = 350, is_healthy=True): + """Wait until container is healthy.""" + container = client.containers.get(container_id) + print((container.name, container.status)) + for _ in range(attempts): + if (is_healthy and healthy(container)) or unhealthy(container): + return + else: + time.sleep(1) + container = client.containers.get(container_id) + raise TimeoutError("Timed out waiting for container") + + +def update_wallet_type(agent_command: List, wallet_type: str) -> str: + for i in range(len(agent_command) - 1): + if agent_command[i] == "--wallet-type": + agent_command[i + 1] = wallet_type + return wallet_type + raise Exception("Error unable to upgrade wallet type to askar-anoncreds") + + +def get_wallet_name(agent_command: List) -> str: + for i in range(len(agent_command) - 1): + if agent_command[i] == "--wallet-name": + return agent_command[i + 1] + raise Exception("Error unable to upgrade wallet type to askar-anoncreds") + + +# anoncreds utilities: +def anoncreds_presentation_summary(presentation: V20PresExRecord) -> str: + """Summarize a presentation exchange record.""" + request = presentation.pres_request + return "Summary: " + json.dumps( + { + "state": presentation.state, + "verified": presentation.verified, + "presentation_request": ( + request.model_dump(by_alias=True) if request else None + ), + }, + indent=2, + sort_keys=True, + ) + + +@dataclass +class SchemaResultAnoncreds(Minimal): + """Schema result.""" + + schema_state: dict + + +@dataclass +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 anoncreds_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 or is_issuer_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 anoncreds_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 diff --git a/scripts/run_tests b/scripts/run_tests index 5f6ede8dad..af9c9c91be 100755 --- a/scripts/run_tests +++ b/scripts/run_tests @@ -15,7 +15,7 @@ for arg in "$@"; do done if [[ $FAST -eq 0 ]]; then - $CONTAINER_RUNTIME build --platform linux/amd64 -t aries-cloudagent-test -f ../docker/Dockerfile.test --build-arg "all_extras=$ALL_EXTRAS" .. || exit 1 + $CONTAINER_RUNTIME build --platform linux/amd64 -t acapy-agent-test -f ../docker/Dockerfile.test --build-arg "all_extras=$ALL_EXTRAS" .. || exit 1 fi DOCKER_ARGS="" @@ -33,7 +33,7 @@ if [ -n "${ENABLE_PTVSD}" ]; then fi if [[ $FAST -eq 1 ]]; then - DOCKER_ARGS="${DOCKER_ARGS} -v $(pwd)/../aries_cloudagent:/usr/src/app/aries_cloudagent:z" + DOCKER_ARGS="${DOCKER_ARGS} -v $(pwd)/../acapy_agent:/usr/src/app/acapy_agent:z" fi if [ ! -d ../test-reports ]; then mkdir ../test-reports; fi @@ -47,7 +47,7 @@ if [ ! -z "$TEST_REDIS_CONFIG" ]; then DOCKER_ARGS="$DOCKER_ARGS -e TEST_REDIS_CONFIG=$TEST_REDIS_CONFIG" fi -$CONTAINER_RUNTIME run --rm -ti --name aries-cloudagent-runner \ +$CONTAINER_RUNTIME run --rm -ti --name acapy-agent-runner \ --platform linux/amd64 \ -v "$(pwd)/../test-reports:/usr/src/app/test-reports:z" \ - $DOCKER_ARGS aries-cloudagent-test "$@" + $DOCKER_ARGS acapy-agent-test "$@"