diff --git a/azure/__init__.py b/azure/__init__.py index d378fc67..db7d5de9 100644 --- a/azure/__init__.py +++ b/azure/__init__.py @@ -1,3 +1,3 @@ """Base module for the Python Durable functions.""" from pkgutil import extend_path -__path__ = extend_path(__path__, __name__) +__path__ = extend_path(__path__, __name__) # type: ignore diff --git a/azure/durable_functions/models/DurableOrchestrationClient.py b/azure/durable_functions/models/DurableOrchestrationClient.py index 76554c5f..3f4bb163 100644 --- a/azure/durable_functions/models/DurableOrchestrationClient.py +++ b/azure/durable_functions/models/DurableOrchestrationClient.py @@ -440,6 +440,8 @@ async def wait_for_completion_or_create_check_status_response( lambda: self._create_http_response(200, status.to_json()), OrchestrationRuntimeStatus.Failed: lambda: self._create_http_response(500, status.to_json()), + None: + None } result = switch_statement.get(status.runtime_status) @@ -456,6 +458,7 @@ async def wait_for_completion_or_create_check_status_response( await sleep(sleep_time) else: return self.create_check_status_response(request, instance_id) + return self.create_check_status_response(request, instance_id) async def signal_entity(self, entityId: EntityId, operation_name: str, operation_input: Optional[Any] = None, @@ -640,6 +643,7 @@ async def rewind(self, response = await self._post_async_request(request_url, None) status: int = response[0] + ex_msg: str = "" if status == 200 or status == 202: return elif status == 404: @@ -648,6 +652,9 @@ async def rewind(self, elif status == 410: ex_msg = "The rewind operation is only supported on failed orchestration instances." raise Exception(ex_msg) - else: + elif isinstance(response[1], str): ex_msg = response[1] raise Exception(ex_msg) + else: + ex_msg = "Received unexpected payload from the durable-extension: " + str(response) + raise Exception(ex_msg) diff --git a/azure/durable_functions/models/history/HistoryEvent.py b/azure/durable_functions/models/history/HistoryEvent.py index 84023944..fa6585b1 100644 --- a/azure/durable_functions/models/history/HistoryEvent.py +++ b/azure/durable_functions/models/history/HistoryEvent.py @@ -14,6 +14,13 @@ def __init__(self, EventType: HistoryEventType, EventId: int, IsPlayed: bool, Ti self._is_played: bool = IsPlayed self._timestamp: datetime.datetime = dt_parse(Timestamp) self._is_processed: bool = False + + self.Name = None + self.InstanceId = None + self.TaskScheduledId = None + self.Reason = None + self.Details = None + self.Input = None if kwargs is not None: for key, value in kwargs.items(): self.__setattr__(key, value) diff --git a/azure/durable_functions/tasks/call_entity.py b/azure/durable_functions/tasks/call_entity.py index 467e5b63..5d920405 100644 --- a/azure/durable_functions/tasks/call_entity.py +++ b/azure/durable_functions/tasks/call_entity.py @@ -51,7 +51,7 @@ def call_entity_task( event_raised = None if event_sent: event_input = None - if hasattr(event_sent, "Input"): + if hasattr(event_sent, "Input") and event_sent.Input is not None: event_input = RequestMessage.from_json(event_sent.Input) hist_type = HistoryEventType.EVENT_RAISED extra_constraints = { diff --git a/azure/durable_functions/tasks/task_all.py b/azure/durable_functions/tasks/task_all.py index 0758ae61..9d19a917 100644 --- a/azure/durable_functions/tasks/task_all.py +++ b/azure/durable_functions/tasks/task_all.py @@ -59,7 +59,7 @@ def task_all(tasks: List[Task]): # Incomplete TaskSets do not have results or end-time if not is_completed: - results = None + results = [] end_time = None # Construct TaskSet diff --git a/azure/durable_functions/tasks/task_utilities.py b/azure/durable_functions/tasks/task_utilities.py index cfe8bc2c..b0dd0251 100644 --- a/azure/durable_functions/tasks/task_utilities.py +++ b/azure/durable_functions/tasks/task_utilities.py @@ -304,14 +304,18 @@ def gen_err_message(counter: int, mid_message: str, found: str, expected: str) - # TODO: The HistoryEvent does not necessarily have a name or an instance_id # We should create sub-classes of these types like JS does, to ensure their # precense. + + if event.Name is None: + raise ValueError("History Event for suborchestration found with no {Name} field") + event_name: str = event.Name err_message: str = "" if not(event.Name == name): mid_message = "a function name of {} instead of the provided function name of {}." - err_message = gen_err_message(counter, mid_message, event.Name, name) + err_message = gen_err_message(counter, mid_message, event_name, name) raise ValueError(err_message) if instance_id and not(event.InstanceId == instance_id): mid_message = "an instance id of {} instead of the provided instance id of {}." - err_message = gen_err_message(counter, mid_message, event.Name, name) + err_message = gen_err_message(counter, mid_message, event_name, name) raise ValueError(err_message) return event diff --git a/noxfile.py b/noxfile.py index 25632006..cae7ac72 100644 --- a/noxfile.py +++ b/noxfile.py @@ -16,5 +16,6 @@ def lint(session): @nox.session(python=["3.7", "3.8"]) def typecheck(session): + session.install("-r", "requirements.txt") session.install("mypy") session.run("mypy", "./azure/") \ No newline at end of file