Skip to content

Commit 4c2d18e

Browse files
Run complete Python SDK qualification on landed main commits (#236)
1 parent d6503f3 commit 4c2d18e

11 files changed

Lines changed: 72 additions & 56 deletions

src/durable_workflow/__init__.py

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,6 @@
7878
WorkflowPayloadDecodeError,
7979
WorkflowTerminated,
8080
)
81-
from .nexus import (
82-
NEXUS_CALLER_SDK_LANGUAGE,
83-
NEXUS_OPERATION_RESULT_SCHEMA,
84-
NEXUS_OPERATION_RESULT_VERSION,
85-
NexusOperationResult,
86-
)
8781
from .external_storage import (
8882
EXTERNAL_PAYLOAD_REFERENCE_SCHEMA,
8983
AzureBlobExternalStorage,
@@ -125,6 +119,24 @@
125119
parse_external_task_result,
126120
parse_external_task_result_artifact,
127121
)
122+
from .history_bundle_verify import (
123+
BUNDLE_SCHEMA as HISTORY_BUNDLE_SCHEMA,
124+
)
125+
from .history_bundle_verify import (
126+
BUNDLE_SCHEMA_VERSION as HISTORY_BUNDLE_SCHEMA_VERSION,
127+
)
128+
from .history_bundle_verify import (
129+
REPORT_SCHEMA as HISTORY_BUNDLE_VERIFICATION_REPORT_SCHEMA,
130+
)
131+
from .history_bundle_verify import (
132+
REPORT_SCHEMA_VERSION as HISTORY_BUNDLE_VERIFICATION_REPORT_SCHEMA_VERSION,
133+
)
134+
from .history_bundle_verify import (
135+
verify_bundle as verify_history_bundle,
136+
)
137+
from .history_bundle_verify import (
138+
verify_bundle_json as verify_history_bundle_json,
139+
)
128140
from .interceptors import (
129141
ActivityHandler,
130142
ActivityInterceptorContext,
@@ -149,17 +161,16 @@
149161
NoopMetrics,
150162
PrometheusMetrics,
151163
)
152-
from .retry_policy import RetryPolicy, TransportRetryPolicy
153-
from .serializer import (
154-
PayloadSizeWarningConfig,
155-
PayloadSizeWarningContext,
156-
external_storage_envelope,
157-
to_avro_payload_value,
158-
to_avro_payload_values,
164+
from .nexus import (
165+
NEXUS_CALLER_SDK_LANGUAGE,
166+
NEXUS_OPERATION_RESULT_SCHEMA,
167+
NEXUS_OPERATION_RESULT_VERSION,
168+
NexusOperationResult,
159169
)
160-
from .worker import Worker
161170
from .replay_verify import (
162171
CaseReport as ReplayCaseReport,
172+
)
173+
from .replay_verify import (
163174
GoldenHistoryReport,
164175
SimulationReport,
165176
aggregate_verdicts,
@@ -169,14 +180,15 @@
169180
verify_golden_history,
170181
verify_replay,
171182
)
172-
from .history_bundle_verify import (
173-
BUNDLE_SCHEMA as HISTORY_BUNDLE_SCHEMA,
174-
BUNDLE_SCHEMA_VERSION as HISTORY_BUNDLE_SCHEMA_VERSION,
175-
REPORT_SCHEMA as HISTORY_BUNDLE_VERIFICATION_REPORT_SCHEMA,
176-
REPORT_SCHEMA_VERSION as HISTORY_BUNDLE_VERIFICATION_REPORT_SCHEMA_VERSION,
177-
verify_bundle as verify_history_bundle,
178-
verify_bundle_json as verify_history_bundle_json,
183+
from .retry_policy import RetryPolicy, TransportRetryPolicy
184+
from .serializer import (
185+
PayloadSizeWarningConfig,
186+
PayloadSizeWarningContext,
187+
external_storage_envelope,
188+
to_avro_payload_value,
189+
to_avro_payload_values,
179190
)
191+
from .worker import Worker
180192
from .workflow import (
181193
ActivityRetryPolicy,
182194
ChildWorkflowRetryPolicy,

src/durable_workflow/client.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,12 @@ def _worker_poll_timeout_seconds(timeout: float | None) -> int | None:
7777

7878

7979
def _worker_poll_http_timeout(timeout: float | None) -> float | None:
80-
timeout_seconds = _worker_poll_timeout_seconds(timeout)
81-
if timeout_seconds is None:
80+
if timeout is None:
8281
return None
8382

83+
timeout_seconds = _worker_poll_timeout_seconds(timeout)
84+
assert timeout_seconds is not None
85+
8486
if timeout_seconds == 0:
8587
return max(float(timeout), 1.0)
8688

src/durable_workflow/history_bundle_verify.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ def _check_envelope(bundle: Mapping[str, Any], findings: list[dict[str, Any]]) -
141141
_finding(
142142
"bundle.schema_version_unsupported",
143143
SEVERITY_ERROR,
144-
f"Bundle schema_version [{bundle['schema_version']!s}] is unsupported; expected {BUNDLE_SCHEMA_VERSION}.",
144+
f"Bundle schema_version [{bundle['schema_version']!s}] is unsupported; "
145+
f"expected {BUNDLE_SCHEMA_VERSION}.",
145146
{"observed": bundle["schema_version"]},
146147
)
147148
)
@@ -325,7 +326,8 @@ def _check_commands(bundle: Mapping[str, Any], findings: list[dict[str, Any]]) -
325326
if not isinstance(commands, list):
326327
return
327328

328-
events = bundle.get("history_events") if isinstance(bundle.get("history_events"), list) else []
329+
raw_events = bundle.get("history_events")
330+
events: list[Any] = raw_events if isinstance(raw_events, list) else []
329331
event_command_ids: set[str] = set()
330332
for event in events:
331333
if isinstance(event, Mapping):

src/durable_workflow/python_conformance.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
import sys
1717
from collections.abc import Iterable, Mapping
1818
from pathlib import Path
19-
from typing import Any
19+
from typing import Any, TypeVar
20+
21+
_T = TypeVar("_T")
2022

2123
SCHEMA = "durable-workflow.v2.python-sdk-parity.contract"
2224
VERSION = 1
@@ -761,7 +763,7 @@ def _trace_plane_entries(value: Any, plane: str) -> list[Any]:
761763
return _filtered_traces(_trace_entries(value), plane)
762764

763765

764-
def _filtered_traces(traces: Any, plane: str) -> Any:
766+
def _filtered_traces(traces: Any, plane: str) -> list[Any]:
765767
if not isinstance(traces, list):
766768
return []
767769
return [
@@ -820,7 +822,7 @@ def _copy_mapping(value: Any) -> dict[str, Any]:
820822
return dict(value) if isinstance(value, Mapping) else {}
821823

822824

823-
def _deepcopy_json_like(value: Any) -> Any:
825+
def _deepcopy_json_like(value: _T) -> _T:
824826
return copy.deepcopy(value)
825827

826828

src/durable_workflow/replay_verify.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,16 @@
2929
import json
3030
import sys
3131
import traceback
32-
from collections.abc import Iterable, Mapping, Sequence
32+
from collections.abc import Callable, Iterable, Mapping, Sequence
3333
from dataclasses import dataclass, field
3434
from pathlib import Path
35-
from typing import Any, Callable
35+
from typing import Any
3636

3737
from .errors import ChildWorkflowFailed, NonDeterministicReplayError, WorkflowFailed
3838
from .workflow import (
3939
CompleteWorkflow,
40-
ReplayOutcome,
4140
Replayer,
41+
ReplayOutcome,
4242
ScheduleActivity,
4343
StartChildWorkflow,
4444
)

src/durable_workflow/worker.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -301,10 +301,7 @@ def _query_history_with_export_signal_arguments(
301301
if isinstance(name, str) and name:
302302
signals_by_name.setdefault(name, []).append(raw_signal)
303303

304-
if not signals_by_id and not signals_by_command_id and not signals_by_name:
305-
signals_available = False
306-
else:
307-
signals_available = True
304+
signals_available = bool(signals_by_id or signals_by_command_id or signals_by_name)
308305

309306
activity_results_by_sequence = _activity_result_by_sequence_from_export(history_export)
310307

@@ -431,10 +428,7 @@ def _query_history_events(
431428
*,
432429
default_codec: str | None,
433430
) -> Any:
434-
if isinstance(history, list):
435-
events = history
436-
else:
437-
events = []
431+
events = history if isinstance(history, list) else []
438432

439433
if isinstance(history_export, Mapping):
440434
export_events = history_export.get("history_events")
@@ -1956,10 +1950,8 @@ async def _heartbeat_loop(self) -> None:
19561950
considered for task dispatch when they miss enough heartbeats.
19571951
"""
19581952
while not self._stop.is_set():
1959-
try:
1953+
with contextlib.suppress(asyncio.TimeoutError):
19601954
await asyncio.wait_for(self._stop.wait(), timeout=self._heartbeat_interval)
1961-
except asyncio.TimeoutError:
1962-
pass
19631955
if self._stop.is_set():
19641956
return
19651957
try:

src/durable_workflow/workflow.py

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -392,12 +392,16 @@ def _payload_blobs_or_external_envelopes(
392392
payloads.append(blob if isinstance(blob, str) else str(blob))
393393
return payloads
394394

395-
return serializer.encode_many(
396-
values,
397-
codec=payload_codec,
398-
size_warning=size_warning,
399-
warning_context=warning_contexts,
395+
encoded_payloads: list[str | dict[str, Any]] = []
396+
encoded_payloads.extend(
397+
serializer.encode_many(
398+
values,
399+
codec=payload_codec,
400+
size_warning=size_warning,
401+
warning_context=warning_contexts,
402+
)
400403
)
404+
return encoded_payloads
401405

402406

403407
@dataclass
@@ -2537,7 +2541,7 @@ def _receiver_condition_wait_bindings() -> dict[int, str | None]:
25372541
prefix_receivers: list[int] = []
25382542
prefix_can_bind_to_first_wait = True
25392543
current_wait_id: str | None = None
2540-
receivers_since_wait: list[int | None] = []
2544+
receivers_since_wait: list[int] = []
25412545

25422546
for index, event in enumerate(events):
25432547
event_type = _history_event_type(event)
@@ -3013,11 +3017,10 @@ def _terminal_state(value: Any, *, include_pending: bool) -> _ReplayState:
30133017
prefix="wait_condition predicate raised",
30143018
)])
30153019
if resolution == "satisfied":
3016-
if has_reopened_same_wait:
3017-
if not satisfied:
3018-
consumed_reopen_for_current_wait = True
3019-
wait_yield_count = next_wait_index
3020-
continue
3020+
if has_reopened_same_wait and not satisfied:
3021+
consumed_reopen_for_current_wait = True
3022+
wait_yield_count = next_wait_index
3023+
continue
30213024

30223025
terminal_condition_reopen_cmd = (
30233026
cmd

tests/test_release_docs_audit_workflow.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import re
22
from pathlib import Path
33

4-
54
REPO_ROOT = Path(__file__).resolve().parents[1]
65

76

tests/test_replay_conformance.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
RESULT_SCHEMA,
1010
RESULT_VERSION,
1111
compose_report,
12+
)
13+
from durable_workflow.replay_conformance import (
1214
main as replay_conformance_main,
1315
)
1416

tests/test_replay_verify.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,15 @@
2929
VERDICT_FAILED,
3030
VERDICT_OK,
3131
aggregate_verdicts,
32-
main as replay_verify_main,
3332
promotion_decision_for,
3433
promotion_decision_for_report,
3534
simulate_bundles,
3635
verify_golden_history,
3736
verify_replay,
3837
)
38+
from durable_workflow.replay_verify import (
39+
main as replay_verify_main,
40+
)
3941
from durable_workflow.workflow import WorkflowContext
4042

4143

0 commit comments

Comments
 (0)