Squashed 'SpiffWorkflow/' changes from 4195453a4..1f51db962

1f51db962 Merge pull request #283 from sartography/feature/better_errors
69fb4967e Patching up some bugs and logical disconnects as I test out the errors.
cf5be0096 * Making a few more things consistent in the error messages -- so there isn't filename for validation errors, and file_name for WorkflowExceptions.  Same for line_number vs sourceline. * Assure than an error_type is consistently set on exceptions. * ValidationExceptions should not bild up a detailed error message that replicates information available within it.
440ee16c8 Responding to some excellent suggestions from Elizabeth:
655e415e1 Merge pull request #282 from subhakarks/fix-workfowspec-dump
1f6d3cf4e Explain that the error happened in a pre-script or post script.
8119abd14 Added a top level SpiffWorklowException that all exceptions inherit from.  Aside from a message string you can append information to these exceptions with "add_note", which is a new method that all exceptions have starting in python 3.11 Switched arguments to the WorkflowException, WorkflowTaskException - which now always takes a string message as the first argument, and named arguments thereafter to be consistent with all other error messages in Python. Consistently raise ValidationExceptions whenever we encounter an error anywhere during parsing of xml. The BPMN/WorkflowTaskExecException is removed, in favor of just calling a WorkflowTaskException.  There is nothing BPMN Specific in the logic, so no need for this. Consolidated error message logic so that things like "Did you mean" just get added by default if possible.  So we don't have to separately deal with that logic each time. Better Error messages for DMN (include row number as a part of the error information)
13463b5c5 fix for workflowspec dump
be26100bc Merge pull request #280 from sartography/feature/remove-unused-bpmn-attributes-and-methods
23a5c1d70 remove 'entering_* methods
4e5875ec8 remove sequence flow
5eed83ab1 Merge pull request #278 from sartography/feature/remove-old-serializer
614f1c68a remove compact serializer and references
e7e410d4a remove old serializer and references

git-subtree-dir: SpiffWorkflow
git-subtree-split: 1f51db962ccaed5810f5d0f7d76a932f056430ab
This commit is contained in:
jasquat 2023-01-19 10:47:07 -05:00
parent 80cb923b14
commit af293a91d1
22 changed files with 516 additions and 478 deletions

90
doc/errors.rst Normal file
View File

@ -0,0 +1,90 @@
SpiffWorkflow Exceptions
====================================
Details about the exceptions and exception hierarchy within SpiffWorkflow
SpiffWorkflowException
----------
Base exception for all exceptions raised by SpiffWorkflow
ValidationException
----------
**Extends**
SpiffWorkflowException
Thrown during the parsing of a workflow.
**Attributes/Methods**
- **tag**: The type of xml tag being parsed
- **id**: the id attribute of the xml tag, if available.
- **name**: the name attribute of the xml tag, if available.
- **line_number**: the line number where the tag occurs.
- **file_name**: The name of the file where the error occurred.
- **message**: a human readable error message.
WorkflowException
--------
When an error occurs with a Task Specification (maybe should have been called
a SpecException)
**Extends**
SpiffWorkflowException
**Attributes/Methods**
- **sender**: The TaskSpec - the specific Task, Gateway, etc... that caused the error to happen.
- **error**: a human readable error message describing the problem.
- **get_task_trace**: Provided a specific Task, will work it's way through the workflow / sub-processes
and call activities to show where an error occurred. Useful if the error happened within a deeply nested structure (where call activities include call activities ....)
WorkflowDataException
------------------
When an exception occurs moving data between tasks and Data Objects (including
data inputs and data outputs.)
**Extends**
WorkflowException
**Attributes/Methods**
(in addition to the values in a WorkflowException)
- **task**: The specific task (not the task spec, but the actual executing task)
- **data_input**: The spec of the input variable
- **data_output**: The spec of the output variable
WorkflowTaskException
--------
**Extends**
WorkflowException
**Attributes/Methods**
(in addition to the values in a WorkflowException)
- **task**: The specific task (not the task spec, but the actual executing task)
- **error_msg**: The detailed human readable message. (conflicts with error above)
- **exception**: The original exception this wraps around.
- **line_number** The line number that contains the error
- **offset** The point in the line that caused the error
- **error_line** The content of the line that caused the error.
It will accept the line_number and error_line as arguments - if the
underlying error provided is a SyntaxError it will try to derive this
information from the error.
If this is a name error, it will attempt to calculate a did-you-mean
error_msg.
Unused / Deprecated errors
--------------------
** StorageException **
Deprecated -- Used only by the PrettyXmlSerializer - which is not under active
support.
** DeadMethodCalled **
Something related to WeakMethod -- which doesn't look to be utilized anymore.

View File

