def __init__(self, parent, name, times=None, times_attribute=None, **kwargs): """ Constructor. :type parent: L{SpiffWorkflow.specs.WorkflowSpec} :param parent: A reference to the parent (usually a workflow). :type name: string :param name: A name for the task. :type times: int or None :param times: The number of tasks to create. :type times_attribute: str or None :param times_attribute: The name of an attribute that specifies the number of outgoing tasks. :type kwargs: dict :param kwargs: See L{SpiffWorkflow.specs.TaskSpec}. """ if not times_attribute and not times: raise ValueError('require times or times_attribute argument') TaskSpec.__init__(self, parent, name, **kwargs) self.times_attribute = times_attribute self.times = times self.thread_starter = ThreadStart(parent, **kwargs) self.outputs.append(self.thread_starter) self.thread_starter._connect_notify(self)
def __init__(self, parent, name, times = None, times_attribute = None, **kwargs): """ Constructor. @type parent: L{SpiffWorkflow.specs.WorkflowSpec} @param parent: A reference to the parent (usually a workflow). @type name: string @param name: A name for the task. @type times: int or None @param times: The number of tasks to create. @type times_attribute: str or None @param times_attribute: The name of an attribute that specifies the number of outgoing tasks. @type kwargs: dict @param kwargs: See L{SpiffWorkflow.specs.TaskSpec}. """ if not times_attribute and not times: raise ValueError('require times or times_attribute argument') TaskSpec.__init__(self, parent, name, **kwargs) self.times_attribute = times_attribute self.times = times self.thread_starter = ThreadStart(parent, **kwargs) self.outputs.append(self.thread_starter) self.thread_starter._connect_notify(self)
def __init__(self, parent, name, times=None, times_attribute=None, suppress_threadstart_creation=False, **kwargs): """ Constructor. :type parent: L{SpiffWorkflow.specs.WorkflowSpec} :param parent: A reference to the parent (usually a workflow). :type name: string :param name: A name for the task. :type times: int or None :param times: The number of tasks to create. :type times_attribute: str or None :param times_attribute: The name of a data field that specifies the number of outgoing tasks. :type suppress_threadstart_creation: bool :param suppress_threadstart_creation: Don't create a ThreadStart, because the deserializer is about to. :type kwargs: dict :param kwargs: See L{SpiffWorkflow.specs.TaskSpec}. """ if not times_attribute and not times: raise ValueError('require times or times_attribute argument') TaskSpec.__init__(self, parent, name, **kwargs) self.times_attribute = times_attribute self.times = times if not suppress_threadstart_creation: self.thread_starter = ThreadStart(parent, **kwargs) self.outputs.append(self.thread_starter) self.thread_starter._connect_notify(self) else: self.thread_starter = None
def __init__(self, parent, name, times = None, times_attribute = None, suppress_threadstart_creation = False, **kwargs): """ Constructor. :type parent: L{SpiffWorkflow.specs.WorkflowSpec} :param parent: A reference to the parent (usually a workflow). :type name: string :param name: A name for the task. :type times: int or None :param times: The number of tasks to create. :type times_attribute: str or None :param times_attribute: The name of a data field that specifies the number of outgoing tasks. :type suppress_threadstart_creation: bool :param suppress_threadstart_creation: Don't create a ThreadStart, because the deserializer is about to. :type kwargs: dict :param kwargs: See L{SpiffWorkflow.specs.TaskSpec}. """ if not times_attribute and not times: raise ValueError('require times or times_attribute argument') TaskSpec.__init__(self, parent, name, **kwargs) self.times_attribute = times_attribute self.times = times if not suppress_threadstart_creation: self.thread_starter = ThreadStart(parent, **kwargs) self.outputs.append(self.thread_starter) self.thread_starter._connect_notify(self) else: self.thread_starter = None
class ThreadSplit(TaskSpec): """ When executed, this task performs a split on the current my_task. The number of outgoing my_tasks depends on the runtime value of a specified attribute. If more than one input is connected, the task performs an implicit multi merge. This task has one or more inputs and may have any number of outputs. """ def __init__(self, parent, name, times=None, times_attribute=None, **kwargs): """ Constructor. :type parent: L{SpiffWorkflow.specs.WorkflowSpec} :param parent: A reference to the parent (usually a workflow). :type name: string :param name: A name for the task. :type times: int or None :param times: The number of tasks to create. :type times_attribute: str or None :param times_attribute: The name of an attribute that specifies the number of outgoing tasks. :type kwargs: dict :param kwargs: See L{SpiffWorkflow.specs.TaskSpec}. """ if not times_attribute and not times: raise ValueError('require times or times_attribute argument') TaskSpec.__init__(self, parent, name, **kwargs) self.times_attribute = times_attribute self.times = times self.thread_starter = ThreadStart(parent, **kwargs) self.outputs.append(self.thread_starter) self.thread_starter._connect_notify(self) def connect(self, task_spec): """ Connect the *following* task to this one. In other words, the given task is added as an output task. task -- the task to connect to. """ self.thread_starter.outputs.append(task_spec) task_spec._connect_notify(self.thread_starter) def _find_my_task(self, workflow): for task in workflow.branch_tree: if task.thread_id != my_task.thread_id: continue if task.task == self: return task return None def _get_activated_tasks(self, my_task, destination): """ Returns the list of tasks that were activated in the previous call of execute(). Only returns tasks that point towards the destination task, i.e. those which have destination as a descendant. my_task -- the task of this TaskSpec destination -- the child task """ task = destination._find_ancestor(self.thread_starter) return self.thread_starter._get_activated_tasks(task, destination) def _get_activated_threads(self, my_task): """ Returns the list of threads that were activated in the previous call of execute(). my_task -- the task of this TaskSpec """ return my_task.children def _on_trigger(self, my_task): """ May be called after execute() was already completed to create an additional outbound task. """ # Find a Task for this task. my_task = self._find_my_task(my_task.workflow) for output in self.outputs: new_task = my_task.add_child(output, Task.READY) new_task.triggered = True def _predict_hook(self, my_task): split_n = my_task.get_attribute('split_n', self.times) if split_n is None: split_n = my_task.get_attribute(self.times_attribute, 1) # Predict the outputs. outputs = [] for i in range(split_n): outputs.append(self.thread_starter) if my_task._is_definite(): my_task._sync_children(outputs, Task.FUTURE) else: my_task._sync_children(outputs, Task.LIKELY) def _on_complete_hook(self, my_task): # Split, and remember the number of splits in the context data. split_n = self.times if split_n is None: split_n = my_task.get_attribute(self.times_attribute) # Create the outgoing tasks. outputs = [] for i in range(split_n): outputs.append(self.thread_starter) my_task._sync_children(outputs, Task.FUTURE) for child in my_task.children: child.task_spec._update_state(child) def serialize(self, serializer): return serializer._serialize_thread_split(self)
class ThreadSplit(TaskSpec): """ When executed, this task performs a split on the current my_task. The number of outgoing my_tasks depends on the runtime value of a specified data field. If more than one input is connected, the task performs an implicit multi merge. This task has one or more inputs and may have any number of outputs. """ def __init__(self, parent, name, times = None, times_attribute = None, suppress_threadstart_creation = False, **kwargs): """ Constructor. :type parent: L{SpiffWorkflow.specs.WorkflowSpec} :param parent: A reference to the parent (usually a workflow). :type name: string :param name: A name for the task. :type times: int or None :param times: The number of tasks to create. :type times_attribute: str or None :param times_attribute: The name of a data field that specifies the number of outgoing tasks. :type suppress_threadstart_creation: bool :param suppress_threadstart_creation: Don't create a ThreadStart, because the deserializer is about to. :type kwargs: dict :param kwargs: See L{SpiffWorkflow.specs.TaskSpec}. """ if not times_attribute and not times: raise ValueError('require times or times_attribute argument') TaskSpec.__init__(self, parent, name, **kwargs) self.times_attribute = times_attribute self.times = times if not suppress_threadstart_creation: self.thread_starter = ThreadStart(parent, **kwargs) self.outputs.append(self.thread_starter) self.thread_starter._connect_notify(self) else: self.thread_starter = None def connect(self, task_spec): """ Connect the *following* task to this one. In other words, the given task is added as an output task. task -- the task to connect to. """ self.thread_starter.outputs.append(task_spec) task_spec._connect_notify(self.thread_starter) def _find_my_task(self, workflow): for task in workflow.branch_tree: if task.thread_id != my_task.thread_id: continue if task.task == self: return task return None def _get_activated_tasks(self, my_task, destination): """ Returns the list of tasks that were activated in the previous call of execute(). Only returns tasks that point towards the destination task, i.e. those which have destination as a descendant. my_task -- the task of this TaskSpec destination -- the child task """ task = destination._find_ancestor(self.thread_starter) return self.thread_starter._get_activated_tasks(task, destination) def _get_activated_threads(self, my_task): """ Returns the list of threads that were activated in the previous call of execute(). my_task -- the task of this TaskSpec """ return my_task.children def _on_trigger(self, my_task): """ May be called after execute() was already completed to create an additional outbound task. """ # Find a Task for this task. my_task = self._find_my_task(my_task.workflow) for output in self.outputs: new_task = my_task.add_child(output, Task.READY) new_task.triggered = True def _predict_hook(self, my_task): split_n = my_task.get_data('split_n', self.times) if split_n is None: split_n = my_task.get_data(self.times_attribute, 1) # if we were created with thread_starter suppressed, connect it now. if self.thread_starter is None: self.thread_starter = self.outputs[0] # Predict the outputs. outputs = [] for i in range(split_n): outputs.append(self.thread_starter) if my_task._is_definite(): my_task._sync_children(outputs, Task.FUTURE) else: my_task._sync_children(outputs, Task.LIKELY) def _on_complete_hook(self, my_task): # Split, and remember the number of splits in the context data. split_n = self.times if split_n is None: split_n = my_task.get_data(self.times_attribute) # Create the outgoing tasks. outputs = [] for i in range(split_n): outputs.append(self.thread_starter) my_task._sync_children(outputs, Task.FUTURE) for child in my_task.children: child.task_spec._update_state(child) def serialize(self, serializer): return serializer._serialize_thread_split(self) @classmethod def deserialize(self, serializer, wf_spec, s_state): return serializer._deserialize_thread_split(wf_spec, s_state)
def _deserialize_thread_start(self, wf_spec, s_state): # specs/__init__.py deliberately hides this: forcibly import it from SpiffWorkflow.specs.ThreadStart import ThreadStart spec = ThreadStart(wf_spec) self._deserialize_task_spec(wf_spec, s_state, spec=spec) return spec