11import json
22from datetime import datetime
3- from typing import List , Any , Awaitable , Optional , Dict
3+ from typing import List , Any , Optional , Dict , Union
44from time import time
55from asyncio import sleep
66from urllib .parse import urlparse , quote
1111from .DurableOrchestrationStatus import DurableOrchestrationStatus
1212from .RpcManagementOptions import RpcManagementOptions
1313from .OrchestrationRuntimeStatus import OrchestrationRuntimeStatus
14- from ..models import DurableOrchestrationBindings
14+ from ..models . DurableOrchestrationBindings import DurableOrchestrationBindings
1515from .utils .http_utils import get_async_request , post_async_request , delete_async_request
1616from azure .functions ._durable_functions import _serialize_custom_object
1717
@@ -44,8 +44,8 @@ def __init__(self, context: str):
4444
4545 async def start_new (self ,
4646 orchestration_function_name : str ,
47- instance_id : str = None ,
48- client_input : object = None ) -> Awaitable [ str ] :
47+ instance_id : Optional [ str ] = None ,
48+ client_input : Optional [ Any ] = None ) -> str :
4949 """Start a new instance of the specified orchestrator function.
5050
5151 If an orchestration instance with the specified ID already exists, the
@@ -55,10 +55,10 @@ async def start_new(self,
5555 ----------
5656 orchestration_function_name : str
5757 The name of the orchestrator function to start.
58- instance_id : str
58+ instance_id : Optional[ str]
5959 The ID to use for the new orchestration instance. If no instance id is specified,
6060 the Durable Functions extension will generate a random GUID (recommended).
61- client_input : object
61+ client_input : Optional[Any]
6262 JSON-serializable input value for the orchestrator function.
6363
6464 Returns
@@ -69,22 +69,25 @@ async def start_new(self,
6969 request_url = self ._get_start_new_url (
7070 instance_id = instance_id , orchestration_function_name = orchestration_function_name )
7171
72- response = await self ._post_async_request (request_url , self ._get_json_input (client_input ))
72+ response : List [Any ] = await self ._post_async_request (
73+ request_url , self ._get_json_input (client_input ))
7374
74- if response [0 ] <= 202 and response [1 ]:
75+ status_code : int = response [0 ]
76+ if status_code <= 202 and response [1 ]:
7577 return response [1 ]["id" ]
76- elif response [ 0 ] == 400 :
78+ elif status_code == 400 :
7779 # Orchestrator not found, report clean exception
78- exception_data = response [1 ]
80+ exception_data : Dict [ str , str ] = response [1 ]
7981 exception_message = exception_data ["ExceptionMessage" ]
8082 raise Exception (exception_message )
8183 else :
8284 # Catch all: simply surfacing the durable-extension exception
8385 # we surface the stack trace too, since this may be a more involed exception
84- exception_message = response [1 ]
85- raise Exception (exception_message )
86+ ex_message : Any = response [1 ]
87+ raise Exception (ex_message )
8688
87- def create_check_status_response (self , request , instance_id ):
89+ def create_check_status_response (
90+ self , request : func .HttpRequest , instance_id : str ) -> func .HttpResponse :
8891 """Create a HttpResponse that contains useful information for \
8992 checking the status of the specified instance.
9093
@@ -148,16 +151,16 @@ def get_client_response_links(
148151 payload = self ._orchestration_bindings .management_urls .copy ()
149152
150153 for key , _ in payload .items ():
151- request_is_not_none = not (request is None )
152- if request_is_not_none and request .url :
154+ if not (request is None ) and request .url :
153155 payload [key ] = self ._replace_url_origin (request .url , payload [key ])
154156 payload [key ] = payload [key ].replace (
155157 self ._orchestration_bindings .management_urls ["id" ], instance_id )
156158
157159 return payload
158160
159- async def raise_event (self , instance_id , event_name , event_data = None ,
160- task_hub_name = None , connection_name = None ):
161+ async def raise_event (
162+ self , instance_id : str , event_name : str , event_data : Any = None ,
163+ task_hub_name : str = None , connection_name : str = None ) -> None :
161164 """Send an event notification message to a waiting orchestration instance.
162165
163166 In order to handle the event, the target orchestration instance must be
@@ -169,7 +172,7 @@ async def raise_event(self, instance_id, event_name, event_data=None,
169172 The ID of the orchestration instance that will handle the event.
170173 event_name : str
171174 The name of the event.
172- event_data : any , optional
175+ event_data : Any , optional
173176 The JSON-serializable data associated with the event.
174177 task_hub_name : str, optional
175178 The TaskHubName of the orchestration that will handle the event.
@@ -183,8 +186,8 @@ async def raise_event(self, instance_id, event_name, event_data=None,
183186 Exception
184187 Raises an exception if the status code is 404 or 400 when raising the event.
185188 """
186- if not event_name :
187- raise ValueError ("event_name must be a valid string." )
189+ if event_name == "" :
190+ raise ValueError ("event_name must be a non-empty string." )
188191
189192 request_url = self ._get_raise_event_url (
190193 instance_id , event_name , task_hub_name , connection_name )
@@ -203,9 +206,9 @@ async def raise_event(self, instance_id, event_name, event_data=None,
203206 if error_message :
204207 raise Exception (error_message )
205208
206- async def get_status (self , instance_id : str , show_history : bool = None ,
207- show_history_output : bool = None ,
208- show_input : bool = None ) -> DurableOrchestrationStatus :
209+ async def get_status (self , instance_id : str , show_history : bool = False ,
210+ show_history_output : bool = False ,
211+ show_input : bool = False ) -> DurableOrchestrationStatus :
209212 """Get the status of the specified orchestration instance.
210213
211214 Parameters
@@ -268,7 +271,8 @@ async def get_status_all(self) -> List[DurableOrchestrationStatus]:
268271 if error_message :
269272 raise Exception (error_message )
270273 else :
271- return [DurableOrchestrationStatus .from_json (o ) for o in response [1 ]]
274+ statuses : List [Any ] = response [1 ]
275+ return [DurableOrchestrationStatus .from_json (o ) for o in statuses ]
272276
273277 async def get_status_by (self , created_time_from : datetime = None ,
274278 created_time_to : datetime = None ,
@@ -291,6 +295,7 @@ async def get_status_by(self, created_time_from: datetime = None,
291295 DurableOrchestrationStatus
292296 The status of the requested orchestration instances
293297 """
298+ # TODO: do we really want folks to us this without specifying all the args?
294299 options = RpcManagementOptions (created_time_from = created_time_from ,
295300 created_time_to = created_time_to ,
296301 runtime_status = runtime_status )
@@ -326,19 +331,20 @@ async def purge_instance_history(self, instance_id: str) -> PurgeHistoryResult:
326331 response = await self ._delete_async_request (request_url )
327332 return self ._parse_purge_instance_history_response (response )
328333
329- async def purge_instance_history_by (self , created_time_from : datetime = None ,
330- created_time_to : datetime = None ,
331- runtime_status : List [OrchestrationRuntimeStatus ] = None ) \
334+ async def purge_instance_history_by (
335+ self , created_time_from : Optional [datetime ] = None ,
336+ created_time_to : Optional [datetime ] = None ,
337+ runtime_status : Optional [List [OrchestrationRuntimeStatus ]] = None ) \
332338 -> PurgeHistoryResult :
333339 """Delete the history of all orchestration instances that match the specified conditions.
334340
335341 Parameters
336342 ----------
337- created_time_from : datetime
343+ created_time_from : Optional[ datetime]
338344 Delete orchestration history which were created after this Date.
339- created_time_to: datetime
345+ created_time_to: Optional[ datetime]
340346 Delete orchestration history which were created before this Date.
341- runtime_status: List[OrchestrationRuntimeStatus]
347+ runtime_status: Optional[ List[OrchestrationRuntimeStatus] ]
342348 Delete orchestration instances which match any of the runtimeStatus values
343349 in this list.
344350
@@ -347,14 +353,15 @@ async def purge_instance_history_by(self, created_time_from: datetime = None,
347353 PurgeHistoryResult
348354 The results of the request to purge history
349355 """
356+ # TODO: do we really want folks to us this without specifying all the args?
350357 options = RpcManagementOptions (created_time_from = created_time_from ,
351358 created_time_to = created_time_to ,
352359 runtime_status = runtime_status )
353360 request_url = options .to_url (self ._orchestration_bindings .rpc_base_url )
354361 response = await self ._delete_async_request (request_url )
355362 return self ._parse_purge_instance_history_response (response )
356363
357- async def terminate (self , instance_id : str , reason : str ):
364+ async def terminate (self , instance_id : str , reason : str ) -> None :
358365 """Terminate the specified orchestration instance.
359366
360367 Parameters
@@ -364,6 +371,11 @@ async def terminate(self, instance_id: str, reason: str):
364371 reason: str
365372 The reason for terminating the instance.
366373
374+ Raises
375+ ------
376+ Exception:
377+ When the terminate call failed with an unexpected status code
378+
367379 Returns
368380 -------
369381 None
@@ -446,7 +458,8 @@ async def wait_for_completion_or_create_check_status_response(
446458 return self .create_check_status_response (request , instance_id )
447459
448460 @staticmethod
449- def _create_http_response (status_code : int , body : Any ) -> func .HttpResponse :
461+ def _create_http_response (
462+ status_code : int , body : Union [str , Any ]) -> func .HttpResponse :
450463 body_as_json = body if isinstance (body , str ) else json .dumps (body )
451464 response_args = {
452465 "status_code" : status_code ,
@@ -459,7 +472,7 @@ def _create_http_response(status_code: int, body: Any) -> func.HttpResponse:
459472 return func .HttpResponse (** response_args )
460473
461474 @staticmethod
462- def _get_json_input (client_input : object ) -> str :
475+ def _get_json_input (client_input : object ) -> Optional [ str ] :
463476 """Serialize the orchestrator input.
464477
465478 Parameters
@@ -469,8 +482,10 @@ def _get_json_input(client_input: object) -> str:
469482
470483 Returns
471484 -------
472- str
473- A string representing the JSON-serialization of `client_input`
485+ Optional[str]
486+ If `client_input` is not None, return a string representing
487+ the JSON-serialization of `client_input`. Otherwise, returns
488+ None
474489
475490 Exceptions
476491 ----------
@@ -482,7 +497,7 @@ def _get_json_input(client_input: object) -> str:
482497 return None
483498
484499 @staticmethod
485- def _replace_url_origin (request_url , value_url ) :
500+ def _replace_url_origin (request_url : str , value_url : str ) -> str :
486501 request_parsed_url = urlparse (request_url )
487502 value_parsed_url = urlparse (value_url )
488503 request_url_origin = '{url.scheme}://{url.netloc}/' .format (url = request_parsed_url )
@@ -491,7 +506,8 @@ def _replace_url_origin(request_url, value_url):
491506 return value_url
492507
493508 @staticmethod
494- def _parse_purge_instance_history_response (response : [int , Any ]):
509+ def _parse_purge_instance_history_response (
510+ response : List [Any ]) -> PurgeHistoryResult :
495511 switch_statement = {
496512 200 : lambda : PurgeHistoryResult .from_json (response [1 ]), # instance completed
497513 404 : lambda : PurgeHistoryResult (instancesDeleted = 0 ), # instance not found
@@ -506,17 +522,20 @@ def _parse_purge_instance_history_response(response: [int, Any]):
506522 else :
507523 raise Exception (result )
508524
509- def _get_start_new_url (self , instance_id , orchestration_function_name ):
525+ def _get_start_new_url (
526+ self , instance_id : Optional [str ], orchestration_function_name : str ) -> str :
510527 instance_path = f'/{ instance_id } ' if instance_id is not None else ''
511528 request_url = f'{ self ._orchestration_bindings .rpc_base_url } orchestrators/' \
512529 f'{ orchestration_function_name } { instance_path } '
513530 return request_url
514531
515- def _get_raise_event_url (self , instance_id , event_name , task_hub_name , connection_name ):
532+ def _get_raise_event_url (
533+ self , instance_id : str , event_name : str ,
534+ task_hub_name : Optional [str ], connection_name : Optional [str ]) -> str :
516535 request_url = f'{ self ._orchestration_bindings .rpc_base_url } ' \
517536 f'instances/{ instance_id } /raiseEvent/{ event_name } '
518537
519- query = []
538+ query : List [ str ] = []
520539 if task_hub_name :
521540 query .append (f'taskHub={ task_hub_name } ' )
522541
0 commit comments