diff --git a/Pipfile b/Pipfile index 0a498025..d6bed100 100644 --- a/Pipfile +++ b/Pipfile @@ -48,5 +48,6 @@ pygithub = "*" python-box = "*" python-levenshtein = "*" + [requires] python_version = "3.8" diff --git a/Pipfile.lock b/Pipfile.lock index d411e473..2788ee2e 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -30,6 +30,14 @@ "index": "pypi", "version": "==1.5.4" }, + "amqp": { + "hashes": [ + "sha256:1e759a7f202d910939de6eca45c23a107f6b71111f41d1282c648e9ac3d21901", + "sha256:affdd263d8b8eb3c98170b78bf83867cdb6a14901d586e00ddb65bfe2f0c4e60" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.5" + }, "aniso8601": { "hashes": [ "sha256:be08b19c19ca527af722f2d4ba4dc569db292ec96f7de963746df4bb0bff9250", @@ -42,6 +50,7 @@ "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.3.0" }, "babel": { @@ -49,6 +58,7 @@ "sha256:9d35c22fcc79893c3ecc85ac4a56cde1ecf3f19c540bba0922308a6c06ca6fa5", "sha256:da031ab54472314f210b0adcff1588ee5d1d1d0ba4dbd07b94dba82bde791e05" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.9.0" }, "bcrypt": { @@ -61,6 +71,7 @@ "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1", "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d" ], + "markers": "python_version >= '3.6'", "version": "==3.2.0" }, "beautifulsoup4": { @@ -71,12 +82,27 @@ ], "version": "==4.9.3" }, + "billiard": { + "hashes": [ + "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede", + "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a" + ], + "version": "==3.6.3.0" + }, "blinker": { "hashes": [ "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6" ], "version": "==1.4" }, + "celery": { + "hashes": [ + "sha256:5e8d364e058554e83bbb116e8377d90c79be254785f357cb2cec026e79febe13", + "sha256:f4efebe6f8629b0da2b8e529424de376494f5b7a743c321c8a2ddc2b1414921c" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.5" + }, "certifi": { "hashes": [ "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", @@ -86,51 +112,52 @@ }, "cffi": { "hashes": [ - "sha256:00a1ba5e2e95684448de9b89888ccd02c98d512064b4cb987d48f4b40aa0421e", - "sha256:00e28066507bfc3fe865a31f325c8391a1ac2916219340f87dfad602c3e48e5d", - "sha256:045d792900a75e8b1e1b0ab6787dd733a8190ffcf80e8c8ceb2fb10a29ff238a", - "sha256:0638c3ae1a0edfb77c6765d487fee624d2b1ee1bdfeffc1f0b58c64d149e7eec", - "sha256:105abaf8a6075dc96c1fe5ae7aae073f4696f2905fde6aeada4c9d2926752362", - "sha256:155136b51fd733fa94e1c2ea5211dcd4c8879869008fc811648f16541bf99668", - "sha256:1a465cbe98a7fd391d47dce4b8f7e5b921e6cd805ef421d04f5f66ba8f06086c", - "sha256:1d2c4994f515e5b485fd6d3a73d05526aa0fcf248eb135996b088d25dfa1865b", - "sha256:2c24d61263f511551f740d1a065eb0212db1dbbbbd241db758f5244281590c06", - "sha256:51a8b381b16ddd370178a65360ebe15fbc1c71cf6f584613a7ea08bfad946698", - "sha256:594234691ac0e9b770aee9fcdb8fa02c22e43e5c619456efd0d6c2bf276f3eb2", - "sha256:5cf4be6c304ad0b6602f5c4e90e2f59b47653ac1ed9c662ed379fe48a8f26b0c", - "sha256:64081b3f8f6f3c3de6191ec89d7dc6c86a8a43911f7ecb422c60e90c70be41c7", - "sha256:6bc25fc545a6b3d57b5f8618e59fc13d3a3a68431e8ca5fd4c13241cd70d0009", - "sha256:798caa2a2384b1cbe8a2a139d80734c9db54f9cc155c99d7cc92441a23871c03", - "sha256:7c6b1dece89874d9541fc974917b631406233ea0440d0bdfbb8e03bf39a49b3b", - "sha256:7ef7d4ced6b325e92eb4d3502946c78c5367bc416398d387b39591532536734e", - "sha256:840793c68105fe031f34d6a086eaea153a0cd5c491cde82a74b420edd0a2b909", - "sha256:8d6603078baf4e11edc4168a514c5ce5b3ba6e3e9c374298cb88437957960a53", - "sha256:9cc46bc107224ff5b6d04369e7c595acb700c3613ad7bcf2e2012f62ece80c35", - "sha256:9f7a31251289b2ab6d4012f6e83e58bc3b96bd151f5b5262467f4bb6b34a7c26", - "sha256:9ffb888f19d54a4d4dfd4b3f29bc2c16aa4972f1c2ab9c4ab09b8ab8685b9c2b", - "sha256:a5ed8c05548b54b998b9498753fb9cadbfd92ee88e884641377d8a8b291bcc01", - "sha256:a7711edca4dcef1a75257b50a2fbfe92a65187c47dab5a0f1b9b332c5919a3fb", - "sha256:af5c59122a011049aad5dd87424b8e65a80e4a6477419c0c1015f73fb5ea0293", - "sha256:b18e0a9ef57d2b41f5c68beefa32317d286c3d6ac0484efd10d6e07491bb95dd", - "sha256:b4e248d1087abf9f4c10f3c398896c87ce82a9856494a7155823eb45a892395d", - "sha256:ba4e9e0ae13fc41c6b23299545e5ef73055213e466bd107953e4a013a5ddd7e3", - "sha256:c6332685306b6417a91b1ff9fae889b3ba65c2292d64bd9245c093b1b284809d", - "sha256:d5ff0621c88ce83a28a10d2ce719b2ee85635e85c515f12bac99a95306da4b2e", - "sha256:d9efd8b7a3ef378dd61a1e77367f1924375befc2eba06168b6ebfa903a5e59ca", - "sha256:df5169c4396adc04f9b0a05f13c074df878b6052430e03f50e68adf3a57aa28d", - "sha256:ebb253464a5d0482b191274f1c8bf00e33f7e0b9c66405fbffc61ed2c839c775", - "sha256:ec80dc47f54e6e9a78181ce05feb71a0353854cc26999db963695f950b5fb375", - "sha256:f032b34669220030f905152045dfa27741ce1a6db3324a5bc0b96b6c7420c87b", - "sha256:f60567825f791c6f8a592f3c6e3bd93dd2934e3f9dac189308426bd76b00ef3b", - "sha256:f803eaa94c2fcda012c047e62bc7a51b0bdabda1cad7a92a522694ea2d76e49f" + "sha256:005a36f41773e148deac64b08f233873a4d0c18b053d37da83f6af4d9087b813", + "sha256:0857f0ae312d855239a55c81ef453ee8fd24136eaba8e87a2eceba644c0d4c06", + "sha256:1071534bbbf8cbb31b498d5d9db0f274f2f7a865adca4ae429e147ba40f73dea", + "sha256:158d0d15119b4b7ff6b926536763dc0714313aa59e320ddf787502c70c4d4bee", + "sha256:1f436816fc868b098b0d63b8920de7d208c90a67212546d02f84fe78a9c26396", + "sha256:2894f2df484ff56d717bead0a5c2abb6b9d2bf26d6960c4604d5c48bbc30ee73", + "sha256:29314480e958fd8aab22e4a58b355b629c59bf5f2ac2492b61e3dc06d8c7a315", + "sha256:34eff4b97f3d982fb93e2831e6750127d1355a923ebaeeb565407b3d2f8d41a1", + "sha256:35f27e6eb43380fa080dccf676dece30bef72e4a67617ffda586641cd4508d49", + "sha256:3d3dd4c9e559eb172ecf00a2a7517e97d1e96de2a5e610bd9b68cea3925b4892", + "sha256:43e0b9d9e2c9e5d152946b9c5fe062c151614b262fda2e7b201204de0b99e482", + "sha256:48e1c69bbacfc3d932221851b39d49e81567a4d4aac3b21258d9c24578280058", + "sha256:51182f8927c5af975fece87b1b369f722c570fe169f9880764b1ee3bca8347b5", + "sha256:58e3f59d583d413809d60779492342801d6e82fefb89c86a38e040c16883be53", + "sha256:5de7970188bb46b7bf9858eb6890aad302577a5f6f75091fd7cdd3ef13ef3045", + "sha256:65fa59693c62cf06e45ddbb822165394a288edce9e276647f0046e1ec26920f3", + "sha256:69e395c24fc60aad6bb4fa7e583698ea6cc684648e1ffb7fe85e3c1ca131a7d5", + "sha256:6c97d7350133666fbb5cf4abdc1178c812cb205dc6f41d174a7b0f18fb93337e", + "sha256:6e4714cc64f474e4d6e37cfff31a814b509a35cb17de4fb1999907575684479c", + "sha256:72d8d3ef52c208ee1c7b2e341f7d71c6fd3157138abf1a95166e6165dd5d4369", + "sha256:8ae6299f6c68de06f136f1f9e69458eae58f1dacf10af5c17353eae03aa0d827", + "sha256:8b198cec6c72df5289c05b05b8b0969819783f9418e0409865dac47288d2a053", + "sha256:99cd03ae7988a93dd00bcd9d0b75e1f6c426063d6f03d2f90b89e29b25b82dfa", + "sha256:9cf8022fb8d07a97c178b02327b284521c7708d7c71a9c9c355c178ac4bbd3d4", + "sha256:9de2e279153a443c656f2defd67769e6d1e4163952b3c622dcea5b08a6405322", + "sha256:9e93e79c2551ff263400e1e4be085a1210e12073a31c2011dbbda14bda0c6132", + "sha256:9ff227395193126d82e60319a673a037d5de84633f11279e336f9c0f189ecc62", + "sha256:a465da611f6fa124963b91bf432d960a555563efe4ed1cc403ba5077b15370aa", + "sha256:ad17025d226ee5beec591b52800c11680fca3df50b8b29fe51d882576e039ee0", + "sha256:afb29c1ba2e5a3736f1c301d9d0abe3ec8b86957d04ddfa9d7a6a42b9367e396", + "sha256:b85eb46a81787c50650f2392b9b4ef23e1f126313b9e0e9013b35c15e4288e2e", + "sha256:bb89f306e5da99f4d922728ddcd6f7fcebb3241fc40edebcb7284d7514741991", + "sha256:cbde590d4faaa07c72bf979734738f328d239913ba3e043b1e98fe9a39f8b2b6", + "sha256:cd2868886d547469123fadc46eac7ea5253ea7fcb139f12e1dfc2bbd406427d1", + "sha256:d42b11d692e11b6634f7613ad8df5d6d5f8875f5d48939520d351007b3c13406", + "sha256:f2d45f97ab6bb54753eab54fffe75aaf3de4ff2341c9daee1987ee1837636f1d", + "sha256:fd78e5fee591709f32ef6edb9a015b4aa1a5022598e36227500c8f4e02328d9c" ], - "version": "==1.14.4" + "version": "==1.14.5" }, "chardet": { "hashes": [ "sha256:0d6f53a15db4120f2b08c94f11e7d93d2c911ee118b6b30a04ec3ee8310179fa", "sha256:f864054d66fd9118f2e67044ac8981a54775ec5b67aed0441892edb553d21da5" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==4.0.0" }, "click": { @@ -138,8 +165,29 @@ "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a", "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==7.1.2" }, + "click-didyoumean": { + "hashes": [ + "sha256:112229485c9704ff51362fe34b2d4f0b12fc71cc20f6d2b3afabed4b8bfa6aeb" + ], + "version": "==0.0.3" + }, + "click-plugins": { + "hashes": [ + "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b", + "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8" + ], + "version": "==1.1.1" + }, + "click-repl": { + "hashes": [ + "sha256:9c4c3d022789cae912aad8a3f5e1d7c2cdd016ee1225b5212ad3e8691563cda5", + "sha256:b9f29d52abc4d6059f8e276132a111ab8d94980afe6a5432b9d996544afa95d5" + ], + "version": "==0.1.6" + }, "clickclick": { "hashes": [ "sha256:4efb13e62353e34c5eef7ed6582c4920b418d7dedc86d819e22ee089ba01802c", @@ -154,6 +202,14 @@ ], "version": "==0.9.1" }, + "configparser": { + "hashes": [ + "sha256:005c3b102c96f4be9b8f40dafbd4997db003d07d1caa19f37808be8031475f2a", + "sha256:08e8a59ef1817ac4ed810bb8e17d049566dd6e024e7566f6285c756db2bb4ff8" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.1" + }, "connexion": { "extras": [ "swagger-ui" @@ -225,6 +281,7 @@ "sha256:471ec32b2755172046e28102cd46c481f21c6036a0ec027521eba8521aa4ef35", "sha256:924b6921f822b64ec54f49be6700a126bab0640cfafca78f22c9d429ed590560" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.2.11" }, "docutils": { @@ -232,6 +289,7 @@ "sha256:0c5b78adfbf7762415433f5515cd5c9e762339e23369dbe8000d84a4bf4ab3af", "sha256:c2de3a60e9e7d07be26b7f2b00ca0309c207e06c100f9cc2a94931fc75a478fc" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==0.16" }, "docxtpl": { @@ -314,8 +372,16 @@ "sha256:05b31d2034dd3f2a685cbbae4cfc4ed906b2a733cff7964ada450fd5e462b84e", "sha256:bfc7150eaf809b1c283879302f04c42791136060c6eeb12c0c6674fb1291fae5" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.4.4" }, + "future": { + "hashes": [ + "sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d" + ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", + "version": "==0.18.2" + }, "gunicorn": { "hashes": [ "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626", @@ -336,6 +402,7 @@ "sha256:b307872f855b18632ce0c21c5e45be78c0ea7ae4c15c828c20788b26921eb3f6", "sha256:b97d804b1e9b523befed77c48dacec60e6dcb0b5391d57af6a65a312a90648c0" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.10" }, "imagesize": { @@ -343,6 +410,7 @@ "sha256:6965f19a6a2039c7d48bca7dba2473069ff854c36ae6f19d2cde309d998228a1", "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.2.0" }, "inflection": { @@ -350,6 +418,7 @@ "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417", "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2" ], + "markers": "python_version >= '3.5'", "version": "==0.5.1" }, "itsdangerous": { @@ -357,6 +426,7 @@ "sha256:321b033d07f2a4136d3ec762eac9f16a10ccd60f53c0c91af90217ace7ba1f19", "sha256:b12271b2047cb23eeb98c8b5622e2e5c5e9abd9784a153e9d8ef9cb4dd09d749" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.0" }, "jdcal": { @@ -371,6 +441,7 @@ "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419", "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==2.11.3" }, "jsonschema": { @@ -380,9 +451,20 @@ ], "version": "==3.2.0" }, + "kombu": { + "hashes": [ + "sha256:6dc509178ac4269b0e66ab4881f70a2035c33d3a622e20585f965986a5182006", + "sha256:f4965fba0a4718d47d470beeb5d6446e3357a62402b16c510b6a2f251e05ac3c" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.2" + }, "ldap3": { "hashes": [ "sha256:18c3ee656a6775b9b0d60f7c6c5b094d878d1d90fc03d56731039f0a4b546a91", + "sha256:4139c91f0eef9782df7b77c8cbc6243086affcb6a8a249b768a9658438e5da59", + "sha256:8c949edbad2be8a03e719ba48bd6779f327ec156929562814b3e84ab56889c8c", + "sha256:afc6fc0d01f02af82cd7bfabd3bbfd5dc96a6ae91e97db0a2dab8a0f1b436056", "sha256:c1df41d89459be6f304e0ceec4b00fdea533dbbcd83c802b1272dcdb94620b57" ], "index": "pypi", @@ -435,6 +517,7 @@ "hashes": [ "sha256:17831f0b7087c313c0ffae2bcbbd3c1d5ba9eeac9c38f2eb7b50e8c99fe9d5ab" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.4" }, "markdown": { @@ -500,6 +583,7 @@ "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be", "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.1.1" }, "marshmallow": { @@ -553,6 +637,7 @@ "sha256:c91ec9569facd4757ade0888371eced2ecf49e7982ce5634cc2cf4e7331a4b14", "sha256:ecb5b74c702358cdc21268ff4c37f7466357871f53a30e6f84c686952bef16a9" ], + "markers": "python_version >= '3.7'", "version": "==1.20.1" }, "openapi-spec-validator": { @@ -576,6 +661,7 @@ "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.9" }, "pandas": { @@ -602,6 +688,14 @@ "index": "pypi", "version": "==1.2.2" }, + "prompt-toolkit": { + "hashes": [ + "sha256:0fa02fa80363844a4ab4b8d6891f62dd0645ba672723130423ca4037b80c1974", + "sha256:62c811e46bd09130fb11ab759012a4ae385ce4fb2073442d1898867a824183bd" + ], + "markers": "python_full_version >= '3.6.1'", + "version": "==3.0.16" + }, "psycopg2-binary": { "hashes": [ "sha256:0deac2af1a587ae12836aa07970f5cb91964f05a7c6cdb69d8425ff4c15d4e2c", @@ -645,8 +739,19 @@ }, "pyasn1": { "hashes": [ + "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359", + "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576", + "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf", + "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7", "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d", - "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba" + "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00", + "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8", + "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86", + "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12", + "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776", + "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba", + "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2", + "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3" ], "version": "==0.4.8" }, @@ -655,6 +760,7 @@ "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.20" }, "pygithub": { @@ -667,10 +773,11 @@ }, "pygments": { "hashes": [ - "sha256:bc9591213a8f0e0ca1a5e68a479b4887fdc3e75d0774e5c71c31920c427de435", - "sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337" + "sha256:37a13ba168a02ac54cc5891a42b1caec333e59b66addb7fa633ea8a6d73445c0", + "sha256:b21b072d0ccdf29297a82a2363359d99623597b8a265b8081760e4d0f7153c88" ], - "version": "==2.7.4" + "markers": "python_version >= '3.5'", + "version": "==2.8.0" }, "pyjwt": { "hashes": [ @@ -685,21 +792,23 @@ "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.4.7" }, "pyrsistent": { "hashes": [ "sha256:2e636185d9eb976a18a8a8e96efce62f2905fea90041958d8cc2a189756ebf3e" ], + "markers": "python_version >= '3.5'", "version": "==0.17.3" }, "python-box": { "hashes": [ - "sha256:dcc1a59087f39285b530d433eb6e095dc0e6740312e3eb564e2ef457787e97a6", - "sha256:dd91aa847d2a773b510008902ba3ab083d690800f13e7c540cdaf8e2181e4431" + "sha256:4ed4ef5d34de505a65c01e3f1911de8cdb29484fcae0c035141dce535c6c194a", + "sha256:f2a531f9f5bbef078c175fad6abb31e9b59d40d121ea79993197e6bb221c6be6" ], "index": "pypi", - "version": "==5.2.0" + "version": "==5.3.0" }, "python-dateutil": { "hashes": [ @@ -719,7 +828,9 @@ "hashes": [ "sha256:1bf6e860a8ad52a14c3ee1252d5dc25b2030618ed80c022598f00176adc8367d", "sha256:51fda6bcc5ddbbb7063b2af7509e43bd84bfc32a4ff71349ec7847713882327b", - "sha256:5f98b069316ea1c2ed3f67e7f5df6c0d8f10b689964a4a811ff64f0106819ec8" + "sha256:5f98b069316ea1c2ed3f67e7f5df6c0d8f10b689964a4a811ff64f0106819ec8", + "sha256:c3da2053dbab6b29c94e43c486ff67206eafbe7eb52dbec7390b5e2fb05aac77", + "sha256:ea87e17f6ec459e780e4221f295411462e0d0810858e055fc514684350a2f522" ], "version": "==1.0.4" }, @@ -761,6 +872,7 @@ "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df", "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==5.4.1" }, "recommonmark": { @@ -795,6 +907,7 @@ "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259", "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==1.15.0" }, "snowballstemmer": { @@ -814,17 +927,18 @@ }, "sphinx": { "hashes": [ - "sha256:41cad293f954f7d37f803d97eb184158cfd90f51195131e94875bc07cd08b93c", - "sha256:c314c857e7cd47c856d2c5adff514ac2e6495f8b8e0f886a8a37e9305dfea0d8" + "sha256:11d521e787d9372c289472513d807277caafb1684b33eb4f08f7574c405893a9", + "sha256:e90161222e4d80ce5fc811ace7c6787a226b4f5951545f7f42acf97277bfc35c" ], "index": "pypi", - "version": "==3.4.3" + "version": "==3.5.1" }, "sphinxcontrib-applehelp": { "hashes": [ "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" ], + "markers": "python_version >= '3.5'", "version": "==1.0.2" }, "sphinxcontrib-devhelp": { @@ -832,6 +946,7 @@ "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" ], + "markers": "python_version >= '3.5'", "version": "==1.0.2" }, "sphinxcontrib-htmlhelp": { @@ -839,6 +954,7 @@ "sha256:3c0bc24a2c41e340ac37c85ced6dafc879ab485c095b1d65d2461ac2f7cca86f", "sha256:e8f5bb7e31b2dbb25b9cc435c8ab7a79787ebf7f906155729338f3156d93659b" ], + "markers": "python_version >= '3.5'", "version": "==1.0.3" }, "sphinxcontrib-jsmath": { @@ -846,6 +962,7 @@ "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" ], + "markers": "python_version >= '3.5'", "version": "==1.0.1" }, "sphinxcontrib-qthelp": { @@ -853,6 +970,7 @@ "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" ], + "markers": "python_version >= '3.5'", "version": "==1.0.3" }, "sphinxcontrib-serializinghtml": { @@ -860,6 +978,7 @@ "sha256:eaa0eccc86e982a9b939b2b82d12cc5d013385ba5eadcc7e4fed23f4405f77bc", "sha256:f242a81d423f59617a8e5cf16f5d4d74e28ee9a66f9e5b637a18082991db5a9a" ], + "markers": "python_version >= '3.5'", "version": "==1.1.4" }, "spiffworkflow": { @@ -907,6 +1026,7 @@ "sha256:fd3b96f8c705af8e938eaa99cbd8fd1450f632d38cad55e7367c33b263bf98ec", "sha256:fdd2ed7395df8ac2dbb10cefc44737b66c6a5cd7755c92524733d7a443e5b7e2" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.3.23" }, "swagger-ui-bundle": { @@ -922,20 +1042,38 @@ "sha256:1b465e494e3e0d8939b50680403e3aedaa2bc434b7d5af64dfd3c958d7f5ae80", "sha256:de3eedaad74a2683334e282005cd8d7f22f4d55fa690a2a1020a416cb0a47e73" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", "version": "==1.26.3" }, + "vine": { + "hashes": [ + "sha256:4c9dceab6f76ed92105027c49c823800dd33cacce13bdedc5b914e3514b7fb30", + "sha256:7d3b1624a953da82ef63462013bbd271d3eb75751489f9807598e8f340bd637e" + ], + "markers": "python_version >= '3.6'", + "version": "==5.0.0" + }, "waitress": { "hashes": [ "sha256:1bb436508a7487ac6cb097ae7a7fe5413aefca610550baf58f0940e51ecfb261", "sha256:3d633e78149eb83b60a07dfabb35579c29aac2d24bb803c18b26fb2ab1a584db" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", "version": "==1.4.4" }, + "wcwidth": { + "hashes": [ + "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784", + "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83" + ], + "version": "==0.2.5" + }, "webob": { "hashes": [ "sha256:a3c89a8e9ba0aeb17382836cdb73c516d0ecf6630ec40ec28288f3ed459ce87b", "sha256:aa3a917ed752ba3e0b242234b2a373f9c4e2a75d35291dcbe977649bd21fd108" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==1.8.6" }, "webtest": { @@ -990,6 +1128,7 @@ "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6", "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.3.0" }, "coverage": { @@ -1059,6 +1198,7 @@ "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5", "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==20.9" }, "pbr": { @@ -1074,6 +1214,7 @@ "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0", "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.13.1" }, "py": { @@ -1081,6 +1222,7 @@ "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.10.0" }, "pyparsing": { @@ -1088,6 +1230,7 @@ "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.4.7" }, "pytest": { @@ -1103,6 +1246,7 @@ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", "version": "==0.10.2" } } diff --git a/crc/api/workflow.py b/crc/api/workflow.py index f2cb39d9..20fdd781 100644 --- a/crc/api/workflow.py +++ b/crc/api/workflow.py @@ -8,6 +8,7 @@ from crc.models.api_models import WorkflowApiSchema from crc.models.file import FileModel, LookupDataSchema from crc.models.study import StudyModel, WorkflowMetadata from crc.models.task_event import TaskEventModel, TaskEvent, TaskEventSchema +from crc.models.user import UserModelSchema from crc.models.workflow import WorkflowModel, WorkflowSpecModelSchema, WorkflowSpecModel, WorkflowSpecCategoryModel, \ WorkflowSpecCategoryModelSchema from crc.services.file_service import FileService @@ -123,7 +124,11 @@ def restart_workflow(workflow_id, clear_data=False): def get_task_events(action = None, workflow = None, study = None): """Provides a way to see a history of what has happened, or get a list of tasks that need your attention.""" - query = session.query(TaskEventModel).filter(TaskEventModel.user_uid == g.user.uid) + user = UserService.current_user(allow_admin_impersonate=True) + studies = session.query(StudyModel).filter(StudyModel.user_uid==user.uid) + studyids = [s.id for s in studies] + query = session.query(TaskEventModel).filter((TaskEventModel.study_id.in_(studyids)) | \ + (TaskEventModel.user_uid==user.uid)) if action: query = query.filter(TaskEventModel.action == action) if workflow: diff --git a/crc/models/api_models.py b/crc/models/api_models.py index 1ff623f7..017fa3fe 100644 --- a/crc/models/api_models.py +++ b/crc/models/api_models.py @@ -170,7 +170,7 @@ class NavigationItemSchema(ma.Schema): class WorkflowApi(object): def __init__(self, id, status, next_task, navigation, spec_version, is_latest_spec, workflow_spec_id, total_tasks, completed_tasks, - last_updated, title): + last_updated, is_review, title): self.id = id self.status = status self.next_task = next_task # The next task that requires user input. @@ -182,13 +182,14 @@ class WorkflowApi(object): self.completed_tasks = completed_tasks self.last_updated = last_updated self.title = title + self.is_review = is_review class WorkflowApiSchema(ma.Schema): class Meta: model = WorkflowApi fields = ["id", "status", "next_task", "navigation", "workflow_spec_id", "spec_version", "is_latest_spec", "total_tasks", "completed_tasks", - "last_updated", "title"] + "last_updated", "is_review", "title"] unknown = INCLUDE status = EnumField(WorkflowStatus) @@ -199,7 +200,7 @@ class WorkflowApiSchema(ma.Schema): def make_workflow(self, data, **kwargs): keys = ['id', 'status', 'next_task', 'navigation', 'workflow_spec_id', 'spec_version', 'is_latest_spec', "total_tasks", "completed_tasks", - "last_updated", "title"] + "last_updated", "is_review", "title"] filtered_fields = {key: data[key] for key in keys} filtered_fields['next_task'] = TaskSchema().make_task(data['next_task']) return WorkflowApi(**filtered_fields) diff --git a/crc/models/file.py b/crc/models/file.py index 8693b7e5..d01dc2a3 100644 --- a/crc/models/file.py +++ b/crc/models/file.py @@ -85,6 +85,7 @@ class FileModel(db.Model): # A request was made to delete the file, but we can't because there are # active approvals or running workflows that depend on it. So we archive # it instead, hide it in the interface. + is_review = db.Column(db.Boolean, default=False, nullable=True) archived = db.Column(db.Boolean, default=False, nullable=False) class File(object): diff --git a/crc/models/study.py b/crc/models/study.py index 3b34e8b5..8d263b0f 100644 --- a/crc/models/study.py +++ b/crc/models/study.py @@ -13,6 +13,7 @@ from crc.models.file import FileModel, SimpleFileSchema, FileSchema from crc.models.protocol_builder import ProtocolBuilderStatus, ProtocolBuilderStudy from crc.models.workflow import WorkflowSpecCategoryModel, WorkflowState, WorkflowStatus, WorkflowSpecModel, \ WorkflowModel +from crc.services.file_service import FileService from crc.services.user_service import UserService @@ -78,7 +79,7 @@ class WorkflowMetadata(object): def __init__(self, id, name = None, display_name = None, description = None, spec_version = None, category_id = None, category_display_name = None, state: WorkflowState = None, status: WorkflowStatus = None, total_tasks = None, completed_tasks = None, - display_order = None): + is_review=None,display_order = None): self.id = id self.name = name self.display_name = display_name @@ -90,11 +91,13 @@ class WorkflowMetadata(object): self.status = status self.total_tasks = total_tasks self.completed_tasks = completed_tasks + self.is_review = is_review self.display_order = display_order @classmethod def from_workflow(cls, workflow: WorkflowModel): + is_review = FileService.is_workflow_review(workflow.workflow_spec_id) instance = cls( id=workflow.id, name=workflow.workflow_spec.name, @@ -107,6 +110,7 @@ class WorkflowMetadata(object): status=workflow.status, total_tasks=workflow.total_tasks, completed_tasks=workflow.completed_tasks, + is_review=is_review, display_order=workflow.workflow_spec.display_order ) return instance @@ -119,7 +123,7 @@ class WorkflowMetadataSchema(ma.Schema): model = WorkflowMetadata additional = ["id", "name", "display_name", "description", "total_tasks", "completed_tasks", "display_order", - "category_id", "category_display_name"] + "category_id", "is_review", "category_display_name"] unknown = INCLUDE @@ -144,9 +148,13 @@ class Study(object): def __init__(self, title, last_updated, primary_investigator_id, user_uid, id=None, status=None, irb_status=None, comment="", sponsor="", hsr_number="", ind_number="", categories=[], - files=[], approvals=[], enrollment_date=None, events_history=[], **argsv): + files=[], approvals=[], enrollment_date=None, events_history=[], + last_activity_user="",last_activity_date =None,create_user_display="", **argsv): self.id = id self.user_uid = user_uid + self.create_user_display = create_user_display + self.last_activity_date = last_activity_date + self.last_activity_user = last_activity_user self.title = title self.last_updated = last_updated self.status = status @@ -229,6 +237,7 @@ class StudySchema(ma.Schema): model = Study additional = ["id", "title", "last_updated", "primary_investigator_id", "user_uid", "sponsor", "ind_number", "files", "enrollment_date", + "create_user_display", "last_activity_date","last_activity_user", "events_history"] unknown = INCLUDE diff --git a/crc/models/task_event.py b/crc/models/task_event.py index aa05a4f7..21a239ee 100644 --- a/crc/models/task_event.py +++ b/crc/models/task_event.py @@ -4,6 +4,7 @@ from marshmallow_sqlalchemy import SQLAlchemyAutoSchema from crc import db, ma from crc.models.study import StudyModel, StudySchema, WorkflowMetadataSchema, WorkflowMetadata from crc.models.workflow import WorkflowModel +from crc.services.ldap_service import LdapService class TaskEventModel(db.Model): @@ -43,6 +44,7 @@ class TaskEvent(object): self.study = study self.workflow = workflow self.user_uid = model.user_uid + self.user_display = LdapService.user_info(model.user_uid).display_name self.action = model.action self.task_id = model.task_id self.task_title = model.task_title @@ -60,6 +62,6 @@ class TaskEventSchema(ma.Schema): task_lane = fields.String(allow_none=True, required=False) class Meta: model = TaskEvent - additional = ["id", "user_uid", "action", "task_id", "task_title", + additional = ["id", "user_uid", "user_display", "action", "task_id", "task_title", "task_name", "task_type", "task_state", "task_lane", "date"] unknown = INCLUDE diff --git a/crc/services/file_service.py b/crc/services/file_service.py index d39a45fc..cd4f69f1 100644 --- a/crc/services/file_service.py +++ b/crc/services/file_service.py @@ -57,6 +57,13 @@ class FileService(object): doc_dict = FileService.get_doc_dictionary() return code in doc_dict + @staticmethod + def is_workflow_review(workflow_spec_id): + files = session.query(FileModel).filter(FileModel.workflow_spec_id==workflow_spec_id).all() + review = any([f.is_review for f in files]) + return review + + @staticmethod def add_workflow_file(workflow_id, irb_doc_code, name, content_type, binary_data): """Create a new file and associate it with the workflow @@ -164,6 +171,7 @@ class FileService(object): try: bpmn: etree.Element = etree.fromstring(binary_data) file_model.primary_process_id = FileService.get_process_id(bpmn) + file_model.is_review = FileService.has_swimlane(bpmn) except XMLSyntaxError as xse: raise ApiError("invalid_xml", "Failed to parse xml: " + str(xse), file_name=file_model.name) @@ -177,6 +185,19 @@ class FileService(object): return file_model + @staticmethod + def has_swimlane(et_root: etree.Element): + """ + Look through XML and determine if there are any swimlanes present that have a label. + """ + elements = et_root.xpath('//bpmn:lane', + namespaces={'bpmn':'http://www.omg.org/spec/BPMN/20100524/MODEL'}) + retval = False + for el in elements: + if el.get('name'): + retval = True + return retval + @staticmethod def get_process_id(et_root: etree.Element): process_elements = [] diff --git a/crc/services/study_service.py b/crc/services/study_service.py index 19c1bf3f..68c8f633 100644 --- a/crc/services/study_service.py +++ b/crc/services/study_service.py @@ -21,7 +21,7 @@ from crc.services.file_service import FileService from crc.services.ldap_service import LdapService from crc.services.protocol_builder import ProtocolBuilderService from crc.services.workflow_processor import WorkflowProcessor - +from SpiffWorkflow import Task as SpiffTask class StudyService(object): """Provides common tools for working with a Study""" @@ -55,6 +55,16 @@ class StudyService(object): study_model = session.query(StudyModel).filter_by(id=study_id).first() study = Study.from_model(study_model) + study.create_user_display = LdapService.user_info(study.user_uid).display_name + last_event: TaskEventModel = session.query(TaskEventModel)\ + .filter_by(study_id=study_id,action='COMPLETE')\ + .order_by(TaskEventModel.date.desc()).first() + if last_event is None: + study.last_activity_user = 'Not Started' + study.last_activity_date = "" + else: + study.last_activity_user = LdapService.user_info(last_event.user_uid).display_name + study.last_activity_date = last_event.date study.categories = StudyService.get_categories() workflow_metas = StudyService.__get_workflow_metas(study_id) files = FileService.get_files_for_study(study.id) @@ -65,6 +75,8 @@ class StudyService(object): # master spec and runs it. Don't execute this for Abandoned studies, as # we don't have the information to process them. if study.status != StudyStatus.abandoned: + # this line is taking 99% of the time that is used in get_study. + # see ticket #196 status = StudyService.__get_study_status(study_model) study.warnings = StudyService.__update_status_of_workflow_meta(workflow_metas, status) diff --git a/crc/services/workflow_service.py b/crc/services/workflow_service.py index dbffdf1f..faf0c268 100644 --- a/crc/services/workflow_service.py +++ b/crc/services/workflow_service.py @@ -381,6 +381,7 @@ class WorkflowService(object): spec = db.session.query(WorkflowSpecModel).filter_by(id=processor.workflow_spec_id).first() + is_review = FileService.is_workflow_review(processor.workflow_spec_id) workflow_api = WorkflowApi( id=processor.get_workflow_id(), status=processor.get_status(), @@ -392,6 +393,7 @@ class WorkflowService(object): total_tasks=len(navigation), completed_tasks=processor.workflow_model.completed_tasks, last_updated=processor.workflow_model.last_updated, + is_review=is_review, title=spec.display_name ) if not next_task: # The Next Task can be requested to be a certain task, useful for parallel tasks. diff --git a/migrations/versions/c6261ac7a7bc_.py b/migrations/versions/c6261ac7a7bc_.py new file mode 100644 index 00000000..ab6ee290 --- /dev/null +++ b/migrations/versions/c6261ac7a7bc_.py @@ -0,0 +1,28 @@ +"""empty message + +Revision ID: c6261ac7a7bc +Revises: f186725c1ad3 +Create Date: 2021-02-10 08:01:45.451881 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'c6261ac7a7bc' +down_revision = 'f186725c1ad3' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('file', sa.Column('is_review', sa.Boolean(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('file', 'is_review') + # ### end Alembic commands ### diff --git a/postgres/docker-compose.yml b/postgres/docker-compose.yml index 31116b85..c648d4ce 100644 --- a/postgres/docker-compose.yml +++ b/postgres/docker-compose.yml @@ -5,7 +5,7 @@ services: volumes: - $HOME/docker/volumes/postgres:/var/lib/postgresql/data ports: - - 5432:5432 + - 5003:5432 environment: - POSTGRES_USER=${DB_USER} - POSTGRES_PASSWORD=${DB_PASS}