Skip to content

Commit cba220c

Browse files
committed
subflows
Signed-off-by: Pedro Escaleira <pedroescaleira@hotmail.com>
1 parent 661d634 commit cba220c

File tree

3 files changed

+106
-36
lines changed

3 files changed

+106
-36
lines changed

serverlessworkflow/sdk/state_machine_generator.py

Lines changed: 105 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from typing import Any, Dict, List, Optional, Union
2+
from serverlessworkflow.sdk.action import Action
23
from serverlessworkflow.sdk.callback_state import CallbackState
34
from serverlessworkflow.sdk.function_ref import FunctionRef
45
from serverlessworkflow.sdk.sleep_state import SleepState
@@ -10,6 +11,7 @@
1011
ParallelState,
1112
OperationState,
1213
ForEachState,
14+
Workflow,
1315
)
1416
from serverlessworkflow.sdk.transition_data_condition import TransitionDataCondition
1517
from serverlessworkflow.sdk.end_data_condition import EndDataCondition
@@ -25,13 +27,15 @@ def __init__(
2527
self,
2628
state: State,
2729
state_machine: Union[HierarchicalMachine, GraphMachine],
30+
subflows: List[Workflow] = [],
2831
is_first_state=False,
2932
get_actions=False,
3033
):
3134
self.state = state
3235
self.is_first_state = is_first_state
3336
self.state_machine = state_machine
3437
self.get_actions = get_actions
38+
self.subflows = subflows
3539

3640
if self.get_actions and not isinstance(self.state_machine, HierarchicalMachine):
3741
raise AttributeError(
@@ -314,6 +318,11 @@ def data_based_switch_state_details(self) -> str:
314318

315319
def operation_state_details(self) -> Optional[str]:
316320
descriptions = []
321+
if self.state.name not in self.state_machine.states.keys():
322+
self.state_machine.add_states(self.state.name)
323+
if self.is_first_state:
324+
self.state_machine._initial = self.state.name
325+
317326
if isinstance(self.state, OperationState):
318327
action_mode = self.state.actionMode
319328
if action_mode:
@@ -324,26 +333,11 @@ def operation_state_details(self) -> Optional[str]:
324333
action_mode,
325334
)
326335
)
327-
actions = self.state.actions
328-
if actions:
329-
descriptions.append(
330-
self.state_description(
331-
self.state_key_diagram(self.state.name),
332-
"Num. of actions",
333-
str(len(actions)),
334-
)
336+
descriptions.extend(
337+
self.generate_actions_info(
338+
actions=self.state.actions, action_mode=self.state.actionMode
335339
)
336-
if self.get_actions:
337-
descriptions.append(
338-
f"state {self.state_key_diagram(self.state.name)} {{\n"
339-
f"{self.generate_composite_state(self.state_machine.get_state(self.state.name), self.state.name, actions, action_mode)}\n"
340-
f"}}\n"
341-
)
342-
343-
if self.state.name not in self.state_machine.states.keys():
344-
self.state_machine.add_states(self.state.name)
345-
if self.is_first_state:
346-
self.state_machine._initial = self.state.name
340+
)
347341

348342
return "\n".join(descriptions) if descriptions else None
349343

@@ -368,15 +362,12 @@ def foreach_state_details(self) -> Optional[str]:
368362
input_collection,
369363
)
370364
)
371-
actions = self.state.actions
372-
if actions:
373-
descriptions.append(
374-
self.state_description(
375-
self.state_key_diagram(self.state.name),
376-
"Num. of actions",
377-
str(len(actions)),
378-
)
365+
descriptions.extend(
366+
self.generate_actions_info(
367+
actions=self.state.actions, action_mode=self.state.mode
379368
)
369+
)
370+
380371
return "\n".join(descriptions) if descriptions else None
381372

382373
def callback_state_details(self) -> Optional[str]:
@@ -398,12 +389,7 @@ def callback_state_details(self) -> Optional[str]:
398389
)
399390
)
400391

