Skip to content

Commit ff8df5e

Browse files
authored
Compatibility with 3.9 and small changes (#6)
Signed-off-by: Deepanshu Agarwal <deepanshu.agarwal1984@gmail.com>
1 parent b5b24c7 commit ff8df5e

8 files changed

Lines changed: 77 additions & 75 deletions

File tree

.github/workflows/pr-validation.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
python-version: ["3.10", "3.11"]
19+
python-version: ["3.9","3.10", "3.11"]
2020

2121
steps:
2222
- uses: actions/checkout@v3

durabletask/client.py

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from dataclasses import dataclass
77
from datetime import datetime
88
from enum import Enum
9-
from typing import Any, TypeVar
9+
from typing import Any, TypeVar, Union
1010

1111
import grpc
1212
from google.protobuf import wrappers_pb2
@@ -42,10 +42,10 @@ class OrchestrationState:
4242
runtime_status: OrchestrationStatus
4343
created_at: datetime
4444
last_updated_at: datetime
45-
serialized_input: str | None
46-
serialized_output: str | None
47-
serialized_custom_status: str | None
48-
failure_details: task.FailureDetails | None
45+
serialized_input: Union[str, None]
46+
serialized_output: Union[str, None]
47+
serialized_custom_status: Union[str, None]
48+
failure_details: Union[task.FailureDetails, None]
4949

5050
def raise_if_failed(self):
5151
if self.failure_details is not None:
@@ -64,7 +64,7 @@ def failure_details(self):
6464
return self._failure_details
6565

6666

67-
def new_orchestration_state(instance_id: str, res: pb.GetInstanceResponse) -> OrchestrationState | None:
67+
def new_orchestration_state(instance_id: str, res: pb.GetInstanceResponse) -> Union[OrchestrationState, None]:
6868
if not res.exists:
6969
return None
7070

@@ -92,38 +92,39 @@ def new_orchestration_state(instance_id: str, res: pb.GetInstanceResponse) -> Or
9292
class TaskHubGrpcClient:
9393

9494
def __init__(self, *,
95-
host_address: str | None = None,
95+
host_address: Union[str, None] = None,
9696
log_handler=None,
97-
log_formatter: logging.Formatter | None = None):
97+
log_formatter: Union[logging.Formatter, None] = None):
9898
channel = shared.get_grpc_channel(host_address)
9999
self._stub = stubs.TaskHubSidecarServiceStub(channel)
100100
self._logger = shared.get_logger(log_handler, log_formatter)
101101

102-
def schedule_new_orchestration(self, orchestrator: task.Orchestrator[TInput, TOutput], *,
103-
input: TInput | None = None,
104-
instance_id: str | None = None,
105-
start_at: datetime | None = None) -> str:
102+
def schedule_new_orchestration(self, orchestrator: Union[task.Orchestrator[TInput, TOutput], str], *,
103+
input: Union[TInput, None] = None,
104+
instance_id: Union[str, None] = None,
105+
start_at: Union[datetime, None] = None) -> str:
106106

107-
name = task.get_name(orchestrator)
107+
name = orchestrator if isinstance(orchestrator, str) else task.get_name(orchestrator)
108108

109109
req = pb.CreateInstanceRequest(
110110
name=name,
111111
instanceId=instance_id if instance_id else uuid.uuid4().hex,
112112
input=wrappers_pb2.StringValue(value=shared.to_json(input)) if input else None,
113-
scheduledStartTimestamp=helpers.new_timestamp(start_at) if start_at else None)
113+
scheduledStartTimestamp=helpers.new_timestamp(start_at) if start_at else None,
114+
version=wrappers_pb2.StringValue(value=""))
114115

115116
self._logger.info(f"Starting new '{name}' instance with ID = '{req.instanceId}'.")
116117
res: pb.CreateInstanceResponse = self._stub.StartInstance(req)
117118
return res.instanceId
118119

119-
def get_orchestration_state(self, instance_id: str, *, fetch_payloads: bool = True) -> OrchestrationState | None:
120+
def get_orchestration_state(self, instance_id: str, *, fetch_payloads: bool = True) -> Union[OrchestrationState, None]:
120121
req = pb.GetInstanceRequest(instanceId=instance_id, getInputsAndOutputs=fetch_payloads)
121122
res: pb.GetInstanceResponse = self._stub.GetInstance(req)
122123
return new_orchestration_state(req.instanceId, res)
123124

