diff --git a/dapr/actor/__init__.py b/dapr/actor/__init__.py index 4323caae2..bf21f488c 100644 --- a/dapr/actor/__init__.py +++ b/dapr/actor/__init__.py @@ -20,7 +20,6 @@ from dapr.actor.runtime.remindable import Remindable from dapr.actor.runtime.runtime import ActorRuntime - __all__ = [ 'ActorInterface', 'ActorProxy', diff --git a/dapr/actor/client/proxy.py b/dapr/actor/client/proxy.py index a7648bf97..dcf1ca436 100644 --- a/dapr/actor/client/proxy.py +++ b/dapr/actor/client/proxy.py @@ -21,8 +21,8 @@ from dapr.actor.runtime._type_utils import get_dispatchable_attrs_from_interface from dapr.clients import DaprActorClientBase, DaprActorHttpClient from dapr.clients.retry import RetryPolicy -from dapr.serializers import Serializer, DefaultJSONSerializer from dapr.conf import settings +from dapr.serializers import DefaultJSONSerializer, Serializer # Actor factory Callable type hint. ACTOR_FACTORY_CALLBACK = Callable[[ActorInterface, str, str], 'ActorProxy'] @@ -35,8 +35,7 @@ def create( actor_type: str, actor_id: ActorId, actor_interface: Optional[Type[ActorInterface]] = None, - ) -> 'ActorProxy': - ... + ) -> 'ActorProxy': ... class ActorProxyFactory(ActorFactoryBase): diff --git a/dapr/actor/runtime/_reminder_data.py b/dapr/actor/runtime/_reminder_data.py index 8821c94bc..5453b8162 100644 --- a/dapr/actor/runtime/_reminder_data.py +++ b/dapr/actor/runtime/_reminder_data.py @@ -14,7 +14,6 @@ """ import base64 - from datetime import timedelta from typing import Any, Dict, Optional diff --git a/dapr/actor/runtime/_state_provider.py b/dapr/actor/runtime/_state_provider.py index 54f6b5837..eeb1e4995 100644 --- a/dapr/actor/runtime/_state_provider.py +++ b/dapr/actor/runtime/_state_provider.py @@ -14,12 +14,11 @@ """ import io +from typing import Any, List, Tuple, Type -from typing import Any, List, Type, Tuple -from dapr.actor.runtime.state_change import StateChangeKind, ActorStateChange +from dapr.actor.runtime.state_change import ActorStateChange, StateChangeKind from dapr.clients.base import DaprActorClientBase -from dapr.serializers import Serializer, DefaultJSONSerializer - +from dapr.serializers import DefaultJSONSerializer, Serializer # Mapping StateChangeKind to Dapr State Operation _MAP_CHANGE_KIND_TO_OPERATION = { diff --git a/dapr/actor/runtime/_type_information.py b/dapr/actor/runtime/_type_information.py index 72566eb17..f9171aea8 100644 --- a/dapr/actor/runtime/_type_information.py +++ b/dapr/actor/runtime/_type_information.py @@ -13,10 +13,10 @@ limitations under the License. """ -from dapr.actor.runtime.remindable import Remindable -from dapr.actor.runtime._type_utils import is_dapr_actor, get_actor_interfaces +from typing import TYPE_CHECKING, List, Type -from typing import List, Type, TYPE_CHECKING +from dapr.actor.runtime._type_utils import get_actor_interfaces, is_dapr_actor +from dapr.actor.runtime.remindable import Remindable if TYPE_CHECKING: from dapr.actor.actor_interface import ActorInterface # noqa: F401 diff --git a/dapr/actor/runtime/actor.py b/dapr/actor/runtime/actor.py index 79b1e6ab1..fab02fc70 100644 --- a/dapr/actor/runtime/actor.py +++ b/dapr/actor/runtime/actor.py @@ -14,16 +14,15 @@ """ import uuid - from datetime import timedelta from typing import Any, Optional from dapr.actor.id import ActorId from dapr.actor.runtime._method_context import ActorMethodContext -from dapr.actor.runtime.context import ActorRuntimeContext -from dapr.actor.runtime.state_manager import ActorStateManager from dapr.actor.runtime._reminder_data import ActorReminderData from dapr.actor.runtime._timer_data import TIMER_CALLBACK, ActorTimerData +from dapr.actor.runtime.context import ActorRuntimeContext +from dapr.actor.runtime.state_manager import ActorStateManager class Actor: diff --git a/dapr/actor/runtime/context.py b/dapr/actor/runtime/context.py index ec66ba366..b2610bed4 100644 --- a/dapr/actor/runtime/context.py +++ b/dapr/actor/runtime/context.py @@ -13,16 +13,16 @@ limitations under the License. """ +from typing import TYPE_CHECKING, Callable, Optional + from dapr.actor.id import ActorId from dapr.actor.runtime._state_provider import StateProvider from dapr.clients.base import DaprActorClientBase from dapr.serializers import Serializer -from typing import Callable, Optional, TYPE_CHECKING - if TYPE_CHECKING: - from dapr.actor.runtime.actor import Actor from dapr.actor.runtime._type_information import ActorTypeInformation + from dapr.actor.runtime.actor import Actor class ActorRuntimeContext: diff --git a/dapr/actor/runtime/manager.py b/dapr/actor/runtime/manager.py index a6d1a792a..969e48e2a 100644 --- a/dapr/actor/runtime/manager.py +++ b/dapr/actor/runtime/manager.py @@ -15,17 +15,16 @@ import asyncio import uuid - from typing import Any, Callable, Coroutine, Dict, Optional from dapr.actor.id import ActorId -from dapr.clients.exceptions import DaprInternalError +from dapr.actor.runtime._method_context import ActorMethodContext +from dapr.actor.runtime._reminder_data import ActorReminderData from dapr.actor.runtime.actor import Actor from dapr.actor.runtime.context import ActorRuntimeContext -from dapr.actor.runtime._method_context import ActorMethodContext from dapr.actor.runtime.method_dispatcher import ActorMethodDispatcher -from dapr.actor.runtime._reminder_data import ActorReminderData from dapr.actor.runtime.reentrancy_context import reentrancy_ctx +from dapr.clients.exceptions import DaprInternalError TIMER_METHOD_NAME = 'fire_timer' REMINDER_METHOD_NAME = 'receive_reminder' diff --git a/dapr/actor/runtime/method_dispatcher.py b/dapr/actor/runtime/method_dispatcher.py index 8d9b65114..ffe66d991 100644 --- a/dapr/actor/runtime/method_dispatcher.py +++ b/dapr/actor/runtime/method_dispatcher.py @@ -14,9 +14,10 @@ """ from typing import Any, Dict, List -from dapr.actor.runtime.actor import Actor + from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.actor.runtime._type_utils import get_dispatchable_attrs +from dapr.actor.runtime.actor import Actor class ActorMethodDispatcher: diff --git a/dapr/actor/runtime/reentrancy_context.py b/dapr/actor/runtime/reentrancy_context.py index 0fc9927df..b295b57d7 100644 --- a/dapr/actor/runtime/reentrancy_context.py +++ b/dapr/actor/runtime/reentrancy_context.py @@ -13,7 +13,7 @@ limitations under the License. """ -from typing import Optional from contextvars import ContextVar +from typing import Optional reentrancy_ctx: ContextVar[Optional[str]] = ContextVar('reentrancy_ctx', default=None) diff --git a/dapr/actor/runtime/runtime.py b/dapr/actor/runtime/runtime.py index 3659f1479..b03f0bc75 100644 --- a/dapr/actor/runtime/runtime.py +++ b/dapr/actor/runtime/runtime.py @@ -14,20 +14,18 @@ """ import asyncio - -from typing import Dict, List, Optional, Type, Callable +from typing import Callable, Dict, List, Optional, Type from dapr.actor.id import ActorId +from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.actor.runtime.actor import Actor from dapr.actor.runtime.config import ActorRuntimeConfig from dapr.actor.runtime.context import ActorRuntimeContext -from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.actor.runtime.manager import ActorManager +from dapr.actor.runtime.reentrancy_context import reentrancy_ctx from dapr.clients.http.dapr_actor_http_client import DaprActorHttpClient -from dapr.serializers import Serializer, DefaultJSONSerializer from dapr.conf import settings - -from dapr.actor.runtime.reentrancy_context import reentrancy_ctx +from dapr.serializers import DefaultJSONSerializer, Serializer class ActorRuntime: diff --git a/dapr/actor/runtime/state_change.py b/dapr/actor/runtime/state_change.py index dba21e2c1..4937fcb53 100644 --- a/dapr/actor/runtime/state_change.py +++ b/dapr/actor/runtime/state_change.py @@ -14,7 +14,7 @@ """ from enum import Enum -from typing import TypeVar, Generic, Optional +from typing import Generic, Optional, TypeVar T = TypeVar('T') diff --git a/dapr/aio/clients/__init__.py b/dapr/aio/clients/__init__.py index e945b1307..3f7ce6363 100644 --- a/dapr/aio/clients/__init__.py +++ b/dapr/aio/clients/__init__.py @@ -15,14 +15,15 @@ from typing import Callable, Dict, List, Optional, Union +from google.protobuf.message import Message as GrpcMessage + +from dapr.aio.clients.grpc.client import DaprGrpcClientAsync, InvokeMethodResponse, MetadataTuple from dapr.clients.base import DaprActorClientBase -from dapr.clients.exceptions import DaprInternalError, ERROR_CODE_UNKNOWN -from dapr.aio.clients.grpc.client import DaprGrpcClientAsync, MetadataTuple, InvokeMethodResponse -from dapr.clients.grpc._jobs import Job, FailurePolicy, DropFailurePolicy, ConstantFailurePolicy +from dapr.clients.exceptions import ERROR_CODE_UNKNOWN, DaprInternalError +from dapr.clients.grpc._jobs import ConstantFailurePolicy, DropFailurePolicy, FailurePolicy, Job from dapr.clients.http.dapr_actor_http_client import DaprActorHttpClient from dapr.clients.http.dapr_invocation_http_client import DaprInvocationHttpClient from dapr.conf import settings -from google.protobuf.message import Message as GrpcMessage __all__ = [ 'DaprClient', @@ -37,10 +38,10 @@ ] from grpc.aio import ( # type: ignore - UnaryUnaryClientInterceptor, - UnaryStreamClientInterceptor, - StreamUnaryClientInterceptor, StreamStreamClientInterceptor, + StreamUnaryClientInterceptor, + UnaryStreamClientInterceptor, + UnaryUnaryClientInterceptor, ) diff --git a/dapr/aio/clients/grpc/_request.py b/dapr/aio/clients/grpc/_request.py index b3c3ce2d4..129c556f3 100644 --- a/dapr/aio/clients/grpc/_request.py +++ b/dapr/aio/clients/grpc/_request.py @@ -16,7 +16,7 @@ import io from typing import Union -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions from dapr.clients.grpc._helpers import to_bytes from dapr.clients.grpc._request import DaprRequest from dapr.proto import api_v1, common_v1 diff --git a/dapr/aio/clients/grpc/_response.py b/dapr/aio/clients/grpc/_response.py index 480eb7769..5380ede6d 100644 --- a/dapr/aio/clients/grpc/_response.py +++ b/dapr/aio/clients/grpc/_response.py @@ -15,8 +15,8 @@ from typing import AsyncGenerator, Generic -from dapr.proto import api_v1 from dapr.clients.grpc._response import DaprResponse, TCryptoResponse +from dapr.proto import api_v1 class CryptoResponse(DaprResponse, Generic[TCryptoResponse]): @@ -83,9 +83,7 @@ async def read(self, size: int = -1) -> bytes: return data[:size] -class EncryptResponse(CryptoResponse[api_v1.EncryptResponse]): - ... +class EncryptResponse(CryptoResponse[api_v1.EncryptResponse]): ... -class DecryptResponse(CryptoResponse[api_v1.DecryptResponse]): - ... +class DecryptResponse(CryptoResponse[api_v1.DecryptResponse]): ... diff --git a/dapr/aio/clients/grpc/client.py b/dapr/aio/clients/grpc/client.py index 995b82680..6a5185770 100644 --- a/dapr/aio/clients/grpc/client.py +++ b/dapr/aio/clients/grpc/client.py @@ -14,96 +14,90 @@ """ import asyncio -import time -import socket import json +import socket +import time import uuid - from datetime import datetime +from typing import Any, Awaitable, Callable, Dict, List, Optional, Sequence, Text, Union from urllib.parse import urlencode - from warnings import warn -from typing import Callable, Dict, Optional, Text, Union, Sequence, List, Any, Awaitable -from typing_extensions import Self - -from google.protobuf.message import Message as GrpcMessage -from google.protobuf.empty_pb2 import Empty as GrpcEmpty -from google.protobuf.any_pb2 import Any as GrpcAny - import grpc.aio # type: ignore +from google.protobuf.any_pb2 import Any as GrpcAny +from google.protobuf.empty_pb2 import Empty as GrpcEmpty +from google.protobuf.message import Message as GrpcMessage from grpc.aio import ( # type: ignore - UnaryUnaryClientInterceptor, - UnaryStreamClientInterceptor, - StreamUnaryClientInterceptor, - StreamStreamClientInterceptor, AioRpcError, + StreamStreamClientInterceptor, + StreamUnaryClientInterceptor, + UnaryStreamClientInterceptor, + UnaryUnaryClientInterceptor, ) +from typing_extensions import Self -from dapr.aio.clients.grpc.subscription import Subscription -from dapr.clients.exceptions import DaprInternalError, DaprGrpcError -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions -from dapr.clients.grpc._state import StateOptions, StateItem -from dapr.clients.grpc._helpers import getWorkflowRuntimeStatus -from dapr.clients.health import DaprHealth -from dapr.clients.retry import RetryPolicy -from dapr.common.pubsub.subscription import StreamInactiveError -from dapr.conf.helpers import GrpcEndpoint -from dapr.conf import settings -from dapr.proto import api_v1, api_service_v1, common_v1 -from dapr.proto.runtime.v1.dapr_pb2 import UnsubscribeConfigurationResponse -from dapr.version import __version__ - +from dapr.aio.clients.grpc._request import ( + DecryptRequestIterator, + EncryptRequestIterator, +) +from dapr.aio.clients.grpc._response import ( + DecryptResponse, + EncryptResponse, +) from dapr.aio.clients.grpc.interceptors import ( DaprClientInterceptorAsync, DaprClientTimeoutInterceptorAsync, ) +from dapr.aio.clients.grpc.subscription import Subscription +from dapr.clients.exceptions import DaprGrpcError, DaprInternalError +from dapr.clients.grpc import conversation +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions from dapr.clients.grpc._helpers import ( MetadataTuple, - to_bytes, - validateNotNone, - validateNotBlankString, convert_dict_to_grpc_dict_of_any, convert_value_to_struct, + getWorkflowRuntimeStatus, + to_bytes, + validateNotBlankString, + validateNotNone, ) -from dapr.aio.clients.grpc._request import ( - EncryptRequestIterator, - DecryptRequestIterator, -) -from dapr.aio.clients.grpc._response import ( - EncryptResponse, - DecryptResponse, -) +from dapr.clients.grpc._jobs import Job from dapr.clients.grpc._request import ( - InvokeMethodRequest, BindingRequest, + InvokeMethodRequest, TransactionalStateOperation, ) -from dapr.clients.grpc import conversation - -from dapr.clients.grpc._jobs import Job from dapr.clients.grpc._response import ( BindingResponse, + BulkStateItem, + BulkStatesResponse, + ConfigurationResponse, + ConfigurationWatcher, DaprResponse, - GetSecretResponse, GetBulkSecretResponse, GetMetadataResponse, + GetSecretResponse, + GetWorkflowResponse, InvokeMethodResponse, - UnlockResponseStatus, - StateResponse, - BulkStatesResponse, - BulkStateItem, - ConfigurationResponse, QueryResponse, QueryResponseItem, RegisteredComponents, - ConfigurationWatcher, - TryLockResponse, - UnlockResponse, - GetWorkflowResponse, StartWorkflowResponse, + StateResponse, TopicEventResponse, + TryLockResponse, + UnlockResponse, + UnlockResponseStatus, ) +from dapr.clients.grpc._state import StateItem, StateOptions +from dapr.clients.health import DaprHealth +from dapr.clients.retry import RetryPolicy +from dapr.common.pubsub.subscription import StreamInactiveError +from dapr.conf import settings +from dapr.conf.helpers import GrpcEndpoint +from dapr.proto import api_service_v1, api_v1, common_v1 +from dapr.proto.runtime.v1.dapr_pb2 import UnsubscribeConfigurationResponse +from dapr.version import __version__ class DaprGrpcClientAsync: @@ -170,7 +164,7 @@ def __init__( if not address: address = settings.DAPR_GRPC_ENDPOINT or ( - f'{settings.DAPR_RUNTIME_HOST}:' f'{settings.DAPR_GRPC_PORT}' + f'{settings.DAPR_RUNTIME_HOST}:{settings.DAPR_GRPC_PORT}' ) try: diff --git a/dapr/aio/clients/grpc/interceptors.py b/dapr/aio/clients/grpc/interceptors.py index bf83cf56a..0444d5acb 100644 --- a/dapr/aio/clients/grpc/interceptors.py +++ b/dapr/aio/clients/grpc/interceptors.py @@ -16,7 +16,11 @@ from collections import namedtuple from typing import List, Tuple -from grpc.aio import UnaryUnaryClientInterceptor, StreamStreamClientInterceptor, ClientCallDetails # type: ignore +from grpc.aio import ( # type: ignore + ClientCallDetails, + StreamStreamClientInterceptor, + UnaryUnaryClientInterceptor, +) from dapr.conf import settings diff --git a/dapr/aio/clients/grpc/subscription.py b/dapr/aio/clients/grpc/subscription.py index 9aabf8b28..137badd21 100644 --- a/dapr/aio/clients/grpc/subscription.py +++ b/dapr/aio/clients/grpc/subscription.py @@ -1,13 +1,14 @@ import asyncio + from grpc import StatusCode from grpc.aio import AioRpcError from dapr.clients.grpc._response import TopicEventResponse from dapr.clients.health import DaprHealth from dapr.common.pubsub.subscription import ( + StreamCancelledError, StreamInactiveError, SubscriptionMessage, - StreamCancelledError, ) from dapr.proto import api_v1, appcallback_v1 diff --git a/dapr/clients/__init__.py b/dapr/clients/__init__.py index 78ad99eb4..5d92b56c7 100644 --- a/dapr/clients/__init__.py +++ b/dapr/clients/__init__.py @@ -16,16 +16,16 @@ from typing import Callable, Dict, List, Optional, Union from warnings import warn +from google.protobuf.message import Message as GrpcMessage + from dapr.clients.base import DaprActorClientBase -from dapr.clients.exceptions import DaprInternalError, ERROR_CODE_UNKNOWN -from dapr.clients.grpc.client import DaprGrpcClient, MetadataTuple, InvokeMethodResponse -from dapr.clients.grpc._jobs import Job, FailurePolicy, DropFailurePolicy, ConstantFailurePolicy +from dapr.clients.exceptions import ERROR_CODE_UNKNOWN, DaprInternalError +from dapr.clients.grpc._jobs import ConstantFailurePolicy, DropFailurePolicy, FailurePolicy, Job +from dapr.clients.grpc.client import DaprGrpcClient, InvokeMethodResponse, MetadataTuple from dapr.clients.http.dapr_actor_http_client import DaprActorHttpClient from dapr.clients.http.dapr_invocation_http_client import DaprInvocationHttpClient from dapr.clients.retry import RetryPolicy from dapr.conf import settings -from google.protobuf.message import Message as GrpcMessage - __all__ = [ 'DaprClient', @@ -41,10 +41,10 @@ from grpc import ( # type: ignore - UnaryUnaryClientInterceptor, - UnaryStreamClientInterceptor, - StreamUnaryClientInterceptor, StreamStreamClientInterceptor, + StreamUnaryClientInterceptor, + UnaryStreamClientInterceptor, + UnaryUnaryClientInterceptor, ) diff --git a/dapr/clients/base.py b/dapr/clients/base.py index d2b972245..da2bb5257 100644 --- a/dapr/clients/base.py +++ b/dapr/clients/base.py @@ -23,31 +23,28 @@ class DaprActorClientBase(ABC): @abstractmethod async def invoke_method( self, actor_type: str, actor_id: str, method: str, data: Optional[bytes] = None - ) -> bytes: - ... + ) -> bytes: ... @abstractmethod - async def save_state_transactionally(self, actor_type: str, actor_id: str, data: bytes) -> None: - ... + async def save_state_transactionally( + self, actor_type: str, actor_id: str, data: bytes + ) -> None: ... @abstractmethod - async def get_state(self, actor_type: str, actor_id: str, name: str) -> bytes: - ... + async def get_state(self, actor_type: str, actor_id: str, name: str) -> bytes: ... @abstractmethod async def register_reminder( self, actor_type: str, actor_id: str, name: str, data: bytes - ) -> None: - ... + ) -> None: ... @abstractmethod - async def unregister_reminder(self, actor_type: str, actor_id: str, name: str) -> None: - ... + async def unregister_reminder(self, actor_type: str, actor_id: str, name: str) -> None: ... @abstractmethod - async def register_timer(self, actor_type: str, actor_id: str, name: str, data: bytes) -> None: - ... + async def register_timer( + self, actor_type: str, actor_id: str, name: str, data: bytes + ) -> None: ... @abstractmethod - async def unregister_timer(self, actor_type: str, actor_id: str, name: str) -> None: - ... + async def unregister_timer(self, actor_type: str, actor_id: str, name: str) -> None: ... diff --git a/dapr/clients/exceptions.py b/dapr/clients/exceptions.py index 61ae0d8b6..f6358cb85 100644 --- a/dapr/clients/exceptions.py +++ b/dapr/clients/exceptions.py @@ -12,6 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. """ + import base64 import json from typing import TYPE_CHECKING, Optional @@ -20,9 +21,9 @@ from dapr.serializers import Serializer from google.protobuf.json_format import MessageToDict +from google.rpc import error_details_pb2 # type: ignore from grpc import RpcError # type: ignore from grpc_status import rpc_status # type: ignore -from google.rpc import error_details_pb2 # type: ignore ERROR_CODE_UNKNOWN = 'UNKNOWN' ERROR_CODE_DOES_NOT_EXIST = 'ERR_DOES_NOT_EXIST' diff --git a/dapr/clients/grpc/_conversation_helpers.py b/dapr/clients/grpc/_conversation_helpers.py index 37bb81c18..9f57c9cc7 100644 --- a/dapr/clients/grpc/_conversation_helpers.py +++ b/dapr/clients/grpc/_conversation_helpers.py @@ -16,6 +16,7 @@ import inspect import random import string +import types from dataclasses import fields, is_dataclass from enum import Enum from typing import ( @@ -23,21 +24,19 @@ Callable, Dict, List, + Literal, Mapping, Optional, Sequence, Union, - Literal, + cast, get_args, get_origin, get_type_hints, - cast, ) from dapr.conf import settings -import types - # Make mypy happy. Runtime handle: real class on 3.10+, else None. # TODO: Python 3.9 is about to be end-of-life, so we can drop this at some point next year (2026) UnionType: Any = getattr(types, 'UnionType', None) @@ -190,14 +189,14 @@ def _json_primitive_type(v: Any) -> str: if settings.DAPR_CONVERSATION_TOOLS_LARGE_ENUM_BEHAVIOR == 'error': raise ValueError( f"Enum '{getattr(python_type, '__name__', str(python_type))}' has {count} members, " - f"exceeding DAPR_CONVERSATION_MAX_ENUM_ITEMS={settings.DAPR_CONVERSATION_TOOLS_MAX_ENUM_ITEMS}. " - f"Either reduce the enum size or set DAPR_CONVERSATION_LARGE_ENUM_BEHAVIOR=string to allow compact schema." + f'exceeding DAPR_CONVERSATION_MAX_ENUM_ITEMS={settings.DAPR_CONVERSATION_TOOLS_MAX_ENUM_ITEMS}. ' + f'Either reduce the enum size or set DAPR_CONVERSATION_LARGE_ENUM_BEHAVIOR=string to allow compact schema.' ) # Default behavior: compact schema as a string with helpful context and a few examples example_values = [item.value for item in members[:5]] if members else [] desc = ( - f"{getattr(python_type, '__name__', 'Enum')} (enum with {count} values). " - f"Provide a valid value. Schema compacted to avoid oversized enum listing." + f'{getattr(python_type, "__name__", "Enum")} (enum with {count} values). ' + f'Provide a valid value. Schema compacted to avoid oversized enum listing.' ) schema = {'type': 'string', 'description': desc} if example_values: @@ -696,8 +695,8 @@ def stringify_tool_output(value: Any) -> str: * dataclass -> asdict If JSON serialization still fails, fallback to str(value). If that fails, return ''. """ - import json as _json import base64 as _b64 + import json as _json from dataclasses import asdict as _asdict if isinstance(value, str): @@ -760,20 +759,16 @@ def _default(o: Any): # --- Errors ---- -class ToolError(RuntimeError): - ... +class ToolError(RuntimeError): ... -class ToolNotFoundError(ToolError): - ... +class ToolNotFoundError(ToolError): ... -class ToolExecutionError(ToolError): - ... +class ToolExecutionError(ToolError): ... -class ToolArgumentError(ToolError): - ... +class ToolArgumentError(ToolError): ... def _coerce_bool(value: Any) -> bool: @@ -962,7 +957,7 @@ def _coerce_and_validate(value: Any, expected_type: Any) -> Any: missing.append(pname) if missing: raise ValueError( - f"Missing required constructor arg(s) for {expected_type.__name__}: {', '.join(missing)}" + f'Missing required constructor arg(s) for {expected_type.__name__}: {", ".join(missing)}' ) try: return expected_type(**kwargs) @@ -978,7 +973,7 @@ def _coerce_and_validate(value: Any, expected_type: Any) -> Any: if expected_type is Any or isinstance(value, expected_type): return value raise ValueError( - f"Expected {getattr(expected_type, '__name__', str(expected_type))}, got {type(value).__name__}" + f'Expected {getattr(expected_type, "__name__", str(expected_type))}, got {type(value).__name__}' ) @@ -1014,12 +1009,12 @@ def bind_params_to_func(fn: Callable[..., Any], params: Params): and p.name not in bound.arguments ] if missing: - raise ToolArgumentError(f"Missing required parameter(s): {', '.join(missing)}") + raise ToolArgumentError(f'Missing required parameter(s): {", ".join(missing)}') # unexpected kwargs unless **kwargs present if not any(p.kind is inspect.Parameter.VAR_KEYWORD for p in sig.parameters.values()): extra = set(params) - set(sig.parameters) if extra: - raise ToolArgumentError(f"Unexpected parameter(s): {', '.join(sorted(extra))}") + raise ToolArgumentError(f'Unexpected parameter(s): {", ".join(sorted(extra))}') elif isinstance(params, Sequence): bound = sig.bind(*params) else: diff --git a/dapr/clients/grpc/_helpers.py b/dapr/clients/grpc/_helpers.py index c68b0f56a..8eb9a1e97 100644 --- a/dapr/clients/grpc/_helpers.py +++ b/dapr/clients/grpc/_helpers.py @@ -12,22 +12,22 @@ See the License for the specific language governing permissions and limitations under the License. """ -from enum import Enum -from typing import Any, Dict, List, Optional, Union, Tuple +from enum import Enum +from typing import Any, Dict, List, Optional, Tuple, Union +from google.protobuf import json_format from google.protobuf.any_pb2 import Any as GrpcAny from google.protobuf.message import Message as GrpcMessage +from google.protobuf.struct_pb2 import Struct from google.protobuf.wrappers_pb2 import ( BoolValue, - StringValue, + BytesValue, + DoubleValue, Int32Value, Int64Value, - DoubleValue, - BytesValue, + StringValue, ) -from google.protobuf.struct_pb2 import Struct -from google.protobuf import json_format MetadataDict = Dict[str, List[Union[bytes, str]]] MetadataTuple = Tuple[Tuple[str, Union[bytes, str]], ...] diff --git a/dapr/clients/grpc/_jobs.py b/dapr/clients/grpc/_jobs.py index 896c8db3c..5df9975f0 100644 --- a/dapr/clients/grpc/_jobs.py +++ b/dapr/clients/grpc/_jobs.py @@ -117,9 +117,10 @@ def _get_proto(self): Returns: api_v1.Job: The proto representation of this job. """ - from dapr.proto.runtime.v1 import dapr_pb2 as api_v1 from google.protobuf.any_pb2 import Any as GrpcAny + from dapr.proto.runtime.v1 import dapr_pb2 as api_v1 + # Build the job proto job_proto = api_v1.Job(name=self.name) diff --git a/dapr/clients/grpc/_response.py b/dapr/clients/grpc/_response.py index fff511ff7..6898bc42d 100644 --- a/dapr/clients/grpc/_response.py +++ b/dapr/clients/grpc/_response.py @@ -21,19 +21,19 @@ from datetime import datetime from enum import Enum from typing import ( + TYPE_CHECKING, Callable, Dict, + Generator, + Generic, List, + Mapping, + NamedTuple, Optional, - Text, - Union, Sequence, - TYPE_CHECKING, - NamedTuple, - Generator, + Text, TypeVar, - Generic, - Mapping, + Union, ) from google.protobuf.any_pb2 import Any as GrpcAny @@ -43,11 +43,11 @@ from dapr.clients.grpc._helpers import ( MetadataDict, MetadataTuple, + WorkflowRuntimeStatus, to_bytes, to_str, tuple_to_dict, unpack, - WorkflowRuntimeStatus, ) from dapr.proto import api_service_v1, api_v1, appcallback_v1, common_v1 @@ -707,9 +707,9 @@ def _read_subscribe_config( handler: Callable[[Text, ConfigurationResponse], None], ): try: - responses: List[ - api_v1.SubscribeConfigurationResponse - ] = stub.SubscribeConfigurationAlpha1(req) + responses: List[api_v1.SubscribeConfigurationResponse] = ( + stub.SubscribeConfigurationAlpha1(req) + ) isFirst = True for response in responses: if isFirst: @@ -719,7 +719,7 @@ def _read_subscribe_config( if len(response.items) > 0: handler(response.id, ConfigurationResponse(response.items)) except Exception: - print(f'{self.store_name} configuration watcher for keys ' f'{self.keys} stopped.') + print(f'{self.store_name} configuration watcher for keys {self.keys} stopped.') pass @@ -1065,9 +1065,7 @@ def read(self, size: int = -1) -> bytes: return data[:size] -class EncryptResponse(CryptoResponse[TCryptoResponse]): - ... +class EncryptResponse(CryptoResponse[TCryptoResponse]): ... -class DecryptResponse(CryptoResponse[TCryptoResponse]): - ... +class DecryptResponse(CryptoResponse[TCryptoResponse]): ... diff --git a/dapr/clients/grpc/_state.py b/dapr/clients/grpc/_state.py index 3dc266b22..e20df4293 100644 --- a/dapr/clients/grpc/_state.py +++ b/dapr/clients/grpc/_state.py @@ -1,7 +1,8 @@ from enum import Enum -from dapr.proto import common_v1 from typing import Dict, Optional, Union +from dapr.proto import common_v1 + class Consistency(Enum): """Represents the consistency mode for a Dapr State Api Call""" diff --git a/dapr/clients/grpc/client.py b/dapr/clients/grpc/client.py index e4ffb2646..469681c96 100644 --- a/dapr/clients/grpc/client.py +++ b/dapr/clients/grpc/client.py @@ -12,89 +12,85 @@ See the License for the specific language governing permissions and limitations under the License. """ + +import json +import socket import threading import time -import socket -import json import uuid - +from datetime import datetime +from typing import Any, Callable, Dict, List, Optional, Sequence, Text, Union from urllib.parse import urlencode - from warnings import warn -from typing import Callable, Dict, Optional, Text, Union, Sequence, List, Any - -from typing_extensions import Self -from datetime import datetime -from google.protobuf.message import Message as GrpcMessage -from google.protobuf.empty_pb2 import Empty as GrpcEmpty -from google.protobuf.any_pb2 import Any as GrpcAny - import grpc # type: ignore +from google.protobuf.any_pb2 import Any as GrpcAny +from google.protobuf.empty_pb2 import Empty as GrpcEmpty +from google.protobuf.message import Message as GrpcMessage from grpc import ( # type: ignore - UnaryUnaryClientInterceptor, - UnaryStreamClientInterceptor, - StreamUnaryClientInterceptor, - StreamStreamClientInterceptor, RpcError, + StreamStreamClientInterceptor, + StreamUnaryClientInterceptor, + UnaryStreamClientInterceptor, + UnaryUnaryClientInterceptor, ) +from typing_extensions import Self -from dapr.clients.exceptions import DaprInternalError, DaprGrpcError -from dapr.clients.grpc._state import StateOptions, StateItem -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions -from dapr.clients.grpc.subscription import Subscription, StreamInactiveError -from dapr.clients.grpc.interceptors import DaprClientInterceptor, DaprClientTimeoutInterceptor -from dapr.clients.health import DaprHealth -from dapr.clients.retry import RetryPolicy -from dapr.common.pubsub.subscription import StreamCancelledError -from dapr.conf import settings -from dapr.proto import api_v1, api_service_v1, common_v1 -from dapr.proto.runtime.v1.dapr_pb2 import UnsubscribeConfigurationResponse -from dapr.version import __version__ - +from dapr.clients.exceptions import DaprGrpcError, DaprInternalError +from dapr.clients.grpc import conversation +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions from dapr.clients.grpc._helpers import ( - getWorkflowRuntimeStatus, MetadataTuple, - to_bytes, - validateNotNone, - validateNotBlankString, convert_dict_to_grpc_dict_of_any, convert_value_to_struct, + getWorkflowRuntimeStatus, + to_bytes, + validateNotBlankString, + validateNotNone, ) -from dapr.conf.helpers import GrpcEndpoint +from dapr.clients.grpc._jobs import Job from dapr.clients.grpc._request import ( - InvokeMethodRequest, BindingRequest, - TransactionalStateOperation, - EncryptRequestIterator, DecryptRequestIterator, + EncryptRequestIterator, + InvokeMethodRequest, + TransactionalStateOperation, ) -from dapr.clients.grpc import conversation -from dapr.clients.grpc._jobs import Job from dapr.clients.grpc._response import ( BindingResponse, + BulkStateItem, + BulkStatesResponse, + ConfigurationResponse, + ConfigurationWatcher, DaprResponse, - GetSecretResponse, + DecryptResponse, + EncryptResponse, GetBulkSecretResponse, GetMetadataResponse, + GetSecretResponse, + GetWorkflowResponse, InvokeMethodResponse, - UnlockResponseStatus, - StateResponse, - BulkStatesResponse, - BulkStateItem, - ConfigurationResponse, QueryResponse, QueryResponseItem, RegisteredComponents, - ConfigurationWatcher, - TryLockResponse, - UnlockResponse, - GetWorkflowResponse, StartWorkflowResponse, - EncryptResponse, - DecryptResponse, + StateResponse, TopicEventResponse, + TryLockResponse, + UnlockResponse, + UnlockResponseStatus, ) +from dapr.clients.grpc._state import StateItem, StateOptions +from dapr.clients.grpc.interceptors import DaprClientInterceptor, DaprClientTimeoutInterceptor +from dapr.clients.grpc.subscription import StreamInactiveError, Subscription +from dapr.clients.health import DaprHealth +from dapr.clients.retry import RetryPolicy +from dapr.common.pubsub.subscription import StreamCancelledError +from dapr.conf import settings +from dapr.conf.helpers import GrpcEndpoint, build_grpc_channel_options +from dapr.proto import api_service_v1, api_v1, common_v1 +from dapr.proto.runtime.v1.dapr_pb2 import UnsubscribeConfigurationResponse +from dapr.version import __version__ class DaprGrpcClient: @@ -150,11 +146,9 @@ def __init__( useragent = f'dapr-sdk-python/{__version__}' if not max_grpc_message_length: - options = [ - ('grpc.primary_user_agent', useragent), - ] + base_options = [('grpc.primary_user_agent', useragent)] else: - options = [ + base_options = [ ('grpc.max_send_message_length', max_grpc_message_length), # type: ignore ('grpc.max_receive_message_length', max_grpc_message_length), # type: ignore ('grpc.primary_user_agent', useragent), @@ -162,7 +156,7 @@ def __init__( if not address: address = settings.DAPR_GRPC_ENDPOINT or ( - f'{settings.DAPR_RUNTIME_HOST}:' f'{settings.DAPR_GRPC_PORT}' + f'{settings.DAPR_RUNTIME_HOST}:{settings.DAPR_GRPC_PORT}' ) try: @@ -170,6 +164,9 @@ def __init__( except ValueError as error: raise DaprInternalError(f'{error}') from error + # Merge standard + keepalive + retry options + options = build_grpc_channel_options(base_options) + if self._uri.tls: self._channel = grpc.secure_channel( # type: ignore self._uri.endpoint, diff --git a/dapr/clients/grpc/conversation.py b/dapr/clients/grpc/conversation.py index 1da02dac2..d11c41979 100644 --- a/dapr/clients/grpc/conversation.py +++ b/dapr/clients/grpc/conversation.py @@ -12,6 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. """ + from __future__ import annotations import asyncio @@ -400,13 +401,11 @@ def convert_llm_response_to_conversation_input( class ToolBackend(Protocol): """Interface for executors that knows how to execute a tool call.""" - def invoke(self, spec: ConversationToolsFunction, params: Params) -> Any: - ... + def invoke(self, spec: ConversationToolsFunction, params: Params) -> Any: ... async def ainvoke( self, spec: ConversationToolsFunction, params: Params, *, timeout: Union[float, None] = None - ) -> Any: - ... + ) -> Any: ... @dataclass diff --git a/dapr/clients/grpc/interceptors.py b/dapr/clients/grpc/interceptors.py index 15bde1857..a574fb8c6 100644 --- a/dapr/clients/grpc/interceptors.py +++ b/dapr/clients/grpc/interceptors.py @@ -1,7 +1,11 @@ from collections import namedtuple from typing import List, Tuple -from grpc import UnaryUnaryClientInterceptor, ClientCallDetails, StreamStreamClientInterceptor # type: ignore +from grpc import ( # type: ignore + ClientCallDetails, + StreamStreamClientInterceptor, + UnaryUnaryClientInterceptor, +) from dapr.conf import settings diff --git a/dapr/clients/grpc/subscription.py b/dapr/clients/grpc/subscription.py index 111946b1b..152ca84bb 100644 --- a/dapr/clients/grpc/subscription.py +++ b/dapr/clients/grpc/subscription.py @@ -1,16 +1,17 @@ -from grpc import RpcError, StatusCode, Call # type: ignore +import queue +import threading +from typing import Optional + +from grpc import Call, RpcError, StatusCode # type: ignore from dapr.clients.grpc._response import TopicEventResponse from dapr.clients.health import DaprHealth from dapr.common.pubsub.subscription import ( + StreamCancelledError, StreamInactiveError, SubscriptionMessage, - StreamCancelledError, ) from dapr.proto import api_v1, appcallback_v1 -import queue -import threading -from typing import Optional class Subscription: diff --git a/dapr/clients/health.py b/dapr/clients/health.py index e3daec79d..4f3bdf8dc 100644 --- a/dapr/clients/health.py +++ b/dapr/clients/health.py @@ -12,11 +12,12 @@ See the License for the specific language governing permissions and limitations under the License. """ -import urllib.request -import urllib.error + import time +import urllib.error +import urllib.request -from dapr.clients.http.conf import DAPR_API_TOKEN_HEADER, USER_AGENT_HEADER, DAPR_USER_AGENT +from dapr.clients.http.conf import DAPR_API_TOKEN_HEADER, DAPR_USER_AGENT, USER_AGENT_HEADER from dapr.clients.http.helpers import get_api_url from dapr.conf import settings diff --git a/dapr/clients/http/client.py b/dapr/clients/http/client.py index 86e9ab6f0..072f31b15 100644 --- a/dapr/clients/http/client.py +++ b/dapr/clients/http/client.py @@ -13,25 +13,25 @@ limitations under the License. """ -import aiohttp +from typing import TYPE_CHECKING, Callable, Dict, Mapping, Optional, Tuple, Union -from typing import Callable, Mapping, Dict, Optional, Union, Tuple, TYPE_CHECKING +import aiohttp from dapr.clients.health import DaprHealth from dapr.clients.http.conf import ( + CONTENT_TYPE_HEADER, DAPR_API_TOKEN_HEADER, - USER_AGENT_HEADER, DAPR_USER_AGENT, - CONTENT_TYPE_HEADER, + USER_AGENT_HEADER, ) from dapr.clients.retry import RetryPolicy if TYPE_CHECKING: from dapr.serializers import Serializer -from dapr.conf import settings from dapr.clients._constants import DEFAULT_JSON_CONTENT_TYPE from dapr.clients.exceptions import DaprHttpError, DaprInternalError +from dapr.conf import settings class DaprHttpClient: diff --git a/dapr/clients/http/dapr_actor_http_client.py b/dapr/clients/http/dapr_actor_http_client.py index 186fdbc1c..711153659 100644 --- a/dapr/clients/http/dapr_actor_http_client.py +++ b/dapr/clients/http/dapr_actor_http_client.py @@ -13,15 +13,15 @@ limitations under the License. """ -from typing import Callable, Dict, Optional, Union, TYPE_CHECKING +from typing import TYPE_CHECKING, Callable, Dict, Optional, Union from dapr.clients.http.helpers import get_api_url if TYPE_CHECKING: from dapr.serializers import Serializer -from dapr.clients.http.client import DaprHttpClient from dapr.clients.base import DaprActorClientBase +from dapr.clients.http.client import DaprHttpClient from dapr.clients.retry import RetryPolicy DAPR_REENTRANCY_ID_HEADER = 'Dapr-Reentrancy-Id' diff --git a/dapr/clients/http/dapr_invocation_http_client.py b/dapr/clients/http/dapr_invocation_http_client.py index df4e6d222..604c483c0 100644 --- a/dapr/clients/http/dapr_invocation_http_client.py +++ b/dapr/clients/http/dapr_invocation_http_client.py @@ -14,13 +14,13 @@ """ import asyncio - from typing import Callable, Dict, Optional, Union + from multidict import MultiDict -from dapr.clients.http.client import DaprHttpClient -from dapr.clients.grpc._helpers import MetadataTuple, GrpcMessage +from dapr.clients.grpc._helpers import GrpcMessage, MetadataTuple from dapr.clients.grpc._response import InvokeMethodResponse +from dapr.clients.http.client import DaprHttpClient from dapr.clients.http.conf import CONTENT_TYPE_HEADER from dapr.clients.http.helpers import get_api_url from dapr.clients.retry import RetryPolicy diff --git a/dapr/clients/retry.py b/dapr/clients/retry.py index 171c96fbd..e895e46f3 100644 --- a/dapr/clients/retry.py +++ b/dapr/clients/retry.py @@ -12,11 +12,12 @@ See the License for the specific language governing permissions and limitations under the License. """ + import asyncio -from typing import Optional, List, Callable +import time +from typing import Callable, List, Optional from grpc import RpcError, StatusCode # type: ignore -import time from dapr.conf import settings diff --git a/dapr/common/pubsub/subscription.py b/dapr/common/pubsub/subscription.py index 6f68e180d..eb22a48da 100644 --- a/dapr/common/pubsub/subscription.py +++ b/dapr/common/pubsub/subscription.py @@ -1,7 +1,9 @@ import json +from typing import Optional, Union + from google.protobuf.json_format import MessageToDict + from dapr.proto.runtime.v1.appcallback_pb2 import TopicEventRequest -from typing import Optional, Union class SubscriptionMessage: diff --git a/dapr/conf/__init__.py b/dapr/conf/__init__.py index 7fbe5f2f7..0959311ab 100644 --- a/dapr/conf/__init__.py +++ b/dapr/conf/__init__.py @@ -24,9 +24,7 @@ def __init__(self): default_value = getattr(global_settings, setting) env_variable = os.environ.get(setting) if env_variable: - val = ( - type(default_value)(env_variable) if default_value is not None else env_variable - ) + val = self._coerce_env_value(default_value, env_variable) setattr(self, setting, val) else: setattr(self, setting, default_value) @@ -36,5 +34,27 @@ def __getattr__(self, name): raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'") return getattr(self, name) + @staticmethod + def _coerce_env_value(default_value, env_variable: str): + if default_value is None: + return env_variable + # Handle booleans explicitly to avoid bool('false') == True + if isinstance(default_value, bool): + s = env_variable.strip().lower() + if s in ('1', 'true', 't', 'yes', 'y', 'on'): + return True + if s in ('0', 'false', 'f', 'no', 'n', 'off'): + return False + # Fallback: non-empty -> True for backward-compat + return bool(s) + # Integers + if isinstance(default_value, int) and not isinstance(default_value, bool): + return int(env_variable) + # Floats + if isinstance(default_value, float): + return float(env_variable) + # Other types: try to cast as before + return type(default_value)(env_variable) + settings = Settings() diff --git a/dapr/conf/global_settings.py b/dapr/conf/global_settings.py index 5a64e5d4c..dd2bae86d 100644 --- a/dapr/conf/global_settings.py +++ b/dapr/conf/global_settings.py @@ -34,6 +34,23 @@ DAPR_HTTP_TIMEOUT_SECONDS = 60 +# gRPC keepalive (disabled by default; enable via env to help with idle debugging sessions) +DAPR_GRPC_KEEPALIVE_ENABLED: bool = False +DAPR_GRPC_KEEPALIVE_TIME_MS: int = 120000 # send keepalive pings every 120s +DAPR_GRPC_KEEPALIVE_TIMEOUT_MS: int = ( + 20000 # wait 20s for ack before considering the connection dead +) +DAPR_GRPC_KEEPALIVE_PERMIT_WITHOUT_CALLS: bool = False # allow pings when there are no active calls + +# gRPC retries (disabled by default; enable via env to apply channel service config) +DAPR_GRPC_RETRY_ENABLED: bool = False +DAPR_GRPC_RETRY_MAX_ATTEMPTS: int = 4 +DAPR_GRPC_RETRY_INITIAL_BACKOFF_MS: int = 100 +DAPR_GRPC_RETRY_MAX_BACKOFF_MS: int = 1000 +DAPR_GRPC_RETRY_BACKOFF_MULTIPLIER: float = 2.0 +# Comma-separated list of status codes, e.g., 'UNAVAILABLE,DEADLINE_EXCEEDED' +DAPR_GRPC_RETRY_CODES: str = 'UNAVAILABLE,DEADLINE_EXCEEDED' + # ----- Conversation API settings ------ # Configuration for handling large enums to avoid massive JSON schemas that can exceed LLM token limits diff --git a/dapr/conf/helpers.py b/dapr/conf/helpers.py index ab1e494b2..c6c121f47 100644 --- a/dapr/conf/helpers.py +++ b/dapr/conf/helpers.py @@ -1,5 +1,8 @@ +import json +from urllib.parse import ParseResult, parse_qs, urlparse from warnings import warn -from urllib.parse import urlparse, parse_qs, ParseResult + +from dapr.conf import settings class URIParseConfig: @@ -174,7 +177,7 @@ def tls(self) -> bool: def _validate_path_and_query(self) -> None: if self._parsed_url.path: raise ValueError( - f'paths are not supported for gRPC endpoints:' f" '{self._parsed_url.path}'" + f"paths are not supported for gRPC endpoints: '{self._parsed_url.path}'" ) if self._parsed_url.query: query_dict = parse_qs(self._parsed_url.query) @@ -189,3 +192,68 @@ def _validate_path_and_query(self) -> None: f'query parameters are not supported for gRPC endpoints:' f" '{self._parsed_url.query}'" ) + + +# ------------------------------ +# gRPC channel options helpers +# ------------------------------ + + +def get_grpc_keepalive_options(): + """Return a list of keepalive channel options if enabled, else empty list. + + Options are tuples suitable for passing to grpc.{secure,insecure}_channel. + """ + if not settings.DAPR_GRPC_KEEPALIVE_ENABLED: + return [] + return [ + ('grpc.keepalive_time_ms', int(settings.DAPR_GRPC_KEEPALIVE_TIME_MS)), + ('grpc.keepalive_timeout_ms', int(settings.DAPR_GRPC_KEEPALIVE_TIMEOUT_MS)), + ( + 'grpc.keepalive_permit_without_calls', + 1 if settings.DAPR_GRPC_KEEPALIVE_PERMIT_WITHOUT_CALLS else 0, + ), + ] + + +def get_grpc_retry_service_config_option(): + """Return ('grpc.service_config', json) option if retry is enabled, else None. + + Applies a universal retry policy via gRPC service config. + """ + if not getattr(settings, 'DAPR_GRPC_RETRY_ENABLED', False): + return None + retry_policy = { + 'maxAttempts': int(settings.DAPR_GRPC_RETRY_MAX_ATTEMPTS), + 'initialBackoff': f'{int(settings.DAPR_GRPC_RETRY_INITIAL_BACKOFF_MS) / 1000.0}s', + 'maxBackoff': f'{int(settings.DAPR_GRPC_RETRY_MAX_BACKOFF_MS) / 1000.0}s', + 'backoffMultiplier': float(settings.DAPR_GRPC_RETRY_BACKOFF_MULTIPLIER), + 'retryableStatusCodes': [ + c.strip() for c in str(settings.DAPR_GRPC_RETRY_CODES).split(',') if c.strip() + ], + } + service_config = { + 'methodConfig': [ + { + 'name': [{'service': ''}], # apply to all services + 'retryPolicy': retry_policy, + } + ] + } + return ('grpc.service_config', json.dumps(service_config)) + + +def build_grpc_channel_options(base_options=None): + """Combine base options with keepalive and retry policy options. + + Args: + base_options: optional iterable of (key, value) tuples. + Returns: + list of (key, value) tuples. + """ + options = list(base_options or []) + options.extend(get_grpc_keepalive_options()) + retry_opt = get_grpc_retry_service_config_option() + if retry_opt is not None: + options.append(retry_opt) + return options diff --git a/dapr/serializers/base.py b/dapr/serializers/base.py index 5ff1d9e8b..1aa7dfc89 100644 --- a/dapr/serializers/base.py +++ b/dapr/serializers/base.py @@ -23,8 +23,7 @@ class Serializer(ABC): @abstractmethod def serialize( self, obj: object, custom_hook: Optional[Callable[[object], bytes]] = None - ) -> bytes: - ... + ) -> bytes: ... @abstractmethod def deserialize( @@ -32,5 +31,4 @@ def deserialize( data: bytes, data_type: Optional[Type] = object, custom_hook: Optional[Callable[[bytes], object]] = None, - ) -> Any: - ... + ) -> Any: ... diff --git a/dapr/serializers/json.py b/dapr/serializers/json.py index 4e9665187..59e1c194b 100644 --- a/dapr/serializers/json.py +++ b/dapr/serializers/json.py @@ -14,18 +14,18 @@ """ import base64 -import re import datetime import json - +import re from typing import Any, Callable, Optional, Type + from dateutil import parser from dapr.serializers.base import Serializer from dapr.serializers.util import ( + DAPR_DURATION_PARSER, convert_from_dapr_duration, convert_to_dapr_duration, - DAPR_DURATION_PARSER, ) diff --git a/dev-requirements.txt b/dev-requirements.txt index cbd719859..87b8bf30b 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -3,7 +3,9 @@ mypy-extensions>=0.4.3 mypy-protobuf>=2.9 flake8>=3.7.9 tox>=4.3.0 +pip>=23.0.0 coverage>=5.3 +pytest wheel # used in unit test only opentelemetry-sdk @@ -13,7 +15,7 @@ pyOpenSSL>=23.2.0 # needed for type checking Flask>=1.1 # needed for auto fix -ruff===0.2.2 +ruff===0.14.0 # needed for dapr-ext-workflow durabletask-dapr >= 0.2.0a7 # needed for .env file loading in examples @@ -22,3 +24,4 @@ python-dotenv>=1.0.0 pydantic>=2.0.0 # needed for yaml file generation in examples PyYAML>=6.0.2 + diff --git a/examples/configuration/configuration.py b/examples/configuration/configuration.py index caf676e6b..d579df7fa 100644 --- a/examples/configuration/configuration.py +++ b/examples/configuration/configuration.py @@ -4,8 +4,9 @@ import asyncio from time import sleep + from dapr.clients import DaprClient -from dapr.clients.grpc._response import ConfigurationWatcher, ConfigurationResponse +from dapr.clients.grpc._response import ConfigurationResponse, ConfigurationWatcher configuration: ConfigurationWatcher = ConfigurationWatcher() diff --git a/examples/conversation/real_llm_providers_example.py b/examples/conversation/real_llm_providers_example.py index c103007e0..83affcd40 100644 --- a/examples/conversation/real_llm_providers_example.py +++ b/examples/conversation/real_llm_providers_example.py @@ -163,8 +163,8 @@ def create_tool_from_typed_function_example() -> conversation.ConversationTools: This shows the most advanced approach: define a typed function and automatically generate the complete tool schema from type hints and docstrings. """ - from typing import Optional, List from enum import Enum + from typing import List, Optional conversation.unregister_tool('find_restaurants') @@ -205,8 +205,8 @@ def create_tool_from_tool_decorator_example() -> conversation.ConversationTools: This shows the most advanced approach: define a typed function and automatically generate the complete tool schema from type hints and docstrings. """ - from typing import Optional, List from enum import Enum + from typing import List, Optional conversation.unregister_tool('find_restaurants') @@ -417,7 +417,7 @@ def create_component_configs(self, selected_providers: Optional[List[str]] = Non def test_basic_conversation_alpha2(self, provider_id: str) -> None: """Test basic Alpha2 conversation with a provider.""" print( - f"\n๐Ÿ’ฌ Testing Alpha2 basic conversation with {self.available_providers[provider_id]['display_name']}" + f'\n๐Ÿ’ฌ Testing Alpha2 basic conversation with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -453,7 +453,7 @@ def test_basic_conversation_alpha2(self, provider_id: str) -> None: def test_multi_turn_conversation_alpha2(self, provider_id: str) -> None: """Test multi-turn Alpha2 conversation with different message types.""" print( - f"\n๐Ÿ”„ Testing Alpha2 multi-turn conversation with {self.available_providers[provider_id]['display_name']}" + f'\n๐Ÿ”„ Testing Alpha2 multi-turn conversation with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -484,7 +484,7 @@ def test_multi_turn_conversation_alpha2(self, provider_id: str) -> None: f'โœ… Multi-turn conversation processed {len(response.outputs[0].choices)} message(s)' ) for i, choice in enumerate(response.outputs[0].choices): - print(f' Response {i+1}: {choice.message.content[:100]}...') + print(f' Response {i + 1}: {choice.message.content[:100]}...') else: print('โŒ No multi-turn response received') @@ -494,7 +494,7 @@ def test_multi_turn_conversation_alpha2(self, provider_id: str) -> None: def test_tool_calling_alpha2(self, provider_id: str) -> None: """Test Alpha2 tool calling with a provider.""" print( - f"\n๐Ÿ”ง Testing Alpha2 tool calling with {self.available_providers[provider_id]['display_name']}" + f'\n๐Ÿ”ง Testing Alpha2 tool calling with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -560,7 +560,7 @@ def test_tool_calling_alpha2(self, provider_id: str) -> None: def test_parameter_conversion(self, provider_id: str) -> None: """Test the new parameter conversion feature.""" print( - f"\n๐Ÿ”„ Testing parameter conversion with {self.available_providers[provider_id]['display_name']}" + f'\n๐Ÿ”„ Testing parameter conversion with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -612,7 +612,7 @@ def test_parameter_conversion(self, provider_id: str) -> None: def test_multi_turn_tool_calling_alpha2(self, provider_id: str) -> None: """Test multi-turn Alpha2 tool calling with proper context accumulation.""" print( - f"\n๐Ÿ”„๐Ÿ”ง Testing multi-turn tool calling with {self.available_providers[provider_id]['display_name']}" + f'\n๐Ÿ”„๐Ÿ”ง Testing multi-turn tool calling with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -802,7 +802,7 @@ def test_multi_turn_tool_calling_alpha2(self, provider_id: str) -> None: def test_multi_turn_tool_calling_alpha2_tool_helpers(self, provider_id: str) -> None: """Test multi-turn Alpha2 tool calling with proper context accumulation using higher level abstractions.""" print( - f"\n๐Ÿ”„๐Ÿ”ง Testing multi-turn tool calling with {self.available_providers[provider_id]['display_name']}" + f'\n๐Ÿ”„๐Ÿ”ง Testing multi-turn tool calling with {self.available_providers[provider_id]["display_name"]}' ) # using decorator @@ -954,7 +954,7 @@ def append_response_to_history( def test_function_to_schema_approach(self, provider_id: str) -> None: """Test the best DevEx for most cases: function-to-JSON-schema automatic tool creation.""" print( - f"\n๐ŸŽฏ Testing function-to-schema approach with {self.available_providers[provider_id]['display_name']}" + f'\n๐ŸŽฏ Testing function-to-schema approach with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -1002,7 +1002,7 @@ def test_function_to_schema_approach(self, provider_id: str) -> None: def test_tool_decorated_function_to_schema_approach(self, provider_id: str) -> None: """Test the best DevEx for most cases: function-to-JSON-schema automatic tool creation.""" print( - f"\n๐ŸŽฏ Testing decorator tool function-to-schema approach with {self.available_providers[provider_id]['display_name']}" + f'\n๐ŸŽฏ Testing decorator tool function-to-schema approach with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -1052,7 +1052,7 @@ def test_tool_decorated_function_to_schema_approach(self, provider_id: str) -> N async def test_async_conversation_alpha2(self, provider_id: str) -> None: """Test async Alpha2 conversation with a provider.""" print( - f"\nโšก Testing async Alpha2 conversation with {self.available_providers[provider_id]['display_name']}" + f'\nโšก Testing async Alpha2 conversation with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -1083,7 +1083,7 @@ async def test_async_conversation_alpha2(self, provider_id: str) -> None: async def test_async_tool_calling_alpha2(self, provider_id: str) -> None: """Test async Alpha2 tool calling with a provider.""" print( - f"\n๐Ÿ”งโšก Testing async Alpha2 tool calling with {self.available_providers[provider_id]['display_name']}" + f'\n๐Ÿ”งโšก Testing async Alpha2 tool calling with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -1125,9 +1125,9 @@ async def test_async_tool_calling_alpha2(self, provider_id: str) -> None: def run_comprehensive_test(self, provider_id: str) -> None: """Run comprehensive Alpha2 tests for a provider.""" provider_name = self.available_providers[provider_id]['display_name'] - print(f"\n{'='*60}") + print(f'\n{"=" * 60}') print(f'๐Ÿงช Testing {provider_name} with Alpha2 API') - print(f"{'='*60}") + print(f'{"=" * 60}') # Alpha2 Sync tests self.test_basic_conversation_alpha2(provider_id) @@ -1149,7 +1149,7 @@ def run_comprehensive_test(self, provider_id: str) -> None: def test_basic_conversation_alpha1_legacy(self, provider_id: str) -> None: """Test legacy Alpha1 conversation for comparison.""" print( - f"\n๐Ÿ“š Testing legacy Alpha1 for comparison with {self.available_providers[provider_id]['display_name']}" + f'\n๐Ÿ“š Testing legacy Alpha1 for comparison with {self.available_providers[provider_id]["display_name"]}' ) try: @@ -1235,7 +1235,7 @@ def main(): if provider_id in tester.available_providers: tester.run_comprehensive_test(provider_id) - print(f"\n{'='*60}") + print(f'\n{"=" * 60}') print('๐ŸŽ‰ All Alpha2 tests completed!') print('โœ… Real LLM provider integration with Alpha2 API is working correctly') print('๐Ÿ”ง Features demonstrated:') @@ -1248,7 +1248,7 @@ def main(): print(' โ€ข Function-to-schema using @tool decorator for automatic tool generation') print(' โ€ข Both sync and async implementations') print(' โ€ข Backward compatibility with Alpha1') - print(f"{'='*60}") + print(f'{"=" * 60}') except KeyboardInterrupt: print('\n\nโน๏ธ Tests interrupted by user') diff --git a/examples/crypto/crypto-async.py b/examples/crypto/crypto-async.py index 0946e9bbb..2e49a8282 100644 --- a/examples/crypto/crypto-async.py +++ b/examples/crypto/crypto-async.py @@ -14,7 +14,7 @@ import asyncio from dapr.aio.clients import DaprClient -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions # Name of the crypto component to use CRYPTO_COMPONENT_NAME = 'crypto-localstorage' diff --git a/examples/crypto/crypto.py b/examples/crypto/crypto.py index a282ba453..afe00f343 100644 --- a/examples/crypto/crypto.py +++ b/examples/crypto/crypto.py @@ -12,7 +12,7 @@ # ------------------------------------------------------------ from dapr.clients import DaprClient -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions # Name of the crypto component to use CRYPTO_COMPONENT_NAME = 'crypto-localstorage' diff --git a/examples/demo_actor/demo_actor/demo_actor.py b/examples/demo_actor/demo_actor/demo_actor.py index 0d65d57d2..f9306d47c 100644 --- a/examples/demo_actor/demo_actor/demo_actor.py +++ b/examples/demo_actor/demo_actor/demo_actor.py @@ -11,10 +11,11 @@ # limitations under the License. import datetime +from typing import Optional -from dapr.actor import Actor, Remindable from demo_actor_interface import DemoActorInterface -from typing import Optional + +from dapr.actor import Actor, Remindable class DemoActor(Actor, DemoActorInterface, Remindable): diff --git a/examples/demo_actor/demo_actor/demo_actor_client.py b/examples/demo_actor/demo_actor/demo_actor_client.py index df0e9f737..ad0dfccb6 100644 --- a/examples/demo_actor/demo_actor/demo_actor_client.py +++ b/examples/demo_actor/demo_actor/demo_actor_client.py @@ -12,10 +12,11 @@ import asyncio -from dapr.actor import ActorProxy, ActorId, ActorProxyFactory -from dapr.clients.retry import RetryPolicy from demo_actor_interface import DemoActorInterface +from dapr.actor import ActorId, ActorProxy, ActorProxyFactory +from dapr.clients.retry import RetryPolicy + async def main(): # Create proxy client diff --git a/examples/demo_actor/demo_actor/demo_actor_flask.py b/examples/demo_actor/demo_actor/demo_actor_flask.py index 5715d23d8..de1245ad0 100644 --- a/examples/demo_actor/demo_actor/demo_actor_flask.py +++ b/examples/demo_actor/demo_actor/demo_actor_flask.py @@ -10,13 +10,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +from demo_actor import DemoActor from flask import Flask, jsonify from flask_dapr.actor import DaprActor -from dapr.conf import settings -from dapr.actor.runtime.config import ActorRuntimeConfig, ActorTypeConfig, ActorReentrancyConfig +from dapr.actor.runtime.config import ActorReentrancyConfig, ActorRuntimeConfig, ActorTypeConfig from dapr.actor.runtime.runtime import ActorRuntime -from demo_actor import DemoActor +from dapr.conf import settings app = Flask(f'{DemoActor.__name__}Service') diff --git a/examples/demo_actor/demo_actor/demo_actor_interface.py b/examples/demo_actor/demo_actor/demo_actor_interface.py index be43c2ed6..51c3880c5 100644 --- a/examples/demo_actor/demo_actor/demo_actor_interface.py +++ b/examples/demo_actor/demo_actor/demo_actor_interface.py @@ -18,30 +18,24 @@ class DemoActorInterface(ActorInterface): @abstractmethod @actormethod(name='GetMyData') - async def get_my_data(self) -> object: - ... + async def get_my_data(self) -> object: ... @abstractmethod @actormethod(name='SetMyData') - async def set_my_data(self, data: object) -> None: - ... + async def set_my_data(self, data: object) -> None: ... @abstractmethod @actormethod(name='ClearMyData') - async def clear_my_data(self) -> None: - ... + async def clear_my_data(self) -> None: ... @abstractmethod @actormethod(name='SetReminder') - async def set_reminder(self, enabled: bool) -> None: - ... + async def set_reminder(self, enabled: bool) -> None: ... @abstractmethod @actormethod(name='SetTimer') - async def set_timer(self, enabled: bool) -> None: - ... + async def set_timer(self, enabled: bool) -> None: ... @abstractmethod @actormethod(name='GetReentrancyStatus') - async def get_reentrancy_status(self) -> bool: - ... + async def get_reentrancy_status(self) -> bool: ... diff --git a/examples/demo_actor/demo_actor/demo_actor_service.py b/examples/demo_actor/demo_actor/demo_actor_service.py index c53d06e25..c67b28c87 100644 --- a/examples/demo_actor/demo_actor/demo_actor_service.py +++ b/examples/demo_actor/demo_actor/demo_actor_service.py @@ -10,12 +10,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from fastapi import FastAPI # type: ignore -from dapr.actor.runtime.config import ActorRuntimeConfig, ActorTypeConfig, ActorReentrancyConfig -from dapr.actor.runtime.runtime import ActorRuntime from dapr.ext.fastapi import DaprActor # type: ignore from demo_actor import DemoActor +from fastapi import FastAPI # type: ignore +from dapr.actor.runtime.config import ActorReentrancyConfig, ActorRuntimeConfig, ActorTypeConfig +from dapr.actor.runtime.runtime import ActorRuntime app = FastAPI(title=f'{DemoActor.__name__}Service') diff --git a/examples/demo_workflow/app.py b/examples/demo_workflow/app.py index c89dcae6e..36ad5e843 100644 --- a/examples/demo_workflow/app.py +++ b/examples/demo_workflow/app.py @@ -12,15 +12,17 @@ from datetime import timedelta from time import sleep + from dapr.ext.workflow import ( - WorkflowRuntime, DaprWorkflowContext, - WorkflowActivityContext, RetryPolicy, + WorkflowActivityContext, + WorkflowRuntime, ) -from dapr.conf import Settings + from dapr.clients import DaprClient from dapr.clients.exceptions import DaprInternalError +from dapr.conf import Settings settings = Settings() @@ -192,8 +194,7 @@ def main(): instance_id=instance_id, workflow_component=workflow_component ) print( - f'Get response from {workflow_name} ' - f'after terminate call: {get_response.runtime_status}' + f'Get response from {workflow_name} after terminate call: {get_response.runtime_status}' ) child_get_response = d.get_workflow( instance_id=child_instance_id, workflow_component=workflow_component diff --git a/examples/distributed_lock/lock.py b/examples/distributed_lock/lock.py index d18d955f6..2f6364065 100644 --- a/examples/distributed_lock/lock.py +++ b/examples/distributed_lock/lock.py @@ -11,9 +11,10 @@ # limitations under the License. # ------------------------------------------------------------ -from dapr.clients import DaprClient import warnings +from dapr.clients import DaprClient + def main(): # Lock parameters diff --git a/examples/error_handling/error_handling.py b/examples/error_handling/error_handling.py index b75ebed97..ae42a88cd 100644 --- a/examples/error_handling/error_handling.py +++ b/examples/error_handling/error_handling.py @@ -1,7 +1,6 @@ from dapr.clients import DaprClient from dapr.clients.exceptions import DaprGrpcError - with DaprClient() as d: storeName = 'statestore' diff --git a/examples/grpc_proxying/helloworld_service_pb2.py b/examples/grpc_proxying/helloworld_service_pb2.py index e05049653..09e0a62ff 100644 --- a/examples/grpc_proxying/helloworld_service_pb2.py +++ b/examples/grpc_proxying/helloworld_service_pb2.py @@ -2,11 +2,13 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # source: helloworld_service.proto """Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() diff --git a/examples/grpc_proxying/helloworld_service_pb2_grpc.py b/examples/grpc_proxying/helloworld_service_pb2_grpc.py index b5403111b..14b2d40ee 100644 --- a/examples/grpc_proxying/helloworld_service_pb2_grpc.py +++ b/examples/grpc_proxying/helloworld_service_pb2_grpc.py @@ -1,7 +1,7 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" -import grpc +import grpc import helloworld_service_pb2 as helloworld__service__pb2 diff --git a/examples/grpc_proxying/invoke-caller.py b/examples/grpc_proxying/invoke-caller.py index a07298448..51b748296 100644 --- a/examples/grpc_proxying/invoke-caller.py +++ b/examples/grpc_proxying/invoke-caller.py @@ -1,10 +1,11 @@ import asyncio +import json import logging +import time import grpc import helloworld_service_pb2_grpc -from helloworld_service_pb2 import HelloRequest, HelloReply -import json, time +from helloworld_service_pb2 import HelloReply, HelloRequest async def run() -> None: diff --git a/examples/grpc_proxying/invoke-receiver.py b/examples/grpc_proxying/invoke-receiver.py index ec36b036c..0b31b53ad 100644 --- a/examples/grpc_proxying/invoke-receiver.py +++ b/examples/grpc_proxying/invoke-receiver.py @@ -1,10 +1,10 @@ +import json import logging import grpc import helloworld_service_pb2_grpc -from helloworld_service_pb2 import HelloRequest, HelloReply from dapr.ext.grpc import App -import json +from helloworld_service_pb2 import HelloReply, HelloRequest class HelloWorldService(helloworld_service_pb2_grpc.HelloWorldService): diff --git a/examples/invoke-custom-data/invoke-caller.py b/examples/invoke-custom-data/invoke-caller.py index 27dabd4de..caeb84313 100644 --- a/examples/invoke-custom-data/invoke-caller.py +++ b/examples/invoke-custom-data/invoke-caller.py @@ -1,7 +1,7 @@ -from dapr.clients import DaprClient - import proto.response_pb2 as response_messages +from dapr.clients import DaprClient + with DaprClient() as d: # Create a typed message with content type and body resp = d.invoke_method( diff --git a/examples/invoke-custom-data/invoke-receiver.py b/examples/invoke-custom-data/invoke-receiver.py index e2ad83ce5..543d4fceb 100644 --- a/examples/invoke-custom-data/invoke-receiver.py +++ b/examples/invoke-custom-data/invoke-receiver.py @@ -1,6 +1,5 @@ -from dapr.ext.grpc import App, InvokeMethodRequest - import proto.response_pb2 as response_messages +from dapr.ext.grpc import App, InvokeMethodRequest app = App() diff --git a/examples/invoke-custom-data/proto/response_pb2.py b/examples/invoke-custom-data/proto/response_pb2.py index 373ce113f..ae019cbcb 100644 --- a/examples/invoke-custom-data/proto/response_pb2.py +++ b/examples/invoke-custom-data/proto/response_pb2.py @@ -2,11 +2,13 @@ # Generated by the protocol buffer compiler. DO NOT EDIT! # source: response.proto """Generated protocol buffer code.""" + from google.protobuf import descriptor as _descriptor from google.protobuf import descriptor_pool as _descriptor_pool from google.protobuf import message as _message from google.protobuf import reflection as _reflection from google.protobuf import symbol_database as _symbol_database + # @@protoc_insertion_point(imports) _sym_db = _symbol_database.Default() diff --git a/examples/invoke-custom-data/proto/response_pb2_grpc.py b/examples/invoke-custom-data/proto/response_pb2_grpc.py index 8a9393943..bf947056a 100644 --- a/examples/invoke-custom-data/proto/response_pb2_grpc.py +++ b/examples/invoke-custom-data/proto/response_pb2_grpc.py @@ -1,3 +1,4 @@ # Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT! """Client and server classes corresponding to protobuf-defined services.""" + import grpc diff --git a/examples/invoke-http/invoke-receiver.py b/examples/invoke-http/invoke-receiver.py index 8609464af..928f86987 100644 --- a/examples/invoke-http/invoke-receiver.py +++ b/examples/invoke-http/invoke-receiver.py @@ -1,7 +1,8 @@ # from dapr.ext.grpc import App, InvokeMethodRequest, InvokeMethodResponse -from flask import Flask, request import json +from flask import Flask, request + app = Flask(__name__) diff --git a/examples/jobs/job_management.py b/examples/jobs/job_management.py index fd8c7af88..adfeefef4 100644 --- a/examples/jobs/job_management.py +++ b/examples/jobs/job_management.py @@ -1,9 +1,10 @@ import json from datetime import datetime, timedelta -from dapr.clients import DaprClient, Job, DropFailurePolicy, ConstantFailurePolicy from google.protobuf.any_pb2 import Any as GrpcAny +from dapr.clients import ConstantFailurePolicy, DaprClient, DropFailurePolicy, Job + def create_job_data(message: str): """Helper function to create job payload data.""" diff --git a/examples/jobs/job_processing.py b/examples/jobs/job_processing.py index 9f5733b79..a92a659f4 100644 --- a/examples/jobs/job_processing.py +++ b/examples/jobs/job_processing.py @@ -15,8 +15,10 @@ import threading import time from datetime import datetime, timedelta + from dapr.ext.grpc import App, JobEvent -from dapr.clients import DaprClient, Job, ConstantFailurePolicy + +from dapr.clients import ConstantFailurePolicy, DaprClient, Job try: from google.protobuf.any_pb2 import Any as GrpcAny diff --git a/examples/pubsub-simple/subscriber.py b/examples/pubsub-simple/subscriber.py index daa11bc89..4d36f2807 100644 --- a/examples/pubsub-simple/subscriber.py +++ b/examples/pubsub-simple/subscriber.py @@ -11,14 +11,15 @@ # limitations under the License. # ------------------------------------------------------------ +import json from time import sleep + from cloudevents.sdk.event import v1 from dapr.ext.grpc import App + from dapr.clients.grpc._response import TopicEventResponse from dapr.proto import appcallback_v1 -import json - app = App() should_retry = True # To control whether dapr should retry sending a message diff --git a/examples/pubsub-streaming-async/subscriber-handler.py b/examples/pubsub-streaming-async/subscriber-handler.py index 06a492af5..c9c8203c2 100644 --- a/examples/pubsub-streaming-async/subscriber-handler.py +++ b/examples/pubsub-streaming-async/subscriber-handler.py @@ -1,5 +1,6 @@ import argparse import asyncio + from dapr.aio.clients import DaprClient from dapr.clients.grpc._response import TopicEventResponse diff --git a/examples/state_store/state_store.py b/examples/state_store/state_store.py index 301c675bc..b783fcdc9 100644 --- a/examples/state_store/state_store.py +++ b/examples/state_store/state_store.py @@ -5,11 +5,9 @@ import grpc from dapr.clients import DaprClient - from dapr.clients.grpc._request import TransactionalStateOperation, TransactionOperationType from dapr.clients.grpc._state import StateItem - with DaprClient() as d: storeName = 'statestore' diff --git a/examples/state_store_query/state_store_query.py b/examples/state_store_query/state_store_query.py index f532f0eb0..26c64da3e 100644 --- a/examples/state_store_query/state_store_query.py +++ b/examples/state_store_query/state_store_query.py @@ -2,10 +2,9 @@ dapr run python3 state_store_query.py """ -from dapr.clients import DaprClient - import json +from dapr.clients import DaprClient with DaprClient() as d: store_name = 'statestore' diff --git a/examples/w3c-tracing/invoke-receiver.py b/examples/w3c-tracing/invoke-receiver.py index 92300aebe..a57d46cea 100644 --- a/examples/w3c-tracing/invoke-receiver.py +++ b/examples/w3c-tracing/invoke-receiver.py @@ -3,6 +3,7 @@ import typing from concurrent import futures +from dapr.ext.grpc import App, InvokeMethodRequest, InvokeMethodResponse from opentelemetry import trace from opentelemetry.exporter.zipkin.json import ZipkinExporter from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer, filters @@ -12,7 +13,6 @@ from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator from dapr.clients import DaprClient -from dapr.ext.grpc import App, InvokeMethodRequest, InvokeMethodResponse # Create a tracer provider tracer_provider = TracerProvider(sampler=ALWAYS_ON) diff --git a/examples/workflow/child_workflow.py b/examples/workflow/child_workflow.py index dccaa631b..57ab2fc3e 100644 --- a/examples/workflow/child_workflow.py +++ b/examples/workflow/child_workflow.py @@ -10,9 +10,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -import dapr.ext.workflow as wf import time +import dapr.ext.workflow as wf + wfr = wf.WorkflowRuntime() diff --git a/examples/workflow/fan_out_fan_in.py b/examples/workflow/fan_out_fan_in.py index e5799862f..f625ea287 100644 --- a/examples/workflow/fan_out_fan_in.py +++ b/examples/workflow/fan_out_fan_in.py @@ -12,6 +12,7 @@ import time from typing import List + import dapr.ext.workflow as wf wfr = wf.WorkflowRuntime() diff --git a/examples/workflow/human_approval.py b/examples/workflow/human_approval.py index 6a8a725d7..e12bf5b5e 100644 --- a/examples/workflow/human_approval.py +++ b/examples/workflow/human_approval.py @@ -11,13 +11,14 @@ # limitations under the License. import threading +import time from dataclasses import asdict, dataclass from datetime import timedelta -import time -from dapr.clients import DaprClient import dapr.ext.workflow as wf +from dapr.clients import DaprClient + wfr = wf.WorkflowRuntime() diff --git a/examples/workflow/monitor.py b/examples/workflow/monitor.py index 6cf575cfe..d4f534df5 100644 --- a/examples/workflow/monitor.py +++ b/examples/workflow/monitor.py @@ -10,10 +10,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +import random from dataclasses import dataclass from datetime import timedelta -import random from time import sleep + import dapr.ext.workflow as wf wfr = wf.WorkflowRuntime() diff --git a/examples/workflow/simple.py b/examples/workflow/simple.py index 76f21eba4..dc0ea0b6a 100644 --- a/examples/workflow/simple.py +++ b/examples/workflow/simple.py @@ -11,16 +11,18 @@ # limitations under the License. from datetime import timedelta from time import sleep + from dapr.ext.workflow import ( - WorkflowRuntime, + DaprWorkflowClient, DaprWorkflowContext, - WorkflowActivityContext, RetryPolicy, - DaprWorkflowClient, + WorkflowActivityContext, + WorkflowRuntime, when_any, ) -from dapr.conf import Settings + from dapr.clients.exceptions import DaprInternalError +from dapr.conf import Settings settings = Settings() diff --git a/examples/workflow/task_chaining.py b/examples/workflow/task_chaining.py index 074cadcd2..8a2058e1c 100644 --- a/examples/workflow/task_chaining.py +++ b/examples/workflow/task_chaining.py @@ -14,7 +14,6 @@ import dapr.ext.workflow as wf - wfr = wf.WorkflowRuntime() diff --git a/ext/dapr-ext-fastapi/dapr/ext/fastapi/__init__.py b/ext/dapr-ext-fastapi/dapr/ext/fastapi/__init__.py index 942603078..e43df65c9 100644 --- a/ext/dapr-ext-fastapi/dapr/ext/fastapi/__init__.py +++ b/ext/dapr-ext-fastapi/dapr/ext/fastapi/__init__.py @@ -16,5 +16,4 @@ from .actor import DaprActor from .app import DaprApp - __all__ = ['DaprActor', 'DaprApp'] diff --git a/ext/dapr-ext-fastapi/dapr/ext/fastapi/actor.py b/ext/dapr-ext-fastapi/dapr/ext/fastapi/actor.py index 93b7860e1..4b3990da4 100644 --- a/ext/dapr-ext-fastapi/dapr/ext/fastapi/actor.py +++ b/ext/dapr-ext-fastapi/dapr/ext/fastapi/actor.py @@ -13,12 +13,12 @@ limitations under the License. """ -from typing import Any, Optional, Type, List +from typing import Any, List, Optional, Type from dapr.actor import Actor, ActorRuntime from dapr.clients.exceptions import ERROR_CODE_UNKNOWN, DaprInternalError from dapr.serializers import DefaultJSONSerializer -from fastapi import FastAPI, APIRouter, Request, Response, status # type: ignore +from fastapi import APIRouter, FastAPI, Request, Response, status # type: ignore from fastapi.logger import logger from fastapi.responses import JSONResponse diff --git a/ext/dapr-ext-fastapi/dapr/ext/fastapi/app.py b/ext/dapr-ext-fastapi/dapr/ext/fastapi/app.py index d926fac5c..6bede5234 100644 --- a/ext/dapr-ext-fastapi/dapr/ext/fastapi/app.py +++ b/ext/dapr-ext-fastapi/dapr/ext/fastapi/app.py @@ -13,6 +13,7 @@ """ from typing import Dict, List, Optional + from fastapi import FastAPI # type: ignore diff --git a/ext/dapr-ext-fastapi/tests/test_app.py b/ext/dapr-ext-fastapi/tests/test_app.py index 831d55ebb..619697994 100644 --- a/ext/dapr-ext-fastapi/tests/test_app.py +++ b/ext/dapr-ext-fastapi/tests/test_app.py @@ -1,11 +1,10 @@ import unittest +from dapr.ext.fastapi import DaprApp from fastapi import FastAPI from fastapi.testclient import TestClient from pydantic import BaseModel -from dapr.ext.fastapi import DaprApp - class Message(BaseModel): body: str diff --git a/ext/dapr-ext-fastapi/tests/test_dapractor.py b/ext/dapr-ext-fastapi/tests/test_dapractor.py index ee863d726..71408c88c 100644 --- a/ext/dapr-ext-fastapi/tests/test_dapractor.py +++ b/ext/dapr-ext-fastapi/tests/test_dapractor.py @@ -16,9 +16,8 @@ import json import unittest -from fastapi import FastAPI - from dapr.ext.fastapi.actor import DaprActor, _wrap_response +from fastapi import FastAPI class DaprActorTest(unittest.TestCase): diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/__init__.py b/ext/dapr-ext-grpc/dapr/ext/grpc/__init__.py index 7d73b4a48..5324c6175 100644 --- a/ext/dapr-ext-grpc/dapr/ext/grpc/__init__.py +++ b/ext/dapr-ext-grpc/dapr/ext/grpc/__init__.py @@ -13,12 +13,11 @@ limitations under the License. """ -from dapr.clients.grpc._request import InvokeMethodRequest, BindingRequest, JobEvent -from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse -from dapr.clients.grpc._jobs import Job, FailurePolicy, DropFailurePolicy, ConstantFailurePolicy - from dapr.ext.grpc.app import App, Rule # type:ignore +from dapr.clients.grpc._jobs import ConstantFailurePolicy, DropFailurePolicy, FailurePolicy, Job +from dapr.clients.grpc._request import BindingRequest, InvokeMethodRequest, JobEvent +from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse __all__ = [ 'App', diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/_health_servicer.py b/ext/dapr-ext-grpc/dapr/ext/grpc/_health_servicer.py index 029dff745..f6d782da1 100644 --- a/ext/dapr-ext-grpc/dapr/ext/grpc/_health_servicer.py +++ b/ext/dapr-ext-grpc/dapr/ext/grpc/_health_servicer.py @@ -1,6 +1,6 @@ -import grpc from typing import Callable, Optional +import grpc from dapr.proto import appcallback_service_v1 from dapr.proto.runtime.v1.appcallback_pb2 import HealthCheckResponse diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/_servicer.py b/ext/dapr-ext-grpc/dapr/ext/grpc/_servicer.py index 996267fdd..8de632f97 100644 --- a/ext/dapr-ext-grpc/dapr/ext/grpc/_servicer.py +++ b/ext/dapr-ext-grpc/dapr/ext/grpc/_servicer.py @@ -12,25 +12,25 @@ See the License for the specific language governing permissions and limitations under the License. """ -import grpc -from cloudevents.sdk.event import v1 # type: ignore from typing import Callable, Dict, List, Optional, Tuple, Union +from cloudevents.sdk.event import v1 # type: ignore from google.protobuf import empty_pb2 from google.protobuf.message import Message as GrpcMessage from google.protobuf.struct_pb2 import Struct -from dapr.proto import appcallback_service_v1, common_v1, appcallback_v1 +import grpc +from dapr.clients._constants import DEFAULT_JSON_CONTENT_TYPE +from dapr.clients.grpc._request import BindingRequest, InvokeMethodRequest, JobEvent +from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse +from dapr.proto import appcallback_service_v1, appcallback_v1, common_v1 +from dapr.proto.common.v1.common_pb2 import InvokeRequest from dapr.proto.runtime.v1.appcallback_pb2 import ( - TopicEventRequest, BindingEventRequest, JobEventRequest, + TopicEventRequest, ) -from dapr.proto.common.v1.common_pb2 import InvokeRequest -from dapr.clients._constants import DEFAULT_JSON_CONTENT_TYPE -from dapr.clients.grpc._request import InvokeMethodRequest, BindingRequest, JobEvent -from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse InvokeMethodCallable = Callable[[InvokeMethodRequest], Union[str, bytes, InvokeMethodResponse]] TopicSubscribeCallable = Callable[[v1.Event], Optional[TopicEventResponse]] diff --git a/ext/dapr-ext-grpc/dapr/ext/grpc/app.py b/ext/dapr-ext-grpc/dapr/ext/grpc/app.py index 9f9ac8472..58e0cdf29 100644 --- a/ext/dapr-ext-grpc/dapr/ext/grpc/app.py +++ b/ext/dapr-ext-grpc/dapr/ext/grpc/app.py @@ -13,14 +13,14 @@ limitations under the License. """ -import grpc - from concurrent import futures from typing import Dict, Optional -from dapr.conf import settings -from dapr.ext.grpc._servicer import _CallbackServicer, Rule # type: ignore from dapr.ext.grpc._health_servicer import _HealthCheckServicer # type: ignore +from dapr.ext.grpc._servicer import Rule, _CallbackServicer # type: ignore + +import grpc +from dapr.conf import settings from dapr.proto import appcallback_service_v1 diff --git a/ext/dapr-ext-grpc/tests/test_app.py b/ext/dapr-ext-grpc/tests/test_app.py index 2a33dd668..315d9e18b 100644 --- a/ext/dapr-ext-grpc/tests/test_app.py +++ b/ext/dapr-ext-grpc/tests/test_app.py @@ -16,7 +16,7 @@ import unittest from cloudevents.sdk.event import v1 -from dapr.ext.grpc import App, Rule, InvokeMethodRequest, BindingRequest +from dapr.ext.grpc import App, BindingRequest, InvokeMethodRequest, Rule class AppTests(unittest.TestCase): diff --git a/ext/dapr-ext-grpc/tests/test_servicier.py b/ext/dapr-ext-grpc/tests/test_servicier.py index 2447eea3c..325d9b6d6 100644 --- a/ext/dapr-ext-grpc/tests/test_servicier.py +++ b/ext/dapr-ext-grpc/tests/test_servicier.py @@ -14,16 +14,15 @@ """ import unittest - from unittest.mock import MagicMock, Mock -from dapr.clients.grpc._request import InvokeMethodRequest -from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse from dapr.ext.grpc._servicer import _CallbackServicer -from dapr.proto import common_v1, appcallback_v1 - from google.protobuf.any_pb2 import Any as GrpcAny +from dapr.clients.grpc._request import InvokeMethodRequest +from dapr.clients.grpc._response import InvokeMethodResponse, TopicEventResponse +from dapr.proto import appcallback_v1, common_v1 + class OnInvokeTests(unittest.TestCase): def setUp(self): diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/__init__.py b/ext/dapr-ext-workflow/dapr/ext/workflow/__init__.py index f78615112..dd2d45b75 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/__init__.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/__init__.py @@ -14,12 +14,12 @@ """ # Import your main classes here -from dapr.ext.workflow.workflow_runtime import WorkflowRuntime, alternate_name from dapr.ext.workflow.dapr_workflow_client import DaprWorkflowClient from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext, when_all, when_any +from dapr.ext.workflow.retry_policy import RetryPolicy from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext +from dapr.ext.workflow.workflow_runtime import WorkflowRuntime, alternate_name from dapr.ext.workflow.workflow_state import WorkflowState, WorkflowStatus -from dapr.ext.workflow.retry_policy import RetryPolicy __all__ = [ 'WorkflowRuntime', diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_client.py b/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_client.py index cc384503a..461bfd43a 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_client.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_client.py @@ -14,23 +14,22 @@ """ from __future__ import annotations + from datetime import datetime from typing import Any, Optional, TypeVar - -from durabletask import client import durabletask.internal.orchestrator_service_pb2 as pb - -from dapr.ext.workflow.workflow_state import WorkflowState -from dapr.ext.workflow.workflow_context import Workflow +from dapr.ext.workflow.logger import Logger, LoggerOptions from dapr.ext.workflow.util import getAddress +from dapr.ext.workflow.workflow_context import Workflow +from dapr.ext.workflow.workflow_state import WorkflowState +from durabletask import client from grpc import RpcError from dapr.clients import DaprInternalError from dapr.clients.http.client import DAPR_API_TOKEN_HEADER from dapr.conf import settings from dapr.conf.helpers import GrpcEndpoint -from dapr.ext.workflow.logger import LoggerOptions, Logger T = TypeVar('T') TInput = TypeVar('TInput') diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_context.py b/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_context.py index 2dee46fe2..1227c5bf7 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_context.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/dapr_workflow_context.py @@ -13,15 +13,14 @@ limitations under the License. """ -from typing import Any, Callable, List, Optional, TypeVar, Union from datetime import datetime, timedelta +from typing import Any, Callable, List, Optional, TypeVar, Union -from durabletask import task - -from dapr.ext.workflow.workflow_context import WorkflowContext, Workflow -from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext -from dapr.ext.workflow.logger import LoggerOptions, Logger +from dapr.ext.workflow.logger import Logger, LoggerOptions from dapr.ext.workflow.retry_policy import RetryPolicy +from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext +from dapr.ext.workflow.workflow_context import Workflow, WorkflowContext +from durabletask import task T = TypeVar('T') TInput = TypeVar('TInput') diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/__init__.py b/ext/dapr-ext-workflow/dapr/ext/workflow/logger/__init__.py index 5583bde7e..b63a763bd 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/__init__.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/logger/__init__.py @@ -1,4 +1,4 @@ -from dapr.ext.workflow.logger.options import LoggerOptions from dapr.ext.workflow.logger.logger import Logger +from dapr.ext.workflow.logger.options import LoggerOptions __all__ = ['LoggerOptions', 'Logger'] diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/logger.py b/ext/dapr-ext-workflow/dapr/ext/workflow/logger/logger.py index 6b0f3fec4..b93e7074f 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/logger.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/logger/logger.py @@ -1,5 +1,6 @@ import logging from typing import Union + from dapr.ext.workflow.logger.options import LoggerOptions diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/options.py b/ext/dapr-ext-workflow/dapr/ext/workflow/logger/options.py index 0be44c52b..15cee8cc3 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/logger/options.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/logger/options.py @@ -13,8 +13,8 @@ limitations under the License. """ -from typing import Union import logging +from typing import Union class LoggerOptions: diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/retry_policy.py b/ext/dapr-ext-workflow/dapr/ext/workflow/retry_policy.py index af1f5ea9e..aa12f479d 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/retry_policy.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/retry_policy.py @@ -13,8 +13,8 @@ limitations under the License. """ -from typing import Optional, TypeVar from datetime import timedelta +from typing import Optional, TypeVar from durabletask import task diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/util.py b/ext/dapr-ext-workflow/dapr/ext/workflow/util.py index 648bc973d..3199e2558 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/util.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/util.py @@ -21,7 +21,7 @@ def getAddress(host: Optional[str] = None, port: Optional[str] = None) -> str: if not host and not port: address = settings.DAPR_GRPC_ENDPOINT or ( - f'{settings.DAPR_RUNTIME_HOST}:' f'{settings.DAPR_GRPC_PORT}' + f'{settings.DAPR_RUNTIME_HOST}:{settings.DAPR_GRPC_PORT}' ) else: host = host or settings.DAPR_RUNTIME_HOST diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_activity_context.py b/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_activity_context.py index f460e8013..331ad6c2c 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_activity_context.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_activity_context.py @@ -14,6 +14,7 @@ """ from __future__ import annotations + from typing import Callable, TypeVar from durabletask import task diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_context.py b/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_context.py index b4c85f6a6..0c93dd128 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_context.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_context.py @@ -14,13 +14,13 @@ """ from __future__ import annotations + from abc import ABC, abstractmethod from datetime import datetime, timedelta from typing import Any, Callable, Generator, Optional, TypeVar, Union -from durabletask import task - from dapr.ext.workflow.workflow_activity_context import Activity +from durabletask import task T = TypeVar('T') TInput = TypeVar('TInput') diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_runtime.py b/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_runtime.py index d1f02b354..b36a04949 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_runtime.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_runtime.py @@ -17,18 +17,17 @@ from functools import wraps from typing import Optional, TypeVar -from durabletask import worker, task - -from dapr.ext.workflow.workflow_context import Workflow from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext -from dapr.ext.workflow.workflow_activity_context import Activity, WorkflowActivityContext +from dapr.ext.workflow.logger import Logger, LoggerOptions from dapr.ext.workflow.util import getAddress +from dapr.ext.workflow.workflow_activity_context import Activity, WorkflowActivityContext +from dapr.ext.workflow.workflow_context import Workflow +from durabletask import task, worker from dapr.clients import DaprInternalError from dapr.clients.http.client import DAPR_API_TOKEN_HEADER from dapr.conf import settings from dapr.conf.helpers import GrpcEndpoint -from dapr.ext.workflow.logger import LoggerOptions, Logger T = TypeVar('T') TInput = TypeVar('TInput') diff --git a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_state.py b/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_state.py index 10847fc54..af1d7e735 100644 --- a/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_state.py +++ b/ext/dapr-ext-workflow/dapr/ext/workflow/workflow_state.py @@ -13,8 +13,8 @@ limitations under the License. """ -from enum import Enum import json +from enum import Enum from durabletask import client diff --git a/ext/dapr-ext-workflow/tests/test_dapr_workflow_context.py b/ext/dapr-ext-workflow/tests/test_dapr_workflow_context.py index 9fdfe0440..6d9368ad9 100644 --- a/ext/dapr-ext-workflow/tests/test_dapr_workflow_context.py +++ b/ext/dapr-ext-workflow/tests/test_dapr_workflow_context.py @@ -13,9 +13,10 @@ limitations under the License. """ +import unittest from datetime import datetime from unittest import mock -import unittest + from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext from durabletask import worker diff --git a/ext/dapr-ext-workflow/tests/test_workflow_activity_context.py b/ext/dapr-ext-workflow/tests/test_workflow_activity_context.py index a45b8b7cd..9a7d6fcc8 100644 --- a/ext/dapr-ext-workflow/tests/test_workflow_activity_context.py +++ b/ext/dapr-ext-workflow/tests/test_workflow_activity_context.py @@ -15,8 +15,9 @@ import unittest from unittest import mock -from durabletask import task + from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext +from durabletask import task mock_orchestration_id = 'orchestration001' mock_task = 10 diff --git a/ext/dapr-ext-workflow/tests/test_workflow_client.py b/ext/dapr-ext-workflow/tests/test_workflow_client.py index 540c0e801..a12a8844b 100644 --- a/ext/dapr-ext-workflow/tests/test_workflow_client.py +++ b/ext/dapr-ext-workflow/tests/test_workflow_client.py @@ -13,14 +13,15 @@ limitations under the License. """ +import unittest from datetime import datetime from typing import Any, Union -import unittest -from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext from unittest import mock + +import durabletask.internal.orchestrator_service_pb2 as pb from dapr.ext.workflow.dapr_workflow_client import DaprWorkflowClient +from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext from durabletask import client -import durabletask.internal.orchestrator_service_pb2 as pb from grpc import RpcError mock_schedule_result = 'workflow001' diff --git a/ext/dapr-ext-workflow/tests/test_workflow_runtime.py b/ext/dapr-ext-workflow/tests/test_workflow_runtime.py index 02d6c6f3b..bf18cd689 100644 --- a/ext/dapr-ext-workflow/tests/test_workflow_runtime.py +++ b/ext/dapr-ext-workflow/tests/test_workflow_runtime.py @@ -13,12 +13,13 @@ limitations under the License. """ -from typing import List import unittest -from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext +from typing import List from unittest import mock -from dapr.ext.workflow.workflow_runtime import WorkflowRuntime, alternate_name + +from dapr.ext.workflow.dapr_workflow_context import DaprWorkflowContext from dapr.ext.workflow.workflow_activity_context import WorkflowActivityContext +from dapr.ext.workflow.workflow_runtime import WorkflowRuntime, alternate_name listOrchestrators: List[str] = [] listActivities: List[str] = [] diff --git a/ext/dapr-ext-workflow/tests/test_workflow_util.py b/ext/dapr-ext-workflow/tests/test_workflow_util.py index 878ee7374..28e92e6c5 100644 --- a/ext/dapr-ext-workflow/tests/test_workflow_util.py +++ b/ext/dapr-ext-workflow/tests/test_workflow_util.py @@ -1,7 +1,8 @@ import unittest -from dapr.ext.workflow.util import getAddress from unittest.mock import patch +from dapr.ext.workflow.util import getAddress + from dapr.conf import settings diff --git a/ext/flask_dapr/flask_dapr/app.py b/ext/flask_dapr/flask_dapr/app.py index c8d5def92..80e42220f 100644 --- a/ext/flask_dapr/flask_dapr/app.py +++ b/ext/flask_dapr/flask_dapr/app.py @@ -14,6 +14,7 @@ """ from typing import Dict, List, Optional + from flask import Flask, jsonify diff --git a/tests/actor/fake_actor_classes.py b/tests/actor/fake_actor_classes.py index 50fe63fcf..2de821779 100644 --- a/tests/actor/fake_actor_classes.py +++ b/tests/actor/fake_actor_classes.py @@ -12,24 +12,22 @@ See the License for the specific language governing permissions and limitations under the License. """ -from dapr.serializers.json import DefaultJSONSerializer -import asyncio +import asyncio from datetime import timedelta from typing import Optional -from dapr.actor.runtime.actor import Actor -from dapr.actor.runtime.remindable import Remindable from dapr.actor.actor_interface import ActorInterface, actormethod - +from dapr.actor.runtime.actor import Actor from dapr.actor.runtime.reentrancy_context import reentrancy_ctx +from dapr.actor.runtime.remindable import Remindable +from dapr.serializers.json import DefaultJSONSerializer # Fake Simple Actor Class for testing class FakeSimpleActorInterface(ActorInterface): @actormethod(name='ActorMethod') - async def actor_method(self, arg: int) -> dict: - ... + async def actor_method(self, arg: int) -> dict: ... class FakeSimpleActor(Actor, FakeSimpleActorInterface): @@ -89,40 +87,32 @@ async def receive_reminder( class FakeActorCls1Interface(ActorInterface): # Fake Actor Class deriving multiple ActorInterfaces @actormethod(name='ActorCls1Method') - async def actor_cls1_method(self, arg): - ... + async def actor_cls1_method(self, arg): ... @actormethod(name='ActorCls1Method1') - async def actor_cls1_method1(self, arg): - ... + async def actor_cls1_method1(self, arg): ... @actormethod(name='ActorCls1Method2') - async def actor_cls1_method2(self, arg): - ... + async def actor_cls1_method2(self, arg): ... class FakeActorCls2Interface(ActorInterface): @actormethod(name='ActorCls2Method') - async def actor_cls2_method(self, arg): - ... + async def actor_cls2_method(self, arg): ... @actormethod(name='ActionMethod') - async def action(self, data: object) -> str: - ... + async def action(self, data: object) -> str: ... @actormethod(name='ActionMethodWithoutArg') - async def action_no_arg(self) -> str: - ... + async def action_no_arg(self) -> str: ... class ReentrantActorInterface(ActorInterface): @actormethod(name='ReentrantMethod') - async def reentrant_method(self, data: object) -> str: - ... + async def reentrant_method(self, data: object) -> str: ... @actormethod(name='ReentrantMethodWithPassthrough') - async def reentrant_pass_through_method(self, arg): - ... + async def reentrant_pass_through_method(self, arg): ... class FakeMultiInterfacesActor( diff --git a/tests/actor/fake_client.py b/tests/actor/fake_client.py index fa5fe1577..311a76e0e 100644 --- a/tests/actor/fake_client.py +++ b/tests/actor/fake_client.py @@ -13,36 +13,34 @@ limitations under the License. """ -from dapr.clients import DaprActorClientBase from typing import Optional +from dapr.clients import DaprActorClientBase + # Fake Dapr Actor Client Base Class for testing class FakeDaprActorClientBase(DaprActorClientBase): async def invoke_method( self, actor_type: str, actor_id: str, method: str, data: Optional[bytes] = None - ) -> bytes: - ... + ) -> bytes: ... - async def save_state_transactionally(self, actor_type: str, actor_id: str, data: bytes) -> None: - ... + async def save_state_transactionally( + self, actor_type: str, actor_id: str, data: bytes + ) -> None: ... - async def get_state(self, actor_type: str, actor_id: str, name: str) -> bytes: - ... + async def get_state(self, actor_type: str, actor_id: str, name: str) -> bytes: ... async def register_reminder( self, actor_type: str, actor_id: str, name: str, data: bytes - ) -> None: - ... + ) -> None: ... - async def unregister_reminder(self, actor_type: str, actor_id: str, name: str) -> None: - ... + async def unregister_reminder(self, actor_type: str, actor_id: str, name: str) -> None: ... - async def register_timer(self, actor_type: str, actor_id: str, name: str, data: bytes) -> None: - ... + async def register_timer( + self, actor_type: str, actor_id: str, name: str, data: bytes + ) -> None: ... - async def unregister_timer(self, actor_type: str, actor_id: str, name: str) -> None: - ... + async def unregister_timer(self, actor_type: str, actor_id: str, name: str) -> None: ... class FakeDaprActorClient(FakeDaprActorClientBase): diff --git a/tests/actor/test_actor.py b/tests/actor/test_actor.py index d9b602c9d..7a7bee2d2 100644 --- a/tests/actor/test_actor.py +++ b/tests/actor/test_actor.py @@ -14,25 +14,22 @@ """ import unittest - -from unittest import mock from datetime import timedelta +from unittest import mock from dapr.actor.id import ActorId +from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.actor.runtime.config import ActorRuntimeConfig from dapr.actor.runtime.context import ActorRuntimeContext from dapr.actor.runtime.runtime import ActorRuntime -from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.conf import settings from dapr.serializers import DefaultJSONSerializer - from tests.actor.fake_actor_classes import ( + FakeMultiInterfacesActor, FakeSimpleActor, FakeSimpleReminderActor, FakeSimpleTimerActor, - FakeMultiInterfacesActor, ) - from tests.actor.fake_client import FakeDaprActorClient from tests.actor.utils import _async_mock, _run from tests.clients.fake_http_server import FakeHttpServer diff --git a/tests/actor/test_actor_factory.py b/tests/actor/test_actor_factory.py index 0715c33f4..4f629bb25 100644 --- a/tests/actor/test_actor_factory.py +++ b/tests/actor/test_actor_factory.py @@ -18,16 +18,13 @@ from dapr.actor import Actor from dapr.actor.id import ActorId from dapr.actor.runtime._type_information import ActorTypeInformation -from dapr.actor.runtime.manager import ActorManager from dapr.actor.runtime.context import ActorRuntimeContext +from dapr.actor.runtime.manager import ActorManager from dapr.serializers import DefaultJSONSerializer - from tests.actor.fake_actor_classes import ( FakeSimpleActorInterface, ) - from tests.actor.fake_client import FakeDaprActorClient - from tests.actor.utils import _run diff --git a/tests/actor/test_actor_manager.py b/tests/actor/test_actor_manager.py index 6c21abfb7..af0e2e410 100644 --- a/tests/actor/test_actor_manager.py +++ b/tests/actor/test_actor_manager.py @@ -19,19 +19,16 @@ from dapr.actor.id import ActorId from dapr.actor.runtime._type_information import ActorTypeInformation -from dapr.actor.runtime.manager import ActorManager from dapr.actor.runtime.context import ActorRuntimeContext +from dapr.actor.runtime.manager import ActorManager from dapr.serializers import DefaultJSONSerializer - from tests.actor.fake_actor_classes import ( FakeMultiInterfacesActor, FakeSimpleActor, FakeSimpleReminderActor, FakeSimpleTimerActor, ) - from tests.actor.fake_client import FakeDaprActorClient - from tests.actor.utils import ( _async_mock, _run, diff --git a/tests/actor/test_actor_reentrancy.py b/tests/actor/test_actor_reentrancy.py index 834273f41..263070f65 100644 --- a/tests/actor/test_actor_reentrancy.py +++ b/tests/actor/test_actor_reentrancy.py @@ -13,22 +13,19 @@ limitations under the License. """ -import unittest import asyncio - +import unittest from unittest import mock +from dapr.actor.runtime.config import ActorReentrancyConfig, ActorRuntimeConfig from dapr.actor.runtime.runtime import ActorRuntime -from dapr.actor.runtime.config import ActorRuntimeConfig, ActorReentrancyConfig from dapr.conf import settings from dapr.serializers import DefaultJSONSerializer - from tests.actor.fake_actor_classes import ( - FakeReentrantActor, FakeMultiInterfacesActor, + FakeReentrantActor, FakeSlowReentrantActor, ) - from tests.actor.utils import _run from tests.clients.fake_http_server import FakeHttpServer @@ -212,9 +209,10 @@ async def expected_return_value(*args, **kwargs): _run(ActorRuntime.deactivate(FakeReentrantActor.__name__, 'test-id')) def test_parse_incoming_reentrancy_header_flask(self): - from ext.flask_dapr import flask_dapr from flask import Flask + from ext.flask_dapr import flask_dapr + app = Flask(f'{FakeReentrantActor.__name__}Service') flask_dapr.DaprActor(app) @@ -244,9 +242,9 @@ def test_parse_incoming_reentrancy_header_flask(self): ) def test_parse_incoming_reentrancy_header_fastapi(self): + from dapr.ext import fastapi from fastapi import FastAPI from fastapi.testclient import TestClient - from dapr.ext import fastapi app = FastAPI(title=f'{FakeReentrantActor.__name__}Service') fastapi.DaprActor(app) diff --git a/tests/actor/test_actor_runtime.py b/tests/actor/test_actor_runtime.py index f17f96cc8..7725c3728 100644 --- a/tests/actor/test_actor_runtime.py +++ b/tests/actor/test_actor_runtime.py @@ -14,20 +14,17 @@ """ import unittest - from datetime import timedelta -from dapr.actor.runtime.runtime import ActorRuntime from dapr.actor.runtime.config import ActorRuntimeConfig +from dapr.actor.runtime.runtime import ActorRuntime from dapr.conf import settings from dapr.serializers import DefaultJSONSerializer - from tests.actor.fake_actor_classes import ( - FakeSimpleActor, FakeMultiInterfacesActor, + FakeSimpleActor, FakeSimpleTimerActor, ) - from tests.actor.utils import _run from tests.clients.fake_http_server import FakeHttpServer diff --git a/tests/actor/test_actor_runtime_config.py b/tests/actor/test_actor_runtime_config.py index 7bbd8cefc..e39894c77 100644 --- a/tests/actor/test_actor_runtime_config.py +++ b/tests/actor/test_actor_runtime_config.py @@ -14,9 +14,9 @@ """ import unittest - from datetime import timedelta -from dapr.actor.runtime.config import ActorRuntimeConfig, ActorReentrancyConfig, ActorTypeConfig + +from dapr.actor.runtime.config import ActorReentrancyConfig, ActorRuntimeConfig, ActorTypeConfig class ActorTypeConfigTests(unittest.TestCase): diff --git a/tests/actor/test_client_proxy.py b/tests/actor/test_client_proxy.py index fe667d629..172e5d283 100644 --- a/tests/actor/test_client_proxy.py +++ b/tests/actor/test_client_proxy.py @@ -12,22 +12,18 @@ See the License for the specific language governing permissions and limitations under the License. """ -import unittest +import unittest from unittest import mock - -from dapr.actor.id import ActorId from dapr.actor.client.proxy import ActorProxy +from dapr.actor.id import ActorId from dapr.serializers import DefaultJSONSerializer from tests.actor.fake_actor_classes import ( - FakeMultiInterfacesActor, FakeActorCls2Interface, + FakeMultiInterfacesActor, ) - - from tests.actor.fake_client import FakeDaprActorClient - from tests.actor.utils import _async_mock, _run diff --git a/tests/actor/test_method_dispatcher.py b/tests/actor/test_method_dispatcher.py index 94f48a7b6..a32fba455 100644 --- a/tests/actor/test_method_dispatcher.py +++ b/tests/actor/test_method_dispatcher.py @@ -15,11 +15,10 @@ import unittest +from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.actor.runtime.context import ActorRuntimeContext from dapr.actor.runtime.method_dispatcher import ActorMethodDispatcher -from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.serializers import DefaultJSONSerializer - from tests.actor.fake_actor_classes import FakeSimpleActor from tests.actor.fake_client import FakeDaprActorClient from tests.actor.utils import _run diff --git a/tests/actor/test_mock_actor.py b/tests/actor/test_mock_actor.py index c37cdf4f8..8a958c425 100644 --- a/tests/actor/test_mock_actor.py +++ b/tests/actor/test_mock_actor.py @@ -9,48 +9,37 @@ class MockTestActorInterface(ActorInterface): @actormethod(name='GetData') - async def get_data(self) -> object: - ... + async def get_data(self) -> object: ... @actormethod(name='SetData') - async def set_data(self, data: object) -> None: - ... + async def set_data(self, data: object) -> None: ... @actormethod(name='ClearData') - async def clear_data(self) -> None: - ... + async def clear_data(self) -> None: ... @actormethod(name='TestData') - async def test_data(self) -> int: - ... + async def test_data(self) -> int: ... @actormethod(name='AddState') - async def add_state(self, name: str, data: object) -> None: - ... + async def add_state(self, name: str, data: object) -> None: ... @actormethod(name='UpdateState') - async def update_state(self, name: str, data: object) -> None: - ... + async def update_state(self, name: str, data: object) -> None: ... @actormethod(name='AddDataNoSave') - async def add_data_no_save(self, data: object) -> None: - ... + async def add_data_no_save(self, data: object) -> None: ... @actormethod(name='RemoveDataNoSave') - async def remove_data_no_save(self) -> None: - ... + async def remove_data_no_save(self) -> None: ... @actormethod(name='SaveState') - async def save_state(self) -> None: - ... + async def save_state(self) -> None: ... @actormethod(name='ToggleReminder') - async def toggle_reminder(self, name: str, enabled: bool) -> None: - ... + async def toggle_reminder(self, name: str, enabled: bool) -> None: ... @actormethod(name='ToggleTimer') - async def toggle_timer(self, name: str, enabled: bool) -> None: - ... + async def toggle_timer(self, name: str, enabled: bool) -> None: ... class MockTestActor(Actor, MockTestActorInterface, Remindable): diff --git a/tests/actor/test_state_manager.py b/tests/actor/test_state_manager.py index c9406dbd2..11a7c4f08 100644 --- a/tests/actor/test_state_manager.py +++ b/tests/actor/test_state_manager.py @@ -15,19 +15,16 @@ import base64 import unittest - from unittest import mock from dapr.actor.id import ActorId +from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.actor.runtime.context import ActorRuntimeContext from dapr.actor.runtime.state_change import StateChangeKind from dapr.actor.runtime.state_manager import ActorStateManager -from dapr.actor.runtime._type_information import ActorTypeInformation from dapr.serializers import DefaultJSONSerializer - from tests.actor.fake_actor_classes import FakeSimpleActor from tests.actor.fake_client import FakeDaprActorClient - from tests.actor.utils import _async_mock, _run diff --git a/tests/actor/test_timer_data.py b/tests/actor/test_timer_data.py index ba410cecd..8a193f416 100644 --- a/tests/actor/test_timer_data.py +++ b/tests/actor/test_timer_data.py @@ -13,9 +13,9 @@ limitations under the License. """ -from typing import Any import unittest from datetime import timedelta +from typing import Any from dapr.actor.runtime._timer_data import ActorTimerData diff --git a/tests/actor/test_type_information.py b/tests/actor/test_type_information.py index 1532e3956..201eb87fb 100644 --- a/tests/actor/test_type_information.py +++ b/tests/actor/test_type_information.py @@ -17,10 +17,10 @@ from dapr.actor.runtime._type_information import ActorTypeInformation from tests.actor.fake_actor_classes import ( - FakeSimpleActor, - FakeMultiInterfacesActor, FakeActorCls1Interface, FakeActorCls2Interface, + FakeMultiInterfacesActor, + FakeSimpleActor, ReentrantActorInterface, ) diff --git a/tests/actor/test_type_utils.py b/tests/actor/test_type_utils.py index f8b2eee2a..6b2a9319b 100644 --- a/tests/actor/test_type_utils.py +++ b/tests/actor/test_type_utils.py @@ -17,19 +17,18 @@ from dapr.actor.actor_interface import ActorInterface from dapr.actor.runtime._type_utils import ( + get_actor_interfaces, get_class_method_args, + get_dispatchable_attrs, get_method_arg_types, get_method_return_types, is_dapr_actor, - get_actor_interfaces, - get_dispatchable_attrs, ) - from tests.actor.fake_actor_classes import ( - FakeSimpleActor, - FakeMultiInterfacesActor, FakeActorCls1Interface, FakeActorCls2Interface, + FakeMultiInterfacesActor, + FakeSimpleActor, ) diff --git a/tests/clients/certs.py b/tests/clients/certs.py index a30b25312..9d851ca46 100644 --- a/tests/clients/certs.py +++ b/tests/clients/certs.py @@ -1,7 +1,7 @@ import os import ssl -import grpc +import grpc from OpenSSL import crypto diff --git a/tests/clients/fake_dapr_server.py b/tests/clients/fake_dapr_server.py index a1cbeb4b7..a1ee695eb 100644 --- a/tests/clients/fake_dapr_server.py +++ b/tests/clients/fake_dapr_server.py @@ -1,48 +1,47 @@ -import grpc import json - from concurrent import futures -from google.protobuf.any_pb2 import Any as GrpcAny +from typing import Dict + +import grpc from google.protobuf import empty_pb2, struct_pb2 -from google.rpc import status_pb2, code_pb2 +from google.protobuf.any_pb2 import Any as GrpcAny +from google.rpc import code_pb2, status_pb2 from grpc_status import rpc_status from dapr.clients.grpc._helpers import to_bytes -from dapr.proto import api_service_v1, common_v1, api_v1, appcallback_v1 -from dapr.proto.common.v1.common_pb2 import ConfigurationItem from dapr.clients.grpc._response import WorkflowRuntimeStatus +from dapr.proto import api_service_v1, api_v1, appcallback_v1, common_v1 +from dapr.proto.common.v1.common_pb2 import ConfigurationItem from dapr.proto.runtime.v1.dapr_pb2 import ( ActiveActorsCount, + ConversationResponseAlpha2, + ConversationResultAlpha2, + ConversationResultChoices, + ConversationResultMessage, + ConversationToolCalls, + ConversationToolCallsOfFunction, + DecryptRequest, + DecryptResponse, + EncryptRequest, + EncryptResponse, GetMetadataResponse, + GetWorkflowRequest, + GetWorkflowResponse, + PauseWorkflowRequest, + PurgeWorkflowRequest, QueryStateItem, + RaiseEventWorkflowRequest, RegisteredComponents, + ResumeWorkflowRequest, SetMetadataRequest, + StartWorkflowRequest, + StartWorkflowResponse, + TerminateWorkflowRequest, TryLockRequest, TryLockResponse, UnlockRequest, UnlockResponse, - StartWorkflowRequest, - StartWorkflowResponse, - GetWorkflowRequest, - GetWorkflowResponse, - PauseWorkflowRequest, - ResumeWorkflowRequest, - TerminateWorkflowRequest, - PurgeWorkflowRequest, - RaiseEventWorkflowRequest, - EncryptRequest, - EncryptResponse, - DecryptRequest, - DecryptResponse, - ConversationResultAlpha2, - ConversationResultChoices, - ConversationResultMessage, - ConversationResponseAlpha2, - ConversationToolCalls, - ConversationToolCallsOfFunction, ) -from typing import Dict - from tests.clients.certs import GrpcCerts from tests.clients.fake_http_server import FakeHttpServer diff --git a/tests/clients/fake_http_server.py b/tests/clients/fake_http_server.py index e08e82d29..8476b18ba 100644 --- a/tests/clients/fake_http_server.py +++ b/tests/clients/fake_http_server.py @@ -1,8 +1,7 @@ import time +from http.server import BaseHTTPRequestHandler, HTTPServer from ssl import PROTOCOL_TLS_SERVER, SSLContext - from threading import Thread -from http.server import BaseHTTPRequestHandler, HTTPServer from tests.clients.certs import HttpCerts diff --git a/tests/clients/test_conversation.py b/tests/clients/test_conversation.py index 8a6cc697e..50daebc64 100644 --- a/tests/clients/test_conversation.py +++ b/tests/clients/test_conversation.py @@ -13,7 +13,6 @@ limitations under the License. """ - import asyncio import json import unittest @@ -33,7 +32,14 @@ from dapr.clients.grpc.conversation import ( ConversationInput, ConversationInputAlpha2, + ConversationMessage, + ConversationMessageOfAssistant, ConversationResponseAlpha2, + ConversationResultAlpha2, + ConversationResultAlpha2Choices, + ConversationResultAlpha2Message, + ConversationToolCalls, + ConversationToolCallsOfFunction, ConversationTools, ConversationToolsFunction, FunctionBackend, @@ -41,18 +47,11 @@ create_system_message, create_tool_message, create_user_message, + execute_registered_tool, execute_registered_tool_async, get_registered_tools, register_tool, unregister_tool, - ConversationResultAlpha2Message, - ConversationResultAlpha2Choices, - ConversationResultAlpha2, - ConversationMessage, - ConversationMessageOfAssistant, - ConversationToolCalls, - ConversationToolCallsOfFunction, - execute_registered_tool, ) from dapr.clients.grpc.conversation import ( tool as tool_decorator, @@ -1010,7 +1009,7 @@ def test_multiline_example(self): def test_zero_indent(self): result = conversation._indent_lines('Title', 'Line one\nLine two', 0) - expected = 'Title: Line one\n' ' Line two' + expected = 'Title: Line one\n Line two' self.assertEqual(result, expected) def test_empty_string(self): @@ -1026,7 +1025,7 @@ def test_title_length_affects_indent(self): # Title length is 1, indent_after_first_line should be indent + len(title) + 2 # indent=2, len(title)=1 => 2 + 1 + 2 = 5 spaces on continuation lines result = conversation._indent_lines('T', 'a\nb', 2) - expected = ' T: a\n' ' b' + expected = ' T: a\n b' self.assertEqual(result, expected) diff --git a/tests/clients/test_conversation_helpers.py b/tests/clients/test_conversation_helpers.py index 62f2f69ae..e7c69b30e 100644 --- a/tests/clients/test_conversation_helpers.py +++ b/tests/clients/test_conversation_helpers.py @@ -12,37 +12,39 @@ See the License for the specific language governing permissions and limitations under the License. """ + +import base64 import io import json -import base64 import unittest import warnings from contextlib import redirect_stdout from dataclasses import dataclass from enum import Enum -from typing import Any, Dict, List, Literal, Optional, Union, Set -from dapr.conf import settings +from typing import Any, Dict, List, Literal, Optional, Set, Union + from dapr.clients.grpc._conversation_helpers import ( - stringify_tool_output, - bind_params_to_func, - function_to_json_schema, + ToolArgumentError, _extract_docstring_args, _python_type_to_json_schema, + bind_params_to_func, extract_docstring_summary, - ToolArgumentError, + function_to_json_schema, + stringify_tool_output, ) from dapr.clients.grpc.conversation import ( - ConversationToolsFunction, - ConversationMessageOfUser, + ConversationMessage, ConversationMessageContent, - ConversationToolCalls, - ConversationToolCallsOfFunction, ConversationMessageOfAssistant, - ConversationMessageOfTool, - ConversationMessage, ConversationMessageOfDeveloper, ConversationMessageOfSystem, + ConversationMessageOfTool, + ConversationMessageOfUser, + ConversationToolCalls, + ConversationToolCallsOfFunction, + ConversationToolsFunction, ) +from dapr.conf import settings def test_string_passthrough(): @@ -2089,8 +2091,7 @@ def f(p: Plain) -> int: bind_params_to_func(f, {'p': {}}) def test_any_and_isinstance_fallback(self): - class C: - ... + class C: ... def f(a: Any, c: C) -> tuple: return a, c diff --git a/tests/clients/test_dapr_grpc_client.py b/tests/clients/test_dapr_grpc_client.py index e0713f703..d4c642858 100644 --- a/tests/clients/test_dapr_grpc_client.py +++ b/tests/clients/test_dapr_grpc_client.py @@ -13,43 +13,43 @@ limitations under the License. """ +import asyncio import json import socket import tempfile import time import unittest import uuid -import asyncio - from unittest.mock import patch -from google.rpc import status_pb2, code_pb2 +from google.rpc import code_pb2, status_pb2 -from dapr.clients.exceptions import DaprGrpcError -from dapr.clients.grpc.client import DaprGrpcClient from dapr.clients import DaprClient -from dapr.clients.grpc.subscription import StreamInactiveError -from dapr.proto import common_v1 -from .fake_dapr_server import FakeDaprSidecar -from dapr.conf import settings +from dapr.clients.exceptions import DaprGrpcError +from dapr.clients.grpc import conversation +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions from dapr.clients.grpc._helpers import to_bytes +from dapr.clients.grpc._jobs import Job from dapr.clients.grpc._request import ( TransactionalStateOperation, TransactionOperationType, ) -from dapr.clients.grpc._jobs import Job -from dapr.clients.grpc._state import StateOptions, Consistency, Concurrency, StateItem -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions from dapr.clients.grpc._response import ( ConfigurationItem, ConfigurationResponse, ConfigurationWatcher, DaprResponse, + TopicEventResponse, UnlockResponseStatus, WorkflowRuntimeStatus, - TopicEventResponse, ) -from dapr.clients.grpc import conversation +from dapr.clients.grpc._state import Concurrency, Consistency, StateItem, StateOptions +from dapr.clients.grpc.client import DaprGrpcClient +from dapr.clients.grpc.subscription import StreamInactiveError +from dapr.conf import settings +from dapr.proto import common_v1 + +from .fake_dapr_server import FakeDaprSidecar class DaprGrpcClientTests(unittest.TestCase): @@ -1694,7 +1694,7 @@ def test_delete_job_alpha1_validation_error(self): def test_jobs_error_handling(self): """Test error handling for Jobs API using fake server's exception mechanism.""" - from google.rpc import status_pb2, code_pb2 + from google.rpc import code_pb2, status_pb2 dapr = DaprGrpcClient(f'{self.scheme}localhost:{self.grpc_port}') diff --git a/tests/clients/test_dapr_grpc_client_async.py b/tests/clients/test_dapr_grpc_client_async.py index 50043912d..8109aa21f 100644 --- a/tests/clients/test_dapr_grpc_client_async.py +++ b/tests/clients/test_dapr_grpc_client_async.py @@ -12,6 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. """ + import json import socket import tempfile @@ -19,28 +20,29 @@ import uuid from unittest.mock import patch -from google.rpc import status_pb2, code_pb2 +from google.rpc import code_pb2, status_pb2 -from dapr.aio.clients.grpc.client import DaprGrpcClientAsync from dapr.aio.clients import DaprClient +from dapr.aio.clients.grpc.client import DaprGrpcClientAsync from dapr.clients.exceptions import DaprGrpcError -from dapr.common.pubsub.subscription import StreamInactiveError -from dapr.proto import common_v1 -from .fake_dapr_server import FakeDaprSidecar -from dapr.conf import settings -from dapr.clients.grpc._helpers import to_bytes -from dapr.clients.grpc._request import TransactionalStateOperation from dapr.clients.grpc import conversation +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions +from dapr.clients.grpc._helpers import to_bytes from dapr.clients.grpc._jobs import Job -from dapr.clients.grpc._state import StateOptions, Consistency, Concurrency, StateItem -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions +from dapr.clients.grpc._request import TransactionalStateOperation from dapr.clients.grpc._response import ( ConfigurationItem, - ConfigurationWatcher, ConfigurationResponse, + ConfigurationWatcher, DaprResponse, UnlockResponseStatus, ) +from dapr.clients.grpc._state import Concurrency, Consistency, StateItem, StateOptions +from dapr.common.pubsub.subscription import StreamInactiveError +from dapr.conf import settings +from dapr.proto import common_v1 + +from .fake_dapr_server import FakeDaprSidecar class DaprGrpcClientAsyncTests(unittest.IsolatedAsyncioTestCase): diff --git a/tests/clients/test_dapr_grpc_client_async_secure.py b/tests/clients/test_dapr_grpc_client_async_secure.py index 652feac20..a49fe5fc0 100644 --- a/tests/clients/test_dapr_grpc_client_async_secure.py +++ b/tests/clients/test_dapr_grpc_client_async_secure.py @@ -14,16 +14,15 @@ """ import unittest - from unittest.mock import patch from dapr.aio.clients.grpc.client import DaprGrpcClientAsync from dapr.clients.health import DaprHealth +from dapr.conf import settings from tests.clients.certs import replacement_get_credentials_func, replacement_get_health_context from tests.clients.test_dapr_grpc_client_async import DaprGrpcClientAsyncTests -from .fake_dapr_server import FakeDaprSidecar -from dapr.conf import settings +from .fake_dapr_server import FakeDaprSidecar DaprGrpcClientAsync.get_credentials = replacement_get_credentials_func DaprHealth.get_ssl_context = replacement_get_health_context diff --git a/tests/clients/test_dapr_grpc_client_secure.py b/tests/clients/test_dapr_grpc_client_secure.py index 41dedca1a..2a6710403 100644 --- a/tests/clients/test_dapr_grpc_client_secure.py +++ b/tests/clients/test_dapr_grpc_client_secure.py @@ -12,6 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. """ + import unittest from unittest.mock import patch @@ -19,8 +20,8 @@ from dapr.clients.health import DaprHealth from dapr.conf import settings from tests.clients.certs import replacement_get_credentials_func, replacement_get_health_context - from tests.clients.test_dapr_grpc_client import DaprGrpcClientTests + from .fake_dapr_server import FakeDaprSidecar diff --git a/tests/clients/test_dapr_grpc_helpers.py b/tests/clients/test_dapr_grpc_helpers.py index 9e794aab7..6c7c27be9 100644 --- a/tests/clients/test_dapr_grpc_helpers.py +++ b/tests/clients/test_dapr_grpc_helpers.py @@ -1,22 +1,22 @@ import base64 import unittest -from google.protobuf.struct_pb2 import Struct from google.protobuf import json_format -from google.protobuf.json_format import ParseError from google.protobuf.any_pb2 import Any as GrpcAny +from google.protobuf.json_format import ParseError +from google.protobuf.struct_pb2 import Struct from google.protobuf.wrappers_pb2 import ( BoolValue, - StringValue, + BytesValue, + DoubleValue, Int32Value, Int64Value, - DoubleValue, - BytesValue, + StringValue, ) from dapr.clients.grpc._helpers import ( - convert_value_to_struct, convert_dict_to_grpc_dict_of_any, + convert_value_to_struct, ) diff --git a/tests/clients/test_dapr_grpc_request.py b/tests/clients/test_dapr_grpc_request.py index 98d8e2005..396a8ec95 100644 --- a/tests/clients/test_dapr_grpc_request.py +++ b/tests/clients/test_dapr_grpc_request.py @@ -16,13 +16,13 @@ import io import unittest +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions from dapr.clients.grpc._request import ( - InvokeMethodRequest, BindingRequest, - EncryptRequestIterator, DecryptRequestIterator, + EncryptRequestIterator, + InvokeMethodRequest, ) -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions from dapr.proto import api_v1, common_v1 diff --git a/tests/clients/test_dapr_grpc_request_async.py b/tests/clients/test_dapr_grpc_request_async.py index 75fe74fce..7782fecdf 100644 --- a/tests/clients/test_dapr_grpc_request_async.py +++ b/tests/clients/test_dapr_grpc_request_async.py @@ -16,8 +16,8 @@ import io import unittest -from dapr.clients.grpc._crypto import EncryptOptions, DecryptOptions -from dapr.aio.clients.grpc._request import EncryptRequestIterator, DecryptRequestIterator +from dapr.aio.clients.grpc._request import DecryptRequestIterator, EncryptRequestIterator +from dapr.clients.grpc._crypto import DecryptOptions, EncryptOptions from dapr.proto import api_v1 diff --git a/tests/clients/test_dapr_grpc_response.py b/tests/clients/test_dapr_grpc_response.py index 1c91805eb..c2fe237f9 100644 --- a/tests/clients/test_dapr_grpc_response.py +++ b/tests/clients/test_dapr_grpc_response.py @@ -18,15 +18,14 @@ from google.protobuf.any_pb2 import Any as GrpcAny from dapr.clients.grpc._response import ( - DaprResponse, - InvokeMethodResponse, BindingResponse, - StateResponse, BulkStateItem, - EncryptResponse, + DaprResponse, DecryptResponse, + EncryptResponse, + InvokeMethodResponse, + StateResponse, ) - from dapr.proto import api_v1, common_v1 diff --git a/tests/clients/test_dapr_grpc_response_async.py b/tests/clients/test_dapr_grpc_response_async.py index 2626cbf41..02b09716f 100644 --- a/tests/clients/test_dapr_grpc_response_async.py +++ b/tests/clients/test_dapr_grpc_response_async.py @@ -15,7 +15,7 @@ import unittest -from dapr.aio.clients.grpc._response import EncryptResponse, DecryptResponse +from dapr.aio.clients.grpc._response import DecryptResponse, EncryptResponse from dapr.proto import api_v1, common_v1 diff --git a/tests/clients/test_exceptions.py b/tests/clients/test_exceptions.py index 08eea4d53..e8b4c6d9f 100644 --- a/tests/clients/test_exceptions.py +++ b/tests/clients/test_exceptions.py @@ -3,9 +3,9 @@ import unittest import grpc -from google.rpc import error_details_pb2, status_pb2, code_pb2 from google.protobuf.any_pb2 import Any from google.protobuf.duration_pb2 import Duration +from google.rpc import code_pb2, error_details_pb2, status_pb2 from dapr.clients import DaprGrpcClient from dapr.clients.exceptions import DaprGrpcError, DaprInternalError diff --git a/tests/clients/test_heatlhcheck.py b/tests/clients/test_heatlhcheck.py index f3be8a475..1f533dc96 100644 --- a/tests/clients/test_heatlhcheck.py +++ b/tests/clients/test_heatlhcheck.py @@ -12,9 +12,10 @@ See the License for the specific language governing permissions and limitations under the License. """ + import time import unittest -from unittest.mock import patch, MagicMock +from unittest.mock import MagicMock, patch from dapr.clients.health import DaprHealth from dapr.conf import settings diff --git a/tests/clients/test_http_helpers.py b/tests/clients/test_http_helpers.py index ab173cd73..abf284dbe 100644 --- a/tests/clients/test_http_helpers.py +++ b/tests/clients/test_http_helpers.py @@ -1,8 +1,8 @@ import unittest from unittest.mock import patch -from dapr.conf import settings from dapr.clients.http.helpers import get_api_url +from dapr.conf import settings class DaprHttpClientHelpersTests(unittest.TestCase): diff --git a/tests/clients/test_http_service_invocation_client.py b/tests/clients/test_http_service_invocation_client.py index c0b43a863..a0a7aadd6 100644 --- a/tests/clients/test_http_service_invocation_client.py +++ b/tests/clients/test_http_service_invocation_client.py @@ -24,13 +24,12 @@ from opentelemetry.sdk.trace.sampling import ALWAYS_ON from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator - +from dapr.clients import DaprClient from dapr.clients.exceptions import DaprInternalError from dapr.conf import settings from dapr.proto import common_v1 from .fake_http_server import FakeHttpServer -from dapr.clients import DaprClient class DaprInvocationHttpClientTests(unittest.TestCase): diff --git a/tests/clients/test_jobs.py b/tests/clients/test_jobs.py index fe3d70b53..645d43256 100644 --- a/tests/clients/test_jobs.py +++ b/tests/clients/test_jobs.py @@ -5,9 +5,10 @@ """ import unittest + from google.protobuf.any_pb2 import Any as GrpcAny -from dapr.clients.grpc._jobs import Job, DropFailurePolicy, ConstantFailurePolicy +from dapr.clients.grpc._jobs import ConstantFailurePolicy, DropFailurePolicy, Job from dapr.proto.runtime.v1 import dapr_pb2 as api_v1 diff --git a/tests/clients/test_retries_policy.py b/tests/clients/test_retries_policy.py index b5137e643..d4a383fc1 100644 --- a/tests/clients/test_retries_policy.py +++ b/tests/clients/test_retries_policy.py @@ -12,11 +12,12 @@ See the License for the specific language governing permissions and limitations under the License. """ + import unittest from unittest import mock -from unittest.mock import Mock, MagicMock, patch, AsyncMock +from unittest.mock import AsyncMock, MagicMock, Mock, patch -from grpc import StatusCode, RpcError +from grpc import RpcError, StatusCode from dapr.clients.retry import RetryPolicy from dapr.serializers import DefaultJSONSerializer diff --git a/tests/clients/test_retries_policy_async.py b/tests/clients/test_retries_policy_async.py index ebe6865db..2b35c35c4 100644 --- a/tests/clients/test_retries_policy_async.py +++ b/tests/clients/test_retries_policy_async.py @@ -12,11 +12,12 @@ See the License for the specific language governing permissions and limitations under the License. """ + import unittest from unittest import mock -from unittest.mock import MagicMock, patch, AsyncMock +from unittest.mock import AsyncMock, MagicMock, patch -from grpc import StatusCode, RpcError +from grpc import RpcError, StatusCode from dapr.clients.retry import RetryPolicy diff --git a/tests/clients/test_secure_http_service_invocation_client.py b/tests/clients/test_secure_http_service_invocation_client.py index 4d1bdda1f..df13d8197 100644 --- a/tests/clients/test_secure_http_service_invocation_client.py +++ b/tests/clients/test_secure_http_service_invocation_client.py @@ -12,6 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. """ + import ssl import typing from asyncio import TimeoutError @@ -29,8 +30,7 @@ from dapr.conf import settings from dapr.proto import common_v1 - -from .certs import replacement_get_health_context, replacement_get_credentials_func, GrpcCerts +from .certs import GrpcCerts, replacement_get_credentials_func, replacement_get_health_context from .fake_http_server import FakeHttpServer from .test_http_service_invocation_client import DaprInvocationHttpClientTests diff --git a/tests/clients/test_subscription.py b/tests/clients/test_subscription.py index ed2eae3fa..21018aaac 100644 --- a/tests/clients/test_subscription.py +++ b/tests/clients/test_subscription.py @@ -1,8 +1,9 @@ -from dapr.clients.grpc.subscription import SubscriptionMessage -from dapr.proto.runtime.v1.appcallback_pb2 import TopicEventRequest +import unittest + from google.protobuf.struct_pb2 import Struct -import unittest +from dapr.clients.grpc.subscription import SubscriptionMessage +from dapr.proto.runtime.v1.appcallback_pb2 import TopicEventRequest class SubscriptionMessageTests(unittest.TestCase): diff --git a/tests/clients/test_timeout_interceptor.py b/tests/clients/test_timeout_interceptor.py index 79859b2e5..c60331bed 100644 --- a/tests/clients/test_timeout_interceptor.py +++ b/tests/clients/test_timeout_interceptor.py @@ -15,6 +15,7 @@ import unittest from unittest.mock import Mock, patch + from dapr.clients.grpc.interceptors import DaprClientTimeoutInterceptor from dapr.conf import settings diff --git a/tests/clients/test_timeout_interceptor_async.py b/tests/clients/test_timeout_interceptor_async.py index d057df9fc..88b5831dc 100644 --- a/tests/clients/test_timeout_interceptor_async.py +++ b/tests/clients/test_timeout_interceptor_async.py @@ -15,6 +15,7 @@ import unittest from unittest.mock import Mock, patch + from dapr.aio.clients.grpc.interceptors import DaprClientTimeoutInterceptorAsync from dapr.conf import settings diff --git a/tests/serializers/test_default_json_serializer.py b/tests/serializers/test_default_json_serializer.py index 86e727ad0..8f65595c0 100644 --- a/tests/serializers/test_default_json_serializer.py +++ b/tests/serializers/test_default_json_serializer.py @@ -13,8 +13,8 @@ limitations under the License. """ -import unittest import datetime +import unittest from dapr.serializers.json import DefaultJSONSerializer diff --git a/tests/serializers/test_util.py b/tests/serializers/test_util.py index 9f3b9e026..25124fdf6 100644 --- a/tests/serializers/test_util.py +++ b/tests/serializers/test_util.py @@ -13,12 +13,12 @@ limitations under the License. """ -import unittest import json +import unittest from datetime import timedelta -from dapr.serializers.util import convert_from_dapr_duration, convert_to_dapr_duration from dapr.serializers.json import DaprJSONDecoder +from dapr.serializers.util import convert_from_dapr_duration, convert_to_dapr_duration class UtilTests(unittest.TestCase): diff --git a/tox.ini b/tox.ini index ebd403c3f..91b41d351 100644 --- a/tox.ini +++ b/tox.ini @@ -2,28 +2,35 @@ skipsdist = True minversion = 3.9.0 envlist = - py{39,310,311,312,313} + py{39,310,311,312,313,314} flake8, ruff, mypy, +# TODO: switch runner to uv (tox-uv plugin) +runner = virtualenv [testenv] setenv = PYTHONDONTWRITEBYTECODE=1 deps = -rdev-requirements.txt +package = editable commands = coverage run -m unittest discover -v ./tests - coverage run -a -m unittest discover -v ./ext/dapr-ext-workflow/tests + # ext/dapr-ext-workflow uses pytest-based tests + coverage run -a -m pytest -q ext/dapr-ext-workflow/tests coverage run -a -m unittest discover -v ./ext/dapr-ext-grpc/tests coverage run -a -m unittest discover -v ./ext/dapr-ext-fastapi/tests coverage run -a -m unittest discover -v ./ext/flask_dapr/tests coverage xml commands_pre = - pip3 install -e {toxinidir}/ - pip3 install -e {toxinidir}/ext/dapr-ext-workflow/ - pip3 install -e {toxinidir}/ext/dapr-ext-grpc/ - pip3 install -e {toxinidir}/ext/dapr-ext-fastapi/ - pip3 install -e {toxinidir}/ext/flask_dapr/ + # TODO: remove this before merging (after durable task is merged) + {envpython} -m pip install -e {toxinidir}/ + {envpython} -m pip install -e {toxinidir}/ext/dapr-ext-workflow/ + {envpython} -m pip install -e {toxinidir}/ext/dapr-ext-grpc/ + {envpython} -m pip install -e {toxinidir}/ext/dapr-ext-fastapi/ + {envpython} -m pip install -e {toxinidir}/ext/flask_dapr/ +# allow for overriding sidecar ports +pass_env = DAPR_GRPC_ENDPOINT,DAPR_HTTP_ENDPOINT,DAPR_RUNTIME_HOST,DAPR_GRPC_PORT,DAPR_HTTP_PORT [testenv:flake8] basepython = python3 @@ -35,8 +42,8 @@ commands = [testenv:ruff] basepython = python3 usedevelop = False -deps = ruff==0.2.2 commands = + ruff check --select I --fix ruff format [testenv:examples]