401-
if self.get_actions:
402-
descriptions.append(
403-
f"state {self.state_key_diagram(self.state.name)} {{\n"
404-
f"{self.generate_composite_state(self.state_machine.get_state(self.state.name), self.state.name, [action], 'sequential')}\n"
405-
f"}}\n"
406-
)
392+
self.generate_actions_info(actions=[action], singular_action=True)
407393
event_ref = self.state.eventRef
408394
if event_ref:
409395
descriptions.append(
@@ -438,7 +424,7 @@ def generate_composite_state(
438424
machine_state: NestedState,
439425
state_name: str,
440426
actions: List[Dict[str, Any]],
441-
action_mode: str,
427+
action_mode: str = "sequential",
442428
) -> str:
443429
transitions = ""
444430
parallel_states = []
@@ -502,6 +488,91 @@ def generate_composite_state(
502488

503489
return transitions
504490

491+
def generate_actions_info(
492+
self,
493+
actions: List[Action],
494+
action_mode: str = "sequential",
495+
singular_action=False,
496+
):
497+
descriptions = []
498+
if actions:
499+
if not singular_action:
500+
descriptions.append(
501+
self.state_description(
502+
self.state_key_diagram(self.state.name),
503+
"Num. of actions",
504+
str(len(actions)),
505+
)
506+
)
507+
if self.get_actions:
508+
descriptions.append(
509+
f"state {self.state_key_diagram(self.state.name)} {{\n"
510+
f"{self.generate_composite_state(self.state_machine.get_state(self.state.name), self.state.name, actions, action_mode)}\n"
511+
f"}}\n"
512+
)
513+
for action in actions:
514+
if action.subFlowRef:
515+
if isinstance(action.subFlowRef, str):
516+
workflow_id = action.subFlowRef
517+
workflow_version = None
518+
else:
519+
workflow_id = action.subFlowRef.workflowId
520+
workflow_version = action.subFlowRef.version
521+
for sf in self.subflows:
522+
if (
523+
sf.id == workflow_id
524+
): # and (workflow_version and sf.version == workflow_version or not workflow_version):
525+
new_machine = HierarchicalMachine(
526+
model=None, initial=None, auto_transitions=False
527+
)
528+
529+
# Generate the state machine for the subflow
530+
for index, state in enumerate(sf.states):
531+
StateMachineGenerator(
532+
state=state,
533+
state_machine=new_machine,
534+
is_first_state=index == 0,
535+
get_actions=self.get_actions,
536+
subflows=self.subflows
537+
).source_code()
538+
539+
# Convert the new_machine into a NestedState
540+
nested_state = NestedState(
541+
action.name if action.name else f"{sf.id}/{sf.version.replace(NestedState.separator, '-')}"
542+
)
543+
self.state_machine_to_nested_state(state_machine=new_machine, nested_state=nested_state)
544+
# else:
545+
# raise Warning("No correct subflow provided")
546+
547+
return descriptions
548+
549+
def add_all_sub_states(cls, original_state: Union[NestedState, HierarchicalMachine], new_state: NestedState):
550+
if len(original_state.states) == 0:
551+
return
552+
for substate in original_state.states.values():
553+
new_state.add_substate(ns := NestedState(substate.name))
554+
cls.add_all_sub_states(substate, ns)
555+
556+
def state_machine_to_nested_state(
557+
self, state_machine: HierarchicalMachine, nested_state: NestedState
558+
) -> NestedState:
559+
self.state_machine.get_state(
560+
self.state.name
561+
).add_substate(nested_state)
562+
563+
self.add_all_sub_states(state_machine, nested_state)
564+
565+
for trigger, event in state_machine.events.items():
566+
for transition_l in event.transitions.values():
567+
for transition in transition_l:
568+
source = transition.source
569+
dest = transition.dest
570+
self.state_machine.add_transition(
571+
trigger=trigger,
572+
source=f"{self.state.name}.{nested_state.name}.{source}",
573+
dest=f"{self.state.name}.{nested_state.name}.{dest}",
574+
)
575+
505576
def get_function_name(
506577
self, fn_ref: Union[Dict[str, Any], str, None]
507578
) -> Optional[str]:

serverlessworkflow/sdk/state_machine_helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def __init__(
3232
)
3333
self.plantuml_graph = "\n\n".join(
3434
StateMachineGenerator(
35-
state, self.machine, index == 0, get_actions=self.get_actions
35+
state=state, state_machine=self.machine, is_first_state=index == 0, get_actions=self.get_actions, subflows=subflows
3636
).source_code()
3737
for index, state in enumerate(workflow.states)
3838
)

setup.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,4 @@
1717
setup_requires=['pytest-runner'],
1818
tests_require=['pytest'],
1919
test_suite='tests',
20-
2120
)

0 commit comments

Comments
 (0)