124125
def wait_for_orchestration_start(self, instance_id: str, *,
125126
fetch_payloads: bool = False,
126-
timeout: int = 60) -> OrchestrationState | None:
127+
timeout: int = 60) -> Union[OrchestrationState, None]:
127128
req = pb.GetInstanceRequest(instanceId=instance_id, getInputsAndOutputs=fetch_payloads)
128129
try:
129130
self._logger.info(f"Waiting up to {timeout}s for instance '{instance_id}' to start.")
@@ -138,7 +139,7 @@ def wait_for_orchestration_start(self, instance_id: str, *,
138139

139140
def wait_for_orchestration_completion(self, instance_id: str, *,
140141
fetch_payloads: bool = True,
141-
timeout: int = 60) -> OrchestrationState | None:
142+
timeout: int = 60) -> Union[OrchestrationState, None]:
142143
req = pb.GetInstanceRequest(instanceId=instance_id, getInputsAndOutputs=fetch_payloads)
143144
try:
144145
self._logger.info(f"Waiting {timeout}s for instance '{instance_id}' to complete.")
@@ -152,7 +153,7 @@ def wait_for_orchestration_completion(self, instance_id: str, *,
152153
raise
153154

154155
def raise_orchestration_event(self, instance_id: str, event_name: str, *,
155-
data: Any | None = None):
156+
data: Union[Any, None] = None):
156157
req = pb.RaiseEventRequest(
157158
instanceId=instance_id,
158159
name=event_name,
@@ -162,7 +163,7 @@ def raise_orchestration_event(self, instance_id: str, event_name: str, *,
162163
self._stub.RaiseEvent(req)
163164

164165
def terminate_orchestration(self, instance_id: str, *,
165-
output: Any | None = None):
166+
output: Union[Any, None] = None):
166167
req = pb.TerminateRequest(
167168
instanceId=instance_id,
168169
output=wrappers_pb2.StringValue(value=shared.to_json(output)) if output else None)

durabletask/internal/helpers.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import traceback
55
from datetime import datetime
6+
from typing import Union
67

78
from google.protobuf import timestamp_pb2, wrappers_pb2
89

@@ -11,14 +12,14 @@
1112
# TODO: The new_xxx_event methods are only used by test code and should be moved elsewhere
1213

1314

14-
def new_orchestrator_started_event(timestamp: datetime | None = None) -> pb.HistoryEvent:
15+
def new_orchestrator_started_event(timestamp: Union[datetime, None] = None) -> pb.HistoryEvent:
1516
ts = timestamp_pb2.Timestamp()
1617
if timestamp is not None:
1718
ts.FromDatetime(timestamp)
1819
return pb.HistoryEvent(eventId=-1, timestamp=ts, orchestratorStarted=pb.OrchestratorStartedEvent())
1920

2021

21-
def new_execution_started_event(name: str, instance_id: str, encoded_input: str | None = None) -> pb.HistoryEvent:
22+
def new_execution_started_event(name: str, instance_id: str, encoded_input: Union[str, None] = None) -> pb.HistoryEvent:
2223
return pb.HistoryEvent(
2324
eventId=-1,
2425
timestamp=timestamp_pb2.Timestamp(),
@@ -48,15 +49,15 @@ def new_timer_fired_event(timer_id: int, fire_at: datetime) -> pb.HistoryEvent:
4849
)
4950

5051

51-
def new_task_scheduled_event(event_id: int, name: str, encoded_input: str | None = None) -> pb.HistoryEvent:
52+
def new_task_scheduled_event(event_id: int, name: str, encoded_input: Union[str, None] = None) -> pb.HistoryEvent:
5253
return pb.HistoryEvent(
5354
eventId=event_id,
5455
timestamp=timestamp_pb2.Timestamp(),
5556
taskScheduled=pb.TaskScheduledEvent(name=name, input=get_string_value(encoded_input))
5657
)
5758

5859

59-
def new_task_completed_event(event_id: int, encoded_output: str | None = None) -> pb.HistoryEvent:
60+
def new_task_completed_event(event_id: int, encoded_output: Union[str, None] = None) -> pb.HistoryEvent:
6061
return pb.HistoryEvent(
6162
eventId=-1,
6263
timestamp=timestamp_pb2.Timestamp(),
@@ -76,7 +77,7 @@ def new_sub_orchestration_created_event(
7677
event_id: int,
7778
name: str,
7879
instance_id: str,
79-
encoded_input: str | None = None) -> pb.HistoryEvent:
80+
encoded_input: Union[str, None] = None) -> pb.HistoryEvent:
8081
return pb.HistoryEvent(
8182
eventId=event_id,
8283
timestamp=timestamp_pb2.Timestamp(),
@@ -87,7 +88,7 @@ def new_sub_orchestration_created_event(
8788
)
8889

8990

90-
def new_sub_orchestration_completed_event(event_id: int, encoded_output: str | None = None) -> pb.HistoryEvent:
91+
def new_sub_orchestration_completed_event(event_id: int, encoded_output: Union[str, None] = None) -> pb.HistoryEvent:
9192
return pb.HistoryEvent(
9293
eventId=-1,
9394
timestamp=timestamp_pb2.Timestamp(),
@@ -115,7 +116,7 @@ def new_failure_details(ex: Exception) -> pb.TaskFailureDetails:
115116
)
116117

117118

118-
def new_event_raised_event(name: str, encoded_input: str | None = None) -> pb.HistoryEvent:
119+
def new_event_raised_event(name: str, encoded_input: Union[str, None] = None) -> pb.HistoryEvent:
119120
return pb.HistoryEvent(
120121
eventId=-1,
121122
timestamp=timestamp_pb2.Timestamp(),
@@ -139,7 +140,7 @@ def new_resume_event() -> pb.HistoryEvent:
139140
)
140141

141142

142-
def new_terminated_event(*, encoded_output: str | None = None) -> pb.HistoryEvent:
143+
def new_terminated_event(*, encoded_output: Union[str, None] = None) -> pb.HistoryEvent:
143144
return pb.HistoryEvent(
144145
eventId=-1,
145146
timestamp=timestamp_pb2.Timestamp(),
@@ -149,7 +150,7 @@ def new_terminated_event(*, encoded_output: str | None = None) -> pb.HistoryEven
149150
)
150151

151152

152-
def get_string_value(val: str | None) -> wrappers_pb2.StringValue | None:
153+
def get_string_value(val: Union[str, None]) -> Union[wrappers_pb2.StringValue, None]:
153154
if val is None:
154155
return None
155156
else:
@@ -159,8 +160,8 @@ def get_string_value(val: str | None) -> wrappers_pb2.StringValue | None:
159160
def new_complete_orchestration_action(
160161
id: int,
161162
status: pb.OrchestrationStatus,
162-
result: str | None = None,
163-
failure_details: pb.TaskFailureDetails | None = None) -> pb.OrchestratorAction:
163+
result: Union[str, None] = None,
164+
failure_details: Union[pb.TaskFailureDetails, None] = None) -> pb.OrchestratorAction:
164165

165166
completeOrchestrationAction = pb.CompleteOrchestrationAction(
166167
orchestrationStatus=status,
@@ -178,7 +179,7 @@ def new_create_timer_action(id: int, fire_at: datetime) -> pb.OrchestratorAction
178179
return pb.OrchestratorAction(id=id, createTimer=pb.CreateTimerAction(fireAt=timestamp))
179180

180181

181-
def new_schedule_task_action(id: int, name: str, encoded_input: str | None) -> pb.OrchestratorAction:
182+
def new_schedule_task_action(id: int, name: str, encoded_input: Union[str, None]) -> pb.OrchestratorAction:
182183
return pb.OrchestratorAction(id=id, scheduleTask=pb.ScheduleTaskAction(
183184
name=name,
184185
input=get_string_value(encoded_input)
@@ -194,8 +195,8 @@ def new_timestamp(dt: datetime) -> timestamp_pb2.Timestamp:
194195
def new_create_sub_orchestration_action(
195196
id: int,
196197
name: str,
197-
instance_id: str | None,
198-
encoded_input: str | None) -> pb.OrchestratorAction:
198+
instance_id: Union[str, None],
199+
encoded_input: Union[str, None]) -> pb.OrchestratorAction:
199200
return pb.OrchestratorAction(id=id, createSubOrchestration=pb.CreateSubOrchestrationAction(
200201
name=name,
201202
instanceId=instance_id,

durabletask/internal/shared.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import json
66
import logging
77
from types import SimpleNamespace
8-
from typing import Any, Dict
8+
from typing import Any, Dict, Union
99

1010
import grpc
1111

@@ -18,16 +18,16 @@ def get_default_host_address() -> str:
1818
return "localhost:4001"
1919

2020

21-
def get_grpc_channel(host_address: str | None) -> grpc.Channel:
21+
def get_grpc_channel(host_address: Union[str, None]) -> grpc.Channel:
2222
if host_address is None:
2323
host_address = get_default_host_address()
2424
channel = grpc.insecure_channel(host_address)
2525
return channel
2626

2727

2828
def get_logger(
29-
log_handler: logging.Handler | None = None,
30-
log_formatter: logging.Formatter | None = None) -> logging.Logger:
29+
log_handler: Union[logging.Handler, None] = None,
30+
log_formatter: Union[logging.Formatter, None] = None) -> logging.Logger:
3131
logger = logging.Logger("durabletask")
3232

3333
# Add a default log handler if none is provided

durabletask/task.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
from abc import ABC, abstractmethod
88
from datetime import datetime, timedelta
9-
from typing import Any, Callable, Generator, Generic, List, TypeVar
9+
from typing import Any, Callable, Generator, Generic, List, TypeVar, Union
1010

1111
import durabletask.internal.helpers as pbh
1212
import durabletask.internal.orchestrator_service_pb2 as pb
@@ -70,7 +70,7 @@ def is_replaying(self) -> bool:
7070
pass
7171

7272
@abstractmethod
73-
def create_timer(self, fire_at: datetime | timedelta) -> Task:
73+
def create_timer(self, fire_at: Union[datetime, timedelta]) -> Task:
7474
"""Create a Timer Task to fire after at the specified deadline.
7575
7676
Parameters
@@ -86,15 +86,15 @@ def create_timer(self, fire_at: datetime | timedelta) -> Task:
8686
pass
8787

8888
@abstractmethod
89-
def call_activity(self, activity: Activity[TInput, TOutput], *,
90-
input: TInput | None = None) -> Task[TOutput]:
89+
def call_activity(self, activity: Union[Activity[TInput, TOutput], str], *,
90+
input: Union[TInput, None] = None) -> Task[TOutput]:
9191
"""Schedule an activity for execution.
9292
9393
Parameters
9494
----------
95-
name: Activity[TInput, TOutput]
95+
activity: Union[Activity[TInput, TOutput], str]
9696
A reference to the activity function to call.
97-
input: TInput | None
97+
input: Union[TInput, None]
9898
The JSON-serializable input (or None) to pass to the activity.
9999
return_type: task.Task[TOutput]
100100
The JSON-serializable output type to expect from the activity result.
@@ -108,17 +108,17 @@ def call_activity(self, activity: Activity[TInput, TOutput], *,
108108

109109
@abstractmethod
110110
def call_sub_orchestrator(self, orchestrator: Orchestrator[TInput, TOutput], *,
111-
input: TInput | None = None,
112-
instance_id: str | None = None) -> Task[TOutput]:
111+
input: Union[TInput, None] = None,
112+
instance_id: Union[str, None] = None) -> Task[TOutput]:
113113
"""Schedule sub-orchestrator function for execution.
114114
115115
Parameters
116116
----------
117117
orchestrator: Orchestrator[TInput, TOutput]
118118
A reference to the orchestrator function to call.
119-
input: TInput | None
119+
input: Union[TInput, None]
120120
The optional JSON-serializable input to pass to the orchestrator function.
121-
instance_id: str | None
121+
instance_id: Union[str, None]
122122
A unique ID to use for the sub-orchestration instance. If not specified, a
123123
random UUID will be used.
124124
@@ -149,7 +149,7 @@ def wait_for_external_event(self, name: str) -> Task:
149149

150150

151151
class FailureDetails:
152-
def __init__(self, message: str, error_type: str, stack_trace: str | None):
152+
def __init__(self, message: str, error_type: str, stack_trace: Union[str, None]):
153153
self._message = message
154154
self._error_type = error_type
155155
self._stack_trace = stack_trace
@@ -163,7 +163,7 @@ def error_type(self) -> str:
163163
return self._error_type
164164

165165
@property
166-
def stack_trace(self) -> str | None:
166+
def stack_trace(self) -> Union[str, None]:
167167
return self._stack_trace
168168

169169

@@ -193,8 +193,8 @@ class OrchestrationStateError(Exception):
193193
class Task(ABC, Generic[T]):
194194
"""Abstract base class for asynchronous tasks in a durable orchestration."""
195195
_result: T
196-
_exception: TaskFailedError | None
197-
_parent: CompositeTask[T] | None
196+
_exception: Union[TaskFailedError, None]
197+
_parent: Union[CompositeTask[T], None]
198198

199199
def __init__(self) -> None:
200200
super().__init__()
@@ -357,7 +357,7 @@ def task_id(self) -> int:
357357

358358

359359
# Orchestrators are generators that yield tasks and receive/return any type
360-
Orchestrator = Callable[[OrchestrationContext, TInput], Generator[Task, Any, Any] | TOutput]
360+
Orchestrator = Callable[[OrchestrationContext, TInput], Union[Generator[Task, Any, Any], TOutput]]
361361

362362
# Activities are simple functions that can be scheduled by orchestrators
363363
Activity = Callable[[ActivityContext, TInput], TOutput]

0 commit comments

Comments
 (0)