Skip to content

Commit 74309f5

Browse files
committed
Factor out helper to share start-workflow code
1 parent fbf2774 commit 74309f5

File tree

2 files changed

+28
-36
lines changed

2 files changed

+28
-36
lines changed

temporalio/client.py

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -494,22 +494,12 @@ async def start_workflow(
494494
already been started.
495495
RPCError: Workflow could not be started for some other reason.
496496
"""
497-
# Use definition if callable
498-
name: str
499-
if isinstance(workflow, str):
500-
name = workflow
501-
elif callable(workflow):
502-
defn = temporalio.workflow._Definition.must_from_run_fn(workflow)
503-
if not defn.name:
504-
raise ValueError("Cannot invoke dynamic workflow explicitly")
505-
name = defn.name
506-
if result_type is None:
507-
result_type = defn.ret_type
508-
else:
509-
raise TypeError("Workflow must be a string or callable")
510497
temporalio.common._warn_on_deprecated_search_attributes(
511498
search_attributes, stack_level=stack_level
512499
)
500+
name, result_type_from_run_fn = (
501+
temporalio.workflow._Definition.get_name_and_result_type(workflow)
502+
)
513503

514504
return await self._impl.start_workflow(
515505
StartWorkflowInput(
@@ -530,7 +520,7 @@ async def start_workflow(
530520
headers={},
531521
start_signal=start_signal,
532522
start_signal_args=start_signal_args,
533-
ret_type=result_type,
523+
ret_type=result_type or result_type_from_run_fn,
534524
rpc_metadata=rpc_metadata,
535525
rpc_timeout=rpc_timeout,
536526
request_eager_start=request_eager_start,
@@ -2321,7 +2311,9 @@ def get_update_handle_for(
23212311
class WithStartWorkflowOperation(Generic[SelfType, ReturnType]):
23222312
"""
23232313
Defines a start-workflow operation used by update-with-start requests.
2324-
Usually created by :py:meth:`Client.create_start_workflow_operation`.
2314+
2315+
Update-With-Start allows you to send an update to a workflow, while starting the
2316+
workflow if necessary.
23252317
"""
23262318

23272319
# Overload for no-param workflow, with_start
@@ -2451,7 +2443,6 @@ def __init__(
24512443
request_eager_start: bool = False,
24522444
) -> None: ...
24532445

2454-
# TODO: reduce duplication with start_workflow
24552446
def __init__(
24562447
self,
24572448
workflow: Union[str, Callable[..., Awaitable[Any]]],
@@ -2484,30 +2475,17 @@ def __init__(
24842475
stack_level: int = 2,
24852476
) -> None:
24862477
"""
2487-
Create a handle for issuing an Update-With-Start request.
2478+
Create a WithStartWorkflowOperation.
24882479
2489-
Update-With-Start allows you to send an update to a workflow, while starting the workflow
2490-
if necessary.
2480+
See :py:meth:`temporalio.client.Client.start_workflow` for documentation of the
2481+
arguments.
24912482
"""
2492-
2493-
# TODO: avoid duplicating this?
2494-
2495-
# Use definition if callable
2496-
name: str
2497-
if isinstance(workflow, str):
2498-
name = workflow
2499-
elif callable(workflow):
2500-
defn = temporalio.workflow._Definition.must_from_run_fn(workflow)
2501-
if not defn.name:
2502-
raise ValueError("Cannot invoke dynamic workflow explicitly")
2503-
name = defn.name
2504-
if result_type is None:
2505-
result_type = defn.ret_type
2506-
else:
2507-
raise TypeError("Workflow must be a string or callable")
25082483
temporalio.common._warn_on_deprecated_search_attributes(
25092484
search_attributes, stack_level=stack_level
25102485
)
2486+
name, result_type_from_run_fn = (
2487+
temporalio.workflow._Definition.get_name_and_result_type(workflow)
2488+
)
25112489

25122490
self._id = id
25132491
self._workflow_handle: Future[WorkflowHandle[SelfType, ReturnType]] = Future()
@@ -2529,7 +2507,7 @@ def __init__(
25292507
headers={},
25302508
start_signal=start_signal,
25312509
start_signal_args=start_signal_args,
2532-
ret_type=result_type,
2510+
ret_type=result_type or result_type_from_run_fn,
25332511
rpc_metadata=rpc_metadata,
25342512
rpc_timeout=rpc_timeout,
25352513
request_eager_start=request_eager_start,

temporalio/workflow.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,6 +1335,20 @@ def must_from_run_fn(fn: Callable[..., Awaitable[Any]]) -> _Definition:
13351335
f"Function {fn_name} missing attributes, was it decorated with @workflow.run and was its class decorated with @workflow.defn?"
13361336
)
13371337

1338+
@classmethod
1339+
def get_name_and_result_type(
1340+
cls, name_or_run_fn: Union[str, Callable[..., Awaitable[Any]]]
1341+
) -> Tuple[str, Optional[Type]]:
1342+
if isinstance(name_or_run_fn, str):
1343+
return name_or_run_fn, None
1344+
elif callable(name_or_run_fn):
1345+
defn = cls.must_from_run_fn(name_or_run_fn)
1346+
if not defn.name:
1347+
raise ValueError("Cannot invoke dynamic workflow explicitly")
1348+
return defn.name, defn.ret_type
1349+
else:
1350+
raise TypeError("Workflow must be a string or callable")
1351+
13381352
@staticmethod
13391353
def _apply_to_class(
13401354
cls: Type,

0 commit comments

Comments
 (0)