@ -26,13 +26,13 @@
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:zoom="0.27433373"
inkscape:cx="-586.87643"
inkscape:cy="1882.7433"
inkscape:zoom="1.5518659"
inkscape:cx="2265.0153"
inkscape:cy="3541.2209"
inkscape:window-width="1916"
inkscape:window-height="1076"
inkscape:window-height="916"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-y="162"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<sodipodi:guide
@ -70,6 +70,18 @@
position="30.565253,-441.07447"
orientation="1,0"
id="guide37861" />
<sodipodi:guide
position="700.40724,-579.16044"
orientation="0,-1"
id="guide49435" />
<sodipodi:guide
position="639.13561,-614.28335"
orientation="0,-1"
id="guide49437" />
<sodipodi:guide
position="734.70955,-597.73685"
orientation="1,0"
id="guide83679" />
</sodipodi:namedview>
<defs
id="defs2">
@ -839,6 +851,91 @@
x="-580.08496"
y="716.69928">Draw the code</tspan></text>
</g>
<path
id="path73257-7-2-9-159-9-8"
style="vector-effect:none;fill:#126d82;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4.433;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 599.99956,911.28335 v 0.91595 c 0.96107,0.84548 1.66181,1.94689 2.02041,3.17567 h -17.54738 c -3.11685,0 -5.68164,2.56482 -5.68164,5.68159 v 3.91192 c 0,3.11682 2.56479,5.68164 5.68164,5.68164 h 5.6851 4.69113 5.6878 c 1.21493,0 2.13344,0.91846 2.13344,2.13344 v 3.91632 c 0,1.21498 -0.91851,2.13346 -2.13344,2.13346 h -14.79076 c -0.75878,-2.29982 -2.93713,-3.97943 -5.47735,-3.97943 -3.16218,0 -5.76138,2.60267 -5.76138,5.76489 0,3.1622 2.5992,5.76399 5.76138,5.76399 2.54974,0 4.73517,-1.69176 5.48615,-4.00482 h 14.78196 c 3.1168,0 5.67808,-2.5613 5.67808,-5.67809 v -3.91632 c 0,-3.11677 -2.56128,-5.68164 -5.67808,-5.68164 h -5.6878 -4.69113 -5.6851 c -1.21497,0 -2.13609,-0.91837 -2.13609,-2.13344 v -3.91192 c 0,-1.21499 0.92112,-2.13696 2.13609,-2.13696 h 17.60609 c -0.33391,1.31874 -1.05865,2.50576 -2.07912,3.4053 v 0.68721 l 11.72877,-5.86483 z m -19.73105,27.11871 c 1.24555,0 2.21936,0.97116 2.21936,2.21674 0,1.24556 -0.97381,2.21936 -2.21936,2.21936 -1.24559,0 -2.21675,-0.9738 -2.21675,-2.21936 0,-1.24558 0.97116,-2.21674 2.21675,-2.21674 z"
sodipodi:nodetypes="cccssssccsssscssscssssccsssscccccsssss"
inkscape:export-filename="/home/dan/spiffworkflow.png"
inkscape:export-xdpi="136.48"
inkscape:export-ydpi="136.48" />
<path
id="path85339"
style="color:#000000;fill:#126d82;fill-rule:evenodd;stroke-width:3.77953;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
d="M 2575.416 3444.2207 L 2575.416 3447.6816 C 2579.0484 3450.8772 2581.6954 3455.0413 2583.0508 3459.6855 L 2516.7305 3459.6855 C 2504.9502 3459.6855 2495.2559 3469.3783 2495.2559 3481.1582 L 2495.2559 3487.6719 L 2475.9883 3506.9375 A 6.6148345 6.6148345 0 0 0 2475.9883 3516.293 L 2495.2559 3535.5586 L 2495.2559 3540.2656 C 2495.2559 3552.0455 2504.9502 3561.7402 2516.7305 3561.7402 L 2583.0508 3561.7402 C 2581.6954 3566.3844 2579.0484 3570.5467 2575.416 3573.7422 L 2575.416 3577.2051 L 2619.7441 3555.041 L 2575.416 3532.875 L 2575.416 3535.4727 C 2579.2729 3538.8725 2582.0114 3543.3595 2583.2734 3548.3438 L 2516.7305 3548.3438 C 2512.1385 3548.3437 2508.6582 3544.8577 2508.6582 3540.2656 L 2508.6582 3535.6543 L 2526.8945 3517.418 L 2538.2168 3517.418 L 2555.9473 3517.418 L 2577.4453 3517.418 L 2577.4453 3504.0078 L 2555.9473 3504.0078 L 2538.2168 3504.0078 L 2525.0801 3504.0078 L 2508.6582 3487.5879 L 2508.6582 3481.1582 C 2508.6582 3476.5661 2512.1385 3473.082 2516.7305 3473.082 L 2583.2734 3473.082 C 2582.0114 3478.0662 2579.2729 3482.5533 2575.416 3485.9531 L 2575.416 3488.5488 L 2619.7441 3466.3828 L 2575.416 3444.2207 z M 2502 3499.6348 L 2513.9844 3511.6211 L 2502.0039 3523.5996 L 2490.0195 3511.6152 L 2502 3499.6348 z "
transform="scale(0.26458333)" />
<path
id="path28509-8"
style="color:#000000;fill:#126d82;fill-rule:evenodd;stroke-width:3.77953;stroke-linecap:round;-inkscape-stroke:none"
d="M 2399.5488 3444.8691 C 2399.2119 3444.8591 2398.8728 3444.8589 2398.5312 3444.8789 C 2393.0057 3445.089 2388.3208 3448.0519 2384.6758 3451.8398 C 2381.0308 3455.6276 2378.0721 3460.419 2375.375 3465.8945 C 2373.2508 3470.2068 2371.3058 3474.9651 2369.5156 3479.9805 L 2345.8223 3493.6602 A 6.6148344 6.6148344 0 0 0 2343.4023 3502.6953 L 2357.3008 3526.7676 C 2353.7347 3544.8143 2351.9297 3558.8242 2351.9297 3558.8242 C 2351.4636 3562.4489 2354.0254 3565.7647 2357.6504 3566.2285 C 2361.2731 3566.6948 2364.5879 3564.1363 2365.0547 3560.5137 C 2365.0547 3560.5137 2366.8057 3547.0108 2370.2109 3529.6914 L 2391.2676 3517.5332 L 2423.0762 3519.1836 C 2421.901 3514.4062 2420.5091 3511.1637 2419.0352 3506.375 L 2394.916 3505.125 L 2382.3672 3483.3887 C 2383.9174 3479.1251 2385.5484 3475.1771 2387.2441 3471.7344 C 2389.5662 3467.0204 2392.0321 3463.2741 2394.2129 3461.0078 C 2396.3937 3458.7414 2397.9351 3458.1336 2399.0332 3458.0918 C 2400.1917 3458.0478 2401.6224 3458.4993 2403.7949 3460.4766 C 2405.9674 3462.454 2408.4992 3465.8585 2410.9258 3470.2285 C 2415.779 3478.9684 2420.2895 3491.437 2423.9551 3504.0078 C 2428.2848 3518.856 2431.4634 3533.6918 2433.3691 3543.4609 C 2428.6211 3543.3167 2423.9981 3541.8521 2420.0293 3539.2148 L 2417.5215 3539.8867 L 2450.4043 3576.9688 L 2460.3398 3528.4141 L 2456.9961 3529.3105 C 2454.8496 3533.6462 2451.5141 3537.2818 2447.3789 3539.793 L 2441.7285 3519.5527 C 2440.2594 3513.4161 2438.5627 3506.8668 2436.6504 3500.3086 C 2432.8362 3487.2285 2428.209 3474.1159 2422.4844 3463.8066 C 2419.6221 3458.652 2416.508 3454.1637 2412.6973 3450.6953 C 2409.1248 3447.4436 2404.6033 3444.9934 2399.5488 3444.8711 L 2399.5488 3444.8691 z M 2375.7188 3477.7051 C 2375.7747 3477.7091 2375.8288 3477.727 2375.8848 3477.7324 A 6.6148344 6.6148344 0 0 0 2375.666 3477.707 C 2375.6835 3477.7081 2375.7013 3477.7038 2375.7188 3477.7051 z M 2372.8359 3493.3379 L 2381.3066 3508.0098 L 2366.6348 3516.4805 L 2358.1641 3501.8086 L 2372.8359 3493.3379 z "
transform="scale(0.26458333)" />
<g
id="g38755">
<path
d="m 590.37968,815.93796 q 2.10753,0 3.40104,1.63919 1.30466,1.63918 1.30466,4.80606 0,2.11867 -0.6133,3.56829 -0.61331,1.43847 -1.69494,2.17443 -1.08165,0.73597 -2.48666,0.73597 -0.90323,0 -1.54998,-0.22302 -0.64675,-0.23417 -1.10395,-0.591 -0.45719,-0.36798 -0.79171,-0.78057 h -0.17842 q 0.0892,0.44604 0.13383,0.91439 0.0446,0.46833 0.0446,0.91437 v 5.02907 h -3.40104 v -17.95302 h 2.76543 l 0.47949,1.6169 h 0.15605 q 0.33452,-0.5018 0.81401,-0.92554 0.47949,-0.42374 1.14855,-0.66905 0.68021,-0.25647 1.57228,-0.25647 z m -1.09279,2.72082 q -0.89207,0 -1.41617,0.36799 -0.52408,0.36798 -0.76942,1.10393 -0.23416,0.73597 -0.25646,1.86222 v 0.36798 q 0,1.2043 0.22301,2.04062 0.23418,0.83631 0.76942,1.27121 0.54639,0.43488 1.49423,0.43488 0.78056,0 1.28236,-0.43488 0.50179,-0.4349 0.74711,-1.27121 0.25646,-0.84748 0.25646,-2.06292 0,-1.82875 -0.56869,-2.75428 -0.56869,-0.92554 -1.76185,-0.92554 z"
id="path105589-9-3"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
d="m 600.11661,816.17212 v 12.46676 h -3.40104 v -12.46676 z m -1.69494,-4.8841 q 0.75826,0 1.30466,0.35683 0.54639,0.34568 0.54639,1.30466 0,0.94782 -0.54639,1.31581 -0.5464,0.35682 -1.30466,0.35682 -0.76942,0 -1.31581,-0.35682 -0.53524,-0.36799 -0.53524,-1.31581 0,-0.95898 0.53524,-1.30466 0.54639,-0.35683 1.31581,-0.35683 z"
id="path105591-5-6"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px"
d="m 619.0778,818.72569 h -2.94385 v 9.91319 h -3.40103 v -9.91319 h -1.87336 v -1.63918 l 1.87336,-0.91439 v -0.91437 q 0,-1.59458 0.53524,-2.4755 0.54639,-0.89209 1.52768,-1.24891 0.99243,-0.36799 2.34169,-0.36799 0.99245,0 1.80646,0.16725 0.81401,0.15605 1.32696,0.35684 l -0.86978,2.4978 q -0.39027,-0.12263 -0.84747,-0.22301 -0.45719,-0.10041 -1.04819,-0.10041 -0.71365,0 -1.04818,0.43488 -0.32338,0.42374 -0.32338,1.09279 v 0.78056 h 2.94385 z"
id="path106049-0-7" />
<path
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px"
d="m 609.97621,818.72569 h -2.94384 v 9.91319 h -3.40104 v -9.91319 h -1.87335 v -1.63918 l 1.87335,-0.91439 v -0.91437 q 0,-1.59458 0.53525,-2.4755 0.5464,-0.89209 1.52767,-1.24891 0.99244,-0.36799 2.34171,-0.36799 0.99243,0 1.80644,0.16725 0.81403,0.15605 1.32697,0.35684 l -0.86978,2.4978 q -0.39028,-0.12263 -0.84746,-0.22301 -0.45719,-0.10041 -1.04819,-0.10041 -0.71366,0 -1.0482,0.43488 -0.32337,0.42374 -0.32337,1.09279 v 0.78056 h 2.94384 z"
id="path105593-48-5" />
<path
d="m 642.93756,812.33621 -4.14815,16.30267 h -3.93629 l -2.20788,-8.56393 q -0.0668,-0.24532 -0.17842,-0.74711 -0.11144,-0.50178 -0.23417,-1.09278 -0.12264,-0.60216 -0.22302,-1.12626 -0.0892,-0.53524 -0.12263,-0.84746 -0.0334,0.31222 -0.13383,0.83632 -0.0892,0.5241 -0.21187,1.11509 -0.11144,0.591 -0.22303,1.10394 -0.11144,0.51294 -0.1784,0.78057 l -2.19675,8.54162 H 625.018 l -4.1593,-16.30267 h 3.40103 l 2.08522,8.89845 q 0.0892,0.40143 0.20073,0.95898 0.12263,0.55753 0.23417,1.17084 0.12264,0.60216 0.21185,1.17085 0.10042,0.55755 0.14503,0.97013 0.0558,-0.42373 0.14502,-0.98128 0.0892,-0.56869 0.18956,-1.14854 0.11144,-0.591 0.22303,-1.0928 0.11144,-0.50179 0.20071,-0.81401 l 2.37516,-9.13262 h 3.26722 l 2.37515,9.13262 q 0.078,0.30107 0.17842,0.81401 0.11144,0.5018 0.22301,1.0928 0.11144,0.591 0.20073,1.15969 0.10041,0.55755 0.14502,0.97013 0.078,-0.55754 0.21187,-1.34926 0.14502,-0.80287 0.30107,-1.59459 0.16724,-0.79171 0.28993,-1.32695 l 2.07408,-8.89845 z"
id="path105595-7-3"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
d="m 654.71528,822.38321 q 0,1.56112 -0.42374,2.76542 -0.41257,1.2043 -1.21544,2.04062 -0.79173,0.82517 -1.91797,1.24891 -1.11508,0.42374 -2.52011,0.42374 -1.3158,0 -2.41974,-0.42374 -1.09279,-0.42374 -1.90682,-1.24891 -0.80287,-0.83632 -1.2489,-2.04062 -0.43489,-1.2043 -0.43489,-2.76542 0,-2.07409 0.73597,-3.51256 0.73595,-1.43846 2.09636,-2.18557 1.36042,-0.74712 3.24494,-0.74712 1.75069,0 3.09996,0.74712 1.3604,0.74711 2.12982,2.18557 0.78056,1.43847 0.78056,3.51256 z m -8.61967,0 q 0,1.2266 0.26762,2.06292 0.26763,0.83631 0.83632,1.26005 0.56871,0.42374 1.48308,0.42374 0.90323,0 1.46077,-0.42374 0.56871,-0.42374 0.82517,-1.26005 0.26762,-0.83632 0.26762,-2.06292 0,-1.23777 -0.26762,-2.05178 -0.25646,-0.82517 -0.82517,-1.23775 -0.5687,-0.41259 -1.48307,-0.41259 -1.34927,0 -1.96256,0.92553 -0.60216,0.92552 -0.60216,2.77659 z"
id="path105597-17-5"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
d="m 663.15875,815.93796 q 0.25648,0 0.59102,0.0334 0.34566,0.0222 0.55753,0.0668 l -0.25646,3.18918 q -0.16725,-0.0558 -0.47949,-0.078 -0.30108,-0.0334 -0.52411,-0.0334 -0.65789,0 -1.28235,0.16724 -0.61331,0.16725 -1.10394,0.54639 -0.49064,0.36799 -0.78056,0.98129 -0.27879,0.60214 -0.27879,1.48307 v 6.34489 h -3.40103 v -12.46675 h 2.57588 l 0.50178,2.09639 h 0.16724 q 0.36797,-0.63561 0.91437,-1.15971 0.55755,-0.53525 1.26006,-0.84746 0.71366,-0.32338 1.53882,-0.32338 z"
id="path105599-2-6"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
d="m 669.19362,811.28802 v 7.76105 q 0,0.7025 -0.0558,1.40503 -0.0558,0.7025 -0.12264,1.40501 h 0.0446 q 0.34568,-0.49064 0.70252,-0.97013 0.36797,-0.47949 0.78057,-0.92554 l 3.49023,-3.79132 h 3.83593 l -4.95101,5.40822 5.25208,7.05854 h -3.92513 l -3.5906,-5.05137 -1.46078,1.17085 v 3.88052 h -3.40103 v -17.35086 z"
id="path105601-7-2"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
d="m 686.97604,818.72569 h -2.94385 v 9.91319 h -3.40103 v -9.91319 h -1.87336 v -1.63918 l 1.87336,-0.91439 v -0.91437 q 0,-1.59458 0.53524,-2.4755 0.54639,-0.89209 1.52768,-1.24891 0.99243,-0.36799 2.34169,-0.36799 0.99245,0 1.80646,0.16725 0.81401,0.15605 1.32696,0.35684 l -0.86978,2.4978 q -0.39027,-0.12263 -0.84747,-0.22301 -0.45719,-0.10041 -1.04819,-0.10041 -0.71365,0 -1.04818,0.43488 -0.32338,0.42374 -0.32338,1.09279 v 0.78056 h 2.94385 z"
id="path105603-22-9"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
d="m 693.05548,828.63888 h -3.40103 v -17.35086 h 3.40103 z"
id="path105605-6-1"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
d="m 706.62835,822.38321 q 0,1.56112 -0.42372,2.76542 -0.41259,1.2043 -1.21546,2.04062 -0.79171,0.82517 -1.91797,1.24891 -1.11508,0.42374 -2.5201,0.42374 -1.31581,0 -2.41975,-0.42374 -1.09279,-0.42374 -1.90682,-1.24891 -0.80287,-0.83632 -1.24889,-2.04062 -0.4349,-1.2043 -0.4349,-2.76542 0,-2.07409 0.73597,-3.51256 0.73595,-1.43846 2.09637,-2.18557 1.36041,-0.74712 3.24493,-0.74712 1.75069,0 3.09996,0.74712 1.3604,0.74711 2.12982,2.18557 0.78056,1.43847 0.78056,3.51256 z m -8.61967,0 q 0,1.2266 0.26763,2.06292 0.26762,0.83631 0.83631,1.26005 0.56871,0.42374 1.48309,0.42374 0.90323,0 1.46076,-0.42374 0.56871,-0.42374 0.82517,-1.26005 0.26762,-0.83632 0.26762,-2.06292 0,-1.23777 -0.26762,-2.05178 -0.25646,-0.82517 -0.82517,-1.23775 -0.5687,-0.41259 -1.48307,-0.41259 -1.34925,0 -1.96256,0.92553 -0.60216,0.92552 -0.60216,2.77659 z"
id="path105607-1-2"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
d="m 719.02496,828.63888 -0.95898,-4.36001 q -0.078,-0.39029 -0.25648,-1.14855 -0.17842,-0.76942 -0.39027,-1.6392 -0.20073,-0.88092 -0.37915,-1.62804 -0.16724,-0.7471 -0.24532,-1.09278 h -0.10041 q -0.078,0.34568 -0.24532,1.09278 -0.16724,0.74712 -0.37913,1.62804 -0.20071,0.88093 -0.37913,1.66149 -0.17842,0.76942 -0.26762,1.17085 l -1.00359,4.31542 h -3.6575 l -3.546,-12.46676 h 3.38989 l 1.43847,5.51973 q 0.14503,0.57985 0.27877,1.38272 0.13383,0.7917 0.23417,1.53882 0.11144,0.73597 0.16725,1.17085 h 0.0892 q 0.0222,-0.32338 0.0892,-0.85862 0.078,-0.53525 0.16725,-1.10394 0.10041,-0.57985 0.17842,-1.03704 0.0892,-0.46835 0.13383,-0.63561 l 1.53882,-5.97691 h 3.74671 l 1.46078,5.97691 q 0.078,0.32338 0.20071,1.02588 0.13382,0.70252 0.23417,1.44964 0.10041,0.73595 0.11144,1.15969 h 0.0892 q 0.0446,-0.37913 0.15604,-1.12624 0.11144,-0.74712 0.25648,-1.56115 0.15605,-0.82515 0.31223,-1.405 l 1.49423,-5.51973 h 3.33412 l -3.5906,12.46676 z"
id="path105609-0-7"
style="font-weight:bold;font-size:13.4639px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#126d82;fill-opacity:1;stroke-width:1.42731px" />
<path
id="path73257-7-2-9-159-9"
style="vector-effect:none;fill:#126d82;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4.433;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="m 574.18839,797.73763 v 0.91595 c 0.96107,0.84548 1.66181,1.94689 2.02041,3.17567 h -17.54738 c -3.11685,0 -5.68164,2.56482 -5.68164,5.68159 v 3.91192 c 0,3.11682 2.56479,5.68164 5.68164,5.68164 h 5.6851 4.69113 5.6878 c 1.21493,0 2.13344,0.91846 2.13344,2.13344 v 3.91632 c 0,1.21498 -0.91851,2.13346 -2.13344,2.13346 h -14.79076 c -0.75878,-2.29982 -2.93713,-3.97943 -5.47735,-3.97943 -3.16218,0 -5.76138,2.60267 -5.76138,5.76489 0,3.1622 2.5992,5.76399 5.76138,5.76399 2.54974,0 4.73517,-1.69176 5.48615,-4.00482 h 14.78196 c 3.1168,0 5.67808,-2.5613 5.67808,-5.67809 v -3.91632 c 0,-3.11677 -2.56128,-5.68164 -5.67808,-5.68164 h -5.6878 -4.69113 -5.6851 c -1.21497,0 -2.13609,-0.91837 -2.13609,-2.13344 v -3.91192 c 0,-1.21499 0.92112,-2.13696 2.13609,-2.13696 h 17.60609 c -0.33391,1.31874 -1.05865,2.50576 -2.07912,3.4053 v 0.68721 l 11.72877,-5.86483 z m -19.73105,27.11871 c 1.24555,0 2.21936,0.97116 2.21936,2.21674 0,1.24556 -0.97381,2.21936 -2.21936,2.21936 -1.24559,0 -2.21675,-0.9738 -2.21675,-2.21936 0,-1.24558 0.97116,-2.21674 2.21675,-2.21674 z"
sodipodi:nodetypes="cccssssccsssscssscssssccsssscccccsssss" />
<text
xml:space="preserve"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-size:7.18046px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Semi-Bold';letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.448779px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="587.66064"
y="805.95227"
id="text109870-49-3"><tspan
sodipodi:role="line"
id="tspan109868-0-6"
style="font-style:normal;font-variant:normal;font-weight:600;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Semi-Bold';fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.448779px"
x="587.66064"
y="805.95227">Draw the code</tspan></text>
</g>
<path
d="m 129.58873,798.16413 q 2.10753,0 3.40104,1.63919 1.30466,1.63918 1.30466,4.80606 0,2.11867 -0.6133,3.56829 -0.61331,1.43847 -1.69494,2.17443 -1.08165,0.73597 -2.48666,0.73597 -0.90323,0 -1.54998,-0.22302 -0.64675,-0.23417 -1.10395,-0.591 -0.45719,-0.36798 -0.79171,-0.78057 h -0.17842 q 0.0892,0.44604 0.13383,0.91439 0.0446,0.46833 0.0446,0.91437 v 5.02907 h -3.40104 v -17.95302 h 2.76543 l 0.47949,1.6169 h 0.15605 q 0.33452,-0.5018 0.81401,-0.92554 0.47949,-0.42374 1.14855,-0.66905 0.68021,-0.25647 1.57228,-0.25647 z m -1.09279,2.72082 q -0.89207,0 -1.41617,0.36799 -0.52408,0.36798 -0.76942,1.10393 -0.23416,0.73597 -0.25646,1.86222 v 0.36798 q 0,1.2043 0.22301,2.04062 0.23418,0.83631 0.76942,1.27121 0.54639,0.43488 1.49423,0.43488 0.78056,0 1.28236,-0.43488 0.50179,-0.4349 0.74711,-1.27121 0.25646,-0.84748 0.25646,-2.06292 0,-1.82875 -0.56869,-2.75428 -0.56869,-0.92554 -1.76185,-0.92554 z"
id="path105589-78"
@ -1029,5 +1126,29 @@
x="141.17513"
y="396.69467"
style="fill:#19788f;fill-opacity:1" />
<circle
style="color:#000000;overflow:visible;fill:none;fill-rule:evenodd;stroke:#126d82;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1309-1"
cx="636.84607"
cy="925.89471"
r="0" />
<circle
style="color:#000000;overflow:visible;fill:none;fill-rule:evenodd;stroke:#126d82;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1309-28"
cx="622.87994"
cy="928.04297"
r="0" />
<circle
style="color:#000000;overflow:visible;fill:none;fill-rule:evenodd;stroke:#126d82;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1309-2"
cx="622.87994"
cy="928.04297"
r="0" />
<circle
style="color:#000000;overflow:visible;fill:none;fill-rule:evenodd;stroke:#126d82;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1309-9"
cx="622.87994"
cy="928.04297"
r="0" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.0 MiB

