A powerful workflow engine implemented in pure Python

Overview

Spiff Workflow

Build Status Coverage Status Code Climate Documentation Status

Summary

Spiff Workflow is a workflow engine implemented in pure Python. It is based on the excellent work of the Workflow Patterns initiative.

Do you need commercial support?

Spiff Workflow is supported by Procedure 8. Get in touch if you need anything!

Main design goals

  • Spiff Workflow aims to directly support as many of the patterns of workflowpatterns.com as possible.
  • Spiff Workflow uses unit testing as much as possible.
  • Spiff Workflow provides a clean Python API.
  • Spiff Workflow allows for mapping patterns into workflow elements that are easy to understand for non-technical users in a workflow GUI editor.
  • Spiff Workflow implements the best possible path prediction for workflows.

Spiff Workflow also provides a parser and workflow emulation layer that can be used to create executable Spiff Workflow specifications from Business Process Model and Notation (BPMN) documents.

Quick Intro

The process of using Spiff Workflow involves the following steps:

  1. Write a workflow specification. A specification may be written using XML (example), JSON, or Python (example).
  2. Run the workflow using the Python API. Example code for running the workflow:
from SpiffWorkflow.specs import WorkflowSpec
from SpiffWorkflow.serializer.prettyxml import XmlSerializer
from SpiffWorkflow import Workflow

# Load the workflow specification:
with open('my_workflow.xml') as fp:
    serializer = XmlSerializer()
    spec = WorkflowSpec.deserialize(serializer, fp.read())

# Create an instance of the workflow, according to the specification.
wf = Workflow(spec)

# Complete tasks as desired. It is the job of the workflow engine to
# guarantee a consistent state of the workflow.
wf.complete_task_from_id(...)

# Of course, you can also persist the workflow instance:
xml = wf.serialize(XmlSerializer, 'workflow_state.xml')

Documentation

Full documentation is here:

http://spiffworkflow.readthedocs.io/en/latest/

