diff --git a/addon_service/addon_operation/models.py b/addon_service/addon_operation/models.py index 7e906465..9fd279c8 100644 --- a/addon_service/addon_operation/models.py +++ b/addon_service/addon_operation/models.py @@ -7,14 +7,17 @@ get_imp_name, ) from addon_service.common.static_dataclass_model import StaticDataclassModel -from addon_toolkit import AddonOperationImp +from addon_toolkit import ( + AddonCapabilities, + AddonOperationImp, +) from addon_toolkit.json_arguments import jsonschema_for_signature_params from addon_toolkit.operation import AddonOperationType # dataclass wrapper for addon_toolkit.AddonOperationImp that sufficiently # meets rest_framework_json_api expectations on a model class -@dataclasses.dataclass(frozen=True, kw_only=True) +@dataclasses.dataclass(frozen=True) class AddonOperationModel(StaticDataclassModel): operation_imp: AddonOperationImp @@ -42,7 +45,7 @@ def implementation_docstring(self) -> str: return self.operation_imp.imp_function.__doc__ or "" @cached_property - def capability(self) -> str: + def capability(self) -> AddonCapabilities: return self.operation_imp.declaration.capability @cached_property diff --git a/addon_service/addon_operation/serializers.py b/addon_service/addon_operation/serializers.py index 875b1f47..fcc39981 100644 --- a/addon_service/addon_operation/serializers.py +++ b/addon_service/addon_operation/serializers.py @@ -1,11 +1,11 @@ from rest_framework_json_api import serializers from rest_framework_json_api.utils import get_resource_type_from_model -from addon_service.addon_imp.models import AddonImp from addon_service.common import view_names from addon_service.common.enums.serializers import EnumNameChoiceField from addon_service.common.serializer_fields import DataclassRelatedDataField from addon_toolkit import AddonCapabilities +from addon_toolkit.imp import AddonImp from .models import AddonOperationModel diff --git a/addon_service/authorized_storage_account/models.py b/addon_service/authorized_storage_account/models.py index 647db7a3..ee2578c8 100644 --- a/addon_service/authorized_storage_account/models.py +++ b/addon_service/authorized_storage_account/models.py @@ -121,7 +121,7 @@ def authorized_operation_names(self): ] @property - def auth_url(self) -> str: + def auth_url(self) -> str | None: """Generates the url required to initiate OAuth2 credentials exchange. Returns None if the ExternalStorageService does not support OAuth2 diff --git a/addon_toolkit/operation.py b/addon_toolkit/operation.py index 75efe879..787d00b5 100644 --- a/addon_toolkit/operation.py +++ b/addon_toolkit/operation.py @@ -7,6 +7,7 @@ Iterator, ) +from .capabilities import AddonCapabilities from .declarator import Declarator @@ -35,7 +36,7 @@ class AddonOperationDeclaration: """ operation_type: AddonOperationType - capability: enum.Enum + capability: AddonCapabilities operation_fn: Callable # the decorated function return_type: type = dataclasses.field( default=type(None), # if not provided, inferred by __post_init__ @@ -99,7 +100,13 @@ def param_dataclasses(self) -> Iterator[type]: @dataclasses.dataclass class RedirectResult: url: str - method: HTTPMethod = HTTPMethod.GET + method: str = HTTPMethod.GET + + def __post_init__(self): + try: + HTTPMethod(self.method) + except ValueError: + raise ValueError(f'invalid http method "{self.method}"') # decorator for operations that may be performed by a client request (e.g. redirect to waterbutler) diff --git a/addon_toolkit/tests/test_addon_protocol.py b/addon_toolkit/tests/test_addon_protocol.py index f3cf470c..267bdaca 100644 --- a/addon_toolkit/tests/test_addon_protocol.py +++ b/addon_toolkit/tests/test_addon_protocol.py @@ -25,7 +25,7 @@ class _MyCapability(enum.Enum): UNUSED = "unused" # for testing when a capability has no operations ### - # shared test env (on `self`) + # shared test env (initialized by setUpClass) _MyProtocol: type # typing.Protocol subclass decorated with `@addon_protocol` _MyImplementation: type # subclass of _MyProtocol _my_imp: AddonImp