commit
efbc06745c
3
Pipfile
3
Pipfile
|
@ -38,13 +38,14 @@ recommonmark = "*"
|
|||
requests = "*"
|
||||
sentry-sdk = {extras = ["flask"],version = "==0.14.4"}
|
||||
sphinx = "*"
|
||||
spiffworkflow = {editable = true,git = "https://github.com/sartography/SpiffWorkflow.git",ref = "master"}
|
||||
spiffworkflow = {git = "https://github.com/sartography/SpiffWorkflow.git",ref = "master"}
|
||||
#spiffworkflow = {editable = true,path="/home/kelly/sartography/SpiffWorkflow/"}
|
||||
swagger-ui-bundle = "*"
|
||||
webtest = "*"
|
||||
werkzeug = "*"
|
||||
xlrd = "*"
|
||||
xlsxwriter = "*"
|
||||
pygithub = "*"
|
||||
|
||||
[requires]
|
||||
python_version = "3.7"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "97a15c4ade88db2b384d52436633889a4d9b0bdcaeea86b8a679ebda6f73fb59"
|
||||
"sha256": "381d29428eb328ad6167774b510b9d818bd1505b95f50454a19f1564782326cc"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {
|
||||
|
@ -30,13 +30,6 @@
|
|||
"index": "pypi",
|
||||
"version": "==1.4.2"
|
||||
},
|
||||
"amqp": {
|
||||
"hashes": [
|
||||
"sha256:24dbaff8ce4f30566bb88976b398e8c4e77637171af3af6f1b9650f48890e60b",
|
||||
"sha256:bb68f8d2bced8f93ccfd07d96c689b716b3227720add971be980accfc2952139"
|
||||
],
|
||||
"version": "==2.6.0"
|
||||
},
|
||||
"aniso8601": {
|
||||
"hashes": [
|
||||
"sha256:529dcb1f5f26ee0df6c0a1ee84b7b27197c3c50fc3a6321d66c544689237d072",
|
||||
|
@ -89,26 +82,12 @@
|
|||
],
|
||||
"version": "==4.9.1"
|
||||
},
|
||||
"billiard": {
|
||||
"hashes": [
|
||||
"sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede",
|
||||
"sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a"
|
||||
],
|
||||
"version": "==3.6.3.0"
|
||||
},
|
||||
"blinker": {
|
||||
"hashes": [
|
||||
"sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"
|
||||
],
|
||||
"version": "==1.4"
|
||||
},
|
||||
"celery": {
|
||||
"hashes": [
|
||||
"sha256:ef17d7dffde7fc73ecab3a3b6389d93d3213bac53fa7f28e68e33647ad50b916",
|
||||
"sha256:fd77e4248bb1b7af5f7922dd8e81156f540306e3a5c4b1c24167c1f5f06025da"
|
||||
],
|
||||
"version": "==4.4.6"
|
||||
},
|
||||
"certifi": {
|
||||
"hashes": [
|
||||
"sha256:5930595817496dd21bb8dc35dad090f1c2cd0adfaf21204bf6732ca5d8ee34d3",
|
||||
|
@ -118,36 +97,36 @@
|
|||
},
|
||||
"cffi": {
|
||||
"hashes": [
|
||||
"sha256:001bf3242a1bb04d985d63e138230802c6c8d4db3668fb545fb5005ddf5bb5ff",
|
||||
"sha256:00789914be39dffba161cfc5be31b55775de5ba2235fe49aa28c148236c4e06b",
|
||||
"sha256:028a579fc9aed3af38f4892bdcc7390508adabc30c6af4a6e4f611b0c680e6ac",
|
||||
"sha256:14491a910663bf9f13ddf2bc8f60562d6bc5315c1f09c704937ef17293fb85b0",
|
||||
"sha256:1cae98a7054b5c9391eb3249b86e0e99ab1e02bb0cc0575da191aedadbdf4384",
|
||||
"sha256:2089ed025da3919d2e75a4d963d008330c96751127dd6f73c8dc0c65041b4c26",
|
||||
"sha256:2d384f4a127a15ba701207f7639d94106693b6cd64173d6c8988e2c25f3ac2b6",
|
||||
"sha256:337d448e5a725bba2d8293c48d9353fc68d0e9e4088d62a9571def317797522b",
|
||||
"sha256:399aed636c7d3749bbed55bc907c3288cb43c65c4389964ad5ff849b6370603e",
|
||||
"sha256:3b911c2dbd4f423b4c4fcca138cadde747abdb20d196c4a48708b8a2d32b16dd",
|
||||
"sha256:3d311bcc4a41408cf5854f06ef2c5cab88f9fded37a3b95936c9879c1640d4c2",
|
||||
"sha256:62ae9af2d069ea2698bf536dcfe1e4eed9090211dbaafeeedf5cb6c41b352f66",
|
||||
"sha256:66e41db66b47d0d8672d8ed2708ba91b2f2524ece3dee48b5dfb36be8c2f21dc",
|
||||
"sha256:675686925a9fb403edba0114db74e741d8181683dcf216be697d208857e04ca8",
|
||||
"sha256:7e63cbcf2429a8dbfe48dcc2322d5f2220b77b2e17b7ba023d6166d84655da55",
|
||||
"sha256:8a6c688fefb4e1cd56feb6c511984a6c4f7ec7d2a1ff31a10254f3c817054ae4",
|
||||
"sha256:8c0ffc886aea5df6a1762d0019e9cb05f825d0eec1f520c51be9d198701daee5",
|
||||
"sha256:95cd16d3dee553f882540c1ffe331d085c9e629499ceadfbda4d4fde635f4b7d",
|
||||
"sha256:99f748a7e71ff382613b4e1acc0ac83bf7ad167fb3802e35e90d9763daba4d78",
|
||||
"sha256:b8c78301cefcf5fd914aad35d3c04c2b21ce8629b5e4f4e45ae6812e461910fa",
|
||||
"sha256:c420917b188a5582a56d8b93bdd8e0f6eca08c84ff623a4c16e809152cd35793",
|
||||
"sha256:c43866529f2f06fe0edc6246eb4faa34f03fe88b64a0a9a942561c8e22f4b71f",
|
||||
"sha256:cab50b8c2250b46fe738c77dbd25ce017d5e6fb35d3407606e7a4180656a5a6a",
|
||||
"sha256:cef128cb4d5e0b3493f058f10ce32365972c554572ff821e175dbc6f8ff6924f",
|
||||
"sha256:cf16e3cf6c0a5fdd9bc10c21687e19d29ad1fe863372b5543deaec1039581a30",
|
||||
"sha256:e56c744aa6ff427a607763346e4170629caf7e48ead6921745986db3692f987f",
|
||||
"sha256:e577934fc5f8779c554639376beeaa5657d54349096ef24abe8c74c5d9c117c3",
|
||||
"sha256:f2b0fa0c01d8a0c7483afd9f31d7ecf2d71760ca24499c8697aeb5ca37dc090c"
|
||||
"sha256:267adcf6e68d77ba154334a3e4fc921b8e63cbb38ca00d33d40655d4228502bc",
|
||||
"sha256:26f33e8f6a70c255767e3c3f957ccafc7f1f706b966e110b855bfe944511f1f9",
|
||||
"sha256:3cd2c044517f38d1b577f05927fb9729d3396f1d44d0c659a445599e79519792",
|
||||
"sha256:4a03416915b82b81af5502459a8a9dd62a3c299b295dcdf470877cb948d655f2",
|
||||
"sha256:4ce1e995aeecf7cc32380bc11598bfdfa017d592259d5da00fc7ded11e61d022",
|
||||
"sha256:4f53e4128c81ca3212ff4cf097c797ab44646a40b42ec02a891155cd7a2ba4d8",
|
||||
"sha256:4fa72a52a906425416f41738728268072d5acfd48cbe7796af07a923236bcf96",
|
||||
"sha256:66dd45eb9530e3dde8f7c009f84568bc7cac489b93d04ac86e3111fb46e470c2",
|
||||
"sha256:6923d077d9ae9e8bacbdb1c07ae78405a9306c8fd1af13bfa06ca891095eb995",
|
||||
"sha256:833401b15de1bb92791d7b6fb353d4af60dc688eaa521bd97203dcd2d124a7c1",
|
||||
"sha256:8416ed88ddc057bab0526d4e4e9f3660f614ac2394b5e019a628cdfff3733849",
|
||||
"sha256:892daa86384994fdf4856cb43c93f40cbe80f7f95bb5da94971b39c7f54b3a9c",
|
||||
"sha256:98be759efdb5e5fa161e46d404f4e0ce388e72fbf7d9baf010aff16689e22abe",
|
||||
"sha256:a6d28e7f14ecf3b2ad67c4f106841218c8ab12a0683b1528534a6c87d2307af3",
|
||||
"sha256:b1d6ebc891607e71fd9da71688fcf332a6630b7f5b7f5549e6e631821c0e5d90",
|
||||
"sha256:b2a2b0d276a136146e012154baefaea2758ef1f56ae9f4e01c612b0831e0bd2f",
|
||||
"sha256:b87dfa9f10a470eee7f24234a37d1d5f51e5f5fa9eeffda7c282e2b8f5162eb1",
|
||||
"sha256:bac0d6f7728a9cc3c1e06d4fcbac12aaa70e9379b3025b27ec1226f0e2d404cf",
|
||||
"sha256:c991112622baee0ae4d55c008380c32ecfd0ad417bcd0417ba432e6ba7328caa",
|
||||
"sha256:cda422d54ee7905bfc53ee6915ab68fe7b230cacf581110df4272ee10462aadc",
|
||||
"sha256:d3148b6ba3923c5850ea197a91a42683f946dba7e8eb82dfa211ab7e708de939",
|
||||
"sha256:d6033b4ffa34ef70f0b8086fd4c3df4bf801fee485a8a7d4519399818351aa8e",
|
||||
"sha256:ddff0b2bd7edcc8c82d1adde6dbbf5e60d57ce985402541cd2985c27f7bec2a0",
|
||||
"sha256:e23cb7f1d8e0f93addf0cae3c5b6f00324cccb4a7949ee558d7b6ca973ab8ae9",
|
||||
"sha256:effd2ba52cee4ceff1a77f20d2a9f9bf8d50353c854a282b8760ac15b9833168",
|
||||
"sha256:f90c2267101010de42f7273c94a1f026e56cbc043f9330acd8a80e64300aba33",
|
||||
"sha256:f960375e9823ae6a07072ff7f8a85954e5a6434f97869f50d0e41649a1c8144f",
|
||||
"sha256:fcf32bf76dc25e30ed793145a57426064520890d7c02866eb93d3e4abe516948"
|
||||
],
|
||||
"version": "==1.14.0"
|
||||
"version": "==1.14.1"
|
||||
},
|
||||
"chardet": {
|
||||
"hashes": [
|
||||
|
@ -177,13 +156,6 @@
|
|||
],
|
||||
"version": "==0.9.1"
|
||||
},
|
||||
"configparser": {
|
||||
"hashes": [
|
||||
"sha256:2ca44140ee259b5e3d8aaf47c79c36a7ab0d5e94d70bd4105c03ede7a20ea5a1",
|
||||
"sha256:cffc044844040c7ce04e9acd1838b5f2e5fa3170182f6fda4d2ea8b0099dbadd"
|
||||
],
|
||||
"version": "==5.0.0"
|
||||
},
|
||||
"connexion": {
|
||||
"extras": [
|
||||
"swagger-ui"
|
||||
|
@ -197,43 +169,50 @@
|
|||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
"sha256:0fc4e0d91350d6f43ef6a61f64a48e917637e1dcfcba4b4b7d543c628ef82c2d",
|
||||
"sha256:10f2a618a6e75adf64329f828a6a5b40244c1c50f5ef4ce4109e904e69c71bd2",
|
||||
"sha256:12eaccd86d9a373aea59869bc9cfa0ab6ba8b1477752110cb4c10d165474f703",
|
||||
"sha256:1874bdc943654ba46d28f179c1846f5710eda3aeb265ff029e0ac2b52daae404",
|
||||
"sha256:1dcebae667b73fd4aa69237e6afb39abc2f27520f2358590c1b13dd90e32abe7",
|
||||
"sha256:1e58fca3d9ec1a423f1b7f2aa34af4f733cbfa9020c8fe39ca451b6071237405",
|
||||
"sha256:214eb2110217f2636a9329bc766507ab71a3a06a8ea30cdeebb47c24dce5972d",
|
||||
"sha256:25fe74b5b2f1b4abb11e103bb7984daca8f8292683957d0738cd692f6a7cc64c",
|
||||
"sha256:32ecee61a43be509b91a526819717d5e5650e009a8d5eda8631a59c721d5f3b6",
|
||||
"sha256:3740b796015b889e46c260ff18b84683fa2e30f0f75a171fb10d2bf9fb91fc70",
|
||||
"sha256:3b2c34690f613525672697910894b60d15800ac7e779fbd0fccf532486c1ba40",
|
||||
"sha256:41d88736c42f4a22c494c32cc48a05828236e37c991bd9760f8923415e3169e4",
|
||||
"sha256:42fa45a29f1059eda4d3c7b509589cc0343cd6bbf083d6118216830cd1a51613",
|
||||
"sha256:4bb385a747e6ae8a65290b3df60d6c8a692a5599dc66c9fa3520e667886f2e10",
|
||||
"sha256:509294f3e76d3f26b35083973fbc952e01e1727656d979b11182f273f08aa80b",
|
||||
"sha256:5c74c5b6045969b07c9fb36b665c9cac84d6c174a809fc1b21bdc06c7836d9a0",
|
||||
"sha256:60a3d36297b65c7f78329b80120f72947140f45b5c7a017ea730f9112b40f2ec",
|
||||
"sha256:6f91b4492c5cde83bfe462f5b2b997cdf96a138f7c58b1140f05de5751623cf1",
|
||||
"sha256:7403675df5e27745571aba1c957c7da2dacb537c21e14007ec3a417bf31f7f3d",
|
||||
"sha256:87bdc8135b8ee739840eee19b184804e5d57f518578ffc797f5afa2c3c297913",
|
||||
"sha256:8a3decd12e7934d0254939e2bf434bf04a5890c5bf91a982685021786a08087e",
|
||||
"sha256:9702e2cb1c6dec01fb8e1a64c015817c0800a6eca287552c47a5ee0ebddccf62",
|
||||
"sha256:a4d511012beb967a39580ba7d2549edf1e6865a33e5fe51e4dce550522b3ac0e",
|
||||
"sha256:bbb387811f7a18bdc61a2ea3d102be0c7e239b0db9c83be7bfa50f095db5b92a",
|
||||
"sha256:bfcc811883699ed49afc58b1ed9f80428a18eb9166422bce3c31a53dba00fd1d",
|
||||
"sha256:c32aa13cc3fe86b0f744dfe35a7f879ee33ac0a560684fef0f3e1580352b818f",
|
||||
"sha256:ca63dae130a2e788f2b249200f01d7fa240f24da0596501d387a50e57aa7075e",
|
||||
"sha256:d54d7ea74cc00482a2410d63bf10aa34ebe1c49ac50779652106c867f9986d6b",
|
||||
"sha256:d67599521dff98ec8c34cd9652cbcfe16ed076a2209625fca9dc7419b6370e5c",
|
||||
"sha256:d82db1b9a92cb5c67661ca6616bdca6ff931deceebb98eecbd328812dab52032",
|
||||
"sha256:d9ad0a988ae20face62520785ec3595a5e64f35a21762a57d115dae0b8fb894a",
|
||||
"sha256:ebf2431b2d457ae5217f3a1179533c456f3272ded16f8ed0b32961a6d90e38ee",
|
||||
"sha256:ed9a21502e9223f563e071759f769c3d6a2e1ba5328c31e86830368e8d78bc9c",
|
||||
"sha256:f50632ef2d749f541ca8e6c07c9928a37f87505ce3a9f20c8446ad310f1aa87b"
|
||||
"sha256:098a703d913be6fbd146a8c50cc76513d726b022d170e5e98dc56d958fd592fb",
|
||||
"sha256:16042dc7f8e632e0dcd5206a5095ebd18cb1d005f4c89694f7f8aafd96dd43a3",
|
||||
"sha256:1adb6be0dcef0cf9434619d3b892772fdb48e793300f9d762e480e043bd8e716",
|
||||
"sha256:27ca5a2bc04d68f0776f2cdcb8bbd508bbe430a7bf9c02315cd05fb1d86d0034",
|
||||
"sha256:28f42dc5172ebdc32622a2c3f7ead1b836cdbf253569ae5673f499e35db0bac3",
|
||||
"sha256:2fcc8b58953d74d199a1a4d633df8146f0ac36c4e720b4a1997e9b6327af43a8",
|
||||
"sha256:304fbe451698373dc6653772c72c5d5e883a4aadaf20343592a7abb2e643dae0",
|
||||
"sha256:30bc103587e0d3df9e52cd9da1dd915265a22fad0b72afe54daf840c984b564f",
|
||||
"sha256:40f70f81be4d34f8d491e55936904db5c527b0711b2a46513641a5729783c2e4",
|
||||
"sha256:4186fc95c9febeab5681bc3248553d5ec8c2999b8424d4fc3a39c9cba5796962",
|
||||
"sha256:46794c815e56f1431c66d81943fa90721bb858375fb36e5903697d5eef88627d",
|
||||
"sha256:4869ab1c1ed33953bb2433ce7b894a28d724b7aa76c19b11e2878034a4e4680b",
|
||||
"sha256:4f6428b55d2916a69f8d6453e48a505c07b2245653b0aa9f0dee38785939f5e4",
|
||||
"sha256:52f185ffd3291196dc1aae506b42e178a592b0b60a8610b108e6ad892cfc1bb3",
|
||||
"sha256:538f2fd5eb64366f37c97fdb3077d665fa946d2b6d95447622292f38407f9258",
|
||||
"sha256:64c4f340338c68c463f1b56e3f2f0423f7b17ba6c3febae80b81f0e093077f59",
|
||||
"sha256:675192fca634f0df69af3493a48224f211f8db4e84452b08d5fcebb9167adb01",
|
||||
"sha256:700997b77cfab016533b3e7dbc03b71d33ee4df1d79f2463a318ca0263fc29dd",
|
||||
"sha256:8505e614c983834239f865da2dd336dcf9d72776b951d5dfa5ac36b987726e1b",
|
||||
"sha256:962c44070c281d86398aeb8f64e1bf37816a4dfc6f4c0f114756b14fc575621d",
|
||||
"sha256:9e536783a5acee79a9b308be97d3952b662748c4037b6a24cbb339dc7ed8eb89",
|
||||
"sha256:9ea749fd447ce7fb1ac71f7616371f04054d969d412d37611716721931e36efd",
|
||||
"sha256:a34cb28e0747ea15e82d13e14de606747e9e484fb28d63c999483f5d5188e89b",
|
||||
"sha256:a3ee9c793ffefe2944d3a2bd928a0e436cd0ac2d9e3723152d6fd5398838ce7d",
|
||||
"sha256:aab75d99f3f2874733946a7648ce87a50019eb90baef931698f96b76b6769a46",
|
||||
"sha256:b1ed2bdb27b4c9fc87058a1cb751c4df8752002143ed393899edb82b131e0546",
|
||||
"sha256:b360d8fd88d2bad01cb953d81fd2edd4be539df7bfec41e8753fe9f4456a5082",
|
||||
"sha256:b8f58c7db64d8f27078cbf2a4391af6aa4e4767cc08b37555c4ae064b8558d9b",
|
||||
"sha256:c1bbb628ed5192124889b51204de27c575b3ffc05a5a91307e7640eff1d48da4",
|
||||
"sha256:c2ff24df02a125b7b346c4c9078c8936da06964cc2d276292c357d64378158f8",
|
||||
"sha256:c890728a93fffd0407d7d37c1e6083ff3f9f211c83b4316fae3778417eab9811",
|
||||
"sha256:c96472b8ca5dc135fb0aa62f79b033f02aa434fb03a8b190600a5ae4102df1fd",
|
||||
"sha256:ce7866f29d3025b5b34c2e944e66ebef0d92e4a4f2463f7266daa03a1332a651",
|
||||
"sha256:e26c993bd4b220429d4ec8c1468eca445a4064a61c74ca08da7429af9bc53bb0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.2"
|
||||
"version": "==5.2.1"
|
||||
},
|
||||
"deprecated": {
|
||||
"hashes": [
|
||||
"sha256:525ba66fb5f90b07169fdd48b6373c18f1ee12728ca277ca44567a367d9d7f74",
|
||||
"sha256:a766c1dccb30c5f6eb2b203f87edd1d8588847709c78589e1521d769addc8218"
|
||||
],
|
||||
"version": "==1.2.10"
|
||||
},
|
||||
"docutils": {
|
||||
"hashes": [
|
||||
|
@ -324,12 +303,6 @@
|
|||
],
|
||||
"version": "==2.4.4"
|
||||
},
|
||||
"future": {
|
||||
"hashes": [
|
||||
"sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
|
||||
],
|
||||
"version": "==0.18.2"
|
||||
},
|
||||
"gunicorn": {
|
||||
"hashes": [
|
||||
"sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626",
|
||||
|
@ -402,13 +375,6 @@
|
|||
],
|
||||
"version": "==3.2.0"
|
||||
},
|
||||
"kombu": {
|
||||
"hashes": [
|
||||
"sha256:be48cdffb54a2194d93ad6533d73f69408486483d189fe9f5990ee24255b0e0a",
|
||||
"sha256:ca1b45faac8c0b18493d02a8571792f3c40291cf2bcf1f55afed3d8f3aa7ba74"
|
||||
],
|
||||
"version": "==4.6.11"
|
||||
},
|
||||
"ldap3": {
|
||||
"hashes": [
|
||||
"sha256:17f04298b70bf7ecaa5db8a7d8622b5a962ef7fc2b245b2eea705ac1c24338c0",
|
||||
|
@ -564,11 +530,11 @@
|
|||
},
|
||||
"openapi-spec-validator": {
|
||||
"hashes": [
|
||||
"sha256:0caacd9829e9e3051e830165367bf58d436d9487b29a09220fa7edb9f47ff81b",
|
||||
"sha256:d4da8aef72bf5be40cf0df444abd20009a41baf9048a8e03750c07a934f1bdd8",
|
||||
"sha256:e489c7a273284bc78277ac22791482e8058d323b4a265015e9fcddf6a8045bcd"
|
||||
"sha256:6dd75e50c94f1bb454d0e374a56418e7e06a07affb2c7f1df88564c5d728dac3",
|
||||
"sha256:79381a69b33423ee400ae1624a461dae7725e450e2e306e32f2dd8d16a4d85cb",
|
||||
"sha256:ec1b01a00e20955a527358886991ae34b4b791b253027ee9f7df5f84b59d91c7"
|
||||
],
|
||||
"version": "==0.2.8"
|
||||
"version": "==0.2.9"
|
||||
},
|
||||
"openpyxl": {
|
||||
"hashes": [
|
||||
|
@ -587,25 +553,25 @@
|
|||
},
|
||||
"pandas": {
|
||||
"hashes": [
|
||||
"sha256:02f1e8f71cd994ed7fcb9a35b6ddddeb4314822a0e09a9c5b2d278f8cb5d4096",
|
||||
"sha256:13f75fb18486759da3ff40f5345d9dd20e7d78f2a39c5884d013456cec9876f0",
|
||||
"sha256:35b670b0abcfed7cad76f2834041dcf7ae47fd9b22b63622d67cdc933d79f453",
|
||||
"sha256:4c73f373b0800eb3062ffd13d4a7a2a6d522792fa6eb204d67a4fad0a40f03dc",
|
||||
"sha256:5759edf0b686b6f25a5d4a447ea588983a33afc8a0081a0954184a4a87fd0dd7",
|
||||
"sha256:5a7cf6044467c1356b2b49ef69e50bf4d231e773c3ca0558807cdba56b76820b",
|
||||
"sha256:69c5d920a0b2a9838e677f78f4dde506b95ea8e4d30da25859db6469ded84fa8",
|
||||
"sha256:8778a5cc5a8437a561e3276b85367412e10ae9fff07db1eed986e427d9a674f8",
|
||||
"sha256:9871ef5ee17f388f1cb35f76dc6106d40cb8165c562d573470672f4cdefa59ef",
|
||||
"sha256:9c31d52f1a7dd2bb4681d9f62646c7aa554f19e8e9addc17e8b1b20011d7522d",
|
||||
"sha256:ab8173a8efe5418bbe50e43f321994ac6673afc5c7c4839014cf6401bbdd0705",
|
||||
"sha256:ae961f1f0e270f1e4e2273f6a539b2ea33248e0e3a11ffb479d757918a5e03a9",
|
||||
"sha256:b3c4f93fcb6e97d993bf87cdd917883b7dab7d20c627699f360a8fb49e9e0b91",
|
||||
"sha256:c9410ce8a3dee77653bc0684cfa1535a7f9c291663bd7ad79e39f5ab58f67ab3",
|
||||
"sha256:f69e0f7b7c09f1f612b1f8f59e2df72faa8a6b41c5a436dde5b615aaf948f107",
|
||||
"sha256:faa42a78d1350b02a7d2f0dbe3c80791cf785663d6997891549d0f86dc49125e"
|
||||
"sha256:0210f8fe19c2667a3817adb6de2c4fd92b1b78e1975ca60c0efa908e0985cbdb",
|
||||
"sha256:0227e3a6e3a22c0e283a5041f1e3064d78fbde811217668bb966ed05386d8a7e",
|
||||
"sha256:0bc440493cf9dc5b36d5d46bbd5508f6547ba68b02a28234cd8e81fdce42744d",
|
||||
"sha256:16504f915f1ae424052f1e9b7cd2d01786f098fbb00fa4e0f69d42b22952d798",
|
||||
"sha256:182a5aeae319df391c3df4740bb17d5300dcd78034b17732c12e62e6dd79e4a4",
|
||||
"sha256:35db623487f00d9392d8af44a24516d6cb9f274afaf73cfcfe180b9c54e007d2",
|
||||
"sha256:40ec0a7f611a3d00d3c666c4cceb9aa3f5bf9fbd81392948a93663064f527203",
|
||||
"sha256:47a03bfef80d6812c91ed6fae43f04f2fa80a4e1b82b35aa4d9002e39529e0b8",
|
||||
"sha256:4b21d46728f8a6be537716035b445e7ef3a75dbd30bd31aa1b251323219d853e",
|
||||
"sha256:4d1a806252001c5db7caecbe1a26e49a6c23421d85a700960f6ba093112f54a1",
|
||||
"sha256:60e20a4ab4d4fec253557d0fc9a4e4095c37b664f78c72af24860c8adcd07088",
|
||||
"sha256:9f61cca5262840ff46ef857d4f5f65679b82188709d0e5e086a9123791f721c8",
|
||||
"sha256:a15835c8409d5edc50b4af93be3377b5dd3eb53517e7f785060df1f06f6da0e2",
|
||||
"sha256:b39508562ad0bb3f384b0db24da7d68a2608b9ddc85b1d931ccaaa92d5e45273",
|
||||
"sha256:ed60848caadeacecefd0b1de81b91beff23960032cded0ac1449242b506a3b3f",
|
||||
"sha256:fc714895b6de6803ac9f661abb316853d0cd657f5d23985222255ad76ccedc25"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.0.5"
|
||||
"version": "==1.1.0"
|
||||
},
|
||||
"psycopg2-binary": {
|
||||
"hashes": [
|
||||
|
@ -657,6 +623,14 @@
|
|||
],
|
||||
"version": "==2.20"
|
||||
},
|
||||
"pygithub": {
|
||||
"hashes": [
|
||||
"sha256:8375a058ec651cc0774244a3bc7395cf93617298735934cdd59e5bcd9a1df96e",
|
||||
"sha256:d2d17d1e3f4474e070353f201164685a95b5a92f5ee0897442504e399c7bc249"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.51"
|
||||
},
|
||||
"pygments": {
|
||||
"hashes": [
|
||||
"sha256:647344a061c249a3b74e230c739f434d7ea4d8b1d5f3721bc0f3558049b38f44",
|
||||
|
@ -685,13 +659,6 @@
|
|||
],
|
||||
"version": "==0.16.0"
|
||||
},
|
||||
"python-box": {
|
||||
"hashes": [
|
||||
"sha256:2df0d0e0769b6d6e7daed8d5e0b10a38e0b5486ee75914c30f2a927f7a374111",
|
||||
"sha256:ddea019b4ee53fe3f822407b0b26ec54ff6233042c68b54244d3503ae4d6218f"
|
||||
],
|
||||
"version": "==5.0.1"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
|
||||
|
@ -714,61 +681,6 @@
|
|||
],
|
||||
"version": "==1.0.4"
|
||||
},
|
||||
"python-levenshtein-wheels": {
|
||||
"hashes": [
|
||||
"sha256:0065529c8aec4c044468286177761857d36981ba6f7fdb62d7d5f7ffd143de5d",
|
||||
"sha256:016924a59d689f9f47d5f7b26b70f31e309255e8dd72602c91e93ceb752b9f92",
|
||||
"sha256:089d046ea7727e583233c71fef1046663ed67b96967063ae8ddc9f551e86a4fc",
|
||||
"sha256:09f9faaaa8f65726f91b44c11d3d622fee0f1780cfbe2bf3f410dd0e7345adcb",
|
||||
"sha256:0aea217eab612acd45dcc3424a2e8dbd977cc309f80359d0c01971f1e65b9a9b",
|
||||
"sha256:0beb91ad80b1573829066e5af36b80190c367be6e0a65292f073353b0388c7fc",
|
||||
"sha256:0ec1bc73f5ed3a1a06e02d13bb3cd22a0b32ebf65a9667bbccba106bfa0546f1",
|
||||
"sha256:0fa2ca69ef803bc6037a8c919e2e8a17b55e94c9c9ffcb4c21befbb15a1d0f40",
|
||||
"sha256:11c77d0d74ab7f46f89a58ae9c2d67349ebc1ae3e18636627f9939d810167c31",
|
||||
"sha256:19a68716a322486ddffc8bf7e5cf44a82f7700b05a10658e6e7fc5c7ae92b13d",
|
||||
"sha256:19a95a01d28d63b042438ba860c4ace90362906a038fa77962ba33325d377d10",
|
||||
"sha256:1a61f3a51e00a3608659bbaabb3f27af37c9dbe84d843369061a3e45cf0d5103",
|
||||
"sha256:1c50aebebab403fb2dd415d70355446ac364dece502b0e2737a1a085bb9a4aa4",
|
||||
"sha256:1d2390d04f9b673391e5ce1a0b054d0565f2e00ea5d1187a044221dc5c02c3e6",
|
||||
"sha256:1e51cdc123625a28709662d24ea0cb4cf6f991845e6054d9f803c78da1d6b08f",
|
||||
"sha256:1eca6dc97dfcf588f53281fe48a6d5c423d4e14bdab658a1aa6efd447acc64e0",
|
||||
"sha256:1f0056d3216b0fe38f25c6f8ebc84bd9f6d34c55a7a9414341b674fb98961399",
|
||||
"sha256:228b59460e9a786e498bdfc8011838b89c6054650b115c86c9c819a055a793b0",
|
||||
"sha256:23020f9ff2cb3457a926dcc470b84f9bd5b7646bd8b8e06b915bdbbc905cb23f",
|
||||
"sha256:2b7b7cf0f43b677f818aa9a610464abf06106c19a51b9ac35bd051a439f337a5",
|
||||
"sha256:3b591c9a7e91480f0d7bf2041d325f578b9b9c2f2d593304377cb28862e7f9a2",
|
||||
"sha256:3ca9c70411ab587d071c1d8fc8b69d0558be8e4aa920f2595e2cb5eb229ccc4c",
|
||||
"sha256:3e6bcca97a7ff4e720352b57ddc26380c0583dcdd4b791acef7b574ad58468a7",
|
||||
"sha256:3ed88f9e638da57647149115c34e0e120cae6f3d35eee7d77e22cc9c1d8eced3",
|
||||
"sha256:445bf7941cb1fa05d6c2a4a502ad4868a5cacd92e8eb77b2bd008cdda9d37c55",
|
||||
"sha256:4ba5e147d76d7ee884fd6eae461438b080bcc9f2c6eb9b576811e1bcfe8f808e",
|
||||
"sha256:4bb128b719c30f3b9feacfe71a338ae07d39dbffc077139416f3535c89f12362",
|
||||
"sha256:4e951907b9b5d40c9f1b611c8bdfe46ff8cf8371877cebbd589bf5840feab662",
|
||||
"sha256:53c0c9964390368fd64460b690f168221c669766b193b7e80ae3950c2b9551f8",
|
||||
"sha256:57c4edef81611098d37176278f2b6a3712bf864eed313496d7d80504805896d1",
|
||||
"sha256:5b36e406937c6463d1c1ef3dd82d3f771d9d845f21351e8a026fe4dd398ea8d0",
|
||||
"sha256:7d0821dab24b430dfdc2cba70a06e6d7a45cb839d0dd0e6db97bb99e23c3d884",
|
||||
"sha256:7f7283dfe50eac8a8cd9b777de9eb50b1edf7dbb46fc7cc9d9b0050d0c135021",
|
||||
"sha256:7f9759095b3fc825464a72b1cae95125e610eba3c70f91557754c32a0bf32ea2",
|
||||
"sha256:8005a4df455569c0d490ddfd9e5a163f21293477fd0ed4ea9effdd723ddd8eaa",
|
||||
"sha256:86e865f29ad3dc3bb4733e5247220173d90f05ac8d2ad18e9689a220f90de55f",
|
||||
"sha256:98727050ba70eb8d318ec8a8203531c20119347fc8f281102b097326812742ab",
|
||||
"sha256:ac9cdf044dcb9481c7da782db01b50c1f0e7cdd78c8507b963b6d072829c0263",
|
||||
"sha256:acfad8ffed96891fe7c583d92717cd8ec0c03b59a954c389fd4e26a5cdeac610",
|
||||
"sha256:ad15f25abff8220e556d64e2a27c646241b08f00faf1bc02313655696cd3edfa",
|
||||
"sha256:b679f951f842c38665aa54bea4d7403099131f71fac6d8584f893a731fe1266d",
|
||||
"sha256:b8c183dc4aa4e95dc5c373eedc3d205c176805835611fcfec5d9050736c695c4",
|
||||
"sha256:c097a6829967c76526a037ed34500a028f78f0d765c8e3dbd1a7717afd09fb92",
|
||||
"sha256:c2c76f483d05eddec60a5cd89e92385adef565a4f243b1d9a6abe2f6bd2a7c0a",
|
||||
"sha256:c388baa3c04272a7c585d3da24030c142353eb26eb531dd2681502e6be7d7a26",
|
||||
"sha256:cb0f2a711db665b5bf8697b5af3b9884bb1139385c5c12c2e472e4bbee62da99",
|
||||
"sha256:cbac984d7b36e75b440d1c8ff9d3425d778364a0cbc23f8943383d4decd35d5e",
|
||||
"sha256:f55adf069be2d655f8d668594fe1be1b84d9dc8106d380a9ada06f34941c33c8",
|
||||
"sha256:f9084ed3b8997ad4353d124b903f2860a9695b9e080663276d9e58c32e293244",
|
||||
"sha256:fb7df3504222fcb1fa593f76623abbb54d6019eec15aac5d05cd07ad90ac016c"
|
||||
],
|
||||
"version": "==0.13.1"
|
||||
},
|
||||
"pytz": {
|
||||
"hashes": [
|
||||
"sha256:a494d53b6d39c3c6e44c3bec237336e14305e4f29bbf800b599253057fbb79ed",
|
||||
|
@ -891,9 +803,8 @@
|
|||
"version": "==1.1.4"
|
||||
},
|
||||
"spiffworkflow": {
|
||||
"editable": true,
|
||||
"git": "https://github.com/sartography/SpiffWorkflow.git",
|
||||
"ref": "74529738b4e16be5aadd846669a201560f81a6d4"
|
||||
"ref": "7c8d59e7b9a978795bc8d1f354002fdc89540672"
|
||||
},
|
||||
"sqlalchemy": {
|
||||
"hashes": [
|
||||
|
@ -938,17 +849,10 @@
|
|||
},
|
||||
"urllib3": {
|
||||
"hashes": [
|
||||
"sha256:3018294ebefce6572a474f0604c2021e33b3fd8006ecd11d62107a5d2a963527",
|
||||
"sha256:88206b0eb87e6d677d424843ac5209e3fb9d0190d0ee169599165ec25e9d9115"
|
||||
"sha256:91056c15fa70756691db97756772bb1eb9678fa585d9184f24534b100dc60f4a",
|
||||
"sha256:e7983572181f5e1522d9c98453462384ee92a0be7fac5f1413a1e35c56cc0461"
|
||||
],
|
||||
"version": "==1.25.9"
|
||||
},
|
||||
"vine": {
|
||||
"hashes": [
|
||||
"sha256:133ee6d7a9016f177ddeaf191c1f58421a1dcc6ee9a42c58b34bed40e1d2cd87",
|
||||
"sha256:ea4947cc56d1fd6f2095c8d543ee25dad966f78692528e68b4fada11ba3f98af"
|
||||
],
|
||||
"version": "==1.3.0"
|
||||
"version": "==1.25.10"
|
||||
},
|
||||
"waitress": {
|
||||
"hashes": [
|
||||
|
@ -980,12 +884,18 @@
|
|||
"index": "pypi",
|
||||
"version": "==1.0.1"
|
||||
},
|
||||
"wrapt": {
|
||||
"hashes": [
|
||||
"sha256:b62ffa81fb85f4332a4f609cab4ac40709470da05643a082ec1eb88e6d9b97d7"
|
||||
],
|
||||
"version": "==1.12.1"
|
||||
},
|
||||
"wtforms": {
|
||||
"hashes": [
|
||||
"sha256:6ff8635f4caeed9f38641d48cfe019d0d3896f41910ab04494143fc027866e1b",
|
||||
"sha256:861a13b3ae521d6700dac3b2771970bd354a63ba7043ecc3a82b5288596a1972"
|
||||
"sha256:7b504fc724d0d1d4d5d5c114e778ec88c37ea53144683e084215eed5155ada4c",
|
||||
"sha256:81195de0ac94fbc8368abbaf9197b88c4f3ffd6c2719b5bf5fc9da744f3d829c"
|
||||
],
|
||||
"version": "==2.3.1"
|
||||
"version": "==2.3.3"
|
||||
},
|
||||
"xlrd": {
|
||||
"hashes": [
|
||||
|
@ -997,11 +907,11 @@
|
|||
},
|
||||
"xlsxwriter": {
|
||||
"hashes": [
|
||||
"sha256:828b3285fc95105f5b1946a6a015b31cf388bd5378fdc6604e4d1b7839df2e77",
|
||||
"sha256:82a3b0e73e3913483da23791d1a25e4d2dbb3837d1be4129473526b9a270a5cc"
|
||||
"sha256:3015f707cf237d277cf1b2d7805f409f0387e32bc52f3c76db9f85098980e828",
|
||||
"sha256:ee3fc2f32890246aba44dd14d777d6b3135e3454f865d8cc669618e20152296b"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==1.2.9"
|
||||
"version": "==1.3.0"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
|
@ -1021,43 +931,43 @@
|
|||
},
|
||||
"coverage": {
|
||||
"hashes": [
|
||||
"sha256:0fc4e0d91350d6f43ef6a61f64a48e917637e1dcfcba4b4b7d543c628ef82c2d",
|
||||
"sha256:10f2a618a6e75adf64329f828a6a5b40244c1c50f5ef4ce4109e904e69c71bd2",
|
||||
"sha256:12eaccd86d9a373aea59869bc9cfa0ab6ba8b1477752110cb4c10d165474f703",
|
||||
"sha256:1874bdc943654ba46d28f179c1846f5710eda3aeb265ff029e0ac2b52daae404",
|
||||
"sha256:1dcebae667b73fd4aa69237e6afb39abc2f27520f2358590c1b13dd90e32abe7",
|
||||
"sha256:1e58fca3d9ec1a423f1b7f2aa34af4f733cbfa9020c8fe39ca451b6071237405",
|
||||
"sha256:214eb2110217f2636a9329bc766507ab71a3a06a8ea30cdeebb47c24dce5972d",
|
||||
"sha256:25fe74b5b2f1b4abb11e103bb7984daca8f8292683957d0738cd692f6a7cc64c",
|
||||
"sha256:32ecee61a43be509b91a526819717d5e5650e009a8d5eda8631a59c721d5f3b6",
|
||||
"sha256:3740b796015b889e46c260ff18b84683fa2e30f0f75a171fb10d2bf9fb91fc70",
|
||||
"sha256:3b2c34690f613525672697910894b60d15800ac7e779fbd0fccf532486c1ba40",
|
||||
"sha256:41d88736c42f4a22c494c32cc48a05828236e37c991bd9760f8923415e3169e4",
|
||||
"sha256:42fa45a29f1059eda4d3c7b509589cc0343cd6bbf083d6118216830cd1a51613",
|
||||
"sha256:4bb385a747e6ae8a65290b3df60d6c8a692a5599dc66c9fa3520e667886f2e10",
|
||||
"sha256:509294f3e76d3f26b35083973fbc952e01e1727656d979b11182f273f08aa80b",
|
||||
"sha256:5c74c5b6045969b07c9fb36b665c9cac84d6c174a809fc1b21bdc06c7836d9a0",
|
||||
"sha256:60a3d36297b65c7f78329b80120f72947140f45b5c7a017ea730f9112b40f2ec",
|
||||
"sha256:6f91b4492c5cde83bfe462f5b2b997cdf96a138f7c58b1140f05de5751623cf1",
|
||||
"sha256:7403675df5e27745571aba1c957c7da2dacb537c21e14007ec3a417bf31f7f3d",
|
||||
"sha256:87bdc8135b8ee739840eee19b184804e5d57f518578ffc797f5afa2c3c297913",
|
||||
"sha256:8a3decd12e7934d0254939e2bf434bf04a5890c5bf91a982685021786a08087e",
|
||||
"sha256:9702e2cb1c6dec01fb8e1a64c015817c0800a6eca287552c47a5ee0ebddccf62",
|
||||
"sha256:a4d511012beb967a39580ba7d2549edf1e6865a33e5fe51e4dce550522b3ac0e",
|
||||
"sha256:bbb387811f7a18bdc61a2ea3d102be0c7e239b0db9c83be7bfa50f095db5b92a",
|
||||
"sha256:bfcc811883699ed49afc58b1ed9f80428a18eb9166422bce3c31a53dba00fd1d",
|
||||
"sha256:c32aa13cc3fe86b0f744dfe35a7f879ee33ac0a560684fef0f3e1580352b818f",
|
||||
"sha256:ca63dae130a2e788f2b249200f01d7fa240f24da0596501d387a50e57aa7075e",
|
||||
"sha256:d54d7ea74cc00482a2410d63bf10aa34ebe1c49ac50779652106c867f9986d6b",
|
||||
"sha256:d67599521dff98ec8c34cd9652cbcfe16ed076a2209625fca9dc7419b6370e5c",
|
||||
"sha256:d82db1b9a92cb5c67661ca6616bdca6ff931deceebb98eecbd328812dab52032",
|
||||
"sha256:d9ad0a988ae20face62520785ec3595a5e64f35a21762a57d115dae0b8fb894a",
|
||||
"sha256:ebf2431b2d457ae5217f3a1179533c456f3272ded16f8ed0b32961a6d90e38ee",
|
||||
"sha256:ed9a21502e9223f563e071759f769c3d6a2e1ba5328c31e86830368e8d78bc9c",
|
||||
"sha256:f50632ef2d749f541ca8e6c07c9928a37f87505ce3a9f20c8446ad310f1aa87b"
|
||||
"sha256:098a703d913be6fbd146a8c50cc76513d726b022d170e5e98dc56d958fd592fb",
|
||||
"sha256:16042dc7f8e632e0dcd5206a5095ebd18cb1d005f4c89694f7f8aafd96dd43a3",
|
||||
"sha256:1adb6be0dcef0cf9434619d3b892772fdb48e793300f9d762e480e043bd8e716",
|
||||
"sha256:27ca5a2bc04d68f0776f2cdcb8bbd508bbe430a7bf9c02315cd05fb1d86d0034",
|
||||
"sha256:28f42dc5172ebdc32622a2c3f7ead1b836cdbf253569ae5673f499e35db0bac3",
|
||||
"sha256:2fcc8b58953d74d199a1a4d633df8146f0ac36c4e720b4a1997e9b6327af43a8",
|
||||
"sha256:304fbe451698373dc6653772c72c5d5e883a4aadaf20343592a7abb2e643dae0",
|
||||
"sha256:30bc103587e0d3df9e52cd9da1dd915265a22fad0b72afe54daf840c984b564f",
|
||||
"sha256:40f70f81be4d34f8d491e55936904db5c527b0711b2a46513641a5729783c2e4",
|
||||
"sha256:4186fc95c9febeab5681bc3248553d5ec8c2999b8424d4fc3a39c9cba5796962",
|
||||
"sha256:46794c815e56f1431c66d81943fa90721bb858375fb36e5903697d5eef88627d",
|
||||
"sha256:4869ab1c1ed33953bb2433ce7b894a28d724b7aa76c19b11e2878034a4e4680b",
|
||||
"sha256:4f6428b55d2916a69f8d6453e48a505c07b2245653b0aa9f0dee38785939f5e4",
|
||||
"sha256:52f185ffd3291196dc1aae506b42e178a592b0b60a8610b108e6ad892cfc1bb3",
|
||||
"sha256:538f2fd5eb64366f37c97fdb3077d665fa946d2b6d95447622292f38407f9258",
|
||||
"sha256:64c4f340338c68c463f1b56e3f2f0423f7b17ba6c3febae80b81f0e093077f59",
|
||||
"sha256:675192fca634f0df69af3493a48224f211f8db4e84452b08d5fcebb9167adb01",
|
||||
"sha256:700997b77cfab016533b3e7dbc03b71d33ee4df1d79f2463a318ca0263fc29dd",
|
||||
"sha256:8505e614c983834239f865da2dd336dcf9d72776b951d5dfa5ac36b987726e1b",
|
||||
"sha256:962c44070c281d86398aeb8f64e1bf37816a4dfc6f4c0f114756b14fc575621d",
|
||||
"sha256:9e536783a5acee79a9b308be97d3952b662748c4037b6a24cbb339dc7ed8eb89",
|
||||
"sha256:9ea749fd447ce7fb1ac71f7616371f04054d969d412d37611716721931e36efd",
|
||||
"sha256:a34cb28e0747ea15e82d13e14de606747e9e484fb28d63c999483f5d5188e89b",
|
||||
"sha256:a3ee9c793ffefe2944d3a2bd928a0e436cd0ac2d9e3723152d6fd5398838ce7d",
|
||||
"sha256:aab75d99f3f2874733946a7648ce87a50019eb90baef931698f96b76b6769a46",
|
||||
"sha256:b1ed2bdb27b4c9fc87058a1cb751c4df8752002143ed393899edb82b131e0546",
|
||||
"sha256:b360d8fd88d2bad01cb953d81fd2edd4be539df7bfec41e8753fe9f4456a5082",
|
||||
"sha256:b8f58c7db64d8f27078cbf2a4391af6aa4e4767cc08b37555c4ae064b8558d9b",
|
||||
"sha256:c1bbb628ed5192124889b51204de27c575b3ffc05a5a91307e7640eff1d48da4",
|
||||
"sha256:c2ff24df02a125b7b346c4c9078c8936da06964cc2d276292c357d64378158f8",
|
||||
"sha256:c890728a93fffd0407d7d37c1e6083ff3f9f211c83b4316fae3778417eab9811",
|
||||
"sha256:c96472b8ca5dc135fb0aa62f79b033f02aa434fb03a8b190600a5ae4102df1fd",
|
||||
"sha256:ce7866f29d3025b5b34c2e944e66ebef0d92e4a4f2463f7266daa03a1332a651",
|
||||
"sha256:e26c993bd4b220429d4ec8c1468eca445a4064a61c74ca08da7429af9bc53bb0"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.2"
|
||||
"version": "==5.2.1"
|
||||
},
|
||||
"importlib-metadata": {
|
||||
"hashes": [
|
||||
|
@ -1067,6 +977,12 @@
|
|||
"markers": "python_version < '3.8'",
|
||||
"version": "==1.7.0"
|
||||
},
|
||||
"iniconfig": {
|
||||
"hashes": [
|
||||
"sha256:aa0b40f50a00e72323cb5d41302f9c6165728fd764ac8822aa3fff00a40d56b4"
|
||||
],
|
||||
"version": "==1.0.0"
|
||||
},
|
||||
"more-itertools": {
|
||||
"hashes": [
|
||||
"sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5",
|
||||
|
@ -1112,11 +1028,11 @@
|
|||
},
|
||||
"pytest": {
|
||||
"hashes": [
|
||||
"sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1",
|
||||
"sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"
|
||||
"sha256:85228d75db9f45e06e57ef9bf4429267f81ac7c0d742cc9ed63d09886a9fe6f4",
|
||||
"sha256:8b6007800c53fdacd5a5c192203f4e531eb2a1540ad9c752e052ec0f7143dbad"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==5.4.3"
|
||||
"version": "==6.0.1"
|
||||
},
|
||||
"six": {
|
||||
"hashes": [
|
||||
|
@ -1125,12 +1041,12 @@
|
|||
],
|
||||
"version": "==1.15.0"
|
||||
},
|
||||
"wcwidth": {
|
||||
"toml": {
|
||||
"hashes": [
|
||||
"sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784",
|
||||
"sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83"
|
||||
"sha256:926b612be1e5ce0634a2ca03470f95169cf16f939018233a670519cb4ac58b0f",
|
||||
"sha256:bda89d5935c2eac546d648028b9901107a595863cb36bae0c73ac804a9b4ce88"
|
||||
],
|
||||
"version": "==0.2.5"
|
||||
"version": "==0.10.1"
|
||||
},
|
||||
"zipp": {
|
||||
"hashes": [
|
||||
|
|
|
@ -46,6 +46,9 @@ PB_STUDY_DETAILS_URL = environ.get('PB_STUDY_DETAILS_URL', default=PB_BASE_URL +
|
|||
LDAP_URL = environ.get('LDAP_URL', default="ldap.virginia.edu").strip('/') # No trailing slash or http://
|
||||
LDAP_TIMEOUT_SEC = int(environ.get('LDAP_TIMEOUT_SEC', default=1))
|
||||
|
||||
# Github token
|
||||
GITHUB_TOKEN = environ.get('GITHUB_TOKEN', None)
|
||||
|
||||
# Email configuration
|
||||
DEFAULT_SENDER = 'askresearch@virginia.edu'
|
||||
FALLBACK_EMAILS = ['askresearch@virginia.edu', 'sartographysupport@googlegroups.com']
|
||||
|
|
|
@ -3,19 +3,22 @@ import json
|
|||
|
||||
from flask import url_for
|
||||
from flask_admin import Admin
|
||||
from flask_admin.actions import action
|
||||
from flask_admin.contrib import sqla
|
||||
from flask_admin.contrib.sqla import ModelView
|
||||
from sqlalchemy import desc
|
||||
from werkzeug.utils import redirect
|
||||
from jinja2 import Markup
|
||||
|
||||
from crc import db, app
|
||||
from crc.api.user import verify_token, verify_token_admin
|
||||
from crc.models.approval import ApprovalModel
|
||||
from crc.models.file import FileModel
|
||||
from crc.models.file import FileModel, FileDataModel
|
||||
from crc.models.task_event import TaskEventModel
|
||||
from crc.models.study import StudyModel
|
||||
from crc.models.user import UserModel
|
||||
from crc.models.workflow import WorkflowModel
|
||||
from crc.services.file_service import FileService
|
||||
|
||||
|
||||
class AdminModelView(sqla.ModelView):
|
||||
|
@ -34,26 +37,40 @@ class AdminModelView(sqla.ModelView):
|
|||
# redirect to login page if user doesn't have access
|
||||
return redirect(url_for('home'))
|
||||
|
||||
|
||||
class UserView(AdminModelView):
|
||||
column_filters = ['uid']
|
||||
|
||||
|
||||
class StudyView(AdminModelView):
|
||||
column_filters = ['id', 'primary_investigator_id']
|
||||
column_searchable_list = ['title']
|
||||
|
||||
|
||||
class ApprovalView(AdminModelView):
|
||||
column_filters = ['study_id', 'approver_uid']
|
||||
|
||||
|
||||
class WorkflowView(AdminModelView):
|
||||
column_filters = ['study_id', 'id']
|
||||
|
||||
|
||||
class FileView(AdminModelView):
|
||||
column_filters = ['workflow_id']
|
||||
column_filters = ['workflow_id', 'type']
|
||||
|
||||
@action('publish', 'Publish', 'Are you sure you want to publish this file(s)?')
|
||||
def action_publish(self, ids):
|
||||
FileService.publish_to_github(ids)
|
||||
|
||||
@action('update', 'Update', 'Are you sure you want to update this file(s)?')
|
||||
def action_update(self, ids):
|
||||
FileService.update_from_github(ids)
|
||||
|
||||
|
||||
def json_formatter(view, context, model, name):
|
||||
value = getattr(model, name)
|
||||
json_value = json.dumps(value, ensure_ascii=False, indent=2)
|
||||
return Markup('<pre>{}</pre>'.format(json_value))
|
||||
return Markup(f'<pre>{json_value}</pre>')
|
||||
|
||||
class TaskEventView(AdminModelView):
|
||||
column_filters = ['workflow_id', 'action']
|
||||
|
@ -62,6 +79,7 @@ class TaskEventView(AdminModelView):
|
|||
'form_data': json_formatter,
|
||||
}
|
||||
|
||||
|
||||
admin = Admin(app)
|
||||
|
||||
admin.add_view(StudyView(StudyModel, db.session))
|
||||
|
|
|
@ -31,10 +31,6 @@ def verify_token(token=None):
|
|||
failure_error = ApiError("invalid_token", "Unable to decode the token you provided. Please re-authenticate",
|
||||
status_code=403)
|
||||
|
||||
if not _is_production() and (token is None or 'user' not in g):
|
||||
g.user = UserModel.query.first()
|
||||
token = g.user.encode_auth_token()
|
||||
|
||||
if token:
|
||||
try:
|
||||
token_info = UserModel.decode_auth_token(token)
|
||||
|
@ -47,7 +43,7 @@ def verify_token(token=None):
|
|||
raise failure_error
|
||||
|
||||
# If there's no token and we're in production, get the user from the SSO headers and return their token
|
||||
if not token and _is_production():
|
||||
elif _is_production():
|
||||
uid = _get_request_uid(request)
|
||||
|
||||
if uid is not None:
|
||||
|
@ -63,6 +59,12 @@ def verify_token(token=None):
|
|||
raise ApiError("no_user", "User not found. Please login via the frontend app before accessing this feature.",
|
||||
status_code=403)
|
||||
|
||||
else:
|
||||
# Fall back to a default user if this is not production.
|
||||
g.user = UserModel.query.first()
|
||||
token = g.user.encode_auth_token()
|
||||
|
||||
|
||||
|
||||
def verify_token_admin(token=None):
|
||||
"""
|
||||
|
|
|
@ -40,7 +40,7 @@ class StudyModel(db.Model):
|
|||
|
||||
|
||||
class WorkflowMetadata(object):
|
||||
def __init__(self, id, name, display_name, description, spec_version, category_id, state: WorkflowState, status: WorkflowStatus,
|
||||
def __init__(self, id, name, display_name, description, spec_version, category_id, category_display_name, state: WorkflowState, status: WorkflowStatus,
|
||||
total_tasks, completed_tasks, display_order):
|
||||
self.id = id
|
||||
self.name = name
|
||||
|
@ -48,6 +48,7 @@ class WorkflowMetadata(object):
|
|||
self.description = description
|
||||
self.spec_version = spec_version
|
||||
self.category_id = category_id
|
||||
self.category_display_name = category_display_name
|
||||
self.state = state
|
||||
self.status = status
|
||||
self.total_tasks = total_tasks
|
||||
|
@ -64,6 +65,7 @@ class WorkflowMetadata(object):
|
|||
description=workflow.workflow_spec.description,
|
||||
spec_version=workflow.spec_version(),
|
||||
category_id=workflow.workflow_spec.category_id,
|
||||
category_display_name=workflow.workflow_spec.category.display_name,
|
||||
state=WorkflowState.optional,
|
||||
status=workflow.status,
|
||||
total_tasks=workflow.total_tasks,
|
||||
|
@ -79,7 +81,8 @@ class WorkflowMetadataSchema(ma.Schema):
|
|||
class Meta:
|
||||
model = WorkflowMetadata
|
||||
additional = ["id", "name", "display_name", "description",
|
||||
"total_tasks", "completed_tasks", "display_order"]
|
||||
"total_tasks", "completed_tasks", "display_order",
|
||||
"category_id", "category_display_name"]
|
||||
unknown = INCLUDE
|
||||
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ class TaskEventSchema(ma.Schema):
|
|||
|
||||
study = fields.Nested(StudySchema, dump_only=True)
|
||||
workflow = fields.Nested(WorkflowMetadataSchema, dump_only=True)
|
||||
|
||||
class Meta:
|
||||
model = TaskEvent
|
||||
additional = ["id", "user_uid", "action", "task_id", "task_title",
|
||||
|
|
|
@ -40,7 +40,7 @@ class FactService(Script):
|
|||
else:
|
||||
details = "unknown fact type."
|
||||
|
||||
self.add_data_to_task(task, details)
|
||||
#self.add_data_to_task(task, details)
|
||||
|
||||
print(details)
|
||||
return details
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import copy
|
||||
|
||||
from crc import app
|
||||
from crc.api.common import ApiError
|
||||
from crc.scripts.script import Script
|
||||
from crc.services.ldap_service import LdapService
|
||||
|
||||
|
||||
class Ldap(Script):
|
||||
"""This Script allows to be introduced as part of a workflow and called from there, taking
|
||||
a UID (or several) as input and looking it up through LDAP to return the person's details """
|
||||
|
||||
def get_description(self):
|
||||
return """
|
||||
Attempts to create a dictionary with person details, using the
|
||||
provided argument (a UID) and look it up through LDAP.
|
||||
|
||||
Examples:
|
||||
supervisor_info = ldap(supervisor_uid) // Sets the supervisor information to ldap details for the given uid.
|
||||
"""
|
||||
|
||||
def do_task_validate_only(self, task, *args, **kwargs):
|
||||
return self.set_users_info_in_task(task, args)
|
||||
|
||||
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
|
||||
return self.set_users_info_in_task(task, args)
|
||||
|
||||
def set_users_info_in_task(self, task, args):
|
||||
if len(args) != 1:
|
||||
raise ApiError(code="missing_argument",
|
||||
message="Ldap takes a single argument, the "
|
||||
"UID for the person we want to look up")
|
||||
uid = args[0]
|
||||
user_info_dict = {}
|
||||
|
||||
user_info = LdapService.user_info(uid)
|
||||
user_info_dict = {
|
||||
"display_name": user_info.display_name,
|
||||
"given_name": user_info.given_name,
|
||||
"email_address": user_info.email_address,
|
||||
"telephone_number": user_info.telephone_number,
|
||||
"title": user_info.title,
|
||||
"department": user_info.department,
|
||||
"affiliation": user_info.affiliation,
|
||||
"sponsor_type": user_info.sponsor_type,
|
||||
"uid": user_info.uid,
|
||||
"proper_name": user_info.proper_name()
|
||||
}
|
||||
|
||||
return user_info_dict
|
|
@ -11,7 +11,7 @@ class RequestApproval(Script):
|
|||
return """
|
||||
Creates an approval request on this workflow, by the given approver_uid(s),"
|
||||
Takes multiple arguments, which should point to data located in current task
|
||||
or be quoted strings. The order is important. Approvals will be processed
|
||||
or be quoted strings. The order is important. Approvals will be processed
|
||||
in this order.
|
||||
|
||||
Example:
|
||||
|
|
|
@ -23,6 +23,53 @@ class Script(object):
|
|||
"This is an internal error. The script you are trying to execute '%s' " % self.__class__.__name__ +
|
||||
"does must provide a validate_only option that mimics the do_task, " +
|
||||
"but does not make external calls or database updates." )
|
||||
@staticmethod
|
||||
def generate_augmented_list(task, study_id,workflow_id):
|
||||
"""
|
||||
this makes a dictionary of lambda functions that are closed over the class instance that
|
||||
They represent. This is passed into PythonScriptParser as a list of helper functions that are
|
||||
available for running. In general, they maintain the do_task call structure that they had, but
|
||||
they always return a value rather than updating the task data.
|
||||
|
||||
We may be able to remove the task for each of these calls if we are not using it other than potentially
|
||||
updating the task data.
|
||||
"""
|
||||
def make_closure(subclass,task,study_id,workflow_id):
|
||||
instance = subclass()
|
||||
return lambda *a : subclass.do_task(instance,task,study_id,workflow_id,*a)
|
||||
execlist = {}
|
||||
subclasses = Script.get_all_subclasses()
|
||||
for x in range(len(subclasses)):
|
||||
subclass = subclasses[x]
|
||||
execlist[subclass.__module__.split('.')[-1]] = make_closure(subclass,task,study_id,
|
||||
workflow_id)
|
||||
return execlist
|
||||
|
||||
@staticmethod
|
||||
def generate_augmented_validate_list(task, study_id, workflow_id):
|
||||
"""
|
||||
this makes a dictionary of lambda functions that are closed over the class instance that
|
||||
They represent. This is passed into PythonScriptParser as a list of helper functions that are
|
||||
available for running. In general, they maintain the do_task call structure that they had, but
|
||||
they always return a value rather than updating the task data.
|
||||
|
||||
We may be able to remove the task for each of these calls if we are not using it other than potentially
|
||||
updating the task data.
|
||||
"""
|
||||
|
||||
def make_closure_validate(subclass,task,study_id,workflow_id):
|
||||
instance = subclass()
|
||||
return lambda *a : subclass.do_task_validate_only(instance,task,study_id,workflow_id,*a)
|
||||
execlist = {}
|
||||
subclasses = Script.get_all_subclasses()
|
||||
for x in range(len(subclasses)):
|
||||
subclass = subclasses[x]
|
||||
execlist[subclass.__module__.split('.')[-1]] = make_closure_validate(subclass,task,study_id,
|
||||
workflow_id)
|
||||
return execlist
|
||||
|
||||
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_all_subclasses():
|
||||
|
|
|
@ -8,7 +8,7 @@ from crc.scripts.script import Script
|
|||
from crc.services.file_service import FileService
|
||||
from crc.services.protocol_builder import ProtocolBuilderService
|
||||
from crc.services.study_service import StudyService
|
||||
|
||||
from box import Box
|
||||
|
||||
class StudyInfo(Script):
|
||||
"""Please see the detailed description that is provided below. """
|
||||
|
@ -149,11 +149,11 @@ Returns information specific to the protocol.
|
|||
|
||||
def do_task_validate_only(self, task, study_id, workflow_id, *args, **kwargs):
|
||||
"""For validation only, pretend no results come back from pb"""
|
||||
self.check_args(args)
|
||||
self.check_args(args,2)
|
||||
# Assure the reference file exists (a bit hacky, but we want to raise this error early, and cleanly.)
|
||||
FileService.get_reference_file_data(FileService.DOCUMENT_LIST)
|
||||
FileService.get_reference_file_data(FileService.INVESTIGATOR_LIST)
|
||||
data = {
|
||||
data = Box({
|
||||
"study":{
|
||||
"info": {
|
||||
"id": 12,
|
||||
|
@ -195,38 +195,50 @@ Returns information specific to the protocol.
|
|||
'id': 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
self.add_data_to_task(task=task, data=data["study"])
|
||||
self.add_data_to_task(task, {"documents": StudyService().get_documents_status(study_id)})
|
||||
})
|
||||
if args[0]=='documents':
|
||||
return StudyService().get_documents_status(study_id)
|
||||
return data['study'][args[0]]
|
||||
#self.add_data_to_task(task=task, data=data["study"])
|
||||
#self.add_data_to_task(task, {"documents": StudyService().get_documents_status(study_id)})
|
||||
|
||||
def do_task(self, task, study_id, workflow_id, *args, **kwargs):
|
||||
self.check_args(args)
|
||||
|
||||
self.check_args(args,2)
|
||||
prefix = None
|
||||
if len(args) > 1:
|
||||
prefix = args[1]
|
||||
cmd = args[0]
|
||||
study_info = {}
|
||||
if self.__class__.__name__ in task.data:
|
||||
study_info = task.data[self.__class__.__name__]
|
||||
|
||||
# study_info = {}
|
||||
# if self.__class__.__name__ in task.data:
|
||||
# study_info = task.data[self.__class__.__name__]
|
||||
retval = None
|
||||
if cmd == 'info':
|
||||
study = session.query(StudyModel).filter_by(id=study_id).first()
|
||||
schema = StudySchema()
|
||||
self.add_data_to_task(task, {cmd: schema.dump(study)})
|
||||
retval = schema.dump(study)
|
||||
if cmd == 'investigators':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_investigators(study_id)})
|
||||
retval = StudyService().get_investigators(study_id)
|
||||
if cmd == 'roles':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_investigators(study_id, all=True)})
|
||||
retval = StudyService().get_investigators(study_id, all=True)
|
||||
if cmd == 'details':
|
||||
self.add_data_to_task(task, {cmd: self.pb.get_study_details(study_id)})
|
||||
retval = self.pb.get_study_details(study_id)
|
||||
if cmd == 'approvals':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_approvals(study_id)})
|
||||
retval = StudyService().get_approvals(study_id)
|
||||
if cmd == 'documents':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_documents_status(study_id)})
|
||||
retval = StudyService().get_documents_status(study_id)
|
||||
if cmd == 'protocol':
|
||||
self.add_data_to_task(task, {cmd: StudyService().get_protocol(study_id)})
|
||||
retval = StudyService().get_protocol(study_id)
|
||||
if isinstance(retval,dict) and prefix is not None:
|
||||
return Box({x:retval[x] for x in retval.keys() if x[:len(prefix)] == prefix})
|
||||
elif isinstance(retval,dict):
|
||||
return Box(retval)
|
||||
else:
|
||||
return retval
|
||||
|
||||
|
||||
def check_args(self, args):
|
||||
if len(args) != 1 or (args[0] not in StudyInfo.type_options):
|
||||
|
||||
def check_args(self, args, maxlen=1):
|
||||
if len(args) < 1 or len(args) > maxlen or (args[0] not in StudyInfo.type_options):
|
||||
raise ApiError(code="missing_argument",
|
||||
message="The StudyInfo script requires a single argument which must be "
|
||||
"one of %s" % ",".join(StudyInfo.type_options))
|
||||
|
|
|
@ -2,6 +2,7 @@ import hashlib
|
|||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
from github import Github, UnknownObjectException
|
||||
from uuid import UUID
|
||||
from lxml import etree
|
||||
|
||||
|
@ -332,3 +333,51 @@ class FileService(object):
|
|||
file_model.archived = True
|
||||
session.commit()
|
||||
app.logger.info("Failed to delete file, so archiving it instead. %i, due to %s" % (file_id, str(ie)))
|
||||
|
||||
@staticmethod
|
||||
def update_from_github(file_ids):
|
||||
gh_token = app.config['GITHUB_TOKEN']
|
||||
_github = Github(gh_token)
|
||||
repo = _github.get_user().get_repo('crispy-fiesta')
|
||||
|
||||
for file_id in file_ids:
|
||||
file_data_model = FileDataModel.query.filter_by(
|
||||
file_model_id=file_id
|
||||
).order_by(
|
||||
desc(FileDataModel.version)
|
||||
).first()
|
||||
try:
|
||||
repo_file = repo.get_contents(file_data_model.file_model.name)
|
||||
except UnknownObjectException:
|
||||
# TODO: Add message indicating file is not in the repo
|
||||
pass
|
||||
else:
|
||||
file_data_model.data = repo_file.decoded_content
|
||||
session.add(file_data_model)
|
||||
session.commit()
|
||||
|
||||
@staticmethod
|
||||
def publish_to_github(file_ids):
|
||||
gh_token = app.config['GITHUB_TOKEN']
|
||||
_github = Github(gh_token)
|
||||
repo = _github.get_user().get_repo('crispy-fiesta')
|
||||
|
||||
for file_id in file_ids:
|
||||
file_data_model = FileDataModel.query.filter_by(file_model_id=file_id).first()
|
||||
try:
|
||||
repo_file = repo.get_contents(file_data_model.file_model.name)
|
||||
except UnknownObjectException:
|
||||
repo.create_file(
|
||||
path=file_data_model.file_model.name,
|
||||
message=f'Creating {file_data_model.file_model.name}',
|
||||
content=file_data_model.data
|
||||
)
|
||||
return {'created': True}
|
||||
else:
|
||||
updated = repo.update_file(
|
||||
path=repo_file.path,
|
||||
message=f'Updating {file_data_model.file_model.name}',
|
||||
content=file_data_model.data,
|
||||
sha=repo_file.sha
|
||||
)
|
||||
return {'updated': True}
|
||||
|
|
|
@ -17,6 +17,7 @@ from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser
|
|||
from SpiffWorkflow.exceptions import WorkflowTaskExecException
|
||||
from SpiffWorkflow.specs import WorkflowSpec
|
||||
|
||||
import crc
|
||||
from crc import session, app
|
||||
from crc.api.common import ApiError
|
||||
from crc.models.file import FileDataModel, FileModel, FileType
|
||||
|
@ -28,64 +29,71 @@ from crc import app
|
|||
|
||||
class CustomBpmnScriptEngine(BpmnScriptEngine):
|
||||
"""This is a custom script processor that can be easily injected into Spiff Workflow.
|
||||
Rather than execute arbitrary code, this assumes the script references a fully qualified python class
|
||||
such as myapp.RandomFact. """
|
||||
It will execute python code read in from the bpmn. It will also make any scripts in the
|
||||
scripts directory available for execution. """
|
||||
|
||||
def execute(self, task: SpiffTask, script, data):
|
||||
"""
|
||||
Functions in two modes.
|
||||
1. If the command is proceeded by #! then this is assumed to be a python script, and will
|
||||
attempt to load that python module and execute the do_task method on that script. Scripts
|
||||
must be located in the scripts package and they must extend the script.py class.
|
||||
2. If not proceeded by the #! this will attempt to execute the script directly and assumes it is
|
||||
valid Python.
|
||||
"""
|
||||
# Shlex splits the whole string while respecting double quoted strings within
|
||||
if not script.startswith('#!'):
|
||||
try:
|
||||
super().execute(task, script, data)
|
||||
except SyntaxError as e:
|
||||
raise ApiError.from_task('syntax_error',
|
||||
f'If you are running a pre-defined script, please'
|
||||
f' proceed the script with "#!", otherwise this is assumed to be'
|
||||
f' pure python: {script}, {e.msg}', task=task)
|
||||
else:
|
||||
self.run_predefined_script(task, script[2:], data) # strip off the first two characters.
|
||||
|
||||
def run_predefined_script(self, task: SpiffTask, script, data):
|
||||
commands = shlex.split(script)
|
||||
path_and_command = commands[0].rsplit(".", 1)
|
||||
if len(path_and_command) == 1:
|
||||
module_name = "crc.scripts." + self.camel_to_snake(path_and_command[0])
|
||||
class_name = path_and_command[0]
|
||||
study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
|
||||
if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
|
||||
workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
|
||||
else:
|
||||
module_name = "crc.scripts." + path_and_command[0] + "." + self.camel_to_snake(path_and_command[1])
|
||||
class_name = path_and_command[1]
|
||||
workflow_id = None
|
||||
|
||||
try:
|
||||
mod = __import__(module_name, fromlist=[class_name])
|
||||
klass = getattr(mod, class_name)
|
||||
study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
|
||||
if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
|
||||
workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
|
||||
else:
|
||||
workflow_id = None
|
||||
|
||||
if not isinstance(klass(), Script):
|
||||
raise ApiError.from_task("invalid_script",
|
||||
"This is an internal error. The script '%s:%s' you called " %
|
||||
(module_name, class_name) +
|
||||
"does not properly implement the CRC Script class.",
|
||||
task=task)
|
||||
if task.workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY]:
|
||||
"""If this is running a validation, and not a normal process, then we want to
|
||||
mimic running the script, but not make any external calls or database changes."""
|
||||
klass().do_task_validate_only(task, study_id, workflow_id, *commands[1:])
|
||||
augmentMethods = Script.generate_augmented_validate_list(task, study_id, workflow_id)
|
||||
else:
|
||||
klass().do_task(task, study_id, workflow_id, *commands[1:])
|
||||
except ModuleNotFoundError:
|
||||
raise ApiError.from_task("invalid_script",
|
||||
"Unable to locate Script: '%s:%s'" % (module_name, class_name),
|
||||
task=task)
|
||||
augmentMethods = Script.generate_augmented_list(task, study_id, workflow_id)
|
||||
|
||||
super().execute(task, script, data, externalMethods=augmentMethods)
|
||||
except SyntaxError as e:
|
||||
raise ApiError('syntax_error',
|
||||
f'Something is wrong with your python script '
|
||||
f'please correct the following:'
|
||||
f' {script}, {e.msg}')
|
||||
except NameError as e:
|
||||
raise ApiError('name_error',
|
||||
f'something you are referencing does not exist:'
|
||||
f' {script}, {e.name}')
|
||||
|
||||
# else:
|
||||
# self.run_predefined_script(task, script[2:], data) # strip off the first two characters.
|
||||
|
||||
# def run_predefined_script(self, task: SpiffTask, script, data):
|
||||
# commands = shlex.split(script)
|
||||
# path_and_command = commands[0].rsplit(".", 1)
|
||||
# if len(path_and_command) == 1:
|
||||
# module_name = "crc.scripts." + self.camel_to_snake(path_and_command[0])
|
||||
# class_name = path_and_command[0]
|
||||
# else:
|
||||
# module_name = "crc.scripts." + path_and_command[0] + "." + self.camel_to_snake(path_and_command[1])
|
||||
# class_name = path_and_command[1]
|
||||
# try:
|
||||
# mod = __import__(module_name, fromlist=[class_name])
|
||||
# klass = getattr(mod, class_name)
|
||||
# study_id = task.workflow.data[WorkflowProcessor.STUDY_ID_KEY]
|
||||
# if WorkflowProcessor.WORKFLOW_ID_KEY in task.workflow.data:
|
||||
# workflow_id = task.workflow.data[WorkflowProcessor.WORKFLOW_ID_KEY]
|
||||
# else:
|
||||
# workflow_id = None
|
||||
#
|
||||
# if not isinstance(klass(), Script):
|
||||
# raise ApiError.from_task("invalid_script",
|
||||
# "This is an internal error. The script '%s:%s' you called " %
|
||||
# (module_name, class_name) +
|
||||
# "does not properly implement the CRC Script class.",
|
||||
# task=task)
|
||||
# if task.workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY]:
|
||||
# """If this is running a validation, and not a normal process, then we want to
|
||||
# mimic running the script, but not make any external calls or database changes."""
|
||||
# klass().do_task_validate_only(task, study_id, workflow_id, *commands[1:])
|
||||
# else:
|
||||
# klass().do_task(task, study_id, workflow_id, *commands[1:])
|
||||
# except ModuleNotFoundError:
|
||||
# raise ApiError.from_task("invalid_script",
|
||||
# "Unable to locate Script: '%s:%s'" % (module_name, class_name),
|
||||
# task=task)
|
||||
|
||||
def evaluate_expression(self, task, expression):
|
||||
"""
|
||||
|
@ -180,10 +188,10 @@ class WorkflowProcessor(object):
|
|||
bpmn_workflow = BpmnWorkflow(spec, script_engine=self._script_engine)
|
||||
bpmn_workflow.data[WorkflowProcessor.STUDY_ID_KEY] = workflow_model.study_id
|
||||
bpmn_workflow.data[WorkflowProcessor.VALIDATION_PROCESS_KEY] = validate_only
|
||||
try:
|
||||
bpmn_workflow.do_engine_steps()
|
||||
except WorkflowException as we:
|
||||
raise ApiError.from_task_spec("error_loading_workflow", str(we), we.sender)
|
||||
#try:
|
||||
bpmn_workflow.do_engine_steps()
|
||||
# except WorkflowException as we:
|
||||
# raise ApiError.from_task_spec("error_loading_workflow", str(we), we.sender)
|
||||
return bpmn_workflow
|
||||
|
||||
def save(self):
|
||||
|
|
|
@ -212,7 +212,8 @@
|
|||
<bpmn:scriptTask id="Activity_10nxpt2" name="Load Study Details">
|
||||
<bpmn:incoming>SequenceFlow_1r3yrhy</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_09h1imz</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:businessRuleTask id="Activity_PBMultiSiteCheckQ12" name="PB Multi-Site Check Q12" camunda:decisionRef="Decision_core_info_multi_site_q12">
|
||||
<bpmn:incoming>Flow_09h1imz</bpmn:incoming>
|
||||
|
|
|
@ -453,7 +453,7 @@ Indicate all the possible formats in which you will transmit your data outside o
|
|||
<bpmn:incoming>SequenceFlow_0k2r83n</bpmn:incoming>
|
||||
<bpmn:incoming>SequenceFlow_0t6xl9i</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_16kyite</bpmn:outgoing>
|
||||
<bpmn:script>#! CompleteTemplate NEW_DSP_template.docx Study_DataSecurityPlan</bpmn:script>
|
||||
<bpmn:script>complete_template('NEW_DSP_template.docx','Study_DataSecurityPlan')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:manualTask id="Task_0q6ir2l" name="View Instructions">
|
||||
<bpmn:documentation>##### Instructions
|
||||
|
|
|
@ -53,12 +53,13 @@
|
|||
<bpmn:scriptTask id="Activity_0a14x7j" name="Load Approvals">
|
||||
<bpmn:incoming>Flow_0c7ryff</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_142jtxs</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo approvals</bpmn:script>
|
||||
<bpmn:script>StudyInfo['approvals'] = study_info('approvals')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:scriptTask id="Activity_1aju60t" name="Load Documents">
|
||||
<bpmn:incoming>Flow_1k3su2q</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0c7ryff</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo documents</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['documents'] = study_info('documents')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_142jtxs" sourceRef="Activity_0a14x7j" targetRef="Activity_DisplayDocsAndApprovals" />
|
||||
<bpmn:sequenceFlow id="Flow_0c7ryff" sourceRef="Activity_1aju60t" targetRef="Activity_0a14x7j" />
|
||||
|
|
|
@ -36,7 +36,8 @@
|
|||
<bpmn:scriptTask id="ScriptTask_1fn00ox" name="Load IRB Details">
|
||||
<bpmn:incoming>SequenceFlow_1dhb8f4</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1uzcl1f</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1uzcl1f" sourceRef="ScriptTask_1fn00ox" targetRef="Task_SupplementIDE" />
|
||||
<bpmn:exclusiveGateway id="ExclusiveGateway_1fib89p" name="IS_IDE = True and Number Provided? ">
|
||||
|
|
|
@ -217,7 +217,8 @@ Protocol Owner: **(need to insert value here)**</bpmn:documentation>
|
|||
<bpmn:scriptTask id="Activity_LoadDocuments" name="Load Documents">
|
||||
<bpmn:incoming>SequenceFlow_1dexemq</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1x9d2mo</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo documents</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['documents'] = study_info('documents')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
<bpmn:scriptTask id="ScriptTask_LoadIRBDetails" name="Load IRB Details">
|
||||
<bpmn:incoming>SequenceFlow_1dhb8f4</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1uzcl1f</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1uzcl1f" sourceRef="ScriptTask_LoadIRBDetails" targetRef="Task_SupplementIDE" />
|
||||
<bpmn:businessRuleTask id="Task_SupplementIDE" name="Current IND Status" camunda:decisionRef="decision_ind_check">
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
<bpmn:scriptTask id="ScriptTask_02924vs" name="Load IRB Details">
|
||||
<bpmn:incoming>SequenceFlow_1fmyo77</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_18nr0gf</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1fmyo77" sourceRef="StartEvent_1" targetRef="ScriptTask_02924vs" />
|
||||
<bpmn:sequenceFlow id="SequenceFlow_18nr0gf" sourceRef="ScriptTask_02924vs" targetRef="Activity_FromIRB-API" />
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
<bpmn:scriptTask id="ScriptTask_LoadPersonnel" name="Load IRB Personnel">
|
||||
<bpmn:incoming>Flow_0kcrx5l</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1dcsioh</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo investigators</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:endEvent id="EndEvent_1qor16n">
|
||||
<bpmn:documentation>## The following information was gathered:
|
||||
|
|
|
@ -598,7 +598,7 @@ Use the EHS [Lab Safety Plan During COVID 19 template](https://www.google.com/ur
|
|||
This step is internal to the system and do not require and user interaction</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_11uqavk</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0aqgwvu</bpmn:outgoing>
|
||||
<bpmn:script>#! CompleteTemplate ResearchRampUpPlan.docx RESEARCH_RAMPUP</bpmn:script>
|
||||
<bpmn:script>complete_template('ResearchRampUpPlan.docx','RESEARCH_RAMPUP')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_0aqgwvu" sourceRef="Activity_GenerateRRP" targetRef="Activity_AcknowledgePlanReview" />
|
||||
<bpmn:sequenceFlow id="Flow_0j4rs82" sourceRef="Activity_SubmitPlan" targetRef="Activity_0absozl" />
|
||||
|
@ -755,7 +755,7 @@ Notify the Area Monitor for
|
|||
This step is internal to the system and do not require and user interaction</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_0j4rs82</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_07ge8uf</bpmn:outgoing>
|
||||
<bpmn:script>#!RequestApproval ApprvlApprvr1 ApprvlApprvr2</bpmn:script>
|
||||
<bpmn:script>request_approval('ApprvlApprvr1','ApprvlApprvr2')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:scriptTask id="Activity_1u58hox" name="Update Request">
|
||||
<bpmn:documentation>#### Script Task
|
||||
|
@ -764,7 +764,7 @@ This step is internal to the system and do not require and user interaction</bpm
|
|||
This step is internal to the system and do not require and user interaction</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_16y8glw</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0uc4o6c</bpmn:outgoing>
|
||||
<bpmn:script>#! UpdateStudy title:PIComputingID.label pi:PIComputingID.value</bpmn:script>
|
||||
<bpmn:script>update_study('title:PIComputingID.label','pi:PIComputingID.value')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:userTask id="PersonnelSchedule" name="Upload Weekly Personnel Schedule(s)" camunda:formKey="Personnel Weekly Schedule">
|
||||
<bpmn:documentation>#### Weekly Personnel Schedule(s)
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
<bpmn:scriptTask id="Task_Load_Requirements" name="Load Documents From PB">
|
||||
<bpmn:incoming>SequenceFlow_1ees8ka</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_17ct47v</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo documents</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['documents'] = study_info('documents')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:businessRuleTask id="Activity_1yqy50i" name="Enter Core Info " camunda:decisionRef="enter_core_info">
|
||||
<bpmn:incoming>Flow_1m8285h</bpmn:incoming>
|
||||
|
@ -62,7 +63,8 @@
|
|||
<bpmn:scriptTask id="Activity_0f295la" name="Load Details from PB">
|
||||
<bpmn:incoming>Flow_0pwtiqm</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0eq6px2</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo details</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['details'] = study_info('details')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:businessRuleTask id="Activity_0ahlc3u" name="IDE Supplement" camunda:decisionRef="decision_ide_menu_check">
|
||||
<bpmn:incoming>Flow_14ce1d7</bpmn:incoming>
|
||||
|
@ -91,7 +93,8 @@
|
|||
<bpmn:scriptTask id="Activity_0g3qa1c" name="Load Personnel from PB">
|
||||
<bpmn:incoming>Flow_1qyrmzn</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0vo6ul1</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo investigators</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_1ybicki" sourceRef="Activity_13ep6ar" targetRef="Event_135x8jg" />
|
||||
<bpmn:businessRuleTask id="Activity_13ep6ar" name="Personnel" camunda:decisionRef="personnel">
|
||||
|
|
|
@ -251,7 +251,6 @@ class ExampleDataLoader:
|
|||
master_spec=False,
|
||||
from_tests=True)
|
||||
|
||||
|
||||
def create_spec(self, id, name, display_name="", description="", filepath=None, master_spec=False,
|
||||
category_id=None, display_order=None, from_tests=False):
|
||||
"""Assumes that a directory exists in static/bpmn with the same name as the given id.
|
||||
|
|
|
@ -19,7 +19,7 @@ from crc.models.protocol_builder import ProtocolBuilderStatus
|
|||
from crc.models.task_event import TaskEventModel
|
||||
from crc.models.study import StudyModel
|
||||
from crc.models.user import UserModel
|
||||
from crc.models.workflow import WorkflowSpecModel, WorkflowSpecModelSchema, WorkflowModel
|
||||
from crc.models.workflow import WorkflowSpecModel, WorkflowSpecModelSchema, WorkflowModel, WorkflowSpecCategoryModel
|
||||
from crc.services.file_service import FileService
|
||||
from crc.services.study_service import StudyService
|
||||
from crc.services.workflow_service import WorkflowService
|
||||
|
@ -164,14 +164,21 @@ class BaseTest(unittest.TestCase):
|
|||
self.assertGreater(len(file_data), 0)
|
||||
|
||||
@staticmethod
|
||||
def load_test_spec(dir_name, master_spec=False, category_id=None):
|
||||
def load_test_spec(dir_name, display_name=None, master_spec=False, category_id=None):
|
||||
"""Loads a spec into the database based on a directory in /tests/data"""
|
||||
if category_id is None:
|
||||
category = WorkflowSpecCategoryModel(name="test", display_name="Test Workflows", display_order=0)
|
||||
db.session.add(category)
|
||||
db.session.commit()
|
||||
category_id = category.id
|
||||
|
||||
if session.query(WorkflowSpecModel).filter_by(id=dir_name).count() > 0:
|
||||
return session.query(WorkflowSpecModel).filter_by(id=dir_name).first()
|
||||
filepath = os.path.join(app.root_path, '..', 'tests', 'data', dir_name, "*")
|
||||
if display_name is None:
|
||||
display_name = dir_name
|
||||
return ExampleDataLoader().create_spec(id=dir_name, name=dir_name, filepath=filepath, master_spec=master_spec,
|
||||
category_id=category_id)
|
||||
display_name=display_name, category_id=category_id)
|
||||
|
||||
@staticmethod
|
||||
def protocol_builder_response(file_name):
|
||||
|
@ -263,11 +270,13 @@ class BaseTest(unittest.TestCase):
|
|||
|
||||
return full_study
|
||||
|
||||
def create_workflow(self, workflow_name, study=None, category_id=None, as_user="dhf8r"):
|
||||
def create_workflow(self, workflow_name, display_name=None, study=None, category_id=None, as_user="dhf8r"):
|
||||
db.session.flush()
|
||||
spec = db.session.query(WorkflowSpecModel).filter(WorkflowSpecModel.name == workflow_name).first()
|
||||
if spec is None:
|
||||
spec = self.load_test_spec(workflow_name, category_id=category_id)
|
||||
if display_name is None:
|
||||
display_name = workflow_name
|
||||
spec = self.load_test_spec(workflow_name, display_name, category_id=category_id)
|
||||
if study is None:
|
||||
study = self.create_study(uid=as_user)
|
||||
workflow_model = StudyService._create_workflow_model(study, spec)
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>SequenceFlow_1i7hk1a</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_11c35oq</bpmn:outgoing>
|
||||
<bpmn:script>#! CompleteTemplate Letter.docx AD_CoCApp</bpmn:script>
|
||||
<bpmn:script>complete_template('Letter.docx','AD_CoCApp')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:endEvent id="EndEvent_0evb22x">
|
||||
<bpmn:incoming>SequenceFlow_11c35oq</bpmn:incoming>
|
||||
|
|
|
@ -20,7 +20,7 @@ Email content to be delivered to {{ ApprvlApprvr1 }}
|
|||
---</bpmn:documentation>
|
||||
<bpmn:incoming>Flow_08n2npe</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1xlrgne</bpmn:outgoing>
|
||||
<bpmn:script>#! Email "Camunda Email Subject" ApprvlApprvr1 PIComputingID</bpmn:script>
|
||||
<bpmn:script>email("Camunda Email Subject",'ApprvlApprvr1','PIComputingID')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_1synsig" sourceRef="StartEvent_1" targetRef="Activity_1l9vih3" />
|
||||
<bpmn:sequenceFlow id="Flow_1xlrgne" sourceRef="Activity_0s5v97n" targetRef="Event_0izrcj4" />
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<bpmn:scriptTask id="Invalid_Script_Task" name="An Invalid Script Reference">
|
||||
<bpmn:incoming>SequenceFlow_1pnq3kg</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_12pf6um</bpmn:outgoing>
|
||||
<bpmn:script>#! NoSuchScript withArg1</bpmn:script>
|
||||
<bpmn:script>no_such_script('withArg1')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_12pf6um" sourceRef="Invalid_Script_Task" targetRef="EndEvent_063bpg6" />
|
||||
</bpmn:process>
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
<?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:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="Definitions_0y2dq4f" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="3.7.3">
|
||||
<bpmn:process id="Process_0tad5ma" name="Set Recipients" isExecutable="true">
|
||||
<bpmn:startEvent id="StartEvent_1">
|
||||
<bpmn:outgoing>Flow_1synsig</bpmn:outgoing>
|
||||
</bpmn:startEvent>
|
||||
<bpmn:endEvent id="Event_0izrcj4">
|
||||
<bpmn:incoming>Flow_11e7jgz</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:scriptTask id="Activity_0s5v97n" name="Ldap Replace">
|
||||
<bpmn:incoming>Flow_08n2npe</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_1xlrgne</bpmn:outgoing>
|
||||
<bpmn:script>Supervisor = ldap(Supervisor)
|
||||
Investigator = ldap(Investigator)</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="Flow_1synsig" sourceRef="StartEvent_1" targetRef="Activity_1l9vih3" />
|
||||
<bpmn:sequenceFlow id="Flow_1xlrgne" sourceRef="Activity_0s5v97n" targetRef="Activity_0f78ek5" />
|
||||
<bpmn:sequenceFlow id="Flow_08n2npe" sourceRef="Activity_1l9vih3" targetRef="Activity_0s5v97n" />
|
||||
<bpmn:userTask id="Activity_1l9vih3" name="Set UIDs">
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
<camunda:formField id="Supervisor" label="Approver" type="string" />
|
||||
<camunda:formField id="Investigator" label="Primary Investigator" type="string" />
|
||||
</camunda:formData>
|
||||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>Flow_1synsig</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_08n2npe</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
<bpmn:sequenceFlow id="Flow_11e7jgz" sourceRef="Activity_0f78ek5" targetRef="Event_0izrcj4" />
|
||||
<bpmn:userTask id="Activity_0f78ek5" name="Read UIDs">
|
||||
<bpmn:incoming>Flow_1xlrgne</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_11e7jgz</bpmn:outgoing>
|
||||
</bpmn:userTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0tad5ma">
|
||||
<bpmndi:BPMNEdge id="Flow_11e7jgz_di" bpmnElement="Flow_11e7jgz">
|
||||
<di:waypoint x="720" y="117" />
|
||||
<di:waypoint x="802" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_08n2npe_di" bpmnElement="Flow_08n2npe">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="450" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1xlrgne_di" bpmnElement="Flow_1xlrgne">
|
||||
<di:waypoint x="550" y="117" />
|
||||
<di:waypoint x="620" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNEdge id="Flow_1synsig_di" bpmnElement="Flow_1synsig">
|
||||
<di:waypoint x="215" y="117" />
|
||||
<di:waypoint x="270" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
|
||||
<dc:Bounds x="179" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Event_0izrcj4_di" bpmnElement="Event_0izrcj4">
|
||||
<dc:Bounds x="802" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_04imfm6_di" bpmnElement="Activity_0s5v97n">
|
||||
<dc:Bounds x="450" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_0xugr62_di" bpmnElement="Activity_1l9vih3">
|
||||
<dc:Bounds x="270" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNShape id="Activity_17h05g6_di" bpmnElement="Activity_0f78ek5">
|
||||
<dc:Bounds x="620" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
</bpmn:definitions>
|
|
@ -29,7 +29,8 @@
|
|||
<bpmn:scriptTask id="Task_1v0e2zu" name="Load Personnel">
|
||||
<bpmn:incoming>Flow_0t6p1sb</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1p568pp</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo investigators</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<bpmn:sequenceFlow id="Flow_0ugjw69" sourceRef="MultiInstanceTask" targetRef="Event_End" />
|
||||
<bpmn:userTask id="MultiInstanceTask" name="Gather more information" camunda:formKey="GetEmail">
|
||||
<bpmn:documentation># Please provide addtional information about:
|
||||
## Investigator ID: {{investigator.user_id}}
|
||||
## Investigator ID: {{investigator.user_id}}
|
||||
## Role: {{investigator.type_full}}</bpmn:documentation>
|
||||
<bpmn:extensionElements>
|
||||
<camunda:formData>
|
||||
|
@ -29,7 +29,8 @@
|
|||
<bpmn:scriptTask id="Task_1v0e2zu" name="Load Personnel">
|
||||
<bpmn:incoming>Flow_0t6p1sb</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1p568pp</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo investigators</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['investigators'] = study_info('investigators')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
|
|
|
@ -132,7 +132,7 @@ Autoconverted link https://github.com/nodeca/pica (enable linkify to see)
|
|||
</bpmn:extensionElements>
|
||||
<bpmn:incoming>SequenceFlow_0641sh6</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_0t29gjo</bpmn:outgoing>
|
||||
<bpmn:script>#! FactService</bpmn:script>
|
||||
<bpmn:script>FactService = fact_service()</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:endEvent id="EndEvent_0u1cgrf">
|
||||
<bpmn:documentation># Great Job!
|
||||
|
|
|
@ -8,12 +8,19 @@
|
|||
<bpmn:scriptTask id="Task_Script_Load_Study_Details" name="Load Study Info">
|
||||
<bpmn:incoming>SequenceFlow_1nfe5m9</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_1bqiin0</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo info</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['info'] = study_info('info')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1bqiin0" sourceRef="Task_Script_Load_Study_Details" targetRef="EndEvent_171dj09" />
|
||||
<bpmn:sequenceFlow id="SequenceFlow_1bqiin0" sourceRef="Task_Script_Load_Study_Details" targetRef="Activity_0w91u9s" />
|
||||
<bpmn:endEvent id="EndEvent_171dj09">
|
||||
<bpmn:incoming>SequenceFlow_1bqiin0</bpmn:incoming>
|
||||
<bpmn:incoming>Flow_0ochvmi</bpmn:incoming>
|
||||
</bpmn:endEvent>
|
||||
<bpmn:sequenceFlow id="Flow_0ochvmi" sourceRef="Activity_0w91u9s" targetRef="EndEvent_171dj09" />
|
||||
<bpmn:scriptTask id="Activity_0w91u9s" name="StudyInfo as Script">
|
||||
<bpmn:incoming>SequenceFlow_1bqiin0</bpmn:incoming>
|
||||
<bpmn:outgoing>Flow_0ochvmi</bpmn:outgoing>
|
||||
<bpmn:script>study = study_info('info','p')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
</bpmn:process>
|
||||
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
||||
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_0exnnpv">
|
||||
|
@ -29,10 +36,17 @@
|
|||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="SequenceFlow_1bqiin0_di" bpmnElement="SequenceFlow_1bqiin0">
|
||||
<di:waypoint x="370" y="117" />
|
||||
<di:waypoint x="402" y="117" />
|
||||
<di:waypoint x="430" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="EndEvent_171dj09_di" bpmnElement="EndEvent_171dj09">
|
||||
<dc:Bounds x="402" y="99" width="36" height="36" />
|
||||
<dc:Bounds x="622" y="99" width="36" height="36" />
|
||||
</bpmndi:BPMNShape>
|
||||
<bpmndi:BPMNEdge id="Flow_0ochvmi_di" bpmnElement="Flow_0ochvmi">
|
||||
<di:waypoint x="530" y="117" />
|
||||
<di:waypoint x="622" y="117" />
|
||||
</bpmndi:BPMNEdge>
|
||||
<bpmndi:BPMNShape id="Activity_1wtk4bb_di" bpmnElement="Activity_0w91u9s">
|
||||
<dc:Bounds x="430" y="77" width="100" height="80" />
|
||||
</bpmndi:BPMNShape>
|
||||
</bpmndi:BPMNPlane>
|
||||
</bpmndi:BPMNDiagram>
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
<bpmn:scriptTask id="Task_Load_Requirements" name="Load Required Documents From PM">
|
||||
<bpmn:incoming>SequenceFlow_1ees8ka</bpmn:incoming>
|
||||
<bpmn:outgoing>SequenceFlow_17ct47v</bpmn:outgoing>
|
||||
<bpmn:script>#! StudyInfo documents</bpmn:script>
|
||||
<bpmn:script>StudyInfo = {}
|
||||
StudyInfo['documents'] = study_info('documents')</bpmn:script>
|
||||
</bpmn:scriptTask>
|
||||
<bpmn:businessRuleTask id="Activity_1yqy50i" name="Enter Core Info " camunda:decisionRef="enter_core_info">
|
||||
<bpmn:incoming>Flow_1m8285h</bpmn:incoming>
|
||||
|
|
|
@ -1,9 +1,45 @@
|
|||
from github import UnknownObjectException
|
||||
from sqlalchemy import desc
|
||||
from tests.base_test import BaseTest
|
||||
from unittest.mock import patch, Mock
|
||||
|
||||
from crc import db
|
||||
from crc.models.file import FileDataModel
|
||||
from crc.services.file_service import FileService
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
|
||||
|
||||
class FakeGithubCreates(Mock):
|
||||
def get_user(var):
|
||||
class FakeUser(Mock):
|
||||
def get_repo(var, name):
|
||||
class FakeRepo(Mock):
|
||||
def get_contents(var, filename):
|
||||
raise UnknownObjectException(status='Failure', data='Failed data')
|
||||
def update_file(var, path, message, content, sha):
|
||||
pass
|
||||
return FakeRepo()
|
||||
return FakeUser()
|
||||
|
||||
|
||||
class FakeGithub(Mock):
|
||||
def get_user(var):
|
||||
class FakeUser(Mock):
|
||||
def get_repo(var, name):
|
||||
class FakeRepo(Mock):
|
||||
def get_contents(var, filename):
|
||||
fake_file = Mock()
|
||||
fake_file.decoded_content = b'Some bytes'
|
||||
fake_file.path = '/el/path/'
|
||||
fake_file.data = 'Serious data'
|
||||
fake_file.sha = 'Sha'
|
||||
return fake_file
|
||||
def update_file(var, path, message, content, sha):
|
||||
pass
|
||||
return FakeRepo()
|
||||
return FakeUser()
|
||||
|
||||
|
||||
class TestFileService(BaseTest):
|
||||
"""Largely tested via the test_file_api, and time is tight, but adding new tests here."""
|
||||
|
||||
|
@ -103,3 +139,62 @@ class TestFileService(BaseTest):
|
|||
binary_data=b'5678')
|
||||
file_models = FileService.get_workflow_files(workflow_id=workflow.id)
|
||||
self.assertEqual(2, len(file_models))
|
||||
|
||||
@patch('crc.services.file_service.Github')
|
||||
def test_update_from_github(self, mock_github):
|
||||
mock_github.return_value = FakeGithub()
|
||||
|
||||
self.load_example_data()
|
||||
self.create_reference_document()
|
||||
workflow = self.create_workflow('file_upload_form')
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
irb_code = "UVACompl_PRCAppr" # The first file referenced in pb required docs.
|
||||
file_model = FileService.add_workflow_file(workflow_id=workflow.id,
|
||||
irb_doc_code=irb_code,
|
||||
name="anything.png", content_type="text",
|
||||
binary_data=b'1234')
|
||||
FileService.update_from_github([file_model.id])
|
||||
|
||||
file_model_data = FileDataModel.query.filter_by(
|
||||
file_model_id=file_model.id
|
||||
).order_by(
|
||||
desc(FileDataModel.version)
|
||||
).first()
|
||||
self.assertEqual(file_model_data.data, b'Some bytes')
|
||||
|
||||
@patch('crc.services.file_service.Github')
|
||||
def test_publish_to_github_creates(self, mock_github):
|
||||
mock_github.return_value = FakeGithubCreates()
|
||||
|
||||
self.load_example_data()
|
||||
self.create_reference_document()
|
||||
workflow = self.create_workflow('file_upload_form')
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
irb_code = "UVACompl_PRCAppr" # The first file referenced in pb required docs.
|
||||
file_model = FileService.add_workflow_file(workflow_id=workflow.id,
|
||||
irb_doc_code=irb_code,
|
||||
name="anything.png", content_type="text",
|
||||
binary_data=b'1234')
|
||||
result = FileService.publish_to_github([file_model.id])
|
||||
|
||||
self.assertEqual(result['created'], True)
|
||||
|
||||
@patch('crc.services.file_service.Github')
|
||||
def test_publish_to_github_updates(self, mock_github):
|
||||
mock_github.return_value = FakeGithub()
|
||||
|
||||
self.load_example_data()
|
||||
self.create_reference_document()
|
||||
workflow = self.create_workflow('file_upload_form')
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
irb_code = "UVACompl_PRCAppr" # The first file referenced in pb required docs.
|
||||
file_model = FileService.add_workflow_file(workflow_id=workflow.id,
|
||||
irb_doc_code=irb_code,
|
||||
name="anything.png", content_type="text",
|
||||
binary_data=b'1234')
|
||||
result = FileService.publish_to_github([file_model.id])
|
||||
|
||||
self.assertEqual(result['updated'], True)
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
from tests.base_test import BaseTest
|
||||
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
from crc.scripts.ldap import Ldap
|
||||
from crc.api.common import ApiError
|
||||
from crc import db, mail
|
||||
|
||||
|
||||
class TestLdapLookupScript(BaseTest):
|
||||
|
||||
def test_get_existing_user_details(self):
|
||||
self.load_example_data()
|
||||
self.create_reference_document()
|
||||
workflow = self.create_workflow('empty_workflow')
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
|
||||
script = Ldap()
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "dhf8r")
|
||||
|
||||
self.assertEqual(user_details['display_name'], 'Dan Funk')
|
||||
self.assertEqual(user_details['given_name'], 'Dan')
|
||||
self.assertEqual(user_details['email_address'], 'dhf8r@virginia.edu')
|
||||
self.assertEqual(user_details['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(user_details['title'], 'E42:He\'s a hoopy frood')
|
||||
self.assertEqual(user_details['department'], 'E0:EN-Eng Study of Parallel Universes')
|
||||
self.assertEqual(user_details['affiliation'], 'faculty')
|
||||
self.assertEqual(user_details['sponsor_type'], 'Staff')
|
||||
self.assertEqual(user_details['uid'], 'dhf8r')
|
||||
self.assertEqual(user_details['proper_name'], 'Dan Funk - (dhf8r)')
|
||||
|
||||
def test_get_invalid_user_details(self):
|
||||
self.load_example_data()
|
||||
self.create_reference_document()
|
||||
workflow = self.create_workflow('empty_workflow')
|
||||
processor = WorkflowProcessor(workflow)
|
||||
task = processor.next_task()
|
||||
|
||||
task.data = {
|
||||
'PIComputingID': 'rec3z'
|
||||
}
|
||||
|
||||
script = Ldap()
|
||||
with(self.assertRaises(ApiError)):
|
||||
user_details = script.do_task(task, workflow.study_id, workflow.id, "PIComputingID")
|
||||
|
||||
|
||||
def test_bpmn_task_receives_user_details(self):
|
||||
workflow = self.create_workflow('ldap_replace')
|
||||
|
||||
task_data = {
|
||||
'Supervisor': 'dhf8r',
|
||||
'Investigator': 'lb3dp'
|
||||
}
|
||||
task = self.get_workflow_api(workflow).next_task
|
||||
|
||||
self.complete_form(workflow, task, task_data)
|
||||
|
||||
task = self.get_workflow_api(workflow).next_task
|
||||
|
||||
self.assertEqual(task.data['Supervisor']['display_name'], 'Dan Funk')
|
||||
self.assertEqual(task.data['Supervisor']['given_name'], 'Dan')
|
||||
self.assertEqual(task.data['Supervisor']['email_address'], 'dhf8r@virginia.edu')
|
||||
self.assertEqual(task.data['Supervisor']['telephone_number'], '+1 (434) 924-1723')
|
||||
self.assertEqual(task.data['Supervisor']['title'], 'E42:He\'s a hoopy frood')
|
||||
self.assertEqual(task.data['Supervisor']['department'], 'E0:EN-Eng Study of Parallel Universes')
|
||||
self.assertEqual(task.data['Supervisor']['affiliation'], 'faculty')
|
||||
self.assertEqual(task.data['Supervisor']['sponsor_type'], 'Staff')
|
||||
self.assertEqual(task.data['Supervisor']['uid'], 'dhf8r')
|
||||
self.assertEqual(task.data['Supervisor']['proper_name'], 'Dan Funk - (dhf8r)')
|
|
@ -27,7 +27,10 @@ class TestStudyService(BaseTest):
|
|||
|
||||
# Assure some basic models are in place, This is a damn mess. Our database models need an overhaul to make
|
||||
# this easier - better relationship modeling is now critical.
|
||||
self.load_test_spec("top_level_workflow", master_spec=True)
|
||||
cat = WorkflowSpecCategoryModel(name="approvals", display_name="Approvals", display_order=0)
|
||||
db.session.add(cat)
|
||||
db.session.commit()
|
||||
self.load_test_spec("top_level_workflow", master_spec=True, category_id=cat.id)
|
||||
user = db.session.query(UserModel).filter(UserModel.uid == "dhf8r").first()
|
||||
if not user:
|
||||
user = UserModel(uid="dhf8r", email_address="whatever@stuff.com", display_name="Stayathome Smellalots")
|
||||
|
@ -39,11 +42,7 @@ class TestStudyService(BaseTest):
|
|||
|
||||
study = StudyModel(title="My title", protocol_builder_status=ProtocolBuilderStatus.ACTIVE, user_uid=user.uid)
|
||||
db.session.add(study)
|
||||
cat = WorkflowSpecCategoryModel(name="approvals", display_name="Approvals", display_order=0)
|
||||
db.session.add(cat)
|
||||
db.session.commit()
|
||||
|
||||
self.assertIsNotNone(cat.id)
|
||||
self.load_test_spec("random_fact", category_id=cat.id)
|
||||
|
||||
self.assertIsNotNone(study.id)
|
||||
|
|
|
@ -30,4 +30,4 @@ class TestLdapService(BaseTest):
|
|||
user_info = LdapService.user_info("nosuch")
|
||||
self.assertFalse(True, "An API error should be raised.")
|
||||
except ApiError as ae:
|
||||
self.assertEqual("missing_ldap_record", ae.code)
|
||||
self.assertEqual("missing_ldap_record", ae.code)
|
||||
|
|
|
@ -68,7 +68,7 @@ class TestTasksApi(BaseTest):
|
|||
def test_get_outstanding_tasks_awaiting_current_user(self):
|
||||
submitter = self.create_user(uid='lje5u')
|
||||
supervisor = self.create_user(uid='lb3dp')
|
||||
workflow = self.create_workflow('roles', as_user=submitter.uid)
|
||||
workflow = self.create_workflow('roles', display_name="Roles", as_user=submitter.uid)
|
||||
workflow_api = self.get_workflow_api(workflow, user_uid=submitter.uid)
|
||||
|
||||
# User lje5u can complete the first task, and set her supervisor
|
||||
|
@ -94,6 +94,7 @@ class TestTasksApi(BaseTest):
|
|||
self.assertEquals(1, len(tasks))
|
||||
self.assertEquals(workflow.id, tasks[0]['workflow']['id'])
|
||||
self.assertEquals(workflow.study.id, tasks[0]['study']['id'])
|
||||
self.assertEquals("Test Workflows", tasks[0]['workflow']['category_display_name'])
|
||||
|
||||
# Assure we can say something sensible like:
|
||||
# You have a task called "Approval" to be completed in the "Supervisor Approval" workflow
|
||||
|
@ -178,7 +179,7 @@ class TestTasksApi(BaseTest):
|
|||
workflow_api = self.complete_form(workflow, workflow_api.next_task, data, user_uid=submitter.uid)
|
||||
nav = workflow_api.navigation
|
||||
self.assertEquals(5, len(nav))
|
||||
self.assertEquals('COMPLETED', nav[0]['state']) # We still have some issues here, the navigation will be off when looping back.
|
||||
self.assertEquals('READY', nav[0]['state']) # When you loop back the task is again in the ready state.
|
||||
self.assertEquals('LOCKED', nav[1]['state']) # Second item is locked, it is the review and doesn't belong to this user.
|
||||
self.assertEquals('LOCKED', nav[2]['state']) # third item is a gateway belonging to the supervisor, and is locked.
|
||||
self.assertEquals('READY', workflow_api.next_task.state)
|
||||
|
|
|
@ -89,8 +89,8 @@ class TestWorkflowSpecValidation(BaseTest):
|
|||
self.load_example_data()
|
||||
errors = self.validate_workflow("invalid_script")
|
||||
self.assertEqual(2, len(errors))
|
||||
self.assertEqual("error_loading_workflow", errors[0]['code'])
|
||||
self.assertTrue("NoSuchScript" in errors[0]['message'])
|
||||
self.assertEqual("workflow_validation_exception", errors[0]['code'])
|
||||
#self.assertTrue("NoSuchScript" in errors[0]['message'])
|
||||
self.assertEqual("Invalid_Script_Task", errors[0]['task_id'])
|
||||
self.assertEqual("An Invalid Script Reference", errors[0]['task_name'])
|
||||
self.assertEqual("invalid_script.bpmn", errors[0]['file_name'])
|
||||
|
@ -99,7 +99,7 @@ class TestWorkflowSpecValidation(BaseTest):
|
|||
self.load_example_data()
|
||||
errors = self.validate_workflow("invalid_script2")
|
||||
self.assertEqual(2, len(errors))
|
||||
self.assertEqual("error_loading_workflow", errors[0]['code'])
|
||||
self.assertEqual("workflow_validation_exception", errors[0]['code'])
|
||||
self.assertEqual("Invalid_Script_Task", errors[0]['task_id'])
|
||||
self.assertEqual("An Invalid Script Reference", errors[0]['task_name'])
|
||||
self.assertEqual("invalid_script2.bpmn", errors[0]['file_name'])
|
||||
|
|
Loading…
Reference in New Issue