After

Width:  |  Height:  |  Size: 7.0 MiB

View File

@ -2,7 +2,6 @@
import unittest
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.bpmn.specs.events.event_definitions import MessageEventDefinition
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
__author__ = 'matth'
@ -86,8 +85,7 @@ class ApprovalsTest(BpmnWorkflowTestCase):
self.save_restore()
self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval')
self.do_next_exclusive_step('Parallel_Approvals_SP.Step1')
self.do_next_exclusive_step(
'Parallel_Approvals_SP.Supervisor_Approval')
self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval')
self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
def testSaveRestoreWaiting(self):
@ -108,93 +106,10 @@ class ApprovalsTest(BpmnWorkflowTestCase):
self.save_restore()
self.do_next_exclusive_step('Parallel_Approvals_SP.Step1')
self.save_restore()
self.do_next_exclusive_step(
'Parallel_Approvals_SP.Supervisor_Approval')
self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval')
self.save_restore()
self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
def testReadonlyWaiting(self):
self.do_next_named_step('First_Approval_Wins.Manager_Approval')
readonly = self.get_read_only_workflow()
self.assertEqual(1, len(readonly.get_ready_user_tasks()))
self.assertEqual('Approvals.First_Approval_Wins_Done',
readonly.get_ready_user_tasks()[0].task_spec.name)
self.assertRaises(AssertionError, readonly.do_engine_steps)
self.assertRaises(AssertionError, readonly.refresh_waiting_tasks)
self.assertRaises(AssertionError, readonly.catch, MessageEventDefinition('Cheese'))
self.assertRaises(
AssertionError, readonly.get_ready_user_tasks()[0].complete)
self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done')
readonly = self.get_read_only_workflow()
self.assertEqual(2, len(readonly.get_ready_user_tasks()))
self.assertEqual(
['Approvals.Manager_Approval__P_',
'Approvals.Supervisor_Approval__P_'],
sorted(t.task_spec.name for t in readonly.get_ready_user_tasks()))
self.assertRaises(
AssertionError, readonly.get_ready_user_tasks()[0].complete)
self.do_next_named_step('Approvals.Supervisor_Approval__P_')
readonly = self.get_read_only_workflow()
self.assertEqual(1, len(readonly.get_ready_user_tasks()))
self.assertEqual('Approvals.Manager_Approval__P_',
readonly.get_ready_user_tasks()[0].task_spec.name)
self.assertRaises(
AssertionError, readonly.get_ready_user_tasks()[0].complete)
self.do_next_named_step('Approvals.Manager_Approval__P_')
readonly = self.get_read_only_workflow()
self.assertEqual(1, len(readonly.get_ready_user_tasks()))
self.assertEqual('Approvals.Parallel_Approvals_Done',
readonly.get_ready_user_tasks()[0].task_spec.name)
self.assertRaises(
AssertionError, readonly.get_ready_user_tasks()[0].complete)
self.do_next_exclusive_step('Approvals.Parallel_Approvals_Done')
readonly = self.get_read_only_workflow()
self.assertEqual(2, len(readonly.get_ready_user_tasks()))
self.assertEqual(
['Parallel_Approvals_SP.Manager_Approval',
'Parallel_Approvals_SP.Step1'],
sorted(t.task_spec.name for t in readonly.get_ready_user_tasks()))
self.assertRaises(
AssertionError, readonly.get_ready_user_tasks()[0].complete)
self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval')
readonly = self.get_read_only_workflow()
self.assertEqual(1, len(readonly.get_ready_user_tasks()))
self.assertEqual('Parallel_Approvals_SP.Step1',
readonly.get_ready_user_tasks()[0].task_spec.name)
self.assertRaises(
AssertionError, readonly.get_ready_user_tasks()[0].complete)
self.do_next_exclusive_step('Parallel_Approvals_SP.Step1')
readonly = self.get_read_only_workflow()
self.assertEqual(1, len(readonly.get_ready_user_tasks()))
self.assertEqual('Parallel_Approvals_SP.Supervisor_Approval',
readonly.get_ready_user_tasks()[0].task_spec.name)
self.assertRaises(
AssertionError, readonly.get_ready_user_tasks()[0].complete)
self.do_next_exclusive_step(
'Parallel_Approvals_SP.Supervisor_Approval')
readonly = self.get_read_only_workflow()
self.assertEqual(1, len(readonly.get_ready_user_tasks()))
self.assertEqual('Approvals.Parallel_SP_Done',
readonly.get_ready_user_tasks()[0].task_spec.name)
self.assertRaises(
AssertionError, readonly.get_ready_user_tasks()[0].complete)
self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
readonly = self.get_read_only_workflow()
self.assertEqual(0, len(readonly.get_ready_user_tasks()))
self.assertEqual(0, len(readonly.get_waiting_tasks()))
def suite():
return unittest.TestLoader().loadTestsFromTestCase(ApprovalsTest)

