Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ lint:
# Run type checker
type-check:
@echo "Running mypy type checker..."
uv tool run mypy cadence/
uv run mypy cadence/ tests/

# Run unit tests
test:
Expand Down
12 changes: 8 additions & 4 deletions cadence/data_converter.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import abstractmethod
from typing import Protocol, List, Type, Any
from typing import Protocol, List, Type, Any, Sequence

from cadence.api.v1.common_pb2 import Payload
from json import JSONDecoder
Expand All @@ -24,7 +24,9 @@ def __init__(self) -> None:
# Need to use std lib decoder in order to decode the custom whitespace delimited data format
self._decoder = JSONDecoder(strict=False)

def from_data(self, payload: Payload, type_hints: List[Type | None]) -> List[Any]:
def from_data(
self, payload: Payload, type_hints: Sequence[Type | None]
) -> List[Any]:
if not payload.data:
return DefaultDataConverter._convert_into([], type_hints)

Expand All @@ -33,7 +35,7 @@ def from_data(self, payload: Payload, type_hints: List[Type | None]) -> List[Any
return self._decode_whitespace_delimited(payload_str, type_hints)

def _decode_whitespace_delimited(
self, payload: str, type_hints: List[Type | None]
self, payload: str, type_hints: Sequence[Type | None]
) -> List[Any]:
results: List[Any] = []
start, end = 0, len(payload)
Expand All @@ -46,7 +48,9 @@ def _decode_whitespace_delimited(
return DefaultDataConverter._convert_into(results, type_hints)

@staticmethod
def _convert_into(values: List[Any], type_hints: List[Type | None]) -> List[Any]:
def _convert_into(
values: List[Any], type_hints: Sequence[Type | None]
) -> List[Any]:
results: List[Any] = []
for i, type_hint in enumerate(type_hints):
if not type_hint:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ check_untyped_defs = true
disallow_untyped_decorators = false # Temporarily disable to allow CI to pass
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_unused_ignores = false
warn_no_return = true
warn_unreachable = true
strict_equality = true
Expand Down
6 changes: 3 additions & 3 deletions tests/cadence/_internal/rpc/test_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import pytest
from google.protobuf import any_pb2
from google.rpc import code_pb2, status_pb2
from google.rpc import code_pb2, status_pb2 # type: ignore
from grpc import Status, StatusCode, server
from grpc.aio import insecure_channel
from grpc_status.rpc_status import to_status
from grpc_status.rpc_status import to_status # type: ignore

from cadence._internal.rpc.error import CadenceErrorInterceptor
from cadence.api.v1 import error_pb2, service_meta_pb2_grpc
Expand Down Expand Up @@ -168,7 +168,7 @@ def fake_service():
)
@pytest.mark.asyncio
async def test_map_error(
fake_service, err: Message | Status, expected: CadenceRpcError
fake_service, err: Message | Status, expected: CadenceRpcError | None
):
async with insecure_channel(
f"[::]:{fake_service.port}", interceptors=[CadenceErrorInterceptor()]
Expand Down
4 changes: 2 additions & 2 deletions tests/cadence/_internal/rpc/test_retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

import pytest
from google.protobuf import any_pb2
from google.rpc import status_pb2, code_pb2
from google.rpc import status_pb2, code_pb2 # type: ignore
from grpc import server
from grpc.aio import insecure_channel
from grpc_status.rpc_status import to_status
from grpc_status.rpc_status import to_status # type: ignore

from cadence._internal.rpc.error import CadenceErrorInterceptor
from cadence.api.v1 import error_pb2, service_workflow_pb2_grpc
Expand Down
16 changes: 10 additions & 6 deletions tests/cadence/_internal/workflow/test_deterministic_event_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
from cadence._internal.workflow.deterministic_event_loop import DeterministicEventLoop


async def coro_append(results: list, i: int):
async def coro_append(results: list[int], i: int):
results.append(i)


async def coro_await(size: int):
results = []
results: list[int] = []
for i in range(size):
await coro_append(results, i)
return results
Expand All @@ -19,7 +19,7 @@ async def coro_await_future(future: asyncio.Future):


async def coro_await_task(size: int):
results = []
results: list[int] = []
for i in range(size):
asyncio.create_task(coro_append(results, i))
return results
Expand All @@ -40,11 +40,15 @@ def teardown_method(self):

def test_call_soon(self):
"""Test _run_once executes single callback."""
results = []
expected = []
results: list[int] = []
expected: list[int] = []
for i in range(10000):
expected.append(i)
self.loop.call_soon(lambda x=i: results.append(x))

def add_to_result(result: int):
results.append(result)

self.loop.call_soon(add_to_result, i)

self.loop._run_once()

Expand Down
5 changes: 3 additions & 2 deletions tests/cadence/common_activities.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from typing import Protocol
from dataclasses import dataclass

from cadence import activity
Expand Down Expand Up @@ -43,7 +44,7 @@ async def echo_async(self, incoming: str) -> str:
return incoming


class ActivityInterface:
class ActivityInterface(Protocol):
@activity.defn()
def do_something(self) -> str: ...

Expand All @@ -52,7 +53,7 @@ def do_something(self) -> str: ...
class ActivityImpl(ActivityInterface):
result: str

def do_something(self) -> str:
def do_something(self) -> str: # type: ignore
return self.result


Expand Down
12 changes: 6 additions & 6 deletions tests/cadence/test_client_workflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ def mock_build_request(workflow, args, options):
request.domain = "test-domain"
return request

client._build_start_workflow_request = Mock(side_effect=mock_build_request)
client._build_start_workflow_request = Mock(side_effect=mock_build_request) # type: ignore

execution = await client.start_workflow(
"TestWorkflow",
Expand Down Expand Up @@ -298,7 +298,7 @@ async def test_start_workflow_grpc_error(self, mock_client):
client._workflow_stub = mock_client.workflow_stub

# Mock the internal method
client._build_start_workflow_request = Mock(
client._build_start_workflow_request = Mock( # type: ignore
return_value=StartWorkflowExecutionRequest()
)

Expand All @@ -324,7 +324,7 @@ async def test_start_workflow_with_kwargs(self, mock_client):
client._workflow_stub = mock_client.workflow_stub

# Mock the internal method to capture options
captured_options = None
captured_options: StartWorkflowOptions = StartWorkflowOptions()

def mock_build_request(workflow, args, options):
nonlocal captured_options
Expand All @@ -333,7 +333,7 @@ def mock_build_request(workflow, args, options):
request.workflow_id = "test-workflow-id"
return request

client._build_start_workflow_request = Mock(side_effect=mock_build_request)
client._build_start_workflow_request = Mock(side_effect=mock_build_request) # type: ignore

await client.start_workflow(
"TestWorkflow",
Expand Down Expand Up @@ -365,7 +365,7 @@ async def test_start_workflow_with_default_task_timeout(self, mock_client):
client._workflow_stub = mock_client.workflow_stub

# Mock the internal method to capture options
captured_options = None
captured_options: StartWorkflowOptions = StartWorkflowOptions()

def mock_build_request(workflow, args, options):
nonlocal captured_options
Expand All @@ -374,7 +374,7 @@ def mock_build_request(workflow, args, options):
request.workflow_id = "test-workflow-id"
return request

client._build_start_workflow_request = Mock(side_effect=mock_build_request)
client._build_start_workflow_request = Mock(side_effect=mock_build_request) # type: ignore

await client.start_workflow(
"TestWorkflow",
Expand Down
5 changes: 0 additions & 5 deletions tests/cadence/worker/test_base_task_handler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#!/usr/bin/env python3
"""
Unit tests for BaseTaskHandler class.
"""

import pytest
from unittest.mock import Mock

Expand Down
5 changes: 0 additions & 5 deletions tests/cadence/worker/test_decision_task_handler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#!/usr/bin/env python3
"""
Unit tests for DecisionTaskHandler class.
"""

import pytest
from unittest.mock import Mock, AsyncMock, patch, PropertyMock

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#!/usr/bin/env python3
"""
Integration tests for DecisionTaskHandler and WorkflowEngine.
"""

import pytest
from unittest.mock import Mock, AsyncMock, patch
from cadence.api.v1.service_worker_pb2 import PollForDecisionTaskResponse
Expand Down Expand Up @@ -39,8 +34,8 @@ def registry(self):
"""Create a registry with a test workflow."""
reg = Registry()

@reg.workflow(name="test_workflow")
class TestWorkflow:
@reg.workflow(name="test_workflow") # type: ignore
class TestWorkflow: # type: ignore
@workflow.run
async def run(self, input_data):
"""Simple test workflow that returns the input."""
Expand Down
26 changes: 11 additions & 15 deletions tests/cadence/worker/test_decision_worker_integration.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#!/usr/bin/env python3
"""
Integration tests for DecisionWorker with DecisionTaskHandler.
"""

import asyncio
import pytest
from unittest.mock import Mock, AsyncMock, patch
Expand All @@ -13,6 +8,7 @@
HistoryEvent,
WorkflowExecutionStartedEventAttributes,
)
from cadence.worker import WorkerOptions
from cadence.worker._decision import DecisionWorker
from cadence.worker._registry import Registry
from cadence import workflow
Expand Down Expand Up @@ -52,11 +48,11 @@ async def run(self, input_data):
@pytest.fixture
def decision_worker(self, mock_client, registry):
"""Create a DecisionWorker instance."""
options = {
"identity": "test-worker",
"max_concurrent_decision_task_execution_size": 1,
"decision_task_pollers": 1,
}
options = WorkerOptions(
identity="test-worker",
max_concurrent_decision_task_execution_size=1,
decision_task_pollers=1,
)
return DecisionWorker(
client=mock_client,
task_list="test-task-list",
Expand Down Expand Up @@ -297,11 +293,11 @@ async def test_decision_worker_poll_timeout(self, decision_worker, mock_client):

def test_decision_worker_options_handling(self, mock_client, registry):
"""Test DecisionWorker with various options."""
options = {
"identity": "custom-worker",
"max_concurrent_decision_task_execution_size": 5,
"decision_task_pollers": 3,
}
options = WorkerOptions(
identity="custom-worker",
max_concurrent_decision_task_execution_size=5,
decision_task_pollers=3,
)

worker = DecisionWorker(
client=mock_client,
Expand Down
16 changes: 8 additions & 8 deletions tests/cadence/worker/test_poller.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
@pytest.mark.asyncio
async def test_poller():
permits = asyncio.Semaphore(1)
incoming = asyncio.Queue()
outgoing = asyncio.Queue()
incoming = asyncio.Queue[str]()
outgoing = asyncio.Queue[str]()
poller = Poller(1, permits, incoming.get, outgoing.put)

task = asyncio.create_task(poller.run())
Expand All @@ -25,8 +25,8 @@ async def test_poller():
@pytest.mark.asyncio
async def test_poller_empty_task():
permits = asyncio.Semaphore(1)
incoming = asyncio.Queue()
outgoing = asyncio.Queue()
incoming = asyncio.Queue[str | None]()
outgoing = asyncio.Queue[str]()
poller = Poller(1, permits, incoming.get, outgoing.put)

task = asyncio.create_task(poller.run())
Expand Down Expand Up @@ -56,7 +56,7 @@ async def poll_func():
await done.wait()
return "foo"

outgoing = asyncio.Queue()
outgoing = asyncio.Queue[str]()
poller = Poller(5, permits, poll_func, outgoing.put)
task = asyncio.create_task(poller.run())

Expand Down Expand Up @@ -121,7 +121,7 @@ async def poll_func():
await done.wait()
return "bar"

outgoing = asyncio.Queue()
outgoing = asyncio.Queue[str]()
poller = Poller(1, permits, poll_func, outgoing.put)

task = asyncio.create_task(poller.run())
Expand All @@ -136,7 +136,7 @@ async def poll_func():
async def test_poller_execute_error():
permits = asyncio.Semaphore(1)

outgoing = asyncio.Queue()
outgoing = asyncio.Queue[str]()
call_count = 0

async def execute(item: str):
Expand All @@ -146,7 +146,7 @@ async def execute(item: str):
raise RuntimeError("oh no")
await outgoing.put(item)

incoming = asyncio.Queue()
incoming = asyncio.Queue[str]()
poller = Poller(1, permits, incoming.get, execute)

task = asyncio.create_task(poller.run())
Expand Down
6 changes: 1 addition & 5 deletions tests/cadence/worker/test_registry.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
#!/usr/bin/env python3
"""
Tests for the registry functionality.
"""

# type: ignore
import pytest

from cadence import activity
Expand Down
5 changes: 0 additions & 5 deletions tests/cadence/worker/test_task_handler_integration.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
#!/usr/bin/env python3
"""
Integration tests for task handlers.
"""

import pytest
from contextlib import contextmanager
from unittest.mock import Mock, AsyncMock, patch, PropertyMock
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/helper.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import asyncio
from contextlib import asynccontextmanager
from typing import AsyncGenerator
from typing import AsyncGenerator, Unpack

from cadence import Registry
from cadence.client import ClientOptions, Client
Expand All @@ -16,7 +16,7 @@ def __init__(self, options: ClientOptions, test_name: str) -> None:

@asynccontextmanager
async def worker(
self, registry: Registry, **kwargs: WorkerOptions
self, registry: Registry, **kwargs: Unpack[WorkerOptions]
) -> AsyncGenerator[Worker, None]:
async with self.client() as client:
worker = Worker(client, self.test_name, registry, **kwargs)
Expand Down
1 change: 1 addition & 0 deletions tests/integration_tests/workflow/test_activities.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# type: ignore
import asyncio
from datetime import timedelta

Expand Down
Loading