From ea838f53e0cd8a19aed210fa81eff859dac5f1d3 Mon Sep 17 00:00:00 2001 From: Oliver Stolz Date: Mon, 19 Aug 2024 11:56:45 +0200 Subject: [PATCH] Enable flexible starting task names for plugins - Instead of limiting the starting task name to 'productionTask', it can now be modified by passing the desired name to the Process --- pfdl_scheduler/model/process.py | 10 +++++++++- pfdl_scheduler/petri_net/generator.py | 19 ++++++++----------- pfdl_scheduler/scheduler.py | 2 +- .../validation/semantic_error_checker.py | 6 +++--- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/pfdl_scheduler/model/process.py b/pfdl_scheduler/model/process.py index 09d61bc..c9038fc 100644 --- a/pfdl_scheduler/model/process.py +++ b/pfdl_scheduler/model/process.py @@ -25,14 +25,21 @@ class Process: Attributes: structs: A dict for mapping the Struct names to the Struct objects. task: A dict for mapping the Task names to the Task objects. + start_task_name: the name of the start task of the PFDL program (typically "productionTask"). """ - def __init__(self, structs: Dict[str, Struct] = None, tasks: Dict[str, Task] = None) -> None: + def __init__( + self, + structs: Dict[str, Struct] = None, + tasks: Dict[str, Task] = None, + start_task_name: str = "productionTask", + ) -> None: """Initialize the object. Args: structs: A dict for mapping the Struct names to the Struct objects. tasks: A dict for mapping the Task names to the Task objects. + start_task_name: the name of the start task of the PFDL program (typically "productionTask"). """ if structs: self.structs: Dict[str, Struct] = structs @@ -42,3 +49,4 @@ def __init__(self, structs: Dict[str, Struct] = None, tasks: Dict[str, Task] = N self.tasks: Dict[str, Task] = tasks else: self.tasks: Dict[str, Task] = {} + self.start_task_name = start_task_name diff --git a/pfdl_scheduler/petri_net/generator.py b/pfdl_scheduler/petri_net/generator.py index 0c1dc8b..d1695b6 100644 --- a/pfdl_scheduler/petri_net/generator.py +++ b/pfdl_scheduler/petri_net/generator.py @@ -99,6 +99,7 @@ def __init__( used_in_extension: A boolean indicating if the Generator is used within the extension. generate_test_ids: A boolean indicating if test ids (counting from 0) should be generated. draw_net: A boolean indicating if the petri net should be drawn. + file_name: The desired filename of the petri net image. """ if used_in_extension: @@ -143,7 +144,7 @@ def add_callback(self, transition_uuid: str, callback_function: Callable, *args: def generate_petri_net(self, process: Process) -> PetriNet: """Generates a Petri Net from the given Process object. - Starts from the 'productionTask' and iterates over his statements. + Starts from the start task of the PFDL program and iterates over his statements. For each statement type like Condition or TaskCall a Petri Net component is generated. All components get connected at the end. @@ -151,25 +152,21 @@ def generate_petri_net(self, process: Process) -> PetriNet: A PetriNet instance representing the generated net. """ self.tasks = process.tasks - production_task = process.tasks["productionTask"] + start_task = process.tasks[process.start_task_name] group_uuid = str(uuid.uuid4()) - self.tree = Node(group_uuid, production_task.name) + self.tree = Node(group_uuid, start_task.name) - task_context = TaskAPI(production_task, None) + task_context = TaskAPI(start_task, None) if self.generate_test_ids: task_context.uuid = "0" - self.task_started_uuid = create_place( - production_task.name + "_started", self.net, self.tree - ) + self.task_started_uuid = create_place(start_task.name + "_started", self.net, self.tree) connection_uuid = create_transition("", "", self.net, self.tree) self.add_callback(connection_uuid, self.callbacks.task_started, task_context) self.net.add_input(self.task_started_uuid, connection_uuid, Value(1)) - self.task_finished_uuid = create_place( - production_task.name + "_finished", self.net, self.tree - ) + self.task_finished_uuid = create_place(start_task.name + "_finished", self.net, self.tree) second_connection_uuid = create_transition("", "", self.net, self.tree) @@ -183,7 +180,7 @@ def generate_petri_net(self, process: Process) -> PetriNet: ) self.generate_statements( task_context, - production_task.statements, + start_task.statements, connection_uuid, second_connection_uuid, self.tree, diff --git a/pfdl_scheduler/scheduler.py b/pfdl_scheduler/scheduler.py index 216bd22..b563e7f 100644 --- a/pfdl_scheduler/scheduler.py +++ b/pfdl_scheduler/scheduler.py @@ -480,7 +480,7 @@ def on_task_finished(self, task_api: TaskAPI) -> None: callback(task_api) order_finished = False - if task_api.task.name == "productionTask": + if task_api.task.name == self.process.start_task_name: self.running = False order_finished = True self.petri_net_logic.draw_petri_net() diff --git a/pfdl_scheduler/validation/semantic_error_checker.py b/pfdl_scheduler/validation/semantic_error_checker.py index d8e5254..7330dfa 100644 --- a/pfdl_scheduler/validation/semantic_error_checker.py +++ b/pfdl_scheduler/validation/semantic_error_checker.py @@ -29,7 +29,7 @@ from pfdl_scheduler.utils import helpers # global defines -from pfdl_scheduler.parser.pfdl_tree_visitor import IN_KEY, OUT_KEY, START_TASK +from pfdl_scheduler.parser.pfdl_tree_visitor import IN_KEY, OUT_KEY class SemanticErrorChecker: @@ -105,7 +105,7 @@ def check_tasks(self) -> bool: start_task_found = False for task in self.tasks.values(): - if task.name == START_TASK: + if task.name == self.process.start_task_name: start_task_found = True # use & so all methods will be executed even if a method returns False @@ -117,7 +117,7 @@ def check_tasks(self) -> bool: valid = False if not start_task_found: - error_msg = "The file contains no 'productionTask' (Starting Point)" + error_msg = f"The file contains no '{self.process.start_task_name}' (Starting Point)" self.error_handler.print_error(error_msg, line=1, column=0, off_symbol_length=5) return False