View File

@ -1,118 +0,0 @@
import os
import unittest
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.serializer.BpmnSerializer import BpmnSerializer
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from .BpmnLoaderForTests import TestBpmnParser
class BpmnSerializerTest(unittest.TestCase):
CORRELATE = BpmnSerializer
def load_workflow_spec(self, filename, process_name):
f = os.path.join(os.path.dirname(__file__), 'data', filename)
parser = TestBpmnParser()
parser.add_bpmn_files_by_glob(f)
top_level_spec = parser.get_spec(process_name)
subprocesses = parser.get_subprocess_specs(process_name)
return top_level_spec, subprocesses
def setUp(self):
super(BpmnSerializerTest, self).setUp()
self.serializer = BpmnSerializer()
self.spec, subprocesses = self.load_workflow_spec('random_fact.bpmn', 'random_fact')
self.workflow = BpmnWorkflow(self.spec, subprocesses)
def testDeserializeWorkflowSpec(self):
self.assertIsNotNone(self.spec)
def testSerializeWorkflowSpec(self):
spec_serialized = self.serializer.serialize_workflow_spec(self.spec)
result = self.serializer.deserialize_workflow_spec(spec_serialized)
spec_serialized2 = self.serializer.serialize_workflow_spec(result)
self.assertEqual(spec_serialized, spec_serialized2)
def testSerializeWorkflow(self):
json = self.serializer.serialize_workflow(self.workflow)
print(json)
def testDeserializeWorkflow(self):
self._compare_with_deserialized_copy(self.workflow)
def testDeserializeCallActivityChildren(self):
"""Tested as a part of deserialize workflow."""
pass
def testSerializeTask(self):
json = self.serializer.serialize_workflow(self.workflow)
print(json)
def testDeserializeTask(self):
self._compare_with_deserialized_copy(self.workflow)
def testDeserializeActiveWorkflow(self):
self.workflow.do_engine_steps()
self._compare_with_deserialized_copy(self.workflow)
def testDeserializeWithData(self):
self.workflow.data["test"] = "my_test"
json = self.serializer.serialize_workflow(self.workflow)
wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
self.assertEqual('my_test', wf2.get_data("test"))
def testDeserializeWithDefaultScriptEngineClass(self):
json = self.serializer.serialize_workflow(self.workflow)
wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
self.assertIsNotNone(self.workflow.script_engine)
self.assertIsNotNone(wf2.script_engine)
self.assertEqual(self.workflow.script_engine.__class__,
wf2.script_engine.__class__)
@unittest.skip("Deserialize does not persist the script engine, Fix me.")
def testDeserializeWithCustomScriptEngine(self):
class CustomScriptEngine(PythonScriptEngine):
pass
self.workflow.script_engine = CustomScriptEngine()
json = self.serializer.serialize_workflow(self.workflow)
wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
self.assertEqual(self.workflow.script_engine.__class__,
wf2.script_engine.__class__)
def testDeserializeWithDataOnTask(self):
self.workflow.do_engine_steps()
user_task = self.workflow.get_ready_user_tasks()[0]
user_task.data = {"test":"my_test"}
self._compare_with_deserialized_copy(self.workflow)
def testLastTaskIsSetAndWorksThroughRestore(self):
self.workflow.do_engine_steps()
json = self.serializer.serialize_workflow(self.workflow)
wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
self.assertIsNotNone(self.workflow.last_task)
self.assertIsNotNone(wf2.last_task)
self._compare_workflows(self.workflow, wf2)
def _compare_with_deserialized_copy(self, wf):
json = self.serializer.serialize_workflow(wf)
wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
self._compare_workflows(wf, wf2)
def _compare_workflows(self, w1, w2):
self.assertIsInstance(w1, BpmnWorkflow)
self.assertIsInstance(w2, BpmnWorkflow)
self.assertEqual(w1.data, w2.data)
self.assertEqual(w1.name, w2.name)
for task in w1.get_ready_user_tasks():
w2_task = w2.get_task(task.id)
self.assertIsNotNone(w2_task)
self.assertEqual(task.data, w2_task.data)
def suite():
return unittest.TestLoader().loadTestsFromTestCase(BpmnSerializerTest)
if __name__ == '__main__':
unittest.TextTestRunner(verbosity=2).run(suite())

