Skip to content

Commit

Permalink
Merge branch 'main' into feat/didcommv2-proof-of-concept
Browse files Browse the repository at this point in the history
Signed-off-by: Micah Peltier <micah6_8@yahoo.com>
  • Loading branch information
mepeltier committed Jun 6, 2024
2 parents 8bf1d85 + 1da9872 commit d20918e
Show file tree
Hide file tree
Showing 13 changed files with 125 additions and 82 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/sonar-merge-main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jobs:
name: SonarCloud
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Tests
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/sonar-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
if: github.event.workflow_run.conclusion == 'success'
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download PR number artifact
Expand Down
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Hyperledger Aries Cloud Agent - Python <!-- omit in toc -->

[![pypi releases](https://img.shields.io/pypi/v/aries_cloudagent)](https://pypi.org/project/aries-cloudagent/)

<!-- ![logo](/doc/assets/aries-cloudagent-python-logo-bw.png) -->
<p float="left">
<a href="https://pypi.org/project/aries-cloudagent/"><img src="https://img.shields.io/pypi/v/aries_cloudagent" width="100" height="20" />
<img src="https://sonarcloud.io/images/project_badges/sonarcloud-white.svg" width="120" height="20" />
<img src="https://sonarcloud.io/api/project_badges/measure?project=hyperledger_aries-cloudagent-python&metric=coverage" width="120" height="20" />
&nbsp;<img src="https://sonarcloud.io/api/project_badges/measure?project=hyperledger_aries-cloudagent-python&metric=security_rating" width="100" height="20" />
&nbsp;<img src="https://sonarcloud.io/api/project_badges/measure?project=hyperledger_aries-cloudagent-python&metric=vulnerabilities" width="120" height="20" />
&nbsp;<img src="https://sonarcloud.io/api/project_badges/measure?project=hyperledger_aries-cloudagent-python&metric=ncloc" width="120" height="20" />
</p>

> An easy to use Aries agent for building SSI services using any language that supports sending/receiving HTTP requests.
Expand Down
2 changes: 1 addition & 1 deletion aries_cloudagent/askar/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ def bind_providers(self):
"aries_cloudagent.indy.credx.issuer.IndyCredxIssuer", ref(self)
),
)
injector.bind_provider(
injector.soft_bind_provider(
VCHolder,
ClassProvider(
"aries_cloudagent.storage.vc_holder.askar.AskarVCHolder",
Expand Down
22 changes: 20 additions & 2 deletions aries_cloudagent/config/injector.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Standard Injector implementation."""

from typing import Mapping, Optional, Type
from typing import Dict, Mapping, Optional, Type

from .base import BaseProvider, BaseInjector, InjectionError, InjectType
from .provider import InstanceProvider, CachedProvider
Expand All @@ -18,7 +18,7 @@ def __init__(
):
"""Initialize an `Injector`."""
self.enforce_typing = enforce_typing
self._providers = {}
self._providers: Dict[Type, BaseProvider] = {}
self._settings = Settings(settings)

@property
Expand All @@ -45,6 +45,24 @@ def bind_provider(
provider = CachedProvider(provider)
self._providers[base_cls] = provider

def soft_bind_instance(self, base_cls: Type[InjectType], instance: InjectType):
"""Add a static instance as a soft class binding.
The binding occurs only if a provider for the same type does not already exist.
"""
if not self.get_provider(base_cls):
self.bind_instance(base_cls, instance)

def soft_bind_provider(
self, base_cls: Type[InjectType], provider: BaseProvider, *, cache: bool = False
):
"""Add a dynamic instance resolver as a soft class binding.
The binding occurs only if a provider for the same type does not already exist.
"""
if not self.get_provider(base_cls):
self.bind_provider(base_cls, provider, cache=cache)

def clear_binding(self, base_cls: Type[InjectType]):
"""Remove a previously-added binding."""
if base_cls in self._providers:
Expand Down
33 changes: 33 additions & 0 deletions aries_cloudagent/config/tests/test_injector.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,39 @@ def test_inject_provider(self):
assert mock_provider.settings[self.test_key] == override_settings[self.test_key]
assert mock_provider.injector is self.test_instance

def test_inject_soft_provider_bindings(self):
"""Test injecting providers with soft binding."""
provider = MockProvider(self.test_value)
override = MockProvider("Override")

self.test_instance.soft_bind_provider(str, provider)
assert self.test_instance.inject(str) == self.test_value

self.test_instance.clear_binding(str)
# Bound by a plugin on startup, for example
self.test_instance.bind_provider(str, override)

# Bound later in Profile.bind_providerse
self.test_instance.soft_bind_provider(str, provider)

# We want the plugin value, not the Profile bound value
assert self.test_instance.inject(str) == "Override"

def test_inject_soft_instance_bindings(self):
"""Test injecting providers with soft binding."""
self.test_instance.soft_bind_instance(str, self.test_value)
assert self.test_instance.inject(str) == self.test_value

self.test_instance.clear_binding(str)
# Bound by a plugin on startup, for example
self.test_instance.bind_instance(str, "Override")

# Bound later in Profile.bind_providerse
self.test_instance.soft_bind_instance(str, self.test_value)

# We want the plugin value, not the Profile bound value
assert self.test_instance.inject(str) == "Override"

def test_bad_provider(self):
"""Test empty and invalid provider results."""
self.test_instance.bind_provider(str, MockProvider(None))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from datetime import datetime
from typing import Dict, List, Optional, Sequence, Tuple, Union

import pytz
from dateutil import tz
from dateutil.parser import ParserError
from dateutil.parser import parse as dateutil_parser
from jsonpath_ng import parse
Expand Down Expand Up @@ -613,10 +613,9 @@ def string_to_timezone_aware_datetime(self, datetime_str: str) -> datetime:
if PYTZ_TIMEZONE_PATTERN.search(datetime_str):
result = PYTZ_TIMEZONE_PATTERN.search(datetime_str).group(1)
datetime_str = datetime_str.replace(result, "")
return dateutil_parser(datetime_str).replace(tzinfo=pytz.timezone(result))
return dateutil_parser(datetime_str).replace(tzinfo=tz.gettz(result))
else:
utc = pytz.UTC
return dateutil_parser(datetime_str).replace(tzinfo=utc)
return dateutil_parser(datetime_str).replace(tzinfo=tz.UTC)

def validate_patch(self, to_check: any, _filter: Filter) -> bool:
"""Apply filter on match_value.
Expand Down
11 changes: 5 additions & 6 deletions aries_cloudagent/vc/ld_proofs/suites/bbs_bls_signature_2020.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
"""BbsBlsSignature2020 class."""

from datetime import datetime, timezone
from pytz import utc
from datetime import datetime
from typing import List, Optional, Union

from ....wallet.util import b64_to_bytes, bytes_to_b64
from dateutil import tz

from ....wallet.util import b64_to_bytes, bytes_to_b64
from ..crypto import _KeyPair as KeyPair
from ..document_loader import DocumentLoaderMethod
from ..error import LinkedDataProofException
from ..purposes import _ProofPurpose as ProofPurpose
from ..validation_result import ProofResult

from .bbs_bls_signature_2020_base import BbsBlsSignature2020Base


Expand Down Expand Up @@ -60,9 +59,9 @@ async def create_proof(
# Set created if not already set
if not proof.get("created"):
# Use class date, or now
date = self.date or datetime.now(timezone.utc)
date = self.date or datetime.now(tz.UTC)
if not date.tzinfo:
date = utc.localize(date)
date = date.replace(tzinfo=tz.UTC)
proof["created"] = date.isoformat(timespec="seconds")

# Allow purpose to update the proof; the `proof` is in the
Expand Down
8 changes: 4 additions & 4 deletions aries_cloudagent/vc/ld_proofs/suites/linked_data_signature.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
"""Linked Data Signature class."""

from abc import abstractmethod, ABCMeta
from abc import ABCMeta, abstractmethod
from datetime import datetime, timezone
from hashlib import sha256
from pytz import utc
from typing import Optional, Union

from dateutil import tz

from ..constants import SECURITY_CONTEXT_URL
from ..document_loader import DocumentLoaderMethod
from ..error import LinkedDataProofException
from ..purposes import _ProofPurpose as ProofPurpose
from ..validation_result import ProofResult

from .linked_data_proof import LinkedDataProof


Expand Down Expand Up @@ -99,7 +99,7 @@ async def create_proof(
# Use class date, or now
date = self.date or datetime.now(timezone.utc)
if not date.tzinfo:
date = utc.localize(date)
date = date.replace(tzinfo=tz.UTC)
proof["created"] = date.isoformat(timespec="seconds")

# Allow purpose to update the proof; the `proof` is in the
Expand Down
11 changes: 5 additions & 6 deletions aries_cloudagent/vc/vc_ld/models/credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@
from datetime import datetime
from typing import List, Optional, Union

from pytz import utc

from dateutil import tz
from marshmallow import INCLUDE, ValidationError, fields, post_dump

from ....messaging.models.base import BaseModel, BaseModelSchema
from ....messaging.valid import (
CREDENTIAL_CONTEXT_EXAMPLE,
CREDENTIAL_CONTEXT_VALIDATE,
CREDENTIAL_SUBJECT_EXAMPLE,
CREDENTIAL_SUBJECT_VALIDATE,
CREDENTIAL_STATUS_EXAMPLE,
CREDENTIAL_STATUS_VALIDATE,
CREDENTIAL_SUBJECT_EXAMPLE,
CREDENTIAL_SUBJECT_VALIDATE,
CREDENTIAL_TYPE_EXAMPLE,
CREDENTIAL_TYPE_VALIDATE,
RFC3339_DATETIME_EXAMPLE,
Expand Down Expand Up @@ -176,7 +175,7 @@ def issuance_date(self, date: Union[str, datetime]):
"""Setter for issuance date."""
if isinstance(date, datetime):
if not date.tzinfo:
date = utc.localize(date)
date = date.replace(tzinfo=tz.UTC)
date = date.isoformat()

self._issuance_date = date
Expand All @@ -191,7 +190,7 @@ def expiration_date(self, date: Union[str, datetime, None]):
"""Setter for expiration date."""
if isinstance(date, datetime):
if not date.tzinfo:
date = utc.localize(date)
date = date.replace(tzinfo=tz.UTC)
date = date.isoformat()

self._expiration_date = date
Expand Down
59 changes: 29 additions & 30 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,48 +18,47 @@
sys.path.insert(0, os.path.abspath(".."))

autodoc_mock_imports = [
"setup",
"nacl",
"indy",
"aiohttp_apispec",
"aiohttp_cors",
"aiohttp",
"aiohttp_apispec",
"base58",
"msgpack",
"pytest",
"aioredis",
"anoncreds",
"aries_askar",
"async_timeout",
"asynctest",
"markdown",
"prompt_toolkit",
"multicodec",
"base58",
"configargparse",
"pyld",
"pydid",
"aries_askar",
"indy_vdr",
"aioredis",
"dateutil",
"deepmerge",
"did_peer_2",
"did_peer_4",
"ecdsa",
"indy_credx",
"dateutil",
"packaging",
"indy_vdr",
"indy",
"jsonpath_ng",
"unflatten",
"qrcode",
"rlp",
"nest_asyncio",
"jwt",
"markdown",
"marshmallow",
"typing_extensions",
"async_timeout",
"msgpack",
"multicodec",
"multiformats",
"nacl",
"nest_asyncio",
"packaging",
"portalocker",
"prompt_toolkit",
"pydid",
"pyld",
"pytest",
"pythonjsonlogger",
"jwt",
"yaml",
"pytz",
"multiformats",
"qrcode",
"rlp",
"sd_jwt",
"anoncreds",
"did_peer_2",
"did_peer_4",
"setup",
"typing_extensions",
"unflatten",
"yaml",
]

# "aries_cloudagent.tests.test_conductor",
Expand Down
36 changes: 14 additions & 22 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d20918e

Please sign in to comment.