Skip to content

Commit

Permalink
Merge 1a44d00 into b5778a3
Browse files Browse the repository at this point in the history
  • Loading branch information
danfunk committed May 6, 2021
2 parents b5778a3 + 1a44d00 commit 755ffd8
Show file tree
Hide file tree
Showing 291 changed files with 22,307 additions and 474 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Expand Up @@ -8,3 +8,5 @@ nosetests.xml
.coverage
tests/coverage.xml
.c9revisions
.idea
/venv
6 changes: 2 additions & 4 deletions .travis.yml
@@ -1,10 +1,8 @@
language: python
python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"
- "3.6"
- "3.7"
- "3.8"
install:
- "pip install -r requirements.txt"
- "pip install celery"
Expand Down
2 changes: 2 additions & 0 deletions AUTHORS
@@ -1,3 +1,5 @@
Samuel Abels <http://github.com/knipknap/>
Ziad Sawalha <http://github.com/ziadsawalha/>
Matthew Hampton <http://github.com/matthewhampton/>
Kelly McDonald
Dan Funk
2 changes: 1 addition & 1 deletion CONTRIB
Expand Up @@ -8,7 +8,7 @@ Coding style:
Testing:

Non-public classes and methods MUST be prefixed by _. This is also important
because the test and API documentation machinery makes assumtions based on
because the test and API documentation machinery makes assumptions based on
this convention.

Every added public class MUST have a corresponding unit test. The tests are
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
@@ -1,4 +1,4 @@
FROM python:2-wheezy
FROM python:3.6
RUN apt-get -y update && apt-get upgrade -yu
COPY . /tmp/SpiffWorkflow
RUN cd /tmp/SpiffWorkflow && make wheel && pip install dist/SpiffWorkflow*.whl
6 changes: 6 additions & 0 deletions SpiffWorkflow/__init__.py
Expand Up @@ -5,6 +5,12 @@
from .workflow import Workflow
from .task import Task
from .exceptions import WorkflowException
from .navigation import NavItem
from .bpmn.specs.BpmnSpecMixin import BpmnSpecMixin, SequenceFlow
from .bpmn.specs.UnstructuredJoin import UnstructuredJoin
from .bpmn.specs.MultiInstanceTask import MultiInstanceTask
from .bpmn.specs.CallActivity import CallActivity
from .bpmn.specs.BoundaryEvent import _BoundaryEventParent

import inspect
__all__ = [name for name, obj in list(locals().items())
Expand Down
55 changes: 55 additions & 0 deletions SpiffWorkflow/bpmn/BpmnFeelScriptEngine.py
@@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
from __future__ import division, absolute_import
from builtins import object
# Copyright (C) 2012 Matthew Hampton
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
from SpiffWorkflow.exceptions import WorkflowTaskExecException

from .FeelLikeScriptEngine import FeelLikeScriptEngine
from ..operators import Operator


class BpmnFeelScriptEngine(FeelLikeScriptEngine):
"""
Used during execution of a BPMN workflow to evaluate condition / value
expressions. These are used by Gateways, and by Catching Events
(non-message ones).
Also used to execute scripts.
If you are uncomfortable with the use of eval() and exec, then you should
provide a specialised subclass that parses and executes the scripts /
expressions in a mini-language of your own.
"""

def evaluate(self, task, expression):
"""
Evaluate the given expression, within the context of the given task and
return the result.
"""
try:
if isinstance(expression, Operator):
# I am assuming that this takes care of some kind of XML
# expression judging from the contents of operators.py
return expression._matches(task)
else:
return super().evaluate(expression, **task.data)
except Exception as e:
raise WorkflowTaskExecException(task,
"Error evaluating expression "
"'%s', %s" % (expression, str(e)))

29 changes: 14 additions & 15 deletions SpiffWorkflow/bpmn/BpmnScriptEngine.py
Expand Up @@ -17,11 +17,13 @@
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
from SpiffWorkflow.exceptions import WorkflowTaskExecException

from .PythonScriptEngine import PythonScriptEngine
from ..operators import Operator


class BpmnScriptEngine(object):
class BpmnScriptEngine(PythonScriptEngine):
"""
Used during execution of a BPMN workflow to evaluate condition / value
expressions. These are used by Gateways, and by Catching Events
Expand All @@ -39,18 +41,15 @@ def evaluate(self, task, expression):
Evaluate the given expression, within the context of the given task and
return the result.
"""
if isinstance(expression, Operator):
return expression._matches(task)
else:
return self._eval(task, expression, **task.data)
try:
if isinstance(expression, Operator):
# I am assuming that this takes care of some kind of XML
# expression judging from the contents of operators.py
return expression._matches(task)
else:
return super().evaluate(expression, **task.data)
except Exception as e:
raise WorkflowTaskExecException(task,
"Error evaluating expression "
"'%s', %s" % (expression, str(e)))

def execute(self, task, script, **kwargs):
"""
Execute the script, within the context of the specified task
"""
locals().update(kwargs)
exec(script)

def _eval(self, task, expression, **kwargs):
locals().update(kwargs)
return eval(expression)
81 changes: 81 additions & 0 deletions SpiffWorkflow/bpmn/DMNPythonScriptEngine.py
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
from builtins import object
import ast
import re
import operator
import datetime
from datetime import timedelta
from decimal import Decimal
from SpiffWorkflow.workflow import WorkflowException
from .PythonScriptEngine import PythonScriptEngine, Box

# Copyright (C) 2020 Kelly McDonald
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA

class DMNPythonScriptEngine(PythonScriptEngine):
"""
This simply overrides the python script engine to do some specific things for
DMN - I left the underlying PythonScriptEngine with everything in place so it
will play nice with the existing FeelLikeScriptEngine
"""
def __init__(self):
super().__init__()

def eval_dmn_expression(self, inputExpr, matchExpr, **kwargs):
"""
Here we need to handle a few things such as if it is an equality or if
the equality has already been taken care of. For now, we just assume it is equality.
"""



if matchExpr is None:
return True

nolhs = False
if '?' in matchExpr:
nolhs = True
matchExpr = matchExpr.replace('?', 'dmninputexpr')

rhs, needsEquals = self.validateExpression(matchExpr)

extra = {
'datetime': datetime,
'timedelta': timedelta,
'Decimal': Decimal,
'Box': Box
}

lhs, lhsNeedsEquals = self.validateExpression(inputExpr)
if not lhsNeedsEquals:
raise WorkflowException("Input Expression '%s' is malformed"%inputExpr)
if nolhs:
dmninputexpr = self.evaluate(lhs, externalMethods= extra, **kwargs)
extra = {'dmninputexpr':dmninputexpr,
'datetime':datetime,
'timedelta':timedelta,
'Decimal':Decimal,
'Box':Box
}
return self.evaluate(rhs,externalMethods=extra, **kwargs)
if needsEquals:
expression = lhs + ' == ' + rhs
else:
expression = lhs + rhs

return self.evaluate(expression, externalMethods=extra, **kwargs)

0 comments on commit 755ffd8

Please sign in to comment.