View File

@ -1,13 +1,11 @@
import os
import unittest
import json
from uuid import uuid4
from SpiffWorkflow.task import TaskState
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser
from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer
from SpiffWorkflow.bpmn.serializer.BpmnSerializer import BpmnSerializer
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from tests.SpiffWorkflow.bpmn.BpmnLoaderForTests import TestUserTaskConverter
@ -48,13 +46,6 @@ class BpmnWorkflowSerializerTest(unittest.TestCase):
version = self.serializer.get_version(spec_serialized)
self.assertEqual(version, self.SERIALIZER_VERSION)
def testSerializeToOldSerializerThenNewSerializer(self):
old_serializer = BpmnSerializer()
old_json = old_serializer.serialize_workflow(self.workflow)
new_workflow = old_serializer.deserialize_workflow(old_json)
new_json = self.serializer.serialize_json(new_workflow)
new_workflow_2 = self.serializer.deserialize_json(new_json)
def testSerializeWorkflow(self):
serialized = self.serializer.serialize_json(self.workflow)
json.loads(serialized)

View File

@ -122,7 +122,7 @@ class BpmnWorkflowTestCase(unittest.TestCase):
before_dump = self.workflow.get_dump()
# Check that we can actully convert this to JSON
json_str = json.dumps(before_state)
after = self.serializer.workflow_from_dict(json.loads(json_str), read_only=False)
after = self.serializer.workflow_from_dict(json.loads(json_str))
# Check that serializing and deserializing results in the same workflow
after_state = self.serializer.workflow_to_dict(after)
after_dump = after.get_dump()
@ -132,11 +132,7 @@ class BpmnWorkflowTestCase(unittest.TestCase):
self.workflow = after
def restore(self, state):
self.workflow = self.serializer.workflow_from_dict(state, read_only=False)
def get_read_only_workflow(self):
state = self._get_workflow_state()
return self.serializer.workflow_from_dict(state, read_only=True)
self.workflow = self.serializer.workflow_from_dict(state)
def _get_workflow_state(self, do_steps=True):
if do_steps:

View File

@ -3,9 +3,9 @@
import unittest
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.exceptions import WorkflowTaskException
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
__author__ = 'kellym'
@ -60,7 +60,7 @@ class CallActivityTest(BpmnWorkflowTestCase):
def test_call_acitivity_errors_include_task_trace(self):
error_spec = self.subprocesses.get('ErroringBPMN')
error_spec, subprocesses = self.load_workflow_spec('call_activity_*.bpmn', 'ErroringBPMN')
with self.assertRaises(WorkflowTaskExecException) as context:
with self.assertRaises(WorkflowTaskException) as context:
self.workflow = BpmnWorkflow(error_spec, subprocesses)
self.workflow.do_engine_steps()
self.assertEquals(2, len(context.exception.task_trace))

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
import unittest
from SpiffWorkflow.exceptions import WorkflowTaskException
from SpiffWorkflow.task import TaskState
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
__author__ = 'McDonald, danfunk'
@ -46,7 +46,7 @@ class CustomInlineScriptTest(BpmnWorkflowTestCase):
def test_overwrite_function_with_local_variable(self):
ready_task = self.workflow.get_tasks(TaskState.READY)[0]
ready_task.data = {'custom_function': "bill"}
with self.assertRaises(WorkflowTaskExecException) as e:
with self.assertRaises(WorkflowTaskException) as e:
self.workflow.do_engine_steps()
self.assertTrue('' in str(e.exception))
self.assertTrue('custom_function' in str(e.exception))

View File