Comments
  • BPMN engine documentation

    BPMN engine documentation

    I recently added a ton of documentation for most parts of SpiffWorkflow (and ported the module to Py3). The only missing part is documentation for the BPMN layer, which I am now trying to add.

    @matthewhampton can you help out with the following questions?:

    • What is the purpose of the BpmnWorkflow.accept_message() method?
    • Do you have a minimal example of how to run a BPMN workflow?
    • Why did you add BpmnWorkflow.do_engine_steps() in addition to the already inherited BpmnWorkflow.complete_all()? Is this actually needed?
    opened by knipknap 14
  • Memory Usage

    Memory Usage

    Hi. Thanks very much for maintaining this amazing library! I'm currently using SpiffWorkflow to generate logs for a somewhat big BPMN (~1.5 MB). Unfortunately, creating a Workflow from the spec uses way too much memory (exceeding 100 GB easily).

    I figured that the problem lies within the gateways, since every node with multiple children creates several distinct paths throughout the workflow (whilst also creating mulitple task instances of the same task-spec) creating a total of >10 bil. instances of tasks in just one Workflow.

    Now that I haven't understood the deepest of functionings in SpiffWorkflow: Is it necessary to create those distinct paths from a Gateway up until the end or is there a way to prevent this while maintaining the main functioning?

    Thanks you very much!

    opened by IAsmodai 12
  • Multi Instance Call Activities stopped working since 1.1.1

    Multi Instance Call Activities stopped working since 1.1.1

    Problem:

    Multi Instance Call Activities stopped working since Version 1.1.1.

    Reason:

    Class determination in method _handle_special_cases() works different than isinstance() so CallActivity can't be identified as subclass of SubWorkflowTask.

    Fix:

    In bpmn/specs/MultiInstanceTask.py:

    425c425
    <         classes = [BusinessRuleTask,ScriptTask,SubWorkflowTask,SubWorkflow]
    ---
    >         classes = [BusinessRuleTask,ScriptTask,SubWorkflowTask,SubWorkflow,CallActivity]
    
    opened by kaihasse 10
  • Make a release on PyPi

    Make a release on PyPi

    The latest release on PyPi was 0.3.0 in 2009. The code has changed a fair amount since then. It's time for a new version number - 1.0 maybe? - and a new release.

    opened by dee42 9
  • Initial support for BPMN escalation boundary event on CallActivity tasks

    Initial support for BPMN escalation boundary event on CallActivity tasks

    Escalation boundary events attached to CallActivity tasks will be activated if subworkflow embedded in CallActivity reaches any escalation end event node.

    Boundary events with and without escalation code filter are supported in both interrupting and non-interrupting variants.

    opened by demostenes 8
  • Task.is_descendant_of? can't deal with multiple parents

    Task.is_descendant_of? can't deal with multiple parents

    I've stumbled into this recently, where we rely on Task.is_descendant_of?, however we also support parallel tasks with a Merge. Tasks in Spiff only have one parent, which means that some of our use-cases fail to traverse back in the tree, because the multiple previous paths of a merge can't be traversed (only one).

    I'm working around it with a separate implementation that starts at the "possible parent", and traverses the task tree downwards.

    opened by HoneyryderChuck 7
  • Get Error

    Get Error "Duplicate task spec name" when flow to Multi-Instance twice

    Steps

    • Start Process
    • Complete UserTask A (Multi-Instance) 3 times (set data approved = False)
    • exclusive gateway flow to UserTask B
    • Get Error Message KeyError: 'Duplicate task spec name: Gateway_for_task-A_start'

    Test BPMN File

    <?xml version="1.0" encoding="UTF-8"?>
    <bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0y9pl5m" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
      <bpmn:process id="Process_1" isExecutable="true">
        <bpmn:startEvent id="start-event" name="Start">
          <bpmn:outgoing>start-to-A</bpmn:outgoing>
        </bpmn:startEvent>
        <bpmn:sequenceFlow id="start-to-A" sourceRef="start-event" targetRef="task-A" />
        <bpmn:exclusiveGateway id="check" name="check">
          <bpmn:incoming>go-to-check</bpmn:incoming>
          <bpmn:outgoing>approved-ng</bpmn:outgoing>
          <bpmn:outgoing>approved-ok</bpmn:outgoing>
        </bpmn:exclusiveGateway>
        <bpmn:sequenceFlow id="go-to-check" sourceRef="task-A" targetRef="check" />
        <bpmn:sequenceFlow id="approved-ng" name="ng" sourceRef="check" targetRef="task-B">
          <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">approved == False</bpmn:conditionExpression>
        </bpmn:sequenceFlow>
        <bpmn:sequenceFlow id="approved-ok" name="ok" sourceRef="check" targetRef="task-C">
          <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">approved == True</bpmn:conditionExpression>
        </bpmn:sequenceFlow>
        <bpmn:endEvent id="end-event" name="End">
          <bpmn:incoming>go-to-end</bpmn:incoming>
        </bpmn:endEvent>
        <bpmn:sequenceFlow id="go-to-end" sourceRef="task-C" targetRef="end-event" />
        <bpmn:sequenceFlow id="return-A" sourceRef="task-B" targetRef="task-A" />
        <bpmn:userTask id="task-A" name="A">
          <bpmn:incoming>start-to-A</bpmn:incoming>
          <bpmn:incoming>return-A</bpmn:incoming>
          <bpmn:outgoing>go-to-check</bpmn:outgoing>
          <bpmn:multiInstanceLoopCharacteristics>
            <bpmn:loopCardinality xsi:type="bpmn:tFormalExpression">3</bpmn:loopCardinality>
          </bpmn:multiInstanceLoopCharacteristics>
        </bpmn:userTask>
        <bpmn:userTask id="task-C" name="C">
          <bpmn:incoming>approved-ok</bpmn:incoming>
          <bpmn:outgoing>go-to-end</bpmn:outgoing>
        </bpmn:userTask>
        <bpmn:userTask id="task-B" name="B">
          <bpmn:incoming>approved-ng</bpmn:incoming>
          <bpmn:outgoing>return-A</bpmn:outgoing>
        </bpmn:userTask>
      </bpmn:process>
      <bpmndi:BPMNDiagram id="BPMNDiagram_1">
        <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
          <bpmndi:BPMNEdge id="Flow_1iikmgj_di" bpmnElement="start-to-A">
            <di:waypoint x="215" y="177" />
            <di:waypoint x="270" y="177" />
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge id="Flow_1a8y7jv_di" bpmnElement="go-to-check">
            <di:waypoint x="370" y="177" />
            <di:waypoint x="425" y="177" />
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge id="Flow_1bjb5x4_di" bpmnElement="approved-ng">
            <di:waypoint x="450" y="202" />
            <di:waypoint x="450" y="300" />
            <bpmndi:BPMNLabel>
              <dc:Bounds x="459" y="248" width="13" height="14" />
            </bpmndi:BPMNLabel>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge id="Flow_0lgyq5h_di" bpmnElement="approved-ok">
            <di:waypoint x="475" y="177" />
            <di:waypoint x="590" y="177" />
            <bpmndi:BPMNLabel>
              <dc:Bounds x="527" y="159" width="12" height="14" />
            </bpmndi:BPMNLabel>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge id="Flow_0x702io_di" bpmnElement="go-to-end">
            <di:waypoint x="690" y="177" />
            <di:waypoint x="782" y="177" />
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge id="Flow_0b9ygw9_di" bpmnElement="return-A">
            <di:waypoint x="400" y="340" />
            <di:waypoint x="320" y="340" />
            <di:waypoint x="320" y="217" />
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="start-event">
            <dc:Bounds x="179" y="159" width="36" height="36" />
            <bpmndi:BPMNLabel>
              <dc:Bounds x="185" y="202" width="24" height="14" />
            </bpmndi:BPMNLabel>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape id="Gateway_1qk7uju_di" bpmnElement="check" isMarkerVisible="true">
            <dc:Bounds x="425" y="152" width="50" height="50" />
            <bpmndi:BPMNLabel>
              <dc:Bounds x="436" y="122" width="29" height="14" />
            </bpmndi:BPMNLabel>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape id="Activity_0lo4mlm_di" bpmnElement="task-A">
            <dc:Bounds x="270" y="137" width="100" height="80" />
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape id="Activity_08cbyyr_di" bpmnElement="task-B">
            <dc:Bounds x="400" y="300" width="100" height="80" />
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape id="Activity_1lr38ba_di" bpmnElement="task-C">
            <dc:Bounds x="590" y="137" width="100" height="80" />
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape id="Event_1qba375_di" bpmnElement="end-event">
            <dc:Bounds x="782" y="159" width="36" height="36" />
            <bpmndi:BPMNLabel>
              <dc:Bounds x="790" y="202" width="20" height="14" />
            </bpmndi:BPMNLabel>
          </bpmndi:BPMNShape>
        </bpmndi:BPMNPlane>
      </bpmndi:BPMNDiagram>
    </bpmn:definitions>
    
    
    opened by kadyang 6
  • 1.1.7 contains breaking changes

    1.1.7 contains breaking changes

    Hi 👋 I've tested the upgrade to teh latest version, and it seems that some variables were moved around, specifically TaskStates. The code in question breaks because it relies on available of constants when having tasks, so there's a lot of task.WAITING and the like.

    Would you reconsider reverting this? Even if we would redo the code, It seems a bit of overhead for no real gain, i.e. now I have to import TaskStates in order to access the state static variables.

    opened by HoneyryderChuck 6
  • A year of BPMN / DMN Enhancements

    A year of BPMN / DMN Enhancements

    I'm working on a project that hopes to use SpiffWorkflow to build out a multi-purpose tool for managing some complex workflow tasks for a university. We'd like to support the open source Camunda modeler for creating BPMN diagrams as well. I think this is general purpose enough to be of benefit to a wider community. I wanted to get this in front of you to see if these are additions you believe would be good for SpiffWorkflow, or if I should attempt to create a separate companion project.

    This initial effort is just adding in a basic form processor. But in the future I'd like to support the BMN notation for handing basic business rule definitions. Rather than author detailed documentation for the main project, I'd also like to build out that documentation here, and write tutorials on creating BPMN diagrams and using them to execute a workflow. Delve into serialization for storage and communication over an API, etc ....

    opened by danfunk 6
  • Any real world usage example I can use to inspire myself?

    Any real world usage example I can use to inspire myself?

    Hi,

    I've been taking a look at Spiffworkflow for a project I'm working on and it seems it could perfectly fit the bill, since I need to develop a workflow system where a process may have several steps, several people are involved in this process and have different permissions to execute certain steps, etc.

    However I'm having trouble finding real usages of this library, and how to bind each task to python code or functions (e.g. notify by email a user once a step has been completed), how to decide which person is allowed to execute a certain step on a workflow, etc. Is there any complex implementation I could see as a source of inspiration?

    Thank you and kind regards.

    opened by Rydra 6
  • Documentation issue

    Documentation issue

    Here http://spiffworkflow.readthedocs.io/en/latest/tutorial/index.html, in the json, the president task

    "president": {
                "class": "SpiffWorkflow.specs.ExclusiveChoice.ExclusiveChoice",
                "name": "president",
                "manual": true,
                "inputs": [
                    "general"
                ],
                "outputs": [
                    "workflow_aborted",
                    "nuclear_strike"
                ],
                "choice": null,
                "default_task_spec": "workflow_aborted",
                "cond_task_specs": [
                    [
                        [
                            "SpiffWorkflow.operators.Equal",
                            [
                                [
                                    "Attrib",
                                    "confirmation"
                                ],
                                [
                                    "value",
                                    "yes"
                                ]
                            ]
                        ],
                        "president"
                    ]
                ]
            }
    

    Here in the output task if the condition is true, president is given. I think it should be nuclear_strike.

    opened by junaidiiith 6
  • getting error while restoring state from file which contains subprocess

    getting error while restoring state from file which contains subprocess

    Hi, I am getting the below error when I am restoring the state from a file containing a subprocess. Normally it is working fine without a subprocess.

    I was using/referring spiff-cli example. and this doc

    $ ./run.py -p order_product -d bpmn/product_prices.dmn bpmn/shipping_costs.dmn -b bpmn/events.bpmn bpmn/call_activity.bpmn -r test6.json
    Traceback (most recent call last):
      File "D:\spiff-example-cli\run.py", line 82, in <module>
        wf = serializer.deserialize_json(state.read())
      File "D:\spiff-example-cli\venv\lib\site-packages\SpiffWorkflow\bpmn\serializer\workflow.py", line 143, in deserialize_json
        return self.workflow_from_dict(dct, read_only)
    _1
        subprocesses[sp]['tasks'][task_id]['parent'] = None
    KeyError: 'data
    
    opened by imrushi 1
  • [Question] Support for groups?

    [Question] Support for groups?

    Hi, I was looking at the NodeParser code (1.2.1) and it looks like for Tasks, Groups are not yet supported. But Positions and Lanes are. I'd like to try to add it but maybe better to ask before :)

    I guess the trick would be to get the goups postions from the XML then check the Task positions and find out which one is around ?

    Thanks !

    opened by shazz 9
  • Data Object and Data Object Reference name vs ID

    Data Object and Data Object Reference name vs ID

    Hello,

    I am facing multiple issues regarding the data object and its reference. I am using either Camunda or Modelio to model my BPMN, which is a simple user task that output a decision DataObject and an exclusive gate that either go to the end or redo the user task based on the Decision DataObject.

    I checked both examples (cli and ducks) and tests, but everything is based on Camunda Forms, which isn't a route I want to go. Keeping with BPMN only, I was thinking of using DataObject as a trigger to my python app that something must be provided to the process.

    I currently use a standalone script based on your CLI example (hardcoded the BPMN files, forced the debug and changed the user task to set the value of the data output) to figure out how to work with BPMN and your library. You'll find below relevant part of codes. To summarize, here my issues.

    1. The parser and specs uses BPMN ID as the name, which is a value auto-generated and not exposed in either Modelio or Camunda. This is not very friendly as it require the end-user that will make the process to open the raw XML and find out the BPMN ID of the DataObject and either change it everywhere in the XML to some meaningful value; or go back to the conditional expression and use the non-meaningful BPMN ID as the condition checker.
    2. Even after changing the conditional expression to match the name (BPMN ID), I still get that this name is not defined (maybe the PythonScriptEngine is not considering those DataObject?).

    Thanks for reading me, and hopefully you'll have some idea how to sort this out!

    BTW, I am using a editable from source installation of the package, since the latest released version does not have support for those data object.

    Here is where you use the ID as the name. https://github.com/sartography/SpiffWorkflow/blob/0fa2048ef2d9dd5fe856f2e476df77966bdab892/SpiffWorkflow/bpmn/specs/BpmnProcessSpec.py#L73-L82

    Here is where you use the same ID to check if it exist as a data object. https://github.com/sartography/SpiffWorkflow/blob/0fa2048ef2d9dd5fe856f2e476df77966bdab892/SpiffWorkflow/bpmn/parser/node_parser.py#L30-L48

    Here is how I changed the complete_user_task(task). It is hardcoded for now, assuming only one output requested.

    def complete_user_task(task):
    
        display_task(task)
        if task.data is None:
            task.data = {}
    
        if len(task.task_spec.data_output_associations) > 0:
            task.data[task.task_spec.data_output_associations[0].name] = "redo"
    

    Here is the error I got that the name is not defined.

    Set the value of `DataObject_17prm6c` to `redo`
    {'DataObject_17prm6c': 'redo'}
    Traceback (most recent call last):
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\.venv\src\spiffworkflow\SpiffWorkflow\bpmn\PythonScriptEngine.py", line 196, in evaluate
        return self._evaluate(expression, task.data, task=task)
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\.venv\src\spiffworkflow\SpiffWorkflow\bpmn\PythonScriptEngine.py", line 223, in _evaluate
        return eval(expression, globals, lcls)
      File "<string>", line 1, in <module>
    NameError: name 'DataObject_17prm6c' is not defined
    
    During handling of the above exception, another exception occurred:
    
      File "C:\Users\sa830268\Documents\dev\bin\pyenv\pyenv-win\versions\3.10.5\lib\runpy.py", line 196, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "C:\Users\sa830268\Documents\dev\bin\pyenv\pyenv-win\versions\3.10.5\lib\runpy.py", line 86, in _run_code
        exec(code, run_globals)
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\app\workflow\workflow.py", line 188, in <module>
        run(myWorkflow, True)
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\app\workflow\workflow.py", line 167, in run
        workflow.do_engine_steps()
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\.venv\src\spiffworkflow\SpiffWorkflow\bpmn\workflow.py", line 187, in do_engine_steps
        task.complete()
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\.venv\src\spiffworkflow\SpiffWorkflow\task.py", line 783, in complete
        return self.task_spec._on_complete(self)
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\.venv\src\spiffworkflow\SpiffWorkflow\specs\base.py", line 405, in _on_complete
        self._on_complete_hook(my_task)
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\.venv\src\spiffworkflow\SpiffWorkflow\specs\ExclusiveChoice.py", line 82, in _on_complete_hook
        if condition is None or condition._matches(my_task):
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\.venv\src\spiffworkflow\SpiffWorkflow\bpmn\specs\BpmnSpecMixin.py", line 33, in _matches
        return task.workflow.script_engine.evaluate(task, self.args[0])
      File "C:\Users\sa830268\Documents\dev\projects\be_tracker.backend\.venv\src\spiffworkflow\SpiffWorkflow\bpmn\PythonScriptEngine.py", line 198, in evaluate
        raise WorkflowTaskExecException(task,
    SpiffWorkflow.bpmn.exceptions.WorkflowTaskExecException: Gateway_1i6bkpl: Error evaluating expression 'DataObject_17prm6c=='redo'', name 'DataObject_17prm6c' is not defined
    

    Here my BPMN process from Camunda. It will fail to evaluate decision="redo" because it is stored as DataObject_17prm6c.

      <bpmn:process id="process" name="process" isExecutable="true">
        <bpmn:startEvent id="StartEvent_1">
          <bpmn:extensionElements />
          <bpmn:outgoing>Flow_0xkz2ar</bpmn:outgoing>
        </bpmn:startEvent>
        <bpmn:sequenceFlow id="Flow_0xkz2ar" sourceRef="StartEvent_1" targetRef="Activity_1repqrz" />
        <bpmn:userTask id="Activity_1repqrz" name="Init">
          <bpmn:extensionElements />
          <bpmn:incoming>Flow_0xkz2ar</bpmn:incoming>
          <bpmn:incoming>Flow_0zwwzf9</bpmn:incoming>
          <bpmn:outgoing>Flow_08d7vel</bpmn:outgoing>
          <bpmn:dataOutputAssociation id="DataOutputAssociation_1s559c4">
            <bpmn:targetRef>DataObjectReference_05w9q7s</bpmn:targetRef>
          </bpmn:dataOutputAssociation>
        </bpmn:userTask>
        <bpmn:exclusiveGateway id="Gateway_1i6bkpl" name="Check Decision?" default="Flow_0tgoifw">
          <bpmn:incoming>Flow_08d7vel</bpmn:incoming>
          <bpmn:outgoing>Flow_0tgoifw</bpmn:outgoing>
          <bpmn:outgoing>Flow_0zwwzf9</bpmn:outgoing>
        </bpmn:exclusiveGateway>
        <bpmn:sequenceFlow id="Flow_08d7vel" sourceRef="Activity_1repqrz" targetRef="Gateway_1i6bkpl" />
        <bpmn:endEvent id="Event_0v8tu84">
          <bpmn:incoming>Flow_0tgoifw</bpmn:incoming>
        </bpmn:endEvent>
        <bpmn:sequenceFlow id="Flow_0tgoifw" name="Go" sourceRef="Gateway_1i6bkpl" targetRef="Event_0v8tu84" />
        <bpmn:sequenceFlow id="Flow_0zwwzf9" name="Redo" sourceRef="Gateway_1i6bkpl" targetRef="Activity_1repqrz">
          <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">decision=='redo'</bpmn:conditionExpression>
        </bpmn:sequenceFlow>
        <bpmn:dataObjectReference id="DataObjectReference_05w9q7s" name="Decision" dataObjectRef="DataObject_17prm6c" />
        <bpmn:dataObject id="DataObject_17prm6c" />
      </bpmn:process>
    

    Here the same process as generated by Modelio

        <process isClosed="false" isExecutable="true" processType="Public" name="CR_Process" id="bbc9568e-4664-4a24-929e-bd3854857707">
            <dataObject name="decision" id="REF-af032a66-519a-4e2f-93db-b85804d3dd47"/>
            <startEvent isInterrupting="false" parallelMultiple="false" name="" id="modelio-80b31935-5e9b-4607-b08d-34fca404aa05">
                <ns5:outgoing xmlns:ns5="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="">modelio-6af02fe6-8c7c-4ce6-b581-ef5b0217d60f</ns5:outgoing>
            </startEvent>
            <sequenceFlow sourceRef="modelio-80b31935-5e9b-4607-b08d-34fca404aa05" targetRef="modelio-6331c10a-3991-4fe9-9153-8b705ca1484e" name="" id="modelio-6af02fe6-8c7c-4ce6-b581-ef5b0217d60f"/>
            <userTask implementation="##WebService" isForCompensation="false" startQuantity="1" completionQuantity="1" name="Init" id="modelio-6331c10a-3991-4fe9-9153-8b705ca1484e">
                <ns5:incoming xmlns:ns5="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="">modelio-6af02fe6-8c7c-4ce6-b581-ef5b0217d60f</ns5:incoming>
                <ns5:incoming xmlns:ns5="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="">modelio-15cba2c4-c161-4612-b70a-0d30521ecd5e</ns5:incoming>
                <ns5:outgoing xmlns:ns5="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="">modelio-1641545c-6422-4639-9ad9-8b4fbff74f28</ns5:outgoing>
                <ioSpecification>
                    <dataOutput id="modelio-6331c10a-3991-4fe9-9153-8b705ca1484e-af032a66-519a-4e2f-93db-b85804d3dd47"/>
                    <inputSet id="InputSet_modelio-6331c10a-3991-4fe9-9153-8b705ca1484e"/>
                    <outputSet id="OutputSet_modelio-6331c10a-3991-4fe9-9153-8b705ca1484e">
                        <dataOutputRefs>modelio-6331c10a-3991-4fe9-9153-8b705ca1484e-af032a66-519a-4e2f-93db-b85804d3dd47</dataOutputRefs>
                    </outputSet>
                </ioSpecification>
                <dataOutputAssociation id="modelio-64e43a05-949f-44f0-9912-7f0cb6712af3">
                    <sourceRef>modelio-6331c10a-3991-4fe9-9153-8b705ca1484e-af032a66-519a-4e2f-93db-b85804d3dd47</sourceRef>
                    <targetRef>af032a66-519a-4e2f-93db-b85804d3dd47</targetRef>
                </dataOutputAssociation>
            </userTask>
            <sequenceFlow sourceRef="modelio-6331c10a-3991-4fe9-9153-8b705ca1484e" targetRef="f5552950-c5a9-43c8-b203-b81ab0ddb8ec" name="Sequence Flow" id="modelio-1641545c-6422-4639-9ad9-8b4fbff74f28"/>
            <exclusiveGateway default="e38cee12-2744-48a0-85f6-81280c4b4aa6" gatewayDirection="Unspecified" name="Check Decision?" id="f5552950-c5a9-43c8-b203-b81ab0ddb8ec">
                <ns5:incoming xmlns:ns5="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="">modelio-1641545c-6422-4639-9ad9-8b4fbff74f28</ns5:incoming>
                <ns5:outgoing xmlns:ns5="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="">e38cee12-2744-48a0-85f6-81280c4b4aa6</ns5:outgoing>
                <ns5:outgoing xmlns:ns5="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="">modelio-15cba2c4-c161-4612-b70a-0d30521ecd5e</ns5:outgoing>
            </exclusiveGateway>
            <endEvent name="" id="e3f80147-cf6f-47f4-92f0-9f94e83e1455">
                <ns5:incoming xmlns:ns5="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns="">e38cee12-2744-48a0-85f6-81280c4b4aa6</ns5:incoming>
            </endEvent>
            <dataObjectReference dataObjectRef="REF-af032a66-519a-4e2f-93db-b85804d3dd47" name="decision" id="af032a66-519a-4e2f-93db-b85804d3dd47"/>
            <sequenceFlow sourceRef="f5552950-c5a9-43c8-b203-b81ab0ddb8ec" targetRef="e3f80147-cf6f-47f4-92f0-9f94e83e1455" name="Sequence Flow1" id="e38cee12-2744-48a0-85f6-81280c4b4aa6"/>
            <sequenceFlow sourceRef="f5552950-c5a9-43c8-b203-b81ab0ddb8ec" targetRef="modelio-6331c10a-3991-4fe9-9153-8b705ca1484e" name="Sequence Flow2" id="modelio-15cba2c4-c161-4612-b70a-0d30521ecd5e">
                <conditionExpression>decision=="redo"</conditionExpression>
            </sequenceFlow>
        </process>
    
    opened by sharky98 8
  • DMN

    DMN "-" character is misinterpreted

    Blank fields are displayed with a "-" character in DMN tables. But if the user actually types a "-" into the field, our BPMN editor attempts to interpret it, and fails.

    opened by danfunk 0
  • Drop camunda attributes on Events

    Drop camunda attributes on Events

    Our core BPMN code currently references camunda attributes for some aspects of events. Specifically Expression and ResultVariable. We should not have direct dependencies on these attributes. We could add support for them through the CamundaParser, but no reference to the Camunda namespace should exist in the core BPMN classes and methods.

    We want to create and maintain the oppertunity to evolve our own definition of variable scopes and data handling that will strive to be more in line with the BPMN 2.0 standard, and when not defined there, as pythonic as possible, and in keeping with the scoping of variables that is inherent in python programming.

    opened by danfunk 0
Releases(v1.2.1)
  • v1.2.1(Oct 19, 2022)

    What's Changed

    • do not install importlib-metadata if greater than python 3.7 w/ burnettk by @jasquat in https://github.com/sartography/SpiffWorkflow/pull/253

    New Contributors

    • @jasquat made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/253

    Full Changelog: https://github.com/sartography/SpiffWorkflow/compare/v1.2.0...v1.2.1

    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Oct 14, 2022)

    Data Objects, Messages and Services

    Note: there are some minor breaking changes in this release, please see "Minor Breaking Changes and their Fixes" below for how to fix them.

    This Version of SpiffWorkflow adds support for Data Objects, Messages, and Service Tasks. These are powerful new tools for managing workflows as they grow in complexity. Details below.

    This is also our first step towards a larger ecosystem. One that includes a customized Diagram Editor that is still under development, but available on GitHub and perfectly serviceable. You will need the editor to take full advantage of the new features mentioned above. A new project, code named SpiffArena is also under heavy development. SpiffArena will connect this SpiffWorkflow library to the new BPMN Editor and provide a complete Workflow Engine with a backend and frontend that can be configured to manage and execute a collection of your own BPMN diagrams. Keep an eye out for an initial release before the end of the year.

    In addition to major new features, we've improved some existing core features. The Python Expression Engine is now easier to extend and modify for custom deployments, and SubProcesses have a far stronger and more consistent internal representation and are easier to control. We've also added the ability to unit test your script tasks - to make it much easier to write small python scripts to re-structure your data.

    Finally, we undertook hours of effort to clean up the code base, so that imports are consistent, circular dependencies are removed, and code smells are eliminated. It is by no means perfect, but we are arcing in the right direction.

    Major Changes

    Data Objects, Inputs and Outputs

    We now support Data Objects, providing powerful tools for controlling the scope and access of variables within a workflow. For an overview of how Data Objects work, please check out our article "Understanding BPMN Data Objects". Detailed information is also available in our ReadTheDocs page.

    • explicitly add data associations on serializing MI tasks by @danfunk in PR
    • add messages to data object exceptions by @essweine in PR

    Messages

    Communication between running workflow instances is a powerful tool as workflows become more complex. For a detailed overview of this topic, please check out our article "Understanding BPMN Messages"

    • messages and business rules by @burnettk in PR
    • messages no longer send all keys by @essweine in PR

    Service Tasks

    Service Tasks are now supported, and offer an easy way for BPMN Developers to make calls to external APIs. Examples for working with this critical new tool will be documented in our ReadTheDocs page.

    • First pass of ServiceTask handling by @jbirddog in PR
    • Service task connector delegate by @jbirddog in PR
    • Store service task response in task data by @jbirddog in PR
    • get description aka name when parsing service tasks by @burnettk in PR
    • Follow up on service task bug fix, quote string literals by @jbirddog in PR
    • Pass task data to service task delegate by @jbirddog in PR

    Custom BPMN Editor Support

    Still in heavy development is a custom BPMN Editor, which you can find on GitHub This new editor provides the tools that will make creating valid Service Tasks, Data Objects, and Messages possible. Many thanks to the BPMN.js community for this highly extensible diagramming library!

    • Support for Spiff pre/postscript extensions by @essweine in PR z* parses out spiffworklow:property tags in bpmn extensions and makes th… by @danfunk in PR

    Improved Script Engine

    A Script Engine that is overall easier to understand and extend.

    • Feature/improved script engine by @essweine in PR
    • make globals an argument in the script engine by @essweine in PR

    Script Task Unit Testing

    Added the ability to create, store, and execute assertions against Script Tasks. Allows you to define a Json data structure as input, and an expected Json data structure as output. So you can assert your script is producing exactly the right data.

    • Script Task Unit Test Extensions (Attempt #2) by @danfunk in PR

    New spec_type attribute

    Given the ability to overload classes, and mix-in properties, it could be difficult to look at a Task Spec's class to determine if it was a User Task or Script Task, etc... All Task Specs now have a spec_type attribute, containing a descriptive string of the type, expect to see "User Task", "Script Task", "Start Event" etc...

    • add spec type property to task specs with BPMN names by @essweine in PR

    Improved Subprocess Handling

    • Allows recursive calls to subprocesses, and improves serialization and execution by @essweine in PR
    • add bpmn spec mixin functionality to subworkflow tasks by @essweine in PR
    • handle all data copying in bpmn subworkflow task by @essweine in PR

    Vastly Faster Tests!

    • Profile and improve run time of the test suite by @jbirddog in PR
    • Improve test suite run time, part 2 by @jbirddog in PR
    • ParallelTest.py split by @jbirddog in PR
    • Up some sleep times in tests for CI stability by @jbirddog in PR

    Bug Fixes

    • fix loop reset task to handle multiple subprocess properly by @essweine in PR
    • Bugfix/separate subprocess dict for serializer by @danfunk in PR
    • Update make tests to run tests per the README, remove unused test runners by @jbirddog in PR
    • Bug/service task variable by @jbirddog in PR
    • Fix for failures with Python 3.7 by @jbirddog in PR

    Code Cleanup and Documentation Changes

    • Support custom JSON encoder/decoder in BpmnWorkflowSerializer by @soby in PR
    • Add Python 3.10 to CI by @jbirddog in PR
    • list dependencies by @danfunk in PR
    • Feature/centralized logging by @essweine in PR
    • [FIX] Use self.spec_class instead of direct use of base object by @Giulios74 in PR
    • add more documentation about serializer migration by @essweine in PR
    • docs: Fix a few typos by @timgates42 in PR
    • Fix a few docstring typos in the tests by @jbirddog in PR
    • Remove unused imports by @jbirddog in PR
    • Reorganized parser PR
    • fix for a serialization bug by @danfunk in PR
    • fix serialization bug by @essweine in PR
    • Don't use bpmn exception from core spec by @jbirddog in PR
    • added task name to the spiff logs by @burnettk in PR
    • Remove navigation.py, tests and related bpmn files by @jbirddog in PR
    • Remove bpmn imports from task.py by @jbirddog in PR
    • Remove bpmn references from dict.py and json.py by @jbirddog in PR
    • Remove some lingering bpmn imports by @jbirddog in PR
    • Empty SpiffWorkflow/init.py by @jbirddog in PR
    • Various fixes as I attempted to get our CR-Connect application working against the lastest SpiffWorkflow build by @danfunk in PR

    Minor Breaking Changes and their Fixes

    This Minor Release includes a few minor breaking changes that should be easy to correct. Please apply these fixes as appropriate

    1. Top Level Imports moved to appropriate modules
    REPLACE 'from SpiffWorkflow import WorkflowException'
    WITH 'from SpiffWorkflow.exceptions import WorkflowException'
    
    REPLACE 'from SpiffWorkflow import TaskState'
    WITH:  'from SpiffWorkflow.task import TaskState'
    
    REPLACE:  'from SpiffWorkflow import Task'
    WITH  'from SpiffWorkflow.task import Task'
    
    1. Navigation code was removed
      • Proved to be of little use to folks, was super complex and difficult to maintain.
      • If you depended on this code, you can take the original code and embed it in your project.
    2. remove all references of timeit (no longer in SpiffWorkflow)
      • timing is now available for all tasks in the spiff.metrics log without having to edit the code
      • Same as above, this standalone code can be added to your code if needed.
    3. pythonScriptEngine._evaluate no longer accepts a task argument. If you were overriding this method for some reason, please change your method signature
    4. If you were previously using the workflow.signal() or workflow.message() functions, these should be replaced with workflow.catch().
    5. Task States are JUST integers and TaskSpecNames is now a public dictionary, and can be used to covert a state to human readable string
    REPLACE:  user_task.state.name
    WITH: TaskStateNames[user_task.state]
    

    Other Notes

    1. When inserting custom functions into the PythonExecutionEngine - be aware that the task data will act as the full context for execution, and will contain global functions and methods during the exec call.

    New Contributors

    • @Giulios74 made their first contribution in PR
    • @jbirddog made their first contribution in PR
    • @burnettk made their first contribution in PR

    Full Changelog: PR

    Source code(tar.gz)
    Source code(zip)
  • v1.1.7(May 20, 2022)

    What's Changed

    This push covers a major overhaul of our JSON serializer, which previously depended on using pickle making the json difficult to read and parse outside of Spiff and creating some potential security concerns.

    IMPORTANT: If you have existing workflows stored as JSON you will need to migrate them to the new version, you can do this on the fly by following the Migration Instructions

    • fix broken links by @essweine in https://github.com/sartography/SpiffWorkflow/pull/173
    • Enhancement/167 drop the pickles by @essweine in https://github.com/sartography/SpiffWorkflow/pull/174
    • Bug/serializer call activity issue by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/179
    • refactor: move TaskState object out of Task object by @a358003542 in https://github.com/sartography/SpiffWorkflow/pull/178
    • Enhancement/improve subprocess serialization by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/181

    New Contributors

    • @a358003542 made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/178

    Full Changelog: https://github.com/sartography/SpiffWorkflow/compare/v1.1.6...v1.1.7

    Source code(tar.gz)
    Source code(zip)
  • v1.1.6(Mar 24, 2022)

    This is just a very quick release to fix an issue with 1.1.5 that could prevent people from deserializing their existing workflows.

    What's Changed

    • Error deserializing with v1.1.5 by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/172 Full Changelog: https://github.com/sartography/SpiffWorkflow/compare/v1.1.5...v1.1.6
    Source code(tar.gz)
    Source code(zip)
  • v1.1.5(Mar 18, 2022)

    Overview

    We've made some significant improvements to our documentation and heavily refactored our code around events. We made some minor performance improvements by reducing the size of our serialization (but we are in the midst of a much larger refactor of serialization with even larger payoffs). More details follow.

    What's Changed

    • DMN - pay attention to quotes when you see the '?' symbol. by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/154
    • More improvements to SubWorkflow / MultiInstance by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/155
    • Enhancement/improve bpmn event handling by @essweine in https://github.com/sartography/SpiffWorkflow/pull/156
    • Fix bug where deserialization failed when a sub-workflow had tasks with the same id as the parent workflow by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/160
    • Chore/performance by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/162
    • miscellaneous updates to events by @essweine in https://github.com/sartography/SpiffWorkflow/pull/163
    • Fix updateDotDict to not truncate last segment by @soby in https://github.com/sartography/SpiffWorkflow/pull/165
    • Refactoring the PythonScriptEngine signature methods for DMN: by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/166
    • If a sub-process occurs within a lane, the tasks within that sub-process should be aware that they occur within that lane. by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/168
    • Better Errors for Call Activities by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/169
    • Enhancement/documentation updates by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/170

    New Contributors

    • @soby made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/165

    Full Changelog: https://github.com/sartography/SpiffWorkflow/compare/v1.1.3...v1.1.5

    Source code(tar.gz)
    Source code(zip)
  • v1.1.3(Jan 14, 2022)

  • v1.1.2(Jan 5, 2022)

    This release just updates the documentation, and gets PiPy and GitHub in sync. Please see Release 1.1.1 for additional release notes as these will occur on top of each other.

    Source code(tar.gz)
    Source code(zip)
  • 1.1.1(Jan 5, 2022)

    What's Changed

    • connect gateway start to matching conditions in transitions from exclusive gateways to multiinstance by @essweine in https://github.com/sartography/SpiffWorkflow/pull/141
    • improve error messages on missing processes by @essweine in https://github.com/sartography/SpiffWorkflow/pull/144
    • Replace absolute import self-references with relative imports by @jarradh in https://github.com/sartography/SpiffWorkflow/pull/147
    • looping back to an earlier point in the workflow is grossly inefficient by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/148
    • Enhancement/add transaction subprocesses by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/149

    New Contributors

    • @jarradh made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/147

    Full Changelog: https://github.com/sartography/SpiffWorkflow/compare/1.1...1.1.1

    Source code(tar.gz)
    Source code(zip)
  • 1.1(Nov 3, 2021)

    Features and Improvements

    • Support for DMN v1.3
    • Better handling of timezone for timer events: dateparser.parse('in 10 minutes') now works
    • Script tasks now capture and make available the the script_format attribute if provided.

    Bug Fixes:

    • We should not fail to serialize if a function is included in a script task.
    • Script Engines were not consistent after deserialization. We now require you to pass the correct script engine into when deserializing, and guarantee this engine will be used throughout.
    • Improved the escalation for boundary events
    • User tasks were ordered by their position in the diagram, now script tasks are as well.
    • Some performance improvements for large workflows.
    • We no longer set an arbitrary default for exclusive gateways, and raise an exception if no default is defined, and not condition is met at runtime.

    What's Changed (auto generated)

    • Updated readme. by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/116
    • Add support for date instead of only datetime by @rgcalsaverini in https://github.com/sartography/SpiffWorkflow/pull/81
    • Fix of return type hint in workflow.py by @robocad in https://github.com/sartography/SpiffWorkflow/pull/100
    • Pull request 79 - fixes to Escalation Boundary Events by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/118
    • Initial support for BPMN escalation boundary event on CallActivity tasks by @demostenes in https://github.com/sartography/SpiffWorkflow/pull/79
    • Chore/sonarcloud by @ajlouie in https://github.com/sartography/SpiffWorkflow/pull/119
    • Removes coveralls. Replaces coveralls coverage badge with sonarcloud … by @ajlouie in https://github.com/sartography/SpiffWorkflow/pull/120
    • Replaces mutable default arguments by @ajlouie in https://github.com/sartography/SpiffWorkflow/pull/122
    • Tweaks the xpath so it can handle the DMN v1.3 XML that Camunda's edi… by @ajlouie in https://github.com/sartography/SpiffWorkflow/pull/123
    • Fix #425 by @w4kpm in https://github.com/sartography/SpiffWorkflow/pull/124
    • Small typo in documentation by @afjlambert in https://github.com/sartography/SpiffWorkflow/pull/126
    • One Script Engine to rule them all by @danfunk in https://github.com/sartography/SpiffWorkflow/pull/130
    • Calculate script task position in its parser by @Leashys in https://github.com/sartography/SpiffWorkflow/pull/133
    • Add task-mapping attribute to workflow to make sure workflow will not… by @JsZero in https://github.com/sartography/SpiffWorkflow/pull/135
    • Bug/137 no default exclusive gateway by @essweine in https://github.com/sartography/SpiffWorkflow/pull/139

    New Contributors

    • @rgcalsaverini made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/81
    • @robocad made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/100
    • @ajlouie made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/119
    • @w4kpm made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/124
    • @afjlambert made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/126
    • @Leashys made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/133
    • @JsZero made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/135
    • @essweine made their first contribution in https://github.com/sartography/SpiffWorkflow/pull/139

    Full Changelog: https://github.com/sartography/SpiffWorkflow/compare/1.0...1.1

    Source code(tar.gz)
    Source code(zip)
  • 1.0(Jul 15, 2021)

    Spiff Workflow - Release Notes for Version 1.0

    After a year of extensive development to get SpiffWorkflow to support our effort at building a BPMN based workflow application, Sartography (our software development company) is pleased to announce an official release of Version 1.0 of SpiffWorkflow.

    That's an auspicious jump from the previous 0.6, but we think it merits the version. We have used Spiff Workflow in roughly the present state for several months in a production environment supporting real users. We believe it is ready for this 1.0 moniker. We look forward to the rapid release of many subsequent versions over the coming years.

    Here is a list of major enhancements:

    1. Preserved Features - Most of the previously-existing tests were maintained, so these changes will hopefully still support any existing users. We’ve kept dependencies on external dependencies very low. And where we added things like Box and Levenshtein along the way, we pulled them back out, replacing them with internal implementations.

    2. DMN Support - While it is not eye-watering perfect, we have a baseline of support for DMN processing that is fully integrated into the existing Execution Engine, so your DMN rules can be applied in the same language as your preferred execution language for BPMN expressions.

    3. Forms - We’ve added support for Camunda-specific web forms, which are currently parsed and returned as JSON data structures. We’ve used this to generate Formly (an NPM package for Angular) forms for web pages and it works great, but we hope to extract it in the future and pass this through directly, to make SpiffWorkflow more general-purpose and allow just about any additional complex data to accompany a user task.

    4. BPMN Additional Support - We made nearly innumerable enhancements to BPMN support. These, at a glance, include:

      • Full Serialization - A running BPMN/DMN-based workflow can now be fully serialized into JSON and restored to its original state from that JSON representation.
      • Multi-Instance Tasks - We can now handle multi-instance tasks of nearly any variety, including both Parallel and Sequential variants, as they occur in User Tasks, Script Tasks, or even Sub-Processes.
      • Pools & Lanes - We added support for BPMN pools and lanes which we used to successfully implement some complex approval processes in a production system.
      • Pluggable Script Engine - While our focus was on building a Python Script Engine, we added support for a broad set of FEEL expressions in the BPMN specification. We didn’t end up using them in production, as crossing languages proved to be an enormous headache for everyone, and the ability to write in Python for quick DMN expressions, and also complex scripts tasks proved too useful to deny. We assured that the same script engine is used throughout, and that it can be replaced by an alternate implementation by the calling application.
      • Visual Ordering of Tasks - When you have a series of parallel tasks that are aligned vertically in the diagram, that order is preserved in execution and in navigation data.
      • Sub-Workflows and Call Activities - We spent a lot of time improving the use of sub-workflows and call activities to assure it is easy to compose complex multi-file workflows that behave consistently and as expected.
      • Timer Events - Added ISO duration parsing for fine grained control over timed events.
      • Signals and Messages - Support for BPMN signals and listeners and adding the ability for the calling application to issue events - such as the “Cancel” event, so that workflows that are forced to stop can react before being terminated.
      • Boundary Events - For timed events, and messages, added support for BPMN events that alter the flow based on external events, with support for both interrupting and non-interrupting variants.
      • Looping Back - As BPMN diagrams can easily loop back to previous tasks, we put effort into testing this in SpiffWorkflow and resolving a number of performance and serialization issues related to the natural looping nature of BPMN.
    5. Improved Logging and Better Errors - We spent a lot of time improving and standardizing error messages in Spiff so it is easier to tell what is going on where, when and why, particularly as you attempt to debug issues that occur in Script Tasks. We can even tell you the line in the script that failed, and offer “did you mean…” suggestions through a simple implementation of the Levenshtein distance algorithm. We also added the ability to halt a workflow at a specific engine_step, which can be useful if you want to run tests of your workflow, but have it stop at a specific moment.

    6. Dot Notation - Our one major departure from Python syntax, we added the ability to use dot notation when referencing values deep within the Task Data, we found that using MyData.key was easier than MyData[“key”] for many areas in BPMN and DMN. Resets - We added the ability to reset the workflow to any previously completed task, and resume work from that point.

    7. Navigation - We created a rich and complex navigation generator that is capable of describing any point in the tree of tasks. We found we desperately needed a way to tell where we were when parsing complex diagrams. While it didn’t prove terribly useful in the user interface so far, it’s a ludicrously-robust tool for debugging. At any moment, you can now print out the full data structure in a meaningful, visual way directly from the command line.

    8. Tests - We added hundreds of tests, many of which load up example BPMN diagrams and clearly show expectations of how Spiff should behave in a large array of situations and edge cases.

    9. Performance Improvements - As we used this in production we found numerous performance issues, which we have tried to address - mostly related to serializing and deserializing the workflows which happens a lot in a stateless web-based architecture. We added and iteratively refined some tools for gathering and reporting performance metrics, opening these up to the larger application, so you can debug and get a consistent log and tell if it is your app that is slow, or if things are slow within Spiff.

    10. My God, It’s Full of Edge Cases - Some 40% of our commits are related to edge cases we encountered as we developed dozens of real-world BPMN/DMN-based workflows and fixing issues as we attempted to use complex BPMN elements together.

    Dropping Support for Python 2:

    We did need to remove a few items from Spiff along the way, the most notable is a drop in support for Python 2. Python 3.6, 3.7 and 3.8 are all supported and a part of our automated test suite.

    Special Thanks:

    Sartography (Sartography.com) undertook these efforts to support the development of a custom web application for the University of Virginia. We would like to thank UVA for their support and trust in allowing us to take on the mammoth task of building a general-purpose workflows system, and contributing something back to the open source community.

    Bruce Silver, the author of BPMN Quick and Easy Using Method and Style, whose work we referenced extensively as we made implementation decisions and educated ourselves on the BPMN and DMN standards.

    Samuel Abels (@knipknap) for keeping SpiffWorkflow alive for the past few years, and offering us commit access to make these contributions, and Matthew Hampton for kicking this project off and giving us sound footing on which to build.

    Camunda, for whom, without their open source Modeler and the BPMN.js library, we would not have the tools to effectively build out our models, embed an editor in our application, and pull this mad mess together.

    Kelly McDonald (@w4kpm) who dove deeper into the core of SpiffWorkflow than anyone else, and was instrumental in helping us get some of these major enhancements working correctly.

    We would like to thank Denny Weinberg for his early contributions to DMN support, which we used as a baseline and then extended.

    What is coming:

    Clean-up: Moving forward, we want to drop direct support and parsing of Camunda-specific elements. We would like to pass non-BPMN parsing on to the calling application, allowing users to build plugin-based architectures that can address domain-specific objectives.

    Cleaner Serialization: While our serialization and deserialization is rigorously tested, the JSON it produces is not easy to understand on its own. We would love to take time to clean this up, and make it easier to parse and extract data from a running workflow’s JSON representation.

    Other Projects:

    We are also working on a layered system architecture that will make the development of web-based applications for authoring and running BPMN-based workflows easier to accomplish. We’ve built a full REST based API on top of SpiffWorkflow for our pilot application, but it isn’t general enough to release. We’ve also created Javascript applications for both editing and running workflows specifications in a browser, but these still need to be generalized.

    Our Dream:

    A full stack of interconnected open source tools is the direction we are headed, along with a plug-in based architecture that will work seamlessly across that stack. We believe such grand ambitions are possible. Our ultimate ambition is the development of a Platform as a Service Business that facilitates the use of an increasingly standards compliant suite of powerful open source libraries and components.

    Source code(tar.gz)
    Source code(zip)
Owner
Samuel
Samuel
A flexible python library for building your own cron-like system, with REST APIs and a Web UI.

Nextdoor Scheduler ndscheduler is a flexible python library for building your own cron-like system to schedule jobs, which is to run a tornado process

1k Dec 15, 2022
dragonscales is a highly customizable asynchronous job-scheduler framework

dragonscales 🐉 dragonscales is a highly customizable asynchronous job-scheduler framework. This framework is used to scale the execution of multiple

Sorcero 2 May 16, 2022
Python job scheduling for humans.

schedule Python job scheduling for humans. Run Python functions (or any other callable) periodically using a friendly syntax. A simple to use API for

Dan Bader 10.4k Jan 02, 2023
A calendaring app for Django. It is now stable, Please feel free to use it now. Active development has been taken over by bartekgorny.

Django-schedule A calendaring/scheduling application, featuring: one-time and recurring events calendar exceptions (occurrences changed or cancelled)

Tony Hauber 814 Dec 26, 2022
A Lightweight Cluster/Cloud VM Job Management Tool 🚀

Lightweight Cluster/Cloud VM Job Management 🚀 Are you looking for a tool to manage your training runs locally, on Slurm/Open Grid Engine clusters, SS

29 Dec 12, 2022
The easiest way to automate your data

Hello, world! 👋 We've rebuilt data engineering for the data science era. Prefect is a new workflow management system, designed for modern infrastruct

Prefect 10.9k Jan 04, 2023
Ffxiv-blended-job-icons - All action icons for each class/job are blended together to create new backgrounds for each job/class icon!

ffxiv-blended-job-icons All action icons for each class/job are blended together to create new backgrounds for each job/class icon! I used python to c

Jon Strutz 2 Jul 07, 2022
Another Scheduler is a Kubernetes controller that automatically starts, stops, or restarts pods from a deployment at a specified time using a cron annotation.

Another Scheduler Another Scheduler is a Kubernetes controller that automatically starts, stops, or restarts pods from a deployment at a specified tim

Diego Najar 66 Nov 19, 2022
generate HPC scheduler systems jobs input scripts and submit these scripts to HPC systems and poke until they finish

DPDispatcher DPDispatcher is a python package used to generate HPC(High Performance Computing) scheduler systems (Slurm/PBS/LSF/dpcloudserver) jobs in

DeepModeling 23 Nov 30, 2022
CoSA: Scheduling by Constrained Optimization for Spatial Accelerators

CoSA is a scheduler for spatial DNN accelerators that generate high-performance schedules in one shot using mixed integer programming

UC Berkeley Architecture Research 44 Dec 13, 2022
A simple scheduler tool that provides desktop notifications about classes and opens their meet links in the browser automatically at the start of the class.

This application provides desktop notifications about classes and opens their meet links in browser automatically at the start of the class.

Anshit 14 Jun 29, 2022
Here is the live demonstration of endpoints and celery worker along with RabbitMQ

whelp-task Here is the live demonstration of endpoints and celery worker along with RabbitMQ Before running the application make sure that you have yo

Yalchin403 0 Nov 14, 2021
Python-Repeated-Timer is an open-source & highly performing timer using only standard-libraries.

Python Repeated Timer Python-Repeated-Timer is an open-source & highly performing timer using only standard-libraries.

TACKHYUN JUNG 3 Oct 09, 2022
Clepsydra is a mini framework for task scheduling

Intro Clepsydra is a mini framework for task scheduling All parts are designed to be replaceable. Main ideas are: No pickle! Tasks are stored in reada

Andrey Tikhonov 15 Nov 04, 2022
Automate SQL Jobs Monitoring with python

Automate_SQLJobsMonitoring_python Using python 3rd party modules we can automate

Aejaz Ayaz 1 Dec 27, 2021
A powerful workflow engine implemented in pure Python

Spiff Workflow Summary Spiff Workflow is a workflow engine implemented in pure Python. It is based on the excellent work of the Workflow Patterns init

Samuel 1.3k Jan 08, 2023
Vertigo is an application used to schedule @code4tomorrow classes.

Vertigo Vertigo is an application used to schedule @code4tomorrow classes. It uses the Google Sheets API and is deployed using AWS. Documentation Lear

Ben Nguyen 4 Feb 10, 2022
Remote task execution tool

Gunnery Gunnery is a multipurpose task execution tool for distributed systems with web-based interface. If your application is divided into multiple s

Gunnery 747 Nov 09, 2022
Aiorq is a distributed task queue with asyncio and redis

Aiorq is a distributed task queue with asyncio and redis, which rewrite from arq to make improvement and include web interface.

PY-GZKY 5 Mar 18, 2022
Crontab jobs management in Python

Plan Plan is a Python package for writing and deploying cron jobs. Plan will convert Python code to cron syntax. You can easily manage you

Shipeng Feng 1.2k Dec 28, 2022