@ -31,15 +31,8 @@ class InvalidWorkflowsTest(BpmnWorkflowTestCase):
except ValidationException as ex:
self.assertTrue('No start event found' in ('%r' % ex),
'\'No start event found\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue('No-Start-Event.bpmn20.xml' in ('%r' % ex),
self.assertTrue('No-Start-Event.bpmn20.xml' in ex.file_name,
'\'No-Start-Event.bpmn20.xml\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue('process' in ('%r' % ex),
'\'process\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue(
'sid-669ddebf-4196-41ee-8b04-bcc90bc5f983' in ('%r' % ex),
'\'sid-669ddebf-4196-41ee-8b04-bcc90bc5f983\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue('No Start Event' in ('%r' % ex),
'\'No Start Event\' should be a substring of error message: \'%r\'' % ex)
def testSubprocessNotFound(self):
@ -60,15 +53,12 @@ class InvalidWorkflowsTest(BpmnWorkflowTestCase):
'There is no support implemented for this task type' in (
'%r' % ex),
'\'There is no support implemented for this task type\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue('Unsupported-Task.bpmn20.xml' in ('%r' % ex),
self.assertTrue('Unsupported-Task.bpmn20.xml' in ex.file_name,
'\'Unsupported-Task.bpmn20.xml\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue('businessRuleTask' in ('%r' % ex),
'\'businessRuleTask\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue(
'sid-75EEAB28-3B69-4282-B91A-0F3C97931834' in ('%r' % ex),
'\'sid-75EEAB28-3B69-4282-B91A-0F3C97931834\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue('Business Rule Task' in ('%r' % ex),
'\'Business Rule Task\' should be a substring of error message: \'%r\'' % ex)
self.assertTrue('businessRuleTask' in ex.tag,
'\'businessRuleTask\' should be a substring of the tag: \'%r\'' % ex)
self.assertTrue('Business Rule Task' in ex.name,
'\'Business Rule Task\' should be the name: \'%s\'' % ex.name)
def suite():

View File

@ -1,7 +1,8 @@
import unittest
import os
from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser
from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser, BpmnValidator
from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException
class ParserTest(unittest.TestCase):
@ -27,3 +28,17 @@ class ParserTest(unittest.TestCase):
self.assertEqual(generate.data_output_associations[0].name, 'obj_1')
self.assertEqual(len(read.data_input_associations), 1)
self.assertEqual(read.data_input_associations[0].name, 'obj_1')
def testValidatorError(self):
parser = BpmnParser(validator=BpmnValidator())
bpmn_file = os.path.join(os.path.dirname(__file__), 'data',
'data_object_invalid.bpmn')
errored = False
try:
parser.add_bpmn_file(bpmn_file)
except ValidationException as ex:
errored = True
self.assertEqual(ex.file_name, bpmn_file)
self.assertEqual(14, ex.line_number)
self.assertIn('DataObjectReference_0cm8dnh', str(ex))
assert(errored, "This should have errored out with a validation exception.")

View File

@ -2,7 +2,7 @@
import unittest
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from SpiffWorkflow.exceptions import WorkflowTaskException
from SpiffWorkflow.task import TaskState
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
@ -39,7 +39,7 @@ class InlineScriptTest(BpmnWorkflowTestCase):
# StartTask doesn't know about testvar, it happened earlier.
# calling an exec that references testvar, in the context of the
# start task should fail.
with self.assertRaises(WorkflowTaskExecException):
with self.assertRaises(WorkflowTaskException):
result = self.workflow.script_engine.evaluate(startTask, 'testvar == True')

View File

@ -8,7 +8,6 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..'))
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
class ServiceTaskTest(BpmnWorkflowTestCase):

View File

@ -0,0 +1,152 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_19o7vxg" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="4.11.1" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.17.0">
<bpmn:process id="Process" isExecutable="true">
<bpmn:dataObject id="obj_1" />
<bpmn:startEvent id="Event_0kmwi7u">
<bpmn:outgoing>Flow_18858hr</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_18858hr" sourceRef="Event_0kmwi7u" targetRef="generate_data" />
<bpmn:sequenceFlow id="Flow_0gbxq9s" sourceRef="generate_data" targetRef="task_1" />
<bpmn:sequenceFlow id="Flow_1r7v9yo" sourceRef="task_1" targetRef="read_data" />
<!-- All the Data objects here have the same id, which is not valid according the to the xml schema. -->
<bpmn:dataObjectReference id="DataObjectReference_0cm8dnh" name="Data" dataObjectRef="obj_1" />
<bpmn:dataObjectReference id="DataObjectReference_0cm8dnh" name="Data" dataObjectRef="obj_1" />
<bpmn:dataObjectReference id="DataObjectReference_0cm8dnh" name="Data" dataObjectRef="obj_1" />
<bpmn:endEvent id="Event_0qw1yr0">
<bpmn:incoming>Flow_19pyf8s</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1tnu3ej" sourceRef="read_data" targetRef="subprocess" />
<bpmn:userTask id="read_data" name="Read Data">
<bpmn:incoming>Flow_1r7v9yo</bpmn:incoming>
<bpmn:outgoing>Flow_1tnu3ej</bpmn:outgoing>
<bpmn:property id="Property_1uusomz" name="__targetRef_placeholder" />
<bpmn:dataInputAssociation id="DataInputAssociation_1vaag83">
<bpmn:sourceRef>DataObjectReference_0pztwm3</bpmn:sourceRef>
<bpmn:targetRef>Property_1uusomz</bpmn:targetRef>
</bpmn:dataInputAssociation>
</bpmn:userTask>
<bpmn:userTask id="generate_data" name="Generate Data">
<bpmn:incoming>Flow_18858hr</bpmn:incoming>
<bpmn:outgoing>Flow_0gbxq9s</bpmn:outgoing>
<bpmn:dataOutputAssociation id="DataOutputAssociation_053pozp">
<bpmn:targetRef>DataObjectReference_17fhr1j</bpmn:targetRef>
</bpmn:dataOutputAssociation>
</bpmn:userTask>
<bpmn:userTask id="task_1" name="Task">
<bpmn:incoming>Flow_0gbxq9s</bpmn:incoming>
<bpmn:outgoing>Flow_1r7v9yo</bpmn:outgoing>
</bpmn:userTask>
<bpmn:subProcess id="subprocess" name="Subprocess">
<bpmn:incoming>Flow_1tnu3ej</bpmn:incoming>
<bpmn:outgoing>Flow_19pyf8s</bpmn:outgoing>
<bpmn:property id="Property_1q5wp77" name="__targetRef_placeholder" />
<bpmn:dataInputAssociation id="DataInputAssociation_0w2qahx">
<bpmn:sourceRef>DataObjectReference_0cm8dnh</bpmn:sourceRef>
<bpmn:targetRef>Property_1q5wp77</bpmn:targetRef>
</bpmn:dataInputAssociation>
<bpmn:startEvent id="Event_1wuwx2f">
<bpmn:outgoing>Flow_0yx8lkz</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:task id="placeholder">
<bpmn:incoming>Flow_0yx8lkz</bpmn:incoming>
<bpmn:outgoing>Flow_0rk4i35</bpmn:outgoing>
</bpmn:task>
<bpmn:sequenceFlow id="Flow_0yx8lkz" sourceRef="Event_1wuwx2f" targetRef="placeholder" />
<bpmn:endEvent id="Event_1qcnmnt">
<bpmn:incoming>Flow_0rk4i35</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_0rk4i35" sourceRef="placeholder" targetRef="Event_1qcnmnt" />
</bpmn:subProcess>
<bpmn:sequenceFlow id="Flow_19pyf8s" sourceRef="subprocess" targetRef="Event_0qw1yr0" />
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process">
<bpmndi:BPMNEdge id="Flow_19pyf8s_di" bpmnElement="Flow_19pyf8s">
<di:waypoint x="1110" y="180" />
<di:waypoint x="1192" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1tnu3ej_di" bpmnElement="Flow_1tnu3ej">
<di:waypoint x="680" y="180" />
<di:waypoint x="740" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1r7v9yo_di" bpmnElement="Flow_1r7v9yo">
<di:waypoint x="520" y="180" />
<di:waypoint x="580" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0gbxq9s_di" bpmnElement="Flow_0gbxq9s">
<di:waypoint x="360" y="180" />
<di:waypoint x="420" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_18858hr_di" bpmnElement="Flow_18858hr">
<di:waypoint x="208" y="180" />
<di:waypoint x="260" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_0kmwi7u_di" bpmnElement="Event_0kmwi7u">
<dc:Bounds x="172" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="DataObjectReference_17fhr1j_di" bpmnElement="DataObjectReference_17fhr1j">
<dc:Bounds x="292" y="275" width="36" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="299" y="332" width="25" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="DataObjectReference_0pztwm3_di" bpmnElement="DataObjectReference_0pztwm3">
<dc:Bounds x="612" y="275" width="36" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="619" y="332" width="25" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="DataObjectReference_0cm8dnh_di" bpmnElement="DataObjectReference_0cm8dnh">
<dc:Bounds x="907" y="375" width="36" height="50" />
<bpmndi:BPMNLabel>
<dc:Bounds x="913" y="432" width="25" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_0qw1yr0_di" bpmnElement="Event_0qw1yr0">
<dc:Bounds x="1192" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_08lb08m_di" bpmnElement="read_data">
<dc:Bounds x="580" y="140" width="100" height="80" />
<bpmndi:BPMNLabel />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_00pwxgv_di" bpmnElement="generate_data">
<dc:Bounds x="260" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1xmp3i1_di" bpmnElement="task_1">
<dc:Bounds x="420" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_10c32lr_di" bpmnElement="subprocess" isExpanded="true">
<dc:Bounds x="740" y="80" width="370" height="200" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0rk4i35_di" bpmnElement="Flow_0rk4i35">
<di:waypoint x="970" y="180" />
<di:waypoint x="1032" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0yx8lkz_di" bpmnElement="Flow_0yx8lkz">
<di:waypoint x="816" y="180" />
<di:waypoint x="870" y="180" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Event_1wuwx2f_di" bpmnElement="Event_1wuwx2f">
<dc:Bounds x="780" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_01ooqcb_di" bpmnElement="placeholder">
<dc:Bounds x="870" y="140" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1qcnmnt_di" bpmnElement="Event_1qcnmnt">
<dc:Bounds x="1032" y="162" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="DataInputAssociation_1vaag83_di" bpmnElement="DataInputAssociation_1vaag83">
<di:waypoint x="630" y="275" />
<di:waypoint x="630" y="220" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="DataOutputAssociation_053pozp_di" bpmnElement="DataOutputAssociation_053pozp">
<di:waypoint x="309" y="220" />
<di:waypoint x="308" y="275" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="DataInputAssociation_0w2qahx_di" bpmnElement="DataInputAssociation_0w2qahx">
<di:waypoint x="925" y="375" />
<di:waypoint x="925" y="280" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@ -1,73 +0,0 @@
# -*- coding: utf-8 -*-
from builtins import str
import sys
import unittest
import os
dirname = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(dirname, '..', '..', '..', '..'))
import uuid
from SpiffWorkflow.bpmn.serializer.dict import BPMNDictionarySerializer
from tests.SpiffWorkflow.serializer.baseTest import SerializerTest
from SpiffWorkflow.workflow import Workflow
class BPMNDictionarySerializerTest(SerializerTest):
def setUp(self):
super(BPMNDictionarySerializerTest, self).setUp()
self.serializer = BPMNDictionarySerializer()
self.return_type = dict
def _compare_results(self, item1, item2,
exclude_dynamic=False,
exclude_items=None):
exclude_items = exclude_items if exclude_items is not None else []
if exclude_dynamic:
if 'last_state_change' not in exclude_items:
exclude_items.append('last_state_change')
if 'last_task' not in exclude_items:
exclude_items.append('last_task')
if uuid.UUID not in exclude_items:
exclude_items.append(uuid.UUID)
if type(item1) in exclude_items:
return
if isinstance(item1, dict):
self.assertIsInstance(item2, dict)
for key, value in list(item1.items()):
self.assertIn(key, item2)
if key in exclude_items:
continue
self._compare_results(value, item2[key],
exclude_dynamic=exclude_dynamic,
exclude_items=exclude_items)
for key in item2:
self.assertIn(key, item1)
elif isinstance(item1, list):
msg = "item is not a list (is a " + str(type(item2)) + ")"
self.assertIsInstance(item2, list, msg)
msg = "list lengths differ: {} vs {}".format(
len(item1), len(item2))
self.assertEqual(len(item1), len(item2), msg)
for i, listitem in enumerate(item1):
self._compare_results(listitem, item2[i],
exclude_dynamic=exclude_dynamic,
exclude_items=exclude_items)
elif isinstance(item1, Workflow):
raise Exception("Item is a Workflow")
else:
msg = "{}: types differ: {} vs {}".format(
str(item2), type(item1), type(item2))
self.assertEqual(type(item1), type(item2), msg)
self.assertEqual(item1, item2)
def suite():
return unittest.defaultTestLoader.loadTestsFromTestCase(BPMNDictionarySerializerTest)
if __name__ == '__main__':
unittest.TextTestRunner(verbosity=2).run(suite())

View File

@ -1,38 +0,0 @@
# -*- coding: utf-8 -*-
import sys
import unittest
import os
dirname = os.path.dirname(__file__)
sys.path.insert(0, os.path.join(dirname, '..', '..', '..', '..'))
import json
from SpiffWorkflow.bpmn.serializer.json import BPMNJSONSerializer
from tests.SpiffWorkflow.serializer.dictTest import DictionarySerializerTest
class BPMNJSONSerializerTest(DictionarySerializerTest):
def setUp(self):
super(BPMNJSONSerializerTest, self).setUp()
self.serializer = BPMNJSONSerializer()
self.return_type = str
def _prepare_result(self, item):
return json.loads(item)
def _compare_results(self, item1, item2, exclude_dynamic=False,
exclude_items=None):
if exclude_dynamic:
exclude_items = ['__uuid__']
else:
exclude_items = []
super(BPMNJSONSerializerTest, self)._compare_results(item1, item2,
exclude_dynamic=exclude_dynamic,
exclude_items=exclude_items)
def suite():
return unittest.defaultTestLoader.loadTestsFromTestCase(BPMNJSONSerializerTest)
if __name__ == '__main__':
unittest.TextTestRunner(verbosity=2).run(suite())

View File

@ -1,7 +1,7 @@
import os
import unittest
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from SpiffWorkflow.exceptions import SpiffWorkflowException, WorkflowException
from SpiffWorkflow.task import TaskState
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
@ -15,17 +15,23 @@ class BusinessRuleTaskParserTest(BaseTestCase):
'invalid/InvalidDecision.bpmn', 'Process_1', 'invalid_decision.dmn')
self.workflow = BpmnWorkflow(self.spec)
def testExceptionPrint(self):
e1 = Exception("test 1")
print (e1)
e = SpiffWorkflowException("test")
print (e)
def testDmnRaisesTaskErrors(self):
self.workflow = BpmnWorkflow(self.spec)
self.workflow.get_tasks(TaskState.READY)[0].set_data(x=3)
try:
self.workflow.do_engine_steps()
self.assertTrue(False, "An error should have been raised.")
except WorkflowTaskExecException as we:
except WorkflowException as we:
self.assertTrue(True, "An error was raised..")
self.assertEquals("InvalidDecisionTaskId", we.sender.name)
self.assertEqual("InvalidDecisionTaskId", we.task_spec.name)
self.maxDiff = 1000
self.assertEquals("Error evaluating expression spam= 1", str(we))
self.assertEquals("Error evaluating expression 'spam= 1'. Rule failed on row 1. Business Rule Task 'Invalid Decision'.", str(we))
def suite():
return unittest.TestLoader().loadTestsFromTestCase(BusinessRuleTaskParserTest)

View File

@ -1,5 +1,5 @@
<?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:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.0">
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
<bpmn:process id="Process_1" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_1b29lxw</bpmn:outgoing>
@ -46,59 +46,59 @@ of documentation</bpmn:documentation>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="122" y="106" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="164" y="322" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_0n32cxd_di" bpmnElement="EndEvent_0n32cxd">
<dc:Bounds x="1132" y="106" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="933" y="505" width="0" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_066d5e1_di" bpmnElement="Flow_066d5e1">
<di:waypoint x="850" y="124" />
<di:waypoint x="930" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0z7tfh1_di" bpmnElement="Flow_0z7tfh1">
<di:waypoint x="510" y="124" />
<di:waypoint x="575" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_09ciw49_di" bpmnElement="Flow_09ciw49">
<di:waypoint x="340" y="124" />
<di:waypoint x="410" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0fusz9y_di" bpmnElement="Flow_0fusz9y">
<di:waypoint x="1030" y="124" />
<di:waypoint x="1092" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1b29lxw_di" bpmnElement="Flow_1b29lxw">
<di:waypoint x="188" y="124" />
<di:waypoint x="240" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="SequenceFlow_06fnqj2_di" bpmnElement="SequenceFlow_06fnqj2">
<di:waypoint x="650" y="124" />
<di:waypoint x="700" y="124" />
<di:waypoint x="675" y="124" />
<di:waypoint x="750" y="124" />
<bpmndi:BPMNLabel>
<dc:Bounds x="850" y="462" width="0" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="BusinessRuleTask_1ipm12w_di" bpmnElement="Task_067fajl">
<dc:Bounds x="550" y="84" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_1b29lxw_di" bpmnElement="Flow_1b29lxw">
<di:waypoint x="158" y="124" />
<di:waypoint x="210" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0fusz9y_di" bpmnElement="Flow_0fusz9y">
<di:waypoint x="980" y="124" />
<di:waypoint x="1132" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Activity_1uk7uyi_di" bpmnElement="Activity_0w0chd2">
<dc:Bounds x="880" y="84" width="100" height="80" />
<dc:Bounds x="930" y="84" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_09ciw49_di" bpmnElement="Flow_09ciw49">
<di:waypoint x="310" y="124" />
<di:waypoint x="360" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Activity_1v5khzq_di" bpmnElement="Activity_0qh0jpg">
<dc:Bounds x="210" y="84" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_0z7tfh1_di" bpmnElement="Flow_0z7tfh1">
<di:waypoint x="460" y="124" />
<di:waypoint x="550" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Activity_0vne2ba_di" bpmnElement="Activity_1ftn207">
<dc:Bounds x="360" y="84" width="100" height="80" />
<dc:Bounds x="410" y="84" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_066d5e1_di" bpmnElement="Flow_066d5e1">
<di:waypoint x="800" y="124" />
<di:waypoint x="880" y="124" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNShape id="Activity_0z6lv9u_di" bpmnElement="Activity_1mu3z8p">
<dc:Bounds x="700" y="84" width="100" height="80" />
<dc:Bounds x="750" y="84" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="152" y="106" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="164" y="322" width="90" height="20" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1v5khzq_di" bpmnElement="Activity_0qh0jpg">
<dc:Bounds x="240" y="84" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="EndEvent_0n32cxd_di" bpmnElement="EndEvent_0n32cxd">
<dc:Bounds x="1092" y="106" width="36" height="36" />
<bpmndi:BPMNLabel>
<dc:Bounds x="933" y="505" width="0" height="12" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="BusinessRuleTask_1ipm12w_di" bpmnElement="Task_067fajl">
<dc:Bounds x="575" y="84" width="100" height="80" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/DMN/20151101/dmn.xsd" xmlns:camunda="http://camunda.org/schema/1.0/dmn" id="definitions_1jblnbx" name="definitions" namespace="http://camunda.org/schema/1.0/dmn" exporter="Camunda Modeler" exporterVersion="3.7.0">
<definitions xmlns="https://www.omg.org/spec/DMN/20191111/MODEL/" xmlns:camunda="http://camunda.org/schema/1.0/dmn" xmlns:biodi="http://bpmn.io/schema/dmn/biodi/2.0" id="definitions_1jblnbx" name="definitions" namespace="http://camunda.org/schema/1.0/dmn" exporter="Camunda Modeler" exporterVersion="5.0.0">
<decision id="IntegerDecisionStringOutputTable" name="IntegerDecisionStringOutput">
<decisionTable id="decisionTable">
<input id="InputClause_1tm0ceq" label="x" camunda:inputVariable="">
<input id="InputClause_1tm0ceq" label="x" biodi:width="192" camunda:inputVariable="">
<inputExpression id="LiteralExpression_04o7chw" typeRef="integer">
<text>item.x</text>
</inputExpression>

View File

@ -1,9 +1,7 @@
import json
import unittest
from SpiffWorkflow.camunda.specs.UserTask import FormField, UserTask, Form, \
EnumFormField
from SpiffWorkflow.specs.base import TaskSpec
from SpiffWorkflow.camunda.specs.UserTask import FormField, UserTask, Form, EnumFormField
from SpiffWorkflow.camunda.serializer.task_spec_converters import UserTaskConverter
from SpiffWorkflow.specs.WorkflowSpec import WorkflowSpec
@ -13,7 +11,6 @@ class UserTaskSpecTest(unittest.TestCase):
def create_instance(self):
if 'testtask' in self.wf_spec.task_specs:
del self.wf_spec.task_specs['testtask']
task_spec = TaskSpec(self.wf_spec, 'testtask', description='foo')
self.form = Form()
return UserTask(self.wf_spec, 'userTask', self.form)
@ -33,43 +30,6 @@ class UserTaskSpecTest(unittest.TestCase):
self.assertEqual(self.form, self.user_spec.form)
def testSerialize(self):
pass
def test_text_field(self):
form_field = FormField(form_type="text")
form_field.id = "1234"
self.form.add_field(form_field)
self.assertEqual(form_field, self.user_spec.form.fields[0])
def test_enum_field(self):
enum_field = EnumFormField()
enum_field.label = "Which kind of fool are you"
enum_field.add_option('old fool', 'This is old, therefor it is good.')
enum_field.add_option('new fool',
'This is new, therefor it is better.')
self.form.add_field(enum_field)
self.assertEqual(enum_field, self.user_spec.form.fields[-1])
def test_properties(self):
form_field = FormField(form_type="text")
self.assertFalse(form_field.has_property("wilma"))
form_field.add_property("wilma", "flintstone")
self.assertTrue(form_field.has_property("wilma"))
self.assertEquals("flintstone", form_field.get_property("wilma"))
def test_validations(self):
form_field = FormField(form_type="text")
self.assertFalse(form_field.has_validation("barney"))
form_field.add_validation("barney", "rubble")
self.assertTrue(form_field.has_validation("barney"))
self.assertEquals("rubble", form_field.get_validation("barney"))
def testIsEngineTask(self):
self.assertFalse(self.user_spec.is_engine_task())
def test_convert_to_dict(self):
form = Form()
field1 = FormField(form_type="text")
field1.id = "quest"
field1.label = "What is your quest?"
@ -89,21 +49,14 @@ class UserTaskSpecTest(unittest.TestCase):
field2.add_property("description", "You know what to do.")
field2.add_validation("maxlength", "25")
form.key = "formKey"
form.add_field(field1)
form.add_field(field2)
self.form.key = "formKey"
self.form.add_field(field1)
self.form.add_field(field2)
def JsonableHandler(Obj):
if hasattr(Obj, 'jsonable'):
return Obj.jsonable()
else:
raise 'Object of type %s with value of %s is not JSON serializable' % (
type(Obj), repr(Obj))
json_form = json.dumps(form, default=JsonableHandler)
actual = json.loads(json_form)
expected = {
converter = UserTaskConverter()
dct = converter.to_dict(self.user_spec)
self.assertEqual(dct['name'], 'userTask')
self.assertEqual(dct['form'], {
"fields": [
{
"default_value": "I seek the grail!",
@ -137,12 +90,39 @@ class UserTaskSpecTest(unittest.TestCase):
}
],
"key": "formKey",
}
})
expected_parsed = json.loads(json.dumps(expected))
def test_text_field(self):
form_field = FormField(form_type="text")
form_field.id = "1234"
self.form.add_field(form_field)
self.assertEqual(form_field, self.user_spec.form.fields[0])
self.maxDiff = None
self.assertDictEqual(actual, expected_parsed)
def test_enum_field(self):
enum_field = EnumFormField()
enum_field.label = "Which kind of fool are you"
enum_field.add_option('old fool', 'This is old, therefor it is good.')
enum_field.add_option('new fool',
'This is new, therefor it is better.')
self.form.add_field(enum_field)
self.assertEqual(enum_field, self.user_spec.form.fields[-1])
def test_properties(self):
form_field = FormField(form_type="text")
self.assertFalse(form_field.has_property("wilma"))
form_field.add_property("wilma", "flintstone")
self.assertTrue(form_field.has_property("wilma"))
self.assertEquals("flintstone", form_field.get_property("wilma"))
def test_validations(self):
form_field = FormField(form_type="text")
self.assertFalse(form_field.has_validation("barney"))
form_field.add_validation("barney", "rubble")
self.assertTrue(form_field.has_validation("barney"))
self.assertEquals("rubble", form_field.get_validation("barney"))
def testIsEngineTask(self):
self.assertFalse(self.user_spec.is_engine_task())
def suite():

View File

@ -1,3 +1,4 @@
from SpiffWorkflow.exceptions import SpiffWorkflowException
from SpiffWorkflow.task import TaskState
from .BaseTestCase import BaseTestCase
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
@ -45,6 +46,19 @@ class PrescriptPostsciptTest(BaseTestCase):
ready_tasks[0].complete()
self.assertDictEqual({'a': 1, 'b': 2, 'c': 12, 'z': 6}, ready_tasks[0].data)
def test_for_error(self, save_restore=False):
spec, subprocesses = self.load_workflow_spec('prescript_postscript.bpmn', 'Process_1')
self.workflow = BpmnWorkflow(spec, subprocesses)
if save_restore:
self.save_restore()
ready_tasks = self.workflow.get_tasks(TaskState.READY)
# Calling do-engine steps without setting variables will raise an exception.
with self.assertRaises(SpiffWorkflowException) as se:
self.workflow.do_engine_steps()
ex = se.exception
self.assertIn("Error occurred in the Pre-Script", str(ex))
def call_activity_test(self, save_restore=False):
spec, subprocesses = self.load_workflow_spec('prescript_postscript_*.bpmn', 'parent')

View File

@ -9,7 +9,6 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..'))
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from .BaseTestCase import BaseTestCase
class ServiceTaskDelegate:

View File

@ -9,7 +9,6 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..'))
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from .BaseTestCase import BaseTestCase
class ServiceTaskDelegate: