diff --git a/.Dockerfile b/.Dockerfile
new file mode 100644
index 0000000..1bdb2a5
--- /dev/null
+++ b/.Dockerfile
@@ -0,0 +1,27 @@
+FROM python:3.9-buster
+
+RUN apt-get update \
+ # dependencies for building Python packages \
+ && apt-get install -y libpq-dev python3-dev \
+ && apt-get install -y build-essential \
+ # psycopg2 dependencies
+ && apt-get install -y libpq-dev \
+ # Translations dependencies
+ && apt-get install -y gettext \
+ && apt-get install -y libcairo2 libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info \
+ # cleaning up unused files
+ && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
+ && rm -rf /var/lib/apt/lists/*
+
+RUN mkdir -p /usr/src/app
+WORKDIR /usr/src/app
+
+COPY ./requirements.txt /requirements.txt
+RUN pip install --no-cache-dir -r /requirements.txt \
+ && rm -rf /requirements.txt
+
+COPY . /usr/src/app
+
+EXPOSE 9000
+
+CMD [ "python3", "-m" , "server"]
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index d3012c7..20deaca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
__pycache__
.vscode
-models/diagram_1.bpmn
+models/private/diagram_1.bpmn
models/chatbot_model.bpmn
models/test_podproces.bpmn
models/test_call_activity.bpmn
@@ -8,4 +8,5 @@ models/test_business_rule.bpmn
models/test_dmn.dmn
models/test_exe_dmn.dmn
py-bpmn-env
-database/
\ No newline at end of file
+database/
+env.py
diff --git a/Pipfile b/Pipfile
index 179004f..5f74892 100644
--- a/Pipfile
+++ b/Pipfile
@@ -6,8 +6,24 @@ verify_ssl = true
[dev-packages]
[packages]
-aiohttp = "==3.7.4.post0"
-asyncio = "*"
+pipenv = "2022.5.2"
+aiohttp = "3.7.4.post0"
+aiohttp-cors = "0.7.0"
+async-timeout = "3.0.1"
+asyncio = "3.4.3"
+attrs = "21.2.0"
+certifi = "2021.5.30"
+chardet = "4.0.0"
+charset-normalizer = "2.0.4"
+idna = "3.2"
+multidict = "5.1.0"
+pony = "0.7.14"
+requests = "2.26.0"
+typing-extensions = "3.10.0.0"
+urllib3 = "1.26.6"
+yarl = "1.6.3"
+psycopg2 = "2.9.1"
+gunicorn = "20.1.0"
[requires]
-python_version = "3.9"
+python_version = "3.8.10"
diff --git a/Pipfile.lock b/Pipfile.lock
index 8f43402..1a89772 100644
--- a/Pipfile.lock
+++ b/Pipfile.lock
@@ -1,11 +1,11 @@
{
"_meta": {
"hash": {
- "sha256": "f6b9b69e1a772fdc6e4bceccddb48dde2b41e0e3b1c8d9cd2c854a03389cd9c1"
+ "sha256": "703016ba8391505a78999495aa35d50ab0b700572ba6252f13eef14e62f6c11f"
},
"pipfile-spec": 6,
"requires": {
- "python_version": "3.9"
+ "python_version": "3.8.10"
},
"sources": [
{
@@ -18,54 +18,105 @@
"default": {
"aiohttp": {
"hashes": [
- "sha256:02f46fc0e3c5ac58b80d4d56eb0a7c7d97fcef69ace9326289fb9f1955e65cfe",
- "sha256:0563c1b3826945eecd62186f3f5c7d31abb7391fedc893b7e2b26303b5a9f3fe",
- "sha256:114b281e4d68302a324dd33abb04778e8557d88947875cbf4e842c2c01a030c5",
- "sha256:14762875b22d0055f05d12abc7f7d61d5fd4fe4642ce1a249abdf8c700bf1fd8",
- "sha256:15492a6368d985b76a2a5fdd2166cddfea5d24e69eefed4630cbaae5c81d89bd",
- "sha256:17c073de315745a1510393a96e680d20af8e67e324f70b42accbd4cb3315c9fb",
- "sha256:209b4a8ee987eccc91e2bd3ac36adee0e53a5970b8ac52c273f7f8fd4872c94c",
- "sha256:230a8f7e24298dea47659251abc0fd8b3c4e38a664c59d4b89cca7f6c09c9e87",
- "sha256:2e19413bf84934d651344783c9f5e22dee452e251cfd220ebadbed2d9931dbf0",
- "sha256:393f389841e8f2dfc86f774ad22f00923fdee66d238af89b70ea314c4aefd290",
- "sha256:3cf75f7cdc2397ed4442594b935a11ed5569961333d49b7539ea741be2cc79d5",
- "sha256:3d78619672183be860b96ed96f533046ec97ca067fd46ac1f6a09cd9b7484287",
- "sha256:40eced07f07a9e60e825554a31f923e8d3997cfc7fb31dbc1328c70826e04cde",
- "sha256:493d3299ebe5f5a7c66b9819eacdcfbbaaf1a8e84911ddffcdc48888497afecf",
- "sha256:4b302b45040890cea949ad092479e01ba25911a15e648429c7c5aae9650c67a8",
- "sha256:515dfef7f869a0feb2afee66b957cc7bbe9ad0cdee45aec7fdc623f4ecd4fb16",
- "sha256:547da6cacac20666422d4882cfcd51298d45f7ccb60a04ec27424d2f36ba3eaf",
- "sha256:5df68496d19f849921f05f14f31bd6ef53ad4b00245da3195048c69934521809",
- "sha256:64322071e046020e8797117b3658b9c2f80e3267daec409b350b6a7a05041213",
- "sha256:7615dab56bb07bff74bc865307aeb89a8bfd9941d2ef9d817b9436da3a0ea54f",
- "sha256:79ebfc238612123a713a457d92afb4096e2148be17df6c50fb9bf7a81c2f8013",
- "sha256:7b18b97cf8ee5452fa5f4e3af95d01d84d86d32c5e2bfa260cf041749d66360b",
- "sha256:932bb1ea39a54e9ea27fc9232163059a0b8855256f4052e776357ad9add6f1c9",
- "sha256:a00bb73540af068ca7390e636c01cbc4f644961896fa9363154ff43fd37af2f5",
- "sha256:a5ca29ee66f8343ed336816c553e82d6cade48a3ad702b9ffa6125d187e2dedb",
- "sha256:af9aa9ef5ba1fd5b8c948bb11f44891968ab30356d65fd0cc6707d989cd521df",
- "sha256:bb437315738aa441251214dad17428cafda9cdc9729499f1d6001748e1d432f4",
- "sha256:bdb230b4943891321e06fc7def63c7aace16095be7d9cf3b1e01be2f10fba439",
- "sha256:c6e9dcb4cb338d91a73f178d866d051efe7c62a7166653a91e7d9fb18274058f",
- "sha256:cffe3ab27871bc3ea47df5d8f7013945712c46a3cc5a95b6bee15887f1675c22",
- "sha256:d012ad7911653a906425d8473a1465caa9f8dea7fcf07b6d870397b774ea7c0f",
- "sha256:d9e13b33afd39ddeb377eff2c1c4f00544e191e1d1dee5b6c51ddee8ea6f0cf5",
- "sha256:e4b2b334e68b18ac9817d828ba44d8fcb391f6acb398bcc5062b14b2cbeac970",
- "sha256:e54962802d4b8b18b6207d4a927032826af39395a3bd9196a5af43fc4e60b009",
- "sha256:f705e12750171c0ab4ef2a3c76b9a4024a62c4103e3a55dd6f99265b9bc6fcfc",
- "sha256:f881853d2643a29e643609da57b96d5f9c9b93f62429dcc1cbb413c7d07f0e1a",
- "sha256:fe60131d21b31fd1a14bd43e6bb88256f69dfc3188b3a89d736d6c71ed43ec95"
- ],
- "index": "pypi",
- "version": "==3.7.4.post0"
+ "sha256:01d7bdb774a9acc838e6b8f1d114f45303841b89b95984cbb7d80ea41172a9e3",
+ "sha256:03a6d5349c9ee8f79ab3ff3694d6ce1cfc3ced1c9d36200cb8f08ba06bd3b782",
+ "sha256:04d48b8ce6ab3cf2097b1855e1505181bdd05586ca275f2505514a6e274e8e75",
+ "sha256:0770e2806a30e744b4e21c9d73b7bee18a1cfa3c47991ee2e5a65b887c49d5cf",
+ "sha256:07b05cd3305e8a73112103c834e91cd27ce5b4bd07850c4b4dbd1877d3f45be7",
+ "sha256:086f92daf51a032d062ec5f58af5ca6a44d082c35299c96376a41cbb33034675",
+ "sha256:099ebd2c37ac74cce10a3527d2b49af80243e2a4fa39e7bce41617fbc35fa3c1",
+ "sha256:0c7ebbbde809ff4e970824b2b6cb7e4222be6b95a296e46c03cf050878fc1785",
+ "sha256:102e487eeb82afac440581e5d7f8f44560b36cf0bdd11abc51a46c1cd88914d4",
+ "sha256:11691cf4dc5b94236ccc609b70fec991234e7ef8d4c02dd0c9668d1e486f5abf",
+ "sha256:11a67c0d562e07067c4e86bffc1553f2cf5b664d6111c894671b2b8712f3aba5",
+ "sha256:12de6add4038df8f72fac606dff775791a60f113a725c960f2bab01d8b8e6b15",
+ "sha256:13487abd2f761d4be7c8ff9080de2671e53fff69711d46de703c310c4c9317ca",
+ "sha256:15b09b06dae900777833fe7fc4b4aa426556ce95847a3e8d7548e2d19e34edb8",
+ "sha256:1c182cb873bc91b411e184dab7a2b664d4fea2743df0e4d57402f7f3fa644bac",
+ "sha256:1ed0b6477896559f17b9eaeb6d38e07f7f9ffe40b9f0f9627ae8b9926ae260a8",
+ "sha256:28d490af82bc6b7ce53ff31337a18a10498303fe66f701ab65ef27e143c3b0ef",
+ "sha256:2e5d962cf7e1d426aa0e528a7e198658cdc8aa4fe87f781d039ad75dcd52c516",
+ "sha256:2ed076098b171573161eb146afcb9129b5ff63308960aeca4b676d9d3c35e700",
+ "sha256:2f2f69dca064926e79997f45b2f34e202b320fd3782f17a91941f7eb85502ee2",
+ "sha256:31560d268ff62143e92423ef183680b9829b1b482c011713ae941997921eebc8",
+ "sha256:31d1e1c0dbf19ebccbfd62eff461518dcb1e307b195e93bba60c965a4dcf1ba0",
+ "sha256:37951ad2f4a6df6506750a23f7cbabad24c73c65f23f72e95897bb2cecbae676",
+ "sha256:3af642b43ce56c24d063325dd2cf20ee012d2b9ba4c3c008755a301aaea720ad",
+ "sha256:44db35a9e15d6fe5c40d74952e803b1d96e964f683b5a78c3cc64eb177878155",
+ "sha256:473d93d4450880fe278696549f2e7aed8cd23708c3c1997981464475f32137db",
+ "sha256:477c3ea0ba410b2b56b7efb072c36fa91b1e6fc331761798fa3f28bb224830dd",
+ "sha256:4a4a4e30bf1edcad13fb0804300557aedd07a92cabc74382fdd0ba6ca2661091",
+ "sha256:4aed991a28ea3ce320dc8ce655875e1e00a11bdd29fe9444dd4f88c30d558602",
+ "sha256:51467000f3647d519272392f484126aa716f747859794ac9924a7aafa86cd411",
+ "sha256:55c3d1072704d27401c92339144d199d9de7b52627f724a949fc7d5fc56d8b93",
+ "sha256:589c72667a5febd36f1315aa6e5f56dd4aa4862df295cb51c769d16142ddd7cd",
+ "sha256:5bfde62d1d2641a1f5173b8c8c2d96ceb4854f54a44c23102e2ccc7e02f003ec",
+ "sha256:5c23b1ad869653bc818e972b7a3a79852d0e494e9ab7e1a701a3decc49c20d51",
+ "sha256:61bfc23df345d8c9716d03717c2ed5e27374e0fe6f659ea64edcd27b4b044cf7",
+ "sha256:6ae828d3a003f03ae31915c31fa684b9890ea44c9c989056fea96e3d12a9fa17",
+ "sha256:6c7cefb4b0640703eb1069835c02486669312bf2f12b48a748e0a7756d0de33d",
+ "sha256:6d69f36d445c45cda7b3b26afef2fc34ef5ac0cdc75584a87ef307ee3c8c6d00",
+ "sha256:6f0d5f33feb5f69ddd57a4a4bd3d56c719a141080b445cbf18f238973c5c9923",
+ "sha256:6f8b01295e26c68b3a1b90efb7a89029110d3a4139270b24fda961893216c440",
+ "sha256:713ac174a629d39b7c6a3aa757b337599798da4c1157114a314e4e391cd28e32",
+ "sha256:718626a174e7e467f0558954f94af117b7d4695d48eb980146016afa4b580b2e",
+ "sha256:7187a76598bdb895af0adbd2fb7474d7f6025d170bc0a1130242da817ce9e7d1",
+ "sha256:71927042ed6365a09a98a6377501af5c9f0a4d38083652bcd2281a06a5976724",
+ "sha256:7d08744e9bae2ca9c382581f7dce1273fe3c9bae94ff572c3626e8da5b193c6a",
+ "sha256:7dadf3c307b31e0e61689cbf9e06be7a867c563d5a63ce9dca578f956609abf8",
+ "sha256:81e3d8c34c623ca4e36c46524a3530e99c0bc95ed068fd6e9b55cb721d408fb2",
+ "sha256:844a9b460871ee0a0b0b68a64890dae9c415e513db0f4a7e3cab41a0f2fedf33",
+ "sha256:8b7ef7cbd4fec9a1e811a5de813311ed4f7ac7d93e0fda233c9b3e1428f7dd7b",
+ "sha256:97ef77eb6b044134c0b3a96e16abcb05ecce892965a2124c566af0fd60f717e2",
+ "sha256:99b5eeae8e019e7aad8af8bb314fb908dd2e028b3cdaad87ec05095394cce632",
+ "sha256:a25fa703a527158aaf10dafd956f7d42ac6d30ec80e9a70846253dd13e2f067b",
+ "sha256:a2f635ce61a89c5732537a7896b6319a8fcfa23ba09bec36e1b1ac0ab31270d2",
+ "sha256:a79004bb58748f31ae1cbe9fa891054baaa46fb106c2dc7af9f8e3304dc30316",
+ "sha256:a996d01ca39b8dfe77440f3cd600825d05841088fd6bc0144cc6c2ec14cc5f74",
+ "sha256:b0e20cddbd676ab8a64c774fefa0ad787cc506afd844de95da56060348021e96",
+ "sha256:b6613280ccedf24354406caf785db748bebbddcf31408b20c0b48cb86af76866",
+ "sha256:b9d00268fcb9f66fbcc7cd9fe423741d90c75ee029a1d15c09b22d23253c0a44",
+ "sha256:bb01ba6b0d3f6c68b89fce7305080145d4877ad3acaed424bae4d4ee75faa950",
+ "sha256:c2aef4703f1f2ddc6df17519885dbfa3514929149d3ff900b73f45998f2532fa",
+ "sha256:c34dc4958b232ef6188c4318cb7b2c2d80521c9a56c52449f8f93ab7bc2a8a1c",
+ "sha256:c3630c3ef435c0a7c549ba170a0633a56e92629aeed0e707fec832dee313fb7a",
+ "sha256:c3d6a4d0619e09dcd61021debf7059955c2004fa29f48788a3dfaf9c9901a7cd",
+ "sha256:d15367ce87c8e9e09b0f989bfd72dc641bcd04ba091c68cd305312d00962addd",
+ "sha256:d2f9b69293c33aaa53d923032fe227feac867f81682f002ce33ffae978f0a9a9",
+ "sha256:e999f2d0e12eea01caeecb17b653f3713d758f6dcc770417cf29ef08d3931421",
+ "sha256:ea302f34477fda3f85560a06d9ebdc7fa41e82420e892fc50b577e35fc6a50b2",
+ "sha256:eaba923151d9deea315be1f3e2b31cc39a6d1d2f682f942905951f4e40200922",
+ "sha256:ef9612483cb35171d51d9173647eed5d0069eaa2ee812793a75373447d487aa4",
+ "sha256:f5315a2eb0239185af1bddb1abf472d877fede3cc8d143c6cddad37678293237",
+ "sha256:fa0ffcace9b3aa34d205d8130f7873fcfefcb6a4dd3dd705b0dab69af6712642",
+ "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578"
+ ],
+ "index": "pypi",
+ "version": "==3.8.1"
+ },
+ "aiohttp-cors": {
+ "hashes": [
+ "sha256:0451ba59fdf6909d0e2cd21e4c0a43752bc0703d33fc78ae94d9d9321710193e",
+ "sha256:4d39c6d7100fd9764ed1caf8cebf0eb01bf5e3f24e2e073fda6234bc48b19f5d"
+ ],
+ "index": "pypi",
+ "version": "==0.7.0"
+ },
+ "aiosignal": {
+ "hashes": [
+ "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a",
+ "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2"
+ ],
+ "markers": "python_version >= '3.6'",
+ "version": "==1.2.0"
},
"async-timeout": {
"hashes": [
- "sha256:0c3c816a028d47f659d6ff5c745cb2acf1f966da1fe5c19c77a70282b25f4c5f",
- "sha256:4291ca197d287d274d0b6cb5d6f8f8f82d434ed288f962539ff18cc9012f9ea3"
+ "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15",
+ "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"
],
- "markers": "python_full_version >= '3.5.3'",
- "version": "==3.0.1"
+ "index": "pypi",
+ "version": "==4.0.2"
},
"asyncio": {
"hashes": [
@@ -79,121 +130,379 @@
},
"attrs": {
"hashes": [
- "sha256:31b2eced602aa8423c2aea9c76a724617ed67cf9513173fd3a4f03e3a929c7e6",
- "sha256:832aa3cde19744e49938b91fea06d69ecb9e649c93ba974535d08ad92164f700"
+ "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4",
+ "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"
],
- "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
- "version": "==20.3.0"
+ "index": "pypi",
+ "version": "==21.4.0"
+ },
+ "certifi": {
+ "hashes": [
+ "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872",
+ "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"
+ ],
+ "index": "pypi",
+ "version": "==2021.10.8"
},
"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'",
+ "index": "pypi",
"version": "==4.0.0"
},
+ "charset-normalizer": {
+ "hashes": [
+ "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597",
+ "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"
+ ],
+ "index": "pypi",
+ "version": "==2.0.12"
+ },
+ "distlib": {
+ "hashes": [
+ "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b",
+ "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"
+ ],
+ "version": "==0.3.4"
+ },
+ "filelock": {
+ "hashes": [
+ "sha256:9cd540a9352e432c7246a48fe4e8712b10acb1df2ad1f30e8c070b82ae1fed85",
+ "sha256:f8314284bfffbdcfa0ff3d7992b023d4c628ced6feb957351d4c48d059f56bc0"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==3.6.0"
+ },
+ "frozenlist": {
+ "hashes": [
+ "sha256:006d3595e7d4108a12025ddf415ae0f6c9e736e726a5db0183326fd191b14c5e",
+ "sha256:01a73627448b1f2145bddb6e6c2259988bb8aee0fb361776ff8604b99616cd08",
+ "sha256:03a7dd1bfce30216a3f51a84e6dd0e4a573d23ca50f0346634916ff105ba6e6b",
+ "sha256:0437fe763fb5d4adad1756050cbf855bbb2bf0d9385c7bb13d7a10b0dd550486",
+ "sha256:04cb491c4b1c051734d41ea2552fde292f5f3a9c911363f74f39c23659c4af78",
+ "sha256:0c36e78b9509e97042ef869c0e1e6ef6429e55817c12d78245eb915e1cca7468",
+ "sha256:25af28b560e0c76fa41f550eacb389905633e7ac02d6eb3c09017fa1c8cdfde1",
+ "sha256:2fdc3cd845e5a1f71a0c3518528bfdbfe2efaf9886d6f49eacc5ee4fd9a10953",
+ "sha256:30530930410855c451bea83f7b272fb1c495ed9d5cc72895ac29e91279401db3",
+ "sha256:31977f84828b5bb856ca1eb07bf7e3a34f33a5cddce981d880240ba06639b94d",
+ "sha256:3c62964192a1c0c30b49f403495911298810bada64e4f03249ca35a33ca0417a",
+ "sha256:3f7c935c7b58b0d78c0beea0c7358e165f95f1fd8a7e98baa40d22a05b4a8141",
+ "sha256:40dff8962b8eba91fd3848d857203f0bd704b5f1fa2b3fc9af64901a190bba08",
+ "sha256:40ec383bc194accba825fbb7d0ef3dda5736ceab2375462f1d8672d9f6b68d07",
+ "sha256:436496321dad302b8b27ca955364a439ed1f0999311c393dccb243e451ff66aa",
+ "sha256:4406cfabef8f07b3b3af0f50f70938ec06d9f0fc26cbdeaab431cbc3ca3caeaa",
+ "sha256:45334234ec30fc4ea677f43171b18a27505bfb2dba9aca4398a62692c0ea8868",
+ "sha256:47be22dc27ed933d55ee55845d34a3e4e9f6fee93039e7f8ebadb0c2f60d403f",
+ "sha256:4a44ebbf601d7bac77976d429e9bdb5a4614f9f4027777f9e54fd765196e9d3b",
+ "sha256:4eda49bea3602812518765810af732229b4291d2695ed24a0a20e098c45a707b",
+ "sha256:57f4d3f03a18facacb2a6bcd21bccd011e3b75d463dc49f838fd699d074fabd1",
+ "sha256:603b9091bd70fae7be28bdb8aa5c9990f4241aa33abb673390a7f7329296695f",
+ "sha256:65bc6e2fece04e2145ab6e3c47428d1bbc05aede61ae365b2c1bddd94906e478",
+ "sha256:691ddf6dc50480ce49f68441f1d16a4c3325887453837036e0fb94736eae1e58",
+ "sha256:6983a31698490825171be44ffbafeaa930ddf590d3f051e397143a5045513b01",
+ "sha256:6a202458d1298ced3768f5a7d44301e7c86defac162ace0ab7434c2e961166e8",
+ "sha256:6eb275c6385dd72594758cbe96c07cdb9bd6becf84235f4a594bdf21e3596c9d",
+ "sha256:754728d65f1acc61e0f4df784456106e35afb7bf39cfe37227ab00436fb38676",
+ "sha256:768efd082074bb203c934e83a61654ed4931ef02412c2fbdecea0cff7ecd0274",
+ "sha256:772965f773757a6026dea111a15e6e2678fbd6216180f82a48a40b27de1ee2ab",
+ "sha256:871d42623ae15eb0b0e9df65baeee6976b2e161d0ba93155411d58ff27483ad8",
+ "sha256:88aafd445a233dbbf8a65a62bc3249a0acd0d81ab18f6feb461cc5a938610d24",
+ "sha256:8c905a5186d77111f02144fab5b849ab524f1e876a1e75205cd1386a9be4b00a",
+ "sha256:8cf829bd2e2956066dd4de43fd8ec881d87842a06708c035b37ef632930505a2",
+ "sha256:92e650bd09b5dda929523b9f8e7f99b24deac61240ecc1a32aeba487afcd970f",
+ "sha256:93641a51f89473837333b2f8100f3f89795295b858cd4c7d4a1f18e299dc0a4f",
+ "sha256:94c7a8a9fc9383b52c410a2ec952521906d355d18fccc927fca52ab575ee8b93",
+ "sha256:9f892d6a94ec5c7b785e548e42722e6f3a52f5f32a8461e82ac3e67a3bd073f1",
+ "sha256:acb267b09a509c1df5a4ca04140da96016f40d2ed183cdc356d237286c971b51",
+ "sha256:adac9700675cf99e3615eb6a0eb5e9f5a4143c7d42c05cea2e7f71c27a3d0846",
+ "sha256:aff388be97ef2677ae185e72dc500d19ecaf31b698986800d3fc4f399a5e30a5",
+ "sha256:b5009062d78a8c6890d50b4e53b0ddda31841b3935c1937e2ed8c1bda1c7fb9d",
+ "sha256:b684c68077b84522b5c7eafc1dc735bfa5b341fb011d5552ebe0968e22ed641c",
+ "sha256:b9e3e9e365991f8cc5f5edc1fd65b58b41d0514a6a7ad95ef5c7f34eb49b3d3e",
+ "sha256:bd89acd1b8bb4f31b47072615d72e7f53a948d302b7c1d1455e42622de180eae",
+ "sha256:bde99812f237f79eaf3f04ebffd74f6718bbd216101b35ac7955c2d47c17da02",
+ "sha256:c6c321dd013e8fc20735b92cb4892c115f5cdb82c817b1e5b07f6b95d952b2f0",
+ "sha256:ce6f2ba0edb7b0c1d8976565298ad2deba6f8064d2bebb6ffce2ca896eb35b0b",
+ "sha256:d2257aaba9660f78c7b1d8fea963b68f3feffb1a9d5d05a18401ca9eb3e8d0a3",
+ "sha256:d26b650b71fdc88065b7a21f8ace70175bcf3b5bdba5ea22df4bfd893e795a3b",
+ "sha256:d6d32ff213aef0fd0bcf803bffe15cfa2d4fde237d1d4838e62aec242a8362fa",
+ "sha256:e1e26ac0a253a2907d654a37e390904426d5ae5483150ce3adedb35c8c06614a",
+ "sha256:e30b2f9683812eb30cf3f0a8e9f79f8d590a7999f731cf39f9105a7c4a39489d",
+ "sha256:e84cb61b0ac40a0c3e0e8b79c575161c5300d1d89e13c0e02f76193982f066ed",
+ "sha256:e982878792c971cbd60ee510c4ee5bf089a8246226dea1f2138aa0bb67aff148",
+ "sha256:f20baa05eaa2bcd5404c445ec51aed1c268d62600362dc6cfe04fae34a424bd9",
+ "sha256:f7353ba3367473d1d616ee727945f439e027f0bb16ac1a750219a8344d1d5d3c",
+ "sha256:f96293d6f982c58ebebb428c50163d010c2f05de0cde99fd681bfdc18d4b2dc2",
+ "sha256:ff9310f05b9d9c5c4dd472983dc956901ee6cb2c3ec1ab116ecdde25f3ce4951"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==1.3.0"
+ },
+ "gunicorn": {
+ "hashes": [
+ "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e",
+ "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"
+ ],
+ "index": "pypi",
+ "version": "==20.1.0"
+ },
"idna": {
"hashes": [
- "sha256:5205d03e7bcbb919cc9c19885f9920d622ca52448306f2377daede5cf3faac16",
- "sha256:c5b02147e01ea9920e6b0a3f1f7bb833612d507592c837a6c49552768f4054e1"
+ "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff",
+ "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"
],
- "markers": "python_version >= '3.4'",
- "version": "==3.1"
+ "index": "pypi",
+ "version": "==3.3"
},
"multidict": {
"hashes": [
- "sha256:018132dbd8688c7a69ad89c4a3f39ea2f9f33302ebe567a879da8f4ca73f0d0a",
- "sha256:051012ccee979b2b06be928a6150d237aec75dd6bf2d1eeeb190baf2b05abc93",
- "sha256:05c20b68e512166fddba59a918773ba002fdd77800cad9f55b59790030bab632",
- "sha256:07b42215124aedecc6083f1ce6b7e5ec5b50047afa701f3442054373a6deb656",
- "sha256:0e3c84e6c67eba89c2dbcee08504ba8644ab4284863452450520dad8f1e89b79",
- "sha256:0e929169f9c090dae0646a011c8b058e5e5fb391466016b39d21745b48817fd7",
- "sha256:1ab820665e67373de5802acae069a6a05567ae234ddb129f31d290fc3d1aa56d",
- "sha256:25b4e5f22d3a37ddf3effc0710ba692cfc792c2b9edfb9c05aefe823256e84d5",
- "sha256:2e68965192c4ea61fff1b81c14ff712fc7dc15d2bd120602e4a3494ea6584224",
- "sha256:2f1a132f1c88724674271d636e6b7351477c27722f2ed789f719f9e3545a3d26",
- "sha256:37e5438e1c78931df5d3c0c78ae049092877e5e9c02dd1ff5abb9cf27a5914ea",
- "sha256:3a041b76d13706b7fff23b9fc83117c7b8fe8d5fe9e6be45eee72b9baa75f348",
- "sha256:3a4f32116f8f72ecf2a29dabfb27b23ab7cdc0ba807e8459e59a93a9be9506f6",
- "sha256:46c73e09ad374a6d876c599f2328161bcd95e280f84d2060cf57991dec5cfe76",
- "sha256:46dd362c2f045095c920162e9307de5ffd0a1bfbba0a6e990b344366f55a30c1",
- "sha256:4b186eb7d6ae7c06eb4392411189469e6a820da81447f46c0072a41c748ab73f",
- "sha256:54fd1e83a184e19c598d5e70ba508196fd0bbdd676ce159feb412a4a6664f952",
- "sha256:585fd452dd7782130d112f7ddf3473ffdd521414674c33876187e101b588738a",
- "sha256:5cf3443199b83ed9e955f511b5b241fd3ae004e3cb81c58ec10f4fe47c7dce37",
- "sha256:6a4d5ce640e37b0efcc8441caeea8f43a06addace2335bd11151bc02d2ee31f9",
- "sha256:7df80d07818b385f3129180369079bd6934cf70469f99daaebfac89dca288359",
- "sha256:806068d4f86cb06af37cd65821554f98240a19ce646d3cd24e1c33587f313eb8",
- "sha256:830f57206cc96ed0ccf68304141fec9481a096c4d2e2831f311bde1c404401da",
- "sha256:929006d3c2d923788ba153ad0de8ed2e5ed39fdbe8e7be21e2f22ed06c6783d3",
- "sha256:9436dc58c123f07b230383083855593550c4d301d2532045a17ccf6eca505f6d",
- "sha256:9dd6e9b1a913d096ac95d0399bd737e00f2af1e1594a787e00f7975778c8b2bf",
- "sha256:ace010325c787c378afd7f7c1ac66b26313b3344628652eacd149bdd23c68841",
- "sha256:b47a43177a5e65b771b80db71e7be76c0ba23cc8aa73eeeb089ed5219cdbe27d",
- "sha256:b797515be8743b771aa868f83563f789bbd4b236659ba52243b735d80b29ed93",
- "sha256:b7993704f1a4b204e71debe6095150d43b2ee6150fa4f44d6d966ec356a8d61f",
- "sha256:d5c65bdf4484872c4af3150aeebe101ba560dcfb34488d9a8ff8dbcd21079647",
- "sha256:d81eddcb12d608cc08081fa88d046c78afb1bf8107e6feab5d43503fea74a635",
- "sha256:dc862056f76443a0db4509116c5cd480fe1b6a2d45512a653f9a855cc0517456",
- "sha256:ecc771ab628ea281517e24fd2c52e8f31c41e66652d07599ad8818abaad38cda",
- "sha256:f200755768dc19c6f4e2b672421e0ebb3dd54c38d5a4f262b872d8cfcc9e93b5",
- "sha256:f21756997ad8ef815d8ef3d34edd98804ab5ea337feedcd62fb52d22bf531281",
- "sha256:fc13a9524bc18b6fb6e0dbec3533ba0496bbed167c56d0aabefd965584557d80"
+ "sha256:0327292e745a880459ef71be14e709aaea2f783f3537588fb4ed09b6c01bca60",
+ "sha256:041b81a5f6b38244b34dc18c7b6aba91f9cdaf854d9a39e5ff0b58e2b5773b9c",
+ "sha256:0556a1d4ea2d949efe5fd76a09b4a82e3a4a30700553a6725535098d8d9fb672",
+ "sha256:05f6949d6169878a03e607a21e3b862eaf8e356590e8bdae4227eedadacf6e51",
+ "sha256:07a017cfa00c9890011628eab2503bee5872f27144936a52eaab449be5eaf032",
+ "sha256:0b9e95a740109c6047602f4db4da9949e6c5945cefbad34a1299775ddc9a62e2",
+ "sha256:19adcfc2a7197cdc3987044e3f415168fc5dc1f720c932eb1ef4f71a2067e08b",
+ "sha256:19d9bad105dfb34eb539c97b132057a4e709919ec4dd883ece5838bcbf262b80",
+ "sha256:225383a6603c086e6cef0f2f05564acb4f4d5f019a4e3e983f572b8530f70c88",
+ "sha256:23b616fdc3c74c9fe01d76ce0d1ce872d2d396d8fa8e4899398ad64fb5aa214a",
+ "sha256:2957489cba47c2539a8eb7ab32ff49101439ccf78eab724c828c1a54ff3ff98d",
+ "sha256:2d36e929d7f6a16d4eb11b250719c39560dd70545356365b494249e2186bc389",
+ "sha256:2e4a0785b84fb59e43c18a015ffc575ba93f7d1dbd272b4cdad9f5134b8a006c",
+ "sha256:3368bf2398b0e0fcbf46d85795adc4c259299fec50c1416d0f77c0a843a3eed9",
+ "sha256:373ba9d1d061c76462d74e7de1c0c8e267e9791ee8cfefcf6b0b2495762c370c",
+ "sha256:4070613ea2227da2bfb2c35a6041e4371b0af6b0be57f424fe2318b42a748516",
+ "sha256:45183c96ddf61bf96d2684d9fbaf6f3564d86b34cb125761f9a0ef9e36c1d55b",
+ "sha256:4571f1beddff25f3e925eea34268422622963cd8dc395bb8778eb28418248e43",
+ "sha256:47e6a7e923e9cada7c139531feac59448f1f47727a79076c0b1ee80274cd8eee",
+ "sha256:47fbeedbf94bed6547d3aa632075d804867a352d86688c04e606971595460227",
+ "sha256:497988d6b6ec6ed6f87030ec03280b696ca47dbf0648045e4e1d28b80346560d",
+ "sha256:4bae31803d708f6f15fd98be6a6ac0b6958fcf68fda3c77a048a4f9073704aae",
+ "sha256:50bd442726e288e884f7be9071016c15a8742eb689a593a0cac49ea093eef0a7",
+ "sha256:514fe2b8d750d6cdb4712346a2c5084a80220821a3e91f3f71eec11cf8d28fd4",
+ "sha256:5774d9218d77befa7b70d836004a768fb9aa4fdb53c97498f4d8d3f67bb9cfa9",
+ "sha256:5fdda29a3c7e76a064f2477c9aab1ba96fd94e02e386f1e665bca1807fc5386f",
+ "sha256:5ff3bd75f38e4c43f1f470f2df7a4d430b821c4ce22be384e1459cb57d6bb013",
+ "sha256:626fe10ac87851f4cffecee161fc6f8f9853f0f6f1035b59337a51d29ff3b4f9",
+ "sha256:6701bf8a5d03a43375909ac91b6980aea74b0f5402fbe9428fc3f6edf5d9677e",
+ "sha256:684133b1e1fe91eda8fa7447f137c9490a064c6b7f392aa857bba83a28cfb693",
+ "sha256:6f3cdef8a247d1eafa649085812f8a310e728bdf3900ff6c434eafb2d443b23a",
+ "sha256:75bdf08716edde767b09e76829db8c1e5ca9d8bb0a8d4bd94ae1eafe3dac5e15",
+ "sha256:7c40b7bbece294ae3a87c1bc2abff0ff9beef41d14188cda94ada7bcea99b0fb",
+ "sha256:8004dca28e15b86d1b1372515f32eb6f814bdf6f00952699bdeb541691091f96",
+ "sha256:8064b7c6f0af936a741ea1efd18690bacfbae4078c0c385d7c3f611d11f0cf87",
+ "sha256:89171b2c769e03a953d5969b2f272efa931426355b6c0cb508022976a17fd376",
+ "sha256:8cbf0132f3de7cc6c6ce00147cc78e6439ea736cee6bca4f068bcf892b0fd658",
+ "sha256:9cc57c68cb9139c7cd6fc39f211b02198e69fb90ce4bc4a094cf5fe0d20fd8b0",
+ "sha256:a007b1638e148c3cfb6bf0bdc4f82776cef0ac487191d093cdc316905e504071",
+ "sha256:a2c34a93e1d2aa35fbf1485e5010337c72c6791407d03aa5f4eed920343dd360",
+ "sha256:a45e1135cb07086833ce969555df39149680e5471c04dfd6a915abd2fc3f6dbc",
+ "sha256:ac0e27844758d7177989ce406acc6a83c16ed4524ebc363c1f748cba184d89d3",
+ "sha256:aef9cc3d9c7d63d924adac329c33835e0243b5052a6dfcbf7732a921c6e918ba",
+ "sha256:b9d153e7f1f9ba0b23ad1568b3b9e17301e23b042c23870f9ee0522dc5cc79e8",
+ "sha256:bfba7c6d5d7c9099ba21f84662b037a0ffd4a5e6b26ac07d19e423e6fdf965a9",
+ "sha256:c207fff63adcdf5a485969131dc70e4b194327666b7e8a87a97fbc4fd80a53b2",
+ "sha256:d0509e469d48940147e1235d994cd849a8f8195e0bca65f8f5439c56e17872a3",
+ "sha256:d16cce709ebfadc91278a1c005e3c17dd5f71f5098bfae1035149785ea6e9c68",
+ "sha256:d48b8ee1d4068561ce8033d2c344cf5232cb29ee1a0206a7b828c79cbc5982b8",
+ "sha256:de989b195c3d636ba000ee4281cd03bb1234635b124bf4cd89eeee9ca8fcb09d",
+ "sha256:e07c8e79d6e6fd37b42f3250dba122053fddb319e84b55dd3a8d6446e1a7ee49",
+ "sha256:e2c2e459f7050aeb7c1b1276763364884595d47000c1cddb51764c0d8976e608",
+ "sha256:e5b20e9599ba74391ca0cfbd7b328fcc20976823ba19bc573983a25b32e92b57",
+ "sha256:e875b6086e325bab7e680e4316d667fc0e5e174bb5611eb16b3ea121c8951b86",
+ "sha256:f4f052ee022928d34fe1f4d2bc743f32609fb79ed9c49a1710a5ad6b2198db20",
+ "sha256:fcb91630817aa8b9bc4a74023e4198480587269c272c58b3279875ed7235c293",
+ "sha256:fd9fc9c4849a07f3635ccffa895d57abce554b467d611a5009ba4f39b78a8849",
+ "sha256:feba80698173761cddd814fa22e88b0661e98cb810f9f986c54aa34d281e4937",
+ "sha256:feea820722e69451743a3d56ad74948b68bf456984d63c1a92e8347b7b88452d"
],
- "markers": "python_version >= '3.6'",
- "version": "==5.1.0"
+ "index": "pypi",
+ "version": "==6.0.2"
+ },
+ "pip": {
+ "hashes": [
+ "sha256:b3a9de2c6ef801e9247d1527a4b16f92f2cc141cd1489f3fffaf6a9e96729764",
+ "sha256:c6aca0f2f081363f689f041d90dab2a07a9a07fb840284db2218117a52da800b"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==22.0.4"
+ },
+ "pipenv": {
+ "hashes": [
+ "sha256:06e19a3a2ae7db14a317bdedc61030cdcd132a012410de1e5bdb0e19d0620465",
+ "sha256:71d510c20f99ea5cd3c951f8203140197bcc79fc21a0d74924f97c726a0f2bd3"
+ ],
+ "index": "pypi",
+ "version": "==2022.5.2"
+ },
+ "platformdirs": {
+ "hashes": [
+ "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788",
+ "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==2.5.2"
+ },
+ "pony": {
+ "hashes": [
+ "sha256:5f45fc67587f4520c560a57148cc573b097d42f82f5cb200d72c957b5708198d",
+ "sha256:608a1c1d662983bad2590e650f2bbc1cd6ed48558894ad8f50da4739ff98f614"
+ ],
+ "index": "pypi",
+ "version": "==0.7.16"
+ },
+ "psycopg2": {
+ "hashes": [
+ "sha256:06f32425949bd5fe8f625c49f17ebb9784e1e4fe928b7cce72edc36fb68e4c0c",
+ "sha256:0762c27d018edbcb2d34d51596e4346c983bd27c330218c56c4dc25ef7e819bf",
+ "sha256:083707a696e5e1c330af2508d8fab36f9700b26621ccbcb538abe22e15485362",
+ "sha256:34b33e0162cfcaad151f249c2649fd1030010c16f4bbc40a604c1cb77173dcf7",
+ "sha256:4295093a6ae3434d33ec6baab4ca5512a5082cc43c0505293087b8a46d108461",
+ "sha256:8cf3878353cc04b053822896bc4922b194792df9df2f1ad8da01fb3043602126",
+ "sha256:8e841d1bf3434da985cc5ef13e6f75c8981ced601fd70cc6bf33351b91562981",
+ "sha256:9572e08b50aed176ef6d66f15a21d823bb6f6d23152d35e8451d7d2d18fdac56",
+ "sha256:a81e3866f99382dfe8c15a151f1ca5fde5815fde879348fe5a9884a7c092a305",
+ "sha256:cb10d44e6694d763fa1078a26f7f6137d69f555a78ec85dc2ef716c37447e4b2",
+ "sha256:d3ca6421b942f60c008f81a3541e8faf6865a28d5a9b48544b0ee4f40cac7fca"
+ ],
+ "index": "pypi",
+ "version": "==2.9.3"
+ },
+ "requests": {
+ "hashes": [
+ "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61",
+ "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d"
+ ],
+ "index": "pypi",
+ "version": "==2.27.1"
+ },
+ "setuptools": {
+ "hashes": [
+ "sha256:26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8",
+ "sha256:47c7b0c0f8fc10eec4cf1e71c6fdadf8decaa74ffa087e68cd1c20db7ad6a592"
+ ],
+ "markers": "python_version >= '3.7'",
+ "version": "==62.1.0"
+ },
+ "six": {
+ "hashes": [
+ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
+ "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==1.16.0"
},
"typing-extensions": {
"hashes": [
- "sha256:7cb407020f00f7bfc3cb3e7881628838e69d8f3fcab2f64742a5e76b2f841918",
- "sha256:99d4073b617d30288f569d3f13d2bd7548c3a7e4c8de87db09a9d29bb3a4a60c",
- "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"
+ "sha256:6657594ee297170d19f67d55c05852a874e7eb634f4f753dbd667855e07c1708",
+ "sha256:f1c24655a0da0d1b67f07e17a5e6b2a105894e6824b92096378bb3668ef02376"
+ ],
+ "index": "pypi",
+ "version": "==4.2.0"
+ },
+ "urllib3": {
+ "hashes": [
+ "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14",
+ "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"
+ ],
+ "index": "pypi",
+ "version": "==1.26.9"
+ },
+ "virtualenv": {
+ "hashes": [
+ "sha256:e617f16e25b42eb4f6e74096b9c9e37713cf10bf30168fb4a739f3fa8f898a3a",
+ "sha256:ef589a79795589aada0c1c5b319486797c03b67ac3984c48c669c0e4f50df3a5"
+ ],
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'",
+ "version": "==20.14.1"
+ },
+ "virtualenv-clone": {
+ "hashes": [
+ "sha256:418ee935c36152f8f153c79824bb93eaf6f0f7984bae31d3f48f350b9183501a",
+ "sha256:44d5263bceed0bac3e1424d64f798095233b64def1c5689afa43dc3223caf5b0"
],
- "version": "==3.7.4.3"
+ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+ "version": "==0.5.7"
},
"yarl": {
"hashes": [
- "sha256:00d7ad91b6583602eb9c1d085a2cf281ada267e9a197e8b7cae487dadbfa293e",
- "sha256:0355a701b3998dcd832d0dc47cc5dedf3874f966ac7f870e0f3a6788d802d434",
- "sha256:15263c3b0b47968c1d90daa89f21fcc889bb4b1aac5555580d74565de6836366",
- "sha256:2ce4c621d21326a4a5500c25031e102af589edb50c09b321049e388b3934eec3",
- "sha256:31ede6e8c4329fb81c86706ba8f6bf661a924b53ba191b27aa5fcee5714d18ec",
- "sha256:324ba3d3c6fee56e2e0b0d09bf5c73824b9f08234339d2b788af65e60040c959",
- "sha256:329412812ecfc94a57cd37c9d547579510a9e83c516bc069470db5f75684629e",
- "sha256:4736eaee5626db8d9cda9eb5282028cc834e2aeb194e0d8b50217d707e98bb5c",
- "sha256:4953fb0b4fdb7e08b2f3b3be80a00d28c5c8a2056bb066169de00e6501b986b6",
- "sha256:4c5bcfc3ed226bf6419f7a33982fb4b8ec2e45785a0561eb99274ebbf09fdd6a",
- "sha256:547f7665ad50fa8563150ed079f8e805e63dd85def6674c97efd78eed6c224a6",
- "sha256:5b883e458058f8d6099e4420f0cc2567989032b5f34b271c0827de9f1079a424",
- "sha256:63f90b20ca654b3ecc7a8d62c03ffa46999595f0167d6450fa8383bab252987e",
- "sha256:68dc568889b1c13f1e4745c96b931cc94fdd0defe92a72c2b8ce01091b22e35f",
- "sha256:69ee97c71fee1f63d04c945f56d5d726483c4762845400a6795a3b75d56b6c50",
- "sha256:6d6283d8e0631b617edf0fd726353cb76630b83a089a40933043894e7f6721e2",
- "sha256:72a660bdd24497e3e84f5519e57a9ee9220b6f3ac4d45056961bf22838ce20cc",
- "sha256:73494d5b71099ae8cb8754f1df131c11d433b387efab7b51849e7e1e851f07a4",
- "sha256:7356644cbed76119d0b6bd32ffba704d30d747e0c217109d7979a7bc36c4d970",
- "sha256:8a9066529240171b68893d60dca86a763eae2139dd42f42106b03cf4b426bf10",
- "sha256:8aa3decd5e0e852dc68335abf5478a518b41bf2ab2f330fe44916399efedfae0",
- "sha256:97b5bdc450d63c3ba30a127d018b866ea94e65655efaf889ebeabc20f7d12406",
- "sha256:9ede61b0854e267fd565e7527e2f2eb3ef8858b301319be0604177690e1a3896",
- "sha256:b2e9a456c121e26d13c29251f8267541bd75e6a1ccf9e859179701c36a078643",
- "sha256:b5dfc9a40c198334f4f3f55880ecf910adebdcb2a0b9a9c23c9345faa9185721",
- "sha256:bafb450deef6861815ed579c7a6113a879a6ef58aed4c3a4be54400ae8871478",
- "sha256:c49ff66d479d38ab863c50f7bb27dee97c6627c5fe60697de15529da9c3de724",
- "sha256:ce3beb46a72d9f2190f9e1027886bfc513702d748047b548b05dab7dfb584d2e",
- "sha256:d26608cf178efb8faa5ff0f2d2e77c208f471c5a3709e577a7b3fd0445703ac8",
- "sha256:d597767fcd2c3dc49d6eea360c458b65643d1e4dbed91361cf5e36e53c1f8c96",
- "sha256:d5c32c82990e4ac4d8150fd7652b972216b204de4e83a122546dce571c1bdf25",
- "sha256:d8d07d102f17b68966e2de0e07bfd6e139c7c02ef06d3a0f8d2f0f055e13bb76",
- "sha256:e46fba844f4895b36f4c398c5af062a9808d1f26b2999c58909517384d5deda2",
- "sha256:e6b5460dc5ad42ad2b36cca524491dfcaffbfd9c8df50508bddc354e787b8dc2",
- "sha256:f040bcc6725c821a4c0665f3aa96a4d0805a7aaf2caf266d256b8ed71b9f041c",
- "sha256:f0b059678fd549c66b89bed03efcabb009075bd131c248ecdf087bdb6faba24a",
- "sha256:fcbb48a93e8699eae920f8d92f7160c03567b421bc17362a9ffbbd706a816f71"
+ "sha256:044daf3012e43d4b3538562da94a88fb12a6490652dbc29fb19adfa02cf72eac",
+ "sha256:0cba38120db72123db7c58322fa69e3c0efa933040ffb586c3a87c063ec7cae8",
+ "sha256:167ab7f64e409e9bdd99333fe8c67b5574a1f0495dcfd905bc7454e766729b9e",
+ "sha256:1be4bbb3d27a4e9aa5f3df2ab61e3701ce8fcbd3e9846dbce7c033a7e8136746",
+ "sha256:1ca56f002eaf7998b5fcf73b2421790da9d2586331805f38acd9997743114e98",
+ "sha256:1d3d5ad8ea96bd6d643d80c7b8d5977b4e2fb1bab6c9da7322616fd26203d125",
+ "sha256:1eb6480ef366d75b54c68164094a6a560c247370a68c02dddb11f20c4c6d3c9d",
+ "sha256:1edc172dcca3f11b38a9d5c7505c83c1913c0addc99cd28e993efeaafdfaa18d",
+ "sha256:211fcd65c58bf250fb994b53bc45a442ddc9f441f6fec53e65de8cba48ded986",
+ "sha256:29e0656d5497733dcddc21797da5a2ab990c0cb9719f1f969e58a4abac66234d",
+ "sha256:368bcf400247318382cc150aaa632582d0780b28ee6053cd80268c7e72796dec",
+ "sha256:39d5493c5ecd75c8093fa7700a2fb5c94fe28c839c8e40144b7ab7ccba6938c8",
+ "sha256:3abddf0b8e41445426d29f955b24aeecc83fa1072be1be4e0d194134a7d9baee",
+ "sha256:3bf8cfe8856708ede6a73907bf0501f2dc4e104085e070a41f5d88e7faf237f3",
+ "sha256:3ec1d9a0d7780416e657f1e405ba35ec1ba453a4f1511eb8b9fbab81cb8b3ce1",
+ "sha256:45399b46d60c253327a460e99856752009fcee5f5d3c80b2f7c0cae1c38d56dd",
+ "sha256:52690eb521d690ab041c3919666bea13ab9fbff80d615ec16fa81a297131276b",
+ "sha256:534b047277a9a19d858cde163aba93f3e1677d5acd92f7d10ace419d478540de",
+ "sha256:580c1f15500e137a8c37053e4cbf6058944d4c114701fa59944607505c2fe3a0",
+ "sha256:59218fef177296451b23214c91ea3aba7858b4ae3306dde120224cfe0f7a6ee8",
+ "sha256:5ba63585a89c9885f18331a55d25fe81dc2d82b71311ff8bd378fc8004202ff6",
+ "sha256:5bb7d54b8f61ba6eee541fba4b83d22b8a046b4ef4d8eb7f15a7e35db2e1e245",
+ "sha256:6152224d0a1eb254f97df3997d79dadd8bb2c1a02ef283dbb34b97d4f8492d23",
+ "sha256:67e94028817defe5e705079b10a8438b8cb56e7115fa01640e9c0bb3edf67332",
+ "sha256:695ba021a9e04418507fa930d5f0704edbce47076bdcfeeaba1c83683e5649d1",
+ "sha256:6a1a9fe17621af43e9b9fcea8bd088ba682c8192d744b386ee3c47b56eaabb2c",
+ "sha256:6ab0c3274d0a846840bf6c27d2c60ba771a12e4d7586bf550eefc2df0b56b3b4",
+ "sha256:6feca8b6bfb9eef6ee057628e71e1734caf520a907b6ec0d62839e8293e945c0",
+ "sha256:737e401cd0c493f7e3dd4db72aca11cfe069531c9761b8ea474926936b3c57c8",
+ "sha256:788713c2896f426a4e166b11f4ec538b5736294ebf7d5f654ae445fd44270832",
+ "sha256:797c2c412b04403d2da075fb93c123df35239cd7b4cc4e0cd9e5839b73f52c58",
+ "sha256:8300401dc88cad23f5b4e4c1226f44a5aa696436a4026e456fe0e5d2f7f486e6",
+ "sha256:87f6e082bce21464857ba58b569370e7b547d239ca22248be68ea5d6b51464a1",
+ "sha256:89ccbf58e6a0ab89d487c92a490cb5660d06c3a47ca08872859672f9c511fc52",
+ "sha256:8b0915ee85150963a9504c10de4e4729ae700af11df0dc5550e6587ed7891e92",
+ "sha256:8cce6f9fa3df25f55521fbb5c7e4a736683148bcc0c75b21863789e5185f9185",
+ "sha256:95a1873b6c0dd1c437fb3bb4a4aaa699a48c218ac7ca1e74b0bee0ab16c7d60d",
+ "sha256:9b4c77d92d56a4c5027572752aa35082e40c561eec776048330d2907aead891d",
+ "sha256:9bfcd43c65fbb339dc7086b5315750efa42a34eefad0256ba114cd8ad3896f4b",
+ "sha256:9c1f083e7e71b2dd01f7cd7434a5f88c15213194df38bc29b388ccdf1492b739",
+ "sha256:a1d0894f238763717bdcfea74558c94e3bc34aeacd3351d769460c1a586a8b05",
+ "sha256:a467a431a0817a292121c13cbe637348b546e6ef47ca14a790aa2fa8cc93df63",
+ "sha256:aa32aaa97d8b2ed4e54dc65d241a0da1c627454950f7d7b1f95b13985afd6c5d",
+ "sha256:ac10bbac36cd89eac19f4e51c032ba6b412b3892b685076f4acd2de18ca990aa",
+ "sha256:ac35ccde589ab6a1870a484ed136d49a26bcd06b6a1c6397b1967ca13ceb3913",
+ "sha256:bab827163113177aee910adb1f48ff7af31ee0289f434f7e22d10baf624a6dfe",
+ "sha256:baf81561f2972fb895e7844882898bda1eef4b07b5b385bcd308d2098f1a767b",
+ "sha256:bf19725fec28452474d9887a128e98dd67eee7b7d52e932e6949c532d820dc3b",
+ "sha256:c01a89a44bb672c38f42b49cdb0ad667b116d731b3f4c896f72302ff77d71656",
+ "sha256:c0910c6b6c31359d2f6184828888c983d54d09d581a4a23547a35f1d0b9484b1",
+ "sha256:c10ea1e80a697cf7d80d1ed414b5cb8f1eec07d618f54637067ae3c0334133c4",
+ "sha256:c1164a2eac148d85bbdd23e07dfcc930f2e633220f3eb3c3e2a25f6148c2819e",
+ "sha256:c145ab54702334c42237a6c6c4cc08703b6aa9b94e2f227ceb3d477d20c36c63",
+ "sha256:c17965ff3706beedafd458c452bf15bac693ecd146a60a06a214614dc097a271",
+ "sha256:c19324a1c5399b602f3b6e7db9478e5b1adf5cf58901996fc973fe4fccd73eed",
+ "sha256:c2a1ac41a6aa980db03d098a5531f13985edcb451bcd9d00670b03129922cd0d",
+ "sha256:c6ddcd80d79c96eb19c354d9dca95291589c5954099836b7c8d29278a7ec0bda",
+ "sha256:c9c6d927e098c2d360695f2e9d38870b2e92e0919be07dbe339aefa32a090265",
+ "sha256:cc8b7a7254c0fc3187d43d6cb54b5032d2365efd1df0cd1749c0c4df5f0ad45f",
+ "sha256:cff3ba513db55cc6a35076f32c4cdc27032bd075c9faef31fec749e64b45d26c",
+ "sha256:d260d4dc495c05d6600264a197d9d6f7fc9347f21d2594926202fd08cf89a8ba",
+ "sha256:d6f3d62e16c10e88d2168ba2d065aa374e3c538998ed04996cd373ff2036d64c",
+ "sha256:da6df107b9ccfe52d3a48165e48d72db0eca3e3029b5b8cb4fe6ee3cb870ba8b",
+ "sha256:dfe4b95b7e00c6635a72e2d00b478e8a28bfb122dc76349a06e20792eb53a523",
+ "sha256:e39378894ee6ae9f555ae2de332d513a5763276a9265f8e7cbaeb1b1ee74623a",
+ "sha256:ede3b46cdb719c794427dcce9d8beb4abe8b9aa1e97526cc20de9bd6583ad1ef",
+ "sha256:f2a8508f7350512434e41065684076f640ecce176d262a7d54f0da41d99c5a95",
+ "sha256:f44477ae29025d8ea87ec308539f95963ffdc31a82f42ca9deecf2d505242e72",
+ "sha256:f64394bd7ceef1237cc604b5a89bf748c95982a84bcd3c4bbeb40f685c810794",
+ "sha256:fc4dd8b01a8112809e6b636b00f487846956402834a7fd59d46d4f4267181c41",
+ "sha256:fce78593346c014d0d986b7ebc80d782b7f5e19843ca798ed62f8e3ba8728576",
+ "sha256:fd547ec596d90c8676e369dd8a581a21227fe9b4ad37d0dc7feb4ccf544c2d59"
],
- "markers": "python_version >= '3.6'",
- "version": "==1.6.3"
+ "index": "pypi",
+ "version": "==1.7.2"
}
},
"develop": {}
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..d5e2bb1
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: python server.py
\ No newline at end of file
diff --git a/bpmn_model.py b/bpmn_model.py
index 6ebe0be..e223359 100644
--- a/bpmn_model.py
+++ b/bpmn_model.py
@@ -1,3 +1,5 @@
+from asyncio import get_running_loop
+from concurrent.futures import ThreadPoolExecutor
from types import SimpleNamespace
import xml.etree.ElementTree as ET
from bpmn_types import *
@@ -11,12 +13,10 @@
import os
from uuid import uuid4
import env
+from bpmn_types import Task, ServiceTask
-instance_models = {}
-
-def get_model_for_instance(iid):
- return instance_models.get(iid, None)
+# thread_pool = ThreadPoolExecutor(max_workers=100)
class UserFormMessage:
@@ -25,6 +25,12 @@ def __init__(self, task_id, form_data={}):
self.form_data = form_data
+class ReceiveMessage:
+ def __init__(self, task_id, data={}):
+ self.task_id = task_id
+ self.data = data or {}
+
+
class BpmnModel:
def __init__(self, model_path):
self.pending = []
@@ -77,17 +83,24 @@ def __init__(self, model_path):
break
def to_json(self):
+ tasks = [x.to_json() for x in self.elements.values() if isinstance(x, UserTask) or isinstance(x, ReceiveTask)]
return {
"model_path": self.model_path,
"main_process": self.main_process.__dict__,
- "tasks": [
- x.to_json() for x in self.elements.values() if isinstance(x, UserTask)
- ],
+ "tasks": tasks,
"instances": [i._id for i in self.instances.values()],
}
- async def create_instance(self, _id, variables, process=None):
+ async def create_or_get_instance(self, _id, variables, process=None, initial=None):
+ if _id in self.instances:
+ return self.instances[_id]
+ instance = await self.create_instance(_id, variables, process=None, initial=None)
+ return instance
+
+ async def create_instance(self, _id, variables, process=None, initial=None):
queue = asyncio.Queue()
+ if initial:
+ queue.put_nowait(initial)
if not process:
if self.main_collaboration_process:
# If Collaboration diagram
@@ -95,10 +108,14 @@ async def create_instance(self, _id, variables, process=None):
else:
# If Process diagram
process = list(self.process_elements)[0]
+ instance = await self.instance_obj(_id, process, queue, variables)
+ self.instances[_id] = instance
+ return instance
+
+ async def instance_obj(self, _id, process, queue, variables):
instance = BpmnInstance(
_id, model=self, variables=variables, in_queue=queue, process=process
)
- self.instances[_id] = instance
return instance
# Takes model_path needed for deployed subprocess
@@ -122,7 +139,7 @@ def handle_deployment_subprocesses(self):
class BpmnInstance:
def __init__(self, _id, model, variables, in_queue, process):
- instance_models[_id] = model
+ # instance_models[_id] = model
self._id = _id
self.model = model
self.variables = deepcopy(variables)
@@ -131,6 +148,7 @@ def __init__(self, _id, model, variables, in_queue, process):
self.pending = deepcopy(self.model.process_pending[process])
self.process = process
+
def to_json(self):
return {
"id": self._id,
@@ -148,12 +166,18 @@ def check_condition(cls, state, condition, log):
if condition:
key = condition.partition(":")[0]
value = condition.partition(":")[2]
- if key in state and state[key] == value:
+
+ if key in state and str(state[key]).upper() == str(value).upper():
ok = True
log("\t DONE: Result is", ok)
return ok
- async def run_from_log(self, log):
+ async def run_from_log(self, log,state):
+ if self.state == "running" or self.state == "finished":
+ return self
+ if state == "running" or state == "finished":
+ return self
+
for l in log:
if l.get("activity_id") in self.model.elements:
pending_elements_list = []
@@ -163,26 +187,19 @@ async def run_from_log(self, log):
self.variables = {**l.get("activity_variables"), **self.variables}
return self
- async def run_subprocess(self, process_id):
- new_subproces_instance_id = str(uuid4())
- if not self.model.subprocesses[process_id]:
- new_subprocess_instance = await self.model.create_instance(
- new_subproces_instance_id, {}, process_id
- )
- finished_subprocess = await new_subprocess_instance.run()
- else:
- subprocess_model = BpmnModel(self.model.subprocesses[process_id])
- new_subproces_instance = await subprocess_model.create_instance(
- new_subproces_instance_id, {}, process_id
- )
- finished_subprocess = await new_subproces_instance.run()
- return True
-
- async def run(self):
+ # async def run(self, is_subprocess=False):
+ # def task():
+ # await self._run(is_subprocess=is_subprocess)
+ #
+ # vars = (get_running_loop().run_in_executor(thread_pool, lambda: task(), ))
+ # return vars
+
+ async def run(self, is_subprocess=False):
self.state = "running"
_id = self._id
prefix = f"\t[{_id}]"
+
log = partial(print, prefix) # if _id == "2" else lambda *x: x
in_queue = self.in_queue
@@ -220,7 +237,7 @@ async def run(self):
}
current_and_variables_dict[current._id] = new_variables
# Create new running instance
- db_connector.add_running_instance(instance_id=self._id)
+ db_connector.add_running_instance(instance_id=self._id, state=self.state, ran_as_subprocess=is_subprocess)
if isinstance(current, EndEvent):
exit = True
@@ -232,15 +249,15 @@ async def run(self):
activity_id=current._id,
timestamp=datetime.now(),
pending=[],
- activity_variables={},
+ activity_variables=self.variables,
)
break
if isinstance(current, UserTask):
if (
- message
- and isinstance(message, UserFormMessage)
- and message.task_id == current._id
+ message
+ and isinstance(message, UserFormMessage)
+ and message.task_id == current._id
):
user_action = message.form_data
@@ -257,6 +274,7 @@ async def run(self):
elif isinstance(current, ServiceTask):
log("DOING:", current)
+
can_continue = await current.run(self.variables, _id)
# Helper variables for DB insert
new_variables = {
@@ -274,11 +292,26 @@ async def run(self):
for k in set(self.variables) - set(before_variables)
}
current_and_variables_dict[current._id] = new_variables
+ elif isinstance(current, ReceiveTask):
+ if (
+ message
+ and isinstance(message, ReceiveMessage)
+ and message.task_id == current._id
+ ):
+ log("DOING:", current)
+ can_continue = current.run(self.variables, message.data)
+ # Helper variables for DB insert
+ new_variables = {
+ k: self.variables[k]
+ for k in set(self.variables) - set(before_variables)
+ }
+ current_and_variables_dict[current._id] = new_variables
elif isinstance(current, CallActivity):
- # TODO implement Variables tab CallActivity
+
log("DOING:", current)
- can_continue = await self.run_subprocess(current.called_element)
+ can_continue = await current.run_subprocess(self.model, current.called_element, self.variables)
+ # log("SUBPROCESS DONE WITH VARIABLES\n" + "---> " + str(self.variables))
# Helper variables for DB insert
new_variables = {
k: self.variables[k]
@@ -316,9 +349,10 @@ async def run(self):
continue
if sequence.condition:
- if self.check_condition(
+ cond = self.check_condition(
self.variables, sequence.condition, log
- ):
+ )
+ if cond:
next_tasks.append(elements[sequence.target])
else:
next_tasks.append(elements[sequence.target])
@@ -335,7 +369,9 @@ async def run(self):
if isinstance(next_task, ParallelGateway):
next_task.add_token()
else:
+
log("Waiting for user...", self.pending)
+
queue.append(await in_queue.get())
# Insert finished events into DB
@@ -349,10 +385,13 @@ async def run(self):
pending=[pending._id for pending in self.pending],
activity_variables=current_and_variables_dict[c],
)
+ if not is_subprocess:
+ log("WORKFLOW DONE WITH VARIABLES\n" + "---> ")
- log("DONE")
self.state = "finished"
+ db_connector.change_instance_state(self._id,state=self.state)
self.pending = []
# Running instance finished
db_connector.finish_running_instance(self._id)
+
return self.variables
diff --git a/bpmn_types.py b/bpmn_types.py
index 21f0cab..6944f01 100644
--- a/bpmn_types.py
+++ b/bpmn_types.py
@@ -1,7 +1,20 @@
+import asyncio
+from copy import deepcopy
+from uuid import uuid4
+from xml import etree
+
+import aiohttp
import requests
import os
+
+import xml.etree.ElementTree as ET
+
+from aiohttp import ContentTypeError, ClientSession, ClientTimeout
+
import env
-from utils.common import parse_expression
+from bpmn_model import *
+
+from utils.common import parse_expression, nested_dict_get, nested_dict_set
NS = {
"bpmn": "http://www.omg.org/spec/BPMN/20100524/MODEL",
@@ -10,6 +23,8 @@
BPMN_MAPPINGS = {}
+timeout = ClientTimeout(sock_connect=5)
+
def bpmn_tag(tag):
def wrap(object):
@@ -82,6 +97,30 @@ class Task(BpmnObject):
def parse(self, element):
super(Task, self).parse(element)
+ def _parse_input_output_variables(self, element, input_dict, output_dict):
+ for io in element.findall(".camunda:inputOutput", NS):
+ for inparam in io.findall(".camunda:inputParameter", NS):
+ self._parse_input_output_parameters(inparam, input_dict)
+ for outparam in io.findall(".camunda:outputParameter", NS):
+ self._parse_input_output_parameters(outparam, output_dict)
+
+ def _parse_input_output_parameters(self, element, dictionary):
+ if element.findall(".camunda:list", NS):
+ helper_list = []
+ for lv in element.find("camunda:list", NS):
+ helper_list.append(lv.text) if lv.text else ""
+ dictionary[element.attrib["name"]] = helper_list
+ elif element.findall(".camunda:map", NS):
+ helper_dict = {}
+ for mv in element.find("camunda:map", NS):
+ helper_dict[mv.attrib["key"]] = mv.text
+ dictionary[element.attrib["name"]] = helper_dict
+ elif element.findall(".camunda:script", NS):
+ # script not supported
+ pass
+ else:
+ dictionary[element.attrib["name"]] = element.text if element.text else ""
+
def get_info(self):
return {"type": self.tag}
@@ -178,30 +217,6 @@ def parse(self, element):
self.connector_fields["connector_id"] = ds["type"]
self.connector_fields["input_variables"]["base_url"] = ds["url"]
- def _parse_input_output_variables(self, element, input_dict, output_dict):
- for io in element.findall(".camunda:inputOutput", NS):
- for inparam in io.findall(".camunda:inputParameter", NS):
- self._parse_input_output_parameters(inparam, input_dict)
- for outparam in io.findall(".camunda:outputParameter", NS):
- self._parse_input_output_parameters(outparam, output_dict)
-
- def _parse_input_output_parameters(self, element, dictionary):
- if element.findall(".camunda:list", NS):
- helper_list = []
- for lv in element.find("camunda:list", NS):
- helper_list.append(lv.text) if lv.text else ""
- dictionary[element.attrib["name"]] = helper_list
- elif element.findall(".camunda:map", NS):
- helper_dict = {}
- for mv in element.find("camunda:map", NS):
- helper_dict[mv.attrib["key"]] = mv.text
- dictionary[element.attrib["name"]] = helper_dict
- elif element.findall(".camunda:script", NS):
- # script not supported
- pass
- else:
- dictionary[element.attrib["name"]] = element.text if element.text else ""
-
async def run_connector(self, variables, instance_id):
# Check for URL parameters
parameters = {}
@@ -214,8 +229,9 @@ async def run_connector(self, variables, instance_id):
# JSON data for API
data = {}
- for key, value in self.input_variables.items():
+ for key, val in self.input_variables.items():
# Parse expression if it exists
+ value = val or key
if isinstance(value, str):
value = parse_expression(value, variables)
elif isinstance(value, list):
@@ -233,37 +249,59 @@ async def run_connector(self, variables, instance_id):
url = os.path.join(
self.connector_fields["input_variables"].get("base_url", ""),
- self.connector_fields["input_variables"]["url"].lstrip("/"),
+ (self.connector_fields["input_variables"].get("url") or "").lstrip("/"),
)
# Check method and make request
- if method := self.connector_fields["input_variables"].get("method"):
- if method == "POST":
- call_function = requests.post
- elif method == "PATCH":
- call_function = requests.patch
- else:
- call_function = requests.get
-
- response = call_function(
- url,
- params=parameters,
- json=data,
- )
-
- if response.status_code not in (200, 201):
- raise Exception(response.text)
-
- # Check for output variables
- if self.output_variables:
- r = response.json()
- for key in self.output_variables:
- if key in r:
- variables[key] = r[key]
+ async with aiohttp.ClientSession(timeout=timeout) as client_session:
+ if method := self.connector_fields["input_variables"].get("method") or "GET":
+ if method == "POST":
+ call_function = client_session.post
+ elif method == "PATCH":
+ call_function = client_session.patch
+ else:
+ call_function = client_session.get
+ if not isinstance(data, dict):
+ data = dict(data)
+ response = await call_function(
+ url,
+ params=parameters,
+ json=data,
+ headers={'content-type': 'application/json'}
+ )
+ if response.status not in (200, 201):
+ raise Exception(response.text)
+
+ r = {}
+ try:
+ r = await response.json()
+ except Exception as e:
+ print("error")
+ if not isinstance(e, ContentTypeError):
+ raise e
+
+ # Check for output variables
+
+ if self.output_variables:
+ for key in self.output_variables:
+ value = self.output_variables.get(key)
+ try:
+ if len(value) > 0:
+ variables[key] = parse_expression(expression=value, process_variables=r)
+ except Exception:
+ print("error")
+ if key in r:
+ variables[key] = r[key]
+
+ # print(variables)
+ return r
async def run(self, variables, instance_id):
- if self.connector_fields["connector_id"] == "http-connector":
+
+ if self.connector_fields["connector_id"] == "http-connector" and len(self.connector_fields["connector_id"]) > 0:
await self.run_connector(variables, instance_id)
+ else:
+ return False
return True
@@ -273,23 +311,132 @@ def parse(self, element):
super(SendTask, self).parse(element)
+@bpmn_tag("bpmn:receiveTask")
+class ReceiveTask(Task):
+ def __init__(self):
+ self.documentation = ""
+ self.input_variables = {}
+ self.output_variables = {}
+
+ def parse(self, element):
+
+ super(ReceiveTask, self).parse(element)
+ for ee in element.findall(".//bpmn:extensionElements", NS):
+ # Find direct children inputOutput, Input/Output tab in Camunda
+ self._parse_input_output_variables(
+ ee, self.input_variables, self.output_variables
+ )
+ for d in element.findall(".//bpmn:documentation", NS):
+ self.documentation = d.text
+
+ def run(self, state, user_input):
+ if isinstance(state, dict) and isinstance(user_input, dict):
+ for key in self.output_variables:
+ if key in user_input:
+ state[key] = user_input[key]
+ return True
+
+ def get_info(self):
+ info = super(ReceiveTask, self).get_info()
+ return {
+ **info,
+ "documentation": self.documentation,
+ }
+
+
@bpmn_tag("bpmn:callActivity")
class CallActivity(Task):
def __init__(self):
+ super().__init__()
self.deployment = False
self.called_element = ""
+ self.output_variables = {}
+ self.input_variables = {}
+ #
+ # {source:target}
+ self.in_mapping = {}
+ self.out_mapping = {}
def parse(self, element):
super(CallActivity, self).parse(element)
if element.attrib.get("calledElement"):
self.called_element = element.attrib["calledElement"]
if (
- element.attrib.get(f"{{{NS['camunda']}}}calledElementBinding")
- and element.attrib.get(f"{{{NS['camunda']}}}calledElementBinding")
- == "deployment"
+ element.attrib.get(f"{{{NS['camunda']}}}calledElementBinding")
+ and element.attrib.get(f"{{{NS['camunda']}}}calledElementBinding")
+ == "deployment"
):
self.deployment = True
+ for ee in element.findall(".//bpmn:extensionElements", NS):
+ # Find direct children inputOutput, Input/Output tab in Camunda
+ self._parse_mappings(ee, self.in_mapping, self.out_mapping)
+
+ self._parse_input_output_variables(
+ ee, self.input_variables, self.output_variables
+ )
+
+ def transform_input_variables(self, dict_to_transform):
+ for source, target in self.in_mapping.items():
+ if "." in str(source):
+ nested_value = nested_dict_get(dict_to_transform, str(source))
+ dict_to_transform.pop(str(source).split(".")[0])
+ dict_to_transform[target] = nested_value
+ if source in self.input_variables:
+ dict_to_transform[target] = dict_to_transform.pop(source)
+
+ def transform_output_variables(self, dict_to_transform):
+ for source, target in self.out_mapping.items():
+ if "." in str(source):
+ nested_value = nested_dict_get(dict_to_transform, str(source))
+ dict_to_transform[target] = nested_value
+ if source in dict_to_transform:
+ dict_to_transform[target] = dict_to_transform.pop(source)
+
+ def _parse_mappings(self, ee, in_dict, out_dict):
+ for io in ee.findall(".camunda:in", NS):
+ self._parse_in_out_mapping(io, in_dict)
+ for out in ee.findall(".camunda:out", NS):
+ self._parse_in_out_mapping(out, out_dict)
+
+ def _parse_in_out_mapping(self, element, dictionary):
+ dictionary[element.attrib["source"]] = element.attrib["target"]
+
+ async def run_subprocess(self, parent_model, process_id, parent_variables):
+ new_subproces_instance_id = str(uuid4())
+ inital_variables = {}
+ copied = deepcopy(parent_variables)
+ self.transform_input_variables(copied)
+ for key in self.input_variables:
+ if key in copied:
+ inital_variables[key] = copied[key]
+
+ if not parent_model.subprocesses[process_id]:
+ new_subprocess_instance: BpmnInstance = await parent_model.create_instance(
+ new_subproces_instance_id, inital_variables, process_id
+ )
+
+ finished_subprocess_variables = await new_subprocess_instance.run(is_subprocess=True)
+ else:
+ subprocess_model = BpmnModel(parent_model.subprocesses[process_id])
+ new_subprocess_instance: BpmnInstance = await subprocess_model.create_instance(
+ new_subproces_instance_id, inital_variables, process_id
+ )
+ finished_subprocess_variables = await new_subprocess_instance.run(is_subprocess=True)
+
+ if finished_subprocess_variables is not None:
+ new_vars = dict(deepcopy(finished_subprocess_variables))
+ # todo: check this
+ # if my process outputs "status" in new vars i need to transform it to "ticket_status"
+ # as im expecting "ticket_status" in output_variables
+ # lol this confused me
+ self.transform_output_variables(new_vars)
+ for key in self.output_variables:
+ if key in new_vars:
+ parent_variables[key] = new_vars[key]
+
+ return finished_subprocess_variables is not None
+
@bpmn_tag("bpmn:businessRule")
class BusinessRule(ServiceTask):
@@ -332,6 +479,11 @@ def run(self):
return self.incoming == 0
+@bpmn_tag("bpmn:inclusiveGateway")
+class InclusiveGateway(Gateway):
+ pass
+
+
@bpmn_tag("bpmn:exclusiveGateway")
class ExclusiveGateway(Gateway):
def __init__(self):
diff --git a/db_connector.py b/db_connector.py
index 716d5e7..14550f5 100644
--- a/db_connector.py
+++ b/db_connector.py
@@ -1,5 +1,10 @@
+from typing import Union, Any
+
from pony.orm import *
from datetime import datetime
+
+from pony.orm.core import EntityMeta
+
import env
import os
@@ -16,8 +21,11 @@ class Event(DB.Entity):
class RunningInstance(DB.Entity):
- running = Required(bool)
+ state = Required(str)
+ ran_as_subprocess = Required(bool)
instance_id = Required(str, unique=True)
+ # maybe need this
+ # initiator_instance_id = Optional(str)
def setup_db():
@@ -26,13 +34,13 @@ def setup_db():
if env.DB["provider"] == "postgres":
DB.bind(**env.DB)
else:
- DB.bind(provider="sqlite", filename="database/database.sqlite", create_db=True)
+ DB.bind(provider="sqlite", filename="database/database2.sqlite", create_db=True)
DB.generate_mapping(create_tables=True)
@db_session
def add_event(
- model_name, instance_id, activity_id, timestamp, pending, activity_variables
+ model_name, instance_id, activity_id, timestamp, pending, activity_variables
):
Event(
model_name=model_name,
@@ -45,8 +53,13 @@ def add_event(
@db_session
-def add_running_instance(instance_id):
- RunningInstance(instance_id=instance_id, running=True)
+def add_running_instance(instance_id, ran_as_subprocess=False, state="initialized"):
+ RunningInstance(instance_id=instance_id, state=state, ran_as_subprocess=ran_as_subprocess)
+
+
+@db_session
+def change_instance_state(instance_id, state="initialized"):
+ RunningInstance[instance_id].state = state
@db_session
@@ -56,12 +69,21 @@ def finish_running_instance(instance):
@db_session
-def get_running_instances_log():
+def get_instances_log(state=None):
log = []
- running_instances = RunningInstance.select(lambda ri: ri.running == True)[:]
+ running_instances = None
+
+ if state is not None:
+ state_query = lambda ri: ri.state == state
+ running_instances = RunningInstance.select(state_query)[:]
+ else:
+ running_instances = RunningInstance.select()[:]
+
for instance in running_instances:
instance_dict = {}
instance_dict[instance.instance_id] = {}
+ instance_dict[instance.instance_id]["subprocess"] = instance.ran_as_subprocess
+ instance_dict[instance.instance_id]["state"] = instance.state
events = Event.select(lambda e: e.instance_id == instance.instance_id).order_by(
Event.timestamp
)[:]
@@ -79,3 +101,27 @@ def get_running_instances_log():
log.append(instance_dict)
return log
+
+
+@db_session
+def get_instance(id):
+ instance_dict = {}
+
+ db_instance: RunningInstance = RunningInstance.get(instance_id=id)
+ instance_dict["subprocess"] = db_instance.ran_as_subprocess
+ instance_dict["instance.state"] = db_instance.state
+ events = Event.select(lambda e: e.instance_id == id).order_by(
+ Event.timestamp
+ )[:]
+ events_list = []
+ for event in events:
+ model_path = event.model_name
+ event_dict = {}
+ event_dict["activity_id"] = event.activity_id
+ event_dict["pending"] = event.pending
+ event_dict["activity_variables"] = event.activity_variables
+ events_list.append(event_dict)
+ instance_dict["model_path"] = model_path
+ instance_dict["events"] = events_list
+ instance_dict["running"] = db_instance.running
+ return instance_dict
diff --git a/env.template.py b/env.template.py
index af30f60..c5d8e2a 100644
--- a/env.template.py
+++ b/env.template.py
@@ -1,13 +1,20 @@
SYSTEM_VARS = {"_frontend_url": "http://localhost:9001"}
DB = {
- "provider": "postgres",
- "user": "FILLME",
- "password": "FILLME",
+ "provider": "sqlite",
+ "user": "postgres",
+ "password": "root",
"host": "localhost",
- "database": "bpmn_praksa",
+ "database": "a2",
}
DS = {
"airtable": {"type": "http-connector", "url": "http://0.0.0.0:8082"},
"notification": {"type": "http-connector", "url": "http://0.0.0.0:8081"},
"pdf": {"type": "http-connector", "url": "http://0.0.0.0:8083"},
+ "test": {"type": "http-connector", "url": "http://212.183.159.230/"},
+ "scraper": {"type": "http-connector", "url": "http://172.17.0.1:60194"},
+ "keyword_score_service": {"type": "http-connector", "url": "http://172.17.0.1:19770"},
+ "dart_db": {"type": "http-connector", "url": "http://172.17.0.1:60194"},
+ "db_connector_python": {"type": "http-connector", "url": "http://172.17.0.1:57881"},
+ "meta_desc_gen_service": {"type": "http-connector", "url": "http://172.17.0.1:1307"},
}
+# http://212.183.159.230/
diff --git a/example.py b/example.py
index 95352cf..5972fe7 100644
--- a/example.py
+++ b/example.py
@@ -4,7 +4,7 @@
import sys
-m = BpmnModel("models/model_01.bpmn")
+m = BpmnModel("models/private/model_01.bpmn")
NUM_INSTANCES = 2
diff --git a/models/meta_desc_generator.bpmn b/models/meta_desc_generator.bpmn
new file mode 100644
index 0000000..c910eb2
--- /dev/null
+++ b/models/meta_desc_generator.bpmn
@@ -0,0 +1,223 @@
+
+
+
+
+
+
+
+ Flow_1fomewo
+
+
+
+
+
+
+
+
+ Flow_0015fxf
+ Flow_11e8ue1
+
+
+ Flow_0vs55ro
+ Flow_1m468i0
+ Flow_11e8ue1
+
+
+
+
+
+ POST
+ /checkGenerationExists
+
+ db_connector_python
+
+
+
+
+
+
+
+
+ Flow_1ji1ax5
+ Flow_0vs55ro
+
+
+ exists:true
+
+
+
+
+
+
+ POST
+ /getResult
+
+ db_connector_python
+
+
+
+
+
+
+
+
+ Flow_1m468i0
+ Flow_0dqcaro
+
+
+
+
+
+ POST
+ /saveMetaDesc
+
+ db_connector_python
+
+
+
+
+
+
+ Flow_0tp54c8
+ Flow_0015fxf
+
+
+
+
+
+ POST
+ /startDescSession
+
+ db_connector_python
+
+
+
+
+
+ ${data.doc_id}
+
+
+ Flow_0dqcaro
+ Flow_1y6vtsb
+
+
+
+
+
+ POST
+ /generate
+
+ meta_desc_gen_service
+
+
+
+ ${data.summarized}
+
+
+ Flow_1y6vtsb
+ Flow_0tp54c8
+
+
+
+
+
+
+
+
+
+
+
+
+ Flow_1fomewo
+ Flow_1ji1ax5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/private/diagram_1.bpmn b/models/private/diagram_1.bpmn
new file mode 100644
index 0000000..7ea683e
--- /dev/null
+++ b/models/private/diagram_1.bpmn
@@ -0,0 +1,291 @@
+
+
+
+
+
+
+
+
+ option
+ Event_0wfjns7
+ Gateway_1inkrgm
+ Event_1h94889
+ middle
+ Activity_0vefuka
+ Activity_1x2zly5
+ down
+ up
+ Gateway_0esshpu
+ up_a
+ Event_0525vgw
+ Activity_03l2pph
+ Gateway_0l9h8s3
+ rt
+ manualt
+
+
+
+
+
+
+
+
+ Flow_0iettuo
+ Flow_002fsf6
+
+
+ Flow_0iettuo
+
+
+ Flow_1i48xnl
+ Flow_1gulh84
+ Flow_0xhtft0
+
+
+ Flow_0jkrd5h
+ Flow_08y9i80
+ Flow_1yop6yn
+
+
+
+
+ ${testinput}
+
+
+ Flow_0xhtft0
+ Flow_0g741c8
+
+
+
+
+
+ GET
+
+
+ test
+
+
+ ${testinput}
+
+
+ Flow_0g741c8
+ Flow_1rtwzf5
+
+
+
+
+
+ GET
+
+
+ test
+
+
+ Flow_1rtwzf5
+ Flow_0jkrd5h
+
+
+
+
+
+
+
+ Flow_1i48xnl
+
+
+
+
+
+
+
+ Flow_08qrnf6
+ Flow_08y9i80
+
+
+ Flow_1gulh84
+ Flow_08qrnf6
+ Flow_1wdulu6
+
+
+
+
+
+
+
+ Flow_1wdulu6
+ Flow_1yop6yn
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Flow_1g28ub4
+
+
+
+
+
+ GET
+
+
+ test
+
+
+ Flow_0g07yug
+ Flow_1g28ub4
+
+
+ Flow_002fsf6
+ Flow_0g07yug
+ Flow_05h6gge
+
+
+
+
+
+ ${testinput}
+
+
+
+
+
+ Flow_05h6gge
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/private/meta_desc_gen.bpmn b/models/private/meta_desc_gen.bpmn
new file mode 100644
index 0000000..0f0addb
--- /dev/null
+++ b/models/private/meta_desc_gen.bpmn
@@ -0,0 +1,194 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Flow_1fomewo
+ Flow_1ji1ax5
+
+
+ Flow_1fomewo
+
+
+
+
+
+
+
+
+
+
+
+ POST
+ /startSession
+
+ dart_db
+
+
+
+
+
+
+
+ Flow_1ji1ax5
+ Flow_1y6vtsb
+
+
+
+
+
+ ${data.results}
+ ${data.urls}
+ ${data.bulk}
+
+
+
+ POST
+ /scrape
+
+ scraper
+
+
+ Flow_1y6vtsb
+ Flow_1kn5m6k
+
+
+ bulk:false
+
+
+ Flow_1kn5m6k
+ Flow_1xl9jk8
+ Flow_0e8t4n5
+
+
+ bulk:true
+
+
+
+
+
+
+
+
+
+ /test
+ POST
+
+ keyword_score_service
+
+
+ Flow_1xl9jk8
+ Flow_02lt03j
+
+
+ Flow_0015fxf
+
+
+
+
+
+ POST
+ /saveResults
+
+ dart_db
+
+
+
+
+ ${urls}
+
+
+
+
+ Flow_02lt03j
+ Flow_0e8t4n5
+ Flow_0015fxf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/model_01.bpmn b/models/private/model_01.bpmn
similarity index 100%
rename from models/model_01.bpmn
rename to models/private/model_01.bpmn
diff --git a/models/private/spam_test.bpmn b/models/private/spam_test.bpmn
new file mode 100644
index 0000000..e266690
--- /dev/null
+++ b/models/private/spam_test.bpmn
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+ Flow_0t55lv0
+
+
+
+
+
+ GET
+ 5MB.zip
+
+ test
+
+
+ Flow_0t55lv0
+ Flow_1jpuxxm
+ Flow_0c2r0ko
+
+
+
+
+
+ GET
+ 20MB.zip
+
+ test
+
+
+ Flow_0c2r0ko
+ Flow_1jpuxxm
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/private/strucna_praksa.bpmn b/models/private/strucna_praksa.bpmn
new file mode 100644
index 0000000..077d4fd
--- /dev/null
+++ b/models/private/strucna_praksa.bpmn
@@ -0,0 +1,802 @@
+
+
+
+
+
+
+
+
+ razgovor_za_praksu_poslodavac
+ evaluacija_poslodavac
+ student_prihvacen
+ obavijest_odbijanje
+
+
+ ispunjavanje_prijavnice_student
+ end_event_student
+ predavanje_dnevnika_student
+ start_event_student
+ odabiranje_zadatka_student
+
+
+ obavjestavanje_alociranje_student_slack
+ Gateway_1v1zql0
+ obavjestavanje_studenta_slack_poslodavac
+ obavjestavanje_studenta_email_poslodavac
+ Gateway_022ukch
+ azuriranje_airtable_student
+ slanje_potvrde_slack_profesor
+ Gateway_0q2wy8q
+ Gateway_1b8kjb9
+ slanje_potvrde_email_profesor
+ kreiranje_potvrde_profesor
+ azuriranje_podataka_profesor
+ obavjestavanje_alociranje_student
+ obavjestavanje_poslodavca_student
+ uzimanje_podataka_o_poslodavcu_student
+ potvrda_alociranja_profesor
+ alociranje_profesor
+ studentske_pref
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ kandidat_odobren:true
+
+
+
+
+ kandidat_odobren:false
+
+
+
+
+
+
+ Flow_0ti6tpk
+ Flow_0lsghyt
+
+
+ Prvo trebate manualno alocirati studenta, te nakon toga potvrdite
+
+
+
+
+
+
+
+
+
+ Flow_0lsghyt
+ Flow_07vs9rk
+
+
+
+
+
+
+
+ ${student_id}
+
+
+ /allocation
+ GET
+
+ airtable
+
+
+
+
+
+
+
+
+ Flow_07vs9rk
+ Flow_1vwqbxk
+
+
+ Dobro došli na stručnu studentsku praksu. U prvom koraku odabirete svoje preferencije prema listi ponuđenih zadataka i poslodavaca.
+
+Možete izraziti do tri preferencije. Na prvo mjesto stavite svoj prvi odabir.
+
+Dostupne prakse možete vidjeti na https://bit.ly/...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Flow_12zi41o
+ SequenceFlow_0v5m4rx
+ Flow_1duw845
+
+
+ Flow_12zi41o
+
+
+
+
+
+ /email
+ POST
+
+
+ ${poslodavac_email}
+ poslodavac_after_allocation
+
+
+
+ notification
+
+
+ evaluacija_poslodavac
+ ${email_student}
+ ${ime_student}
+ ${godina_studija}
+
+
+
+ Flow_1vwqbxk
+ Flow_0looqv9
+
+
+
+
+
+ /email
+ POST
+
+
+ ${email_student}
+ student_after_allocation
+
+
+
+ notification
+
+
+ ${poslodavac_email}
+ ${kompanija}
+ ${opis_posla}
+
+
+ Flow_0looqv9
+ Flow_177v773
+
+
+ Flow_0eu1nfh
+ Flow_1rdv20r
+ Flow_1npalzz
+
+
+
+
+
+
+
+
+
+
+
+ Flow_1cx42m5
+ Flow_0eu1nfh
+
+
+ Template za dnevnik dostupan je na http://bit.ly/fipu-praksa-template
+Dnevnik je potrebno predati prije prijave ispitnoga roka.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Flow_03i13r1
+ Flow_1btfl5a
+
+
+
+
+
+ /prijavnica
+ POST
+
+
+ ${student_id}
+
+
+
+ airtable
+
+
+ ${potvrda_kontaktiranja}
+ ${dogovoreni_broj_sati}
+ ${detaljni_opis_zadatka}
+ ${poslodavac_id}
+ ${pocetak_prakse}
+ ${kraj_prakse}
+ ${mobitel}
+ ${oib}
+ ${mentor}
+ ${mentor_mail}
+
+
+
+ Flow_1l8y47v
+ Flow_1bua3l7
+
+
+
+
+
+ /potvrda
+ POST
+
+ pdf
+
+
+ ${email_student}
+ ${mobitel}
+ ${pocetak_prakse}
+ ${kraj_prakse}
+ ${oib}
+ ${mentor}
+ ${dogovoreni_broj_sati}
+ ${ime_student}
+ ${kompanija}
+ ${detaljni_opis_zadatka}
+
+
+
+
+ Flow_1bua3l7
+ Flow_1g3f3ei
+
+
+
+
+
+
+
+ ${email_student}
+ student_pdf
+
+
+ /email
+ POST
+
+ notification
+
+
+ potvrda.pdf
+
+ predavanje_dnevnika_student
+ ${attachment_url}
+
+
+ Flow_0rr5pyh
+ Flow_1jgq625
+
+
+ Flow_1g3f3ei
+ Flow_0rr5pyh
+
+
+ Flow_1jgq625
+ Flow_03i13r1
+
+
+
+
+
+ http://127.0.0.1:8090/notify/student/potvrda/pdf
+ POST
+
+
+ ${email_student}
+
+
+
+ http-connector
+
+
+
+ predavanje_dnevnika_student
+ ${attachment_url}
+
+
+
+
+
+
+
+ /dnevnik
+ POST
+
+
+ ${prijavnica_id}
+
+
+
+ airtable
+
+
+ ${nastavak_rada}
+ ${potvrda_attachment}
+ ${dnevnik_attachment}
+
+
+ Flow_1btfl5a
+ Flow_1cvohty
+
+
+ Flow_1cvohty
+
+
+ Flow_1rdv20r
+ Flow_10qrmyc
+
+
+
+
+
+ /email
+ POST
+
+
+ ${email_student}
+ Approve
+ student_after_approval
+
+
+
+ notification
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_10qrmyc
+ Flow_0k988op
+
+
+
+
+
+ POST
+
+
+ ${email_student}
+
+
+ http://127.0.0.1:8090/notify/student/after/approval
+
+ http-connector
+
+
+ ispunjavanje_prijavnice_student
+
+
+
+
+
+ Flow_0k988op
+ Flow_1ry7vwa
+
+
+ VAŽNO: Prijavnica se popunjava nakon (!) što nastavnik odobri kontakt određenom poduzeću i nakon što student s tim poduzećem dogovori praksu. Popunjenu prijavnicu šaljemo poduzeću na odobrenje i potpis.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Flow_1ry7vwa
+ Flow_1l8y47v
+
+
+ Flow_0kt3aem
+ Flow_177v773
+ Flow_1cx42m5
+
+
+
+
+
+ http://127.0.0.1:8090//notify/student/after/allocation
+ POST
+
+
+ ${email_student}
+
+
+
+ http-connector
+
+
+ ${poslodavac_email}
+ ${opis_posla}
+ ${kompanija}
+
+
+ Flow_0kt3aem
+
+
+
+
+
+ /email
+ POST
+
+
+ ${email_student}
+ Reject
+ student_after_approval
+
+
+
+ notification
+
+
+ ispunjavanje_prijavnice_student
+
+
+
+
+ Flow_1npalzz
+ SequenceFlow_0v5m4rx
+
+
+
+
+
+
+
+
+ POST
+ /student-preference
+
+ airtable
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_1duw845
+ Flow_0ti6tpk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/private/subprocess_test.bpmn b/models/private/subprocess_test.bpmn
new file mode 100644
index 0000000..24b3815
--- /dev/null
+++ b/models/private/subprocess_test.bpmn
@@ -0,0 +1,158 @@
+
+
+
+
+
+
+
+
+ Flow_0jd6o4s
+
+
+
+
+
+ GET
+
+
+ test
+
+
+ Flow_0jd6o4s
+ Flow_0kv37am
+
+
+
+
+ ${time}
+
+
+
+
+ Flow_0kv37am
+ Flow_1s2pndl
+
+
+ Flow_0hgqpj8
+
+
+
+
+
+
+
+
+
+ GET
+
+
+ test
+
+
+ Flow_1s2pndl
+ Flow_0hgqpj8
+
+
+
+
+
+
+ Flow_17poo2h
+
+
+ Flow_1mg4kow
+
+
+
+
+
+ GET
+
+
+ test
+
+
+ Flow_1mg4kow
+ Flow_01x5waz
+
+
+
+
+ ${time}
+
+
+ Flow_01x5waz
+ Flow_17poo2h
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/private/ticketing.bpmn b/models/private/ticketing.bpmn
new file mode 100644
index 0000000..2d24186
--- /dev/null
+++ b/models/private/ticketing.bpmn
@@ -0,0 +1,931 @@
+
+
+
+
+
+
+
+
+ Event_0f1jra8
+ Gateway_1p2wrzn
+ Gateway_1ovp5w8
+ Gateway_1de1jmk
+ zatvori_ticket_job
+ zatvori_ticket
+ provjera
+ Activity_1eq422r
+ Activity_115syfs
+ Activity_1uerjsf
+ Gateway_1564up3
+ Activity_0130ec0
+ potvrda_dodjele
+ Gateway_0odd9av
+ Gateway_0b5f9li
+ Activity_0fvafbe
+ Activity_0toh14w
+ Gateway_08rqdae
+ Activity_0xxjl2s
+ Activity_033gbhu
+ Activity_1643o90
+ Activity_0vqcvof
+ Gateway_1fzwvkz
+ Activity_12v8dd6
+ Activity_1ijx9ch
+ primi_mail
+ Activity_0typnak
+ Gateway_05wo417
+ Activity_0w58ase
+ Activity_1qayqq0
+ Activity_1vjleed
+ Activity_1yflf8w
+ Activity_0txq8tu
+ Activity_004j8gr
+ Activity_1ipxowd
+ radnik_odgovor_studentu
+ Activity_1sg89xe
+
+
+ zatvori_ticket_student
+ Activity_1qag9hu
+ Event_005tjuf
+ Gateway_0b8ppak
+ Activity_0evra9t
+ student_forma
+ Gateway_15ozh9b
+
+
+
+ Flow_1gnsc9o
+
+
+ Flow_1nb14om
+ Flow_1gnsc9o
+ Flow_0ar1rwn
+ Flow_1n982kb
+
+
+ Flow_1po8wtg
+ Flow_1j6qcpl
+ Flow_0svyczs
+ Flow_0axa5ld
+
+
+ Flow_0qcxzcw
+ Flow_0gfpj4b
+ Flow_1po8wtg
+
+
+ Flow_0spb26m
+ Flow_119qqkd
+
+
+ Flow_0svyczs
+ Flow_1hehzz7
+
+
+
+
+ test
+
+
+ ${nastavak_rada}
+ ${potvrda_attachment}
+ ${dnevnik_attachment}
+
+
+ Flow_119qqkd
+ Flow_0gfpj4b
+ Flow_061dipz
+
+
+
+
+ test
+
+
+ ${nastavak_rada}
+ ${potvrda_attachment}
+ ${dnevnik_attachment}
+
+
+ Flow_1hehzz7
+ Flow_0qcxzcw
+
+
+
+
+ test
+
+
+ ${nastavak_rada}
+ ${potvrda_attachment}
+ ${dnevnik_attachment}
+
+
+ Flow_061dipz
+ Flow_1nb14om
+
+
+
+
+ test
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_0ar1rwn
+
+
+
+
+ test
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_1n982kb
+
+
+ Flow_008r62j
+ Flow_0lnhyj7
+ Flow_06is9jd
+ Flow_046dtum
+
+
+
+
+ test
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_06is9jd
+
+
+ Flow_0wl1dyh
+ Flow_008r62j
+
+
+ Flow_17c5f2k
+ Flow_05c0doy
+ Flow_104a55z
+
+
+ Flow_1hnzqzn
+ Flow_0hsk5mi
+ Flow_14n4m0f
+ Flow_1j6qcpl
+
+
+
+
+ test
+
+
+ ${nastavak_rada}
+ ${potvrda_attachment}
+ ${dnevnik_attachment}
+
+
+ Flow_05c0doy
+ Flow_0lnhyj7
+ Flow_1my29ph
+
+
+ Ticket je napravljen te se čeka na managera da dodjeli radniku
+
+
+ test
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_104a55z
+
+
+ Flow_1my29ph
+ Flow_1yq1601
+ Flow_0fli2yh
+
+
+
+
+ test
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_0fli2yh
+
+
+ Flow_03kqyvr
+ Flow_0geba7o
+
+
+ Flow_03kqyvr
+
+
+ Ticket je napravljen te se čeka na managera da dodjeli radniku
+
+
+ test
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_1t3pfoq
+ Flow_1o4c6kj
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ test
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_06tztz6
+
+
+ Ticket je napravljen te se čeka na managera da dodjeli radniku
+
+
+ test
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_1o4c6kj
+ Flow_0kbkp3p
+
+
+ Flow_0kbkp3p
+ Flow_06tztz6
+ Flow_1drzqj2
+ Flow_06yemim
+
+
+
+
+ test
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_06yemim
+
+
+ Flow_1drzqj2
+ Flow_0wl1dyh
+
+
+
+
+ ${a}
+
+
+ Flow_0geba7o
+ Flow_1t3pfoq
+
+
+
+
+ test
+
+
+ ${nastavak_rada}
+ ${potvrda_attachment}
+ ${dnevnik_attachment}
+
+
+ Flow_1mcdjus
+ Flow_1o6mm97
+ Flow_1hnzqzn
+
+
+ Flow_1yq1601
+ Flow_1aqrxco
+ Flow_1iwp7nr
+
+
+
+
+
+
+
+ Ticket je napravljen te se čeka na managera da dodjeli radniku
+
+
+ test
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_0n7qid1
+ Flow_18bdozu
+
+
+ Ticket je napravljen te se čeka na managera da dodjeli radniku
+
+
+ test
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_0yhreyh
+ Flow_18bdozu
+ Flow_17c5f2k
+
+
+ Flow_0bsua64
+ Flow_15ge8s8
+ Flow_0l97pk5
+
+
+
+
+ ${a}
+
+
+ Flow_0l97pk5
+ Flow_0n7qid1
+
+
+ Flow_15ge8s8
+ Flow_0yhreyh
+
+
+
+
+
+ test
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_046dtum
+
+
+
+
+ ${a}
+
+
+ Flow_1iwp7nr
+ Flow_0z10y5v
+
+
+
+
+ Flow_0axa5ld
+ Flow_0bsua64
+ Flow_0spb26m
+
+
+
+
+
+ Ticket je napravljen te se čeka na managera da dodjeli radniku
+
+
+ test
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_0z10y5v
+ Flow_00x4tdz
+
+
+ Ticket je napravljen te se čeka na managera da dodjeli radniku
+
+
+ test
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_00x4tdz
+ Flow_1o6mm97
+
+
+ Ticket je napravljen te se čeka na managera da dodjeli radniku
+
+
+ test
+
+
+ ${napomena}
+ ${zeljeni_poslodavci}
+ ${godina_studija}
+ ${ime_student}
+ ${JMBAG}
+ ${email_student}
+
+
+
+
+
+ Flow_14n4m0f
+
+
+ Flow_1aqrxco
+ Flow_1mcdjus
+
+
+
+
+ test
+
+
+ ispunjavanje_prijavnice_student
+
+ ${kompanija}
+
+
+ Flow_0hsk5mi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/scraper.bpmn b/models/scraper.bpmn
new file mode 100644
index 0000000..6e6b645
--- /dev/null
+++ b/models/scraper.bpmn
@@ -0,0 +1,193 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Flow_1fomewo
+ Flow_1ji1ax5
+
+
+ Flow_1fomewo
+
+
+
+
+
+
+
+
+
+
+
+ POST
+ /startSession
+
+ dart_db
+
+
+
+
+
+
+
+ Flow_1ji1ax5
+ Flow_1y6vtsb
+
+
+
+
+
+ ${data.results}
+ ${data.urls}
+ ${data.bulk}
+
+
+
+ POST
+ /scrape
+
+ scraper
+
+
+ Flow_1y6vtsb
+ Flow_1kn5m6k
+
+
+ bulk:false
+
+
+ Flow_1kn5m6k
+ Flow_1xl9jk8
+ Flow_0e8t4n5
+
+
+ bulk:true
+
+
+
+
+
+
+
+
+
+ /test
+ POST
+
+ keyword_score_service
+
+
+ Flow_1xl9jk8
+ Flow_02lt03j
+
+
+ Flow_0015fxf
+
+
+
+
+
+ POST
+ /saveResults
+
+ dart_db
+
+
+
+
+ ${urls}
+
+
+
+
+ Flow_02lt03j
+ Flow_0e8t4n5
+ Flow_0015fxf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/models/scraper2.bpmn b/models/scraper2.bpmn
new file mode 100644
index 0000000..3e2c640
--- /dev/null
+++ b/models/scraper2.bpmn
@@ -0,0 +1,330 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Flow_1fomewo
+ Flow_1ji1ax5
+
+
+ Flow_1qz11fk
+ Flow_0bf8ugz
+ Flow_0rwpnlo
+
+
+
+
+
+ POST
+ /startSession
+
+ dart_db
+
+
+
+
+
+
+
+ Flow_1ji1ax5
+ Flow_1qz11fk
+
+
+
+
+
+ POST
+ /startSession
+
+ dart_db
+
+
+
+
+
+
+
+ Flow_0bf8ugz
+ Flow_1gsfb1d
+
+
+ Flow_1kn5m6k
+ Flow_1xl9jk8
+ Flow_0e8t4n5
+
+
+
+
+
+
+
+
+
+ /test
+ POST
+
+ keyword_score_service
+
+
+ Flow_1xl9jk8
+ Flow_02lt03j
+
+
+ Flow_0015fxf
+ Flow_0rwpnlo
+
+
+
+
+
+ POST
+ /saveResults
+
+ dart_db
+
+
+
+
+ ${urls}
+
+
+
+
+ Flow_02lt03j
+ Flow_0e8t4n5
+ Flow_0015fxf
+
+
+
+
+
+ ${data.results}
+ ${data.urls}
+ ${data.bulk}
+
+
+
+ POST
+ /scrape
+
+ scraper
+
+
+ Flow_1y6vtsb
+ Flow_1kn5m6k
+
+
+
+
+
+ POST
+ /startSession
+
+ dart_db
+
+
+
+
+
+
+ Flow_1o5ey4z
+ Flow_1i3mrr7
+ Flow_1y6vtsb
+
+
+ Flow_1gsfb1d
+ Flow_1o5ey4z
+ Flow_0enjvxq
+
+
+
+
+
+
+
+
+ Flow_0enjvxq
+ Flow_1i3mrr7
+
+
+ Flow_1fomewo
+
+
+
+
+
+
+
+
+ bulk:false
+
+
+ bulk:true
+
+
+ good:true
+
+
+
+ good:no
+
+
+
+ premium:true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/requirements.txt b/requirements.txt
index af2337c..5138f33 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,3 +1,4 @@
+pipenv==2022.5.2
aiohttp==3.7.4.post0
aiohttp-cors==0.7.0
async-timeout==3.0.1
@@ -14,4 +15,5 @@ typing-extensions==3.10.0.0
urllib3==1.26.6
yarl==1.6.3
psycopg2==2.9.1
-gunicorn==20.1.0
\ No newline at end of file
+gunicorn==20.1.0
+redis-om==0.0.26
\ No newline at end of file
diff --git a/runtime.txt b/runtime.txt
new file mode 100644
index 0000000..f96c0fa
--- /dev/null
+++ b/runtime.txt
@@ -0,0 +1 @@
+python-3.8.10
\ No newline at end of file
diff --git a/server.py b/server.py
index f745831..824da37 100644
--- a/server.py
+++ b/server.py
@@ -1,9 +1,18 @@
+import json
+import time
+import uuid
+from asyncio import sleep
+from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
+
import aiohttp
import os
-from aiohttp import web
from uuid import uuid4
import asyncio
-from bpmn_model import BpmnModel, UserFormMessage, get_model_for_instance
+from aiohttp import web, ClientSession, ClientTimeout
+
+from aiohttp.web_ws import WebSocketResponse
+
+from bpmn_model import BpmnModel, UserFormMessage, ReceiveMessage
import aiohttp_cors
import db_connector
from functools import reduce
@@ -15,25 +24,66 @@
# uuid4 = lambda: 2 # hardcoded for easy testing
models = {}
-for file in os.listdir("models"):
- if file.endswith(".bpmn"):
- m = BpmnModel(file)
- models[file] = m
+
+ignored_files = ["scraper2.bpmn", "fipu_ticketing.bpmn"]
+
+
+def create_models():
+ global models
+ for file in os.listdir("models"):
+ if file.endswith(".bpmn") and file not in ignored_files:
+ try:
+ m = BpmnModel(file)
+ models[file] = m
+ except Exception as e:
+ print("Failed creating BPMN model from " + str(file))
+ raise e
+
+ return models
+
+
+async def get_model_for_instance(iid):
+ instance_dict = db_connector.get_instance(id=iid)
+
+ # creates a new empty instance or gets an existing one
+ instance = await models[instance_dict["model_path"]].create_or_get_instance(
+ iid, {}
+ )
+
+ instance = await instance.run_from_log(instance_dict["events"],instance_dict["state"])
+
+ return instance
async def run_as_server(app):
- app["bpmn_models"] = models
- log = db_connector.get_running_instances_log()
- for l in log:
+ app["bpmn_models"] = create_models()
+ # db_connector.DB.drop_all_tables(with_all_data=True)
+ start_time = time.time()
+ logs = db_connector.get_instances_log(state="running")
+ print("Running: " + str(len(logs)))
+ completed = db_connector.get_instances_log(state=None)
+ print("Completed: " + str(len(completed)))
+ print("--- %s seconds ---" % (time.time() - start_time))
+
+ # return
+ for l in logs:
for key, data in l.items():
if data["model_path"] in app["bpmn_models"]:
instance = await app["bpmn_models"][data["model_path"]].create_instance(
key, {}
)
- instance = await instance.run_from_log(data["events"])
+ instance = await instance.run_from_log(data["events"],data["state"])
asyncio.create_task(instance.run())
+# Placeholder for a service task
+@routes.get("/test")
+async def test_call(request):
+ print("Called test")
+ import sys
+ return web.json_response({"status": "ok", "size": sys.getsizeof(models)})
+
+
@routes.get("/model")
async def get_models(request):
data = [m.to_json() for m in models.values()]
@@ -57,17 +107,52 @@ async def handle_new_instance(request):
return web.json_response({"id": _id})
+@routes.get("/model/{model_name}/instance")
+async def handle_new_instance(request):
+ _id = str(uuid4()) + str(uuid.uuid1())
+
+ model = request.match_info.get("model_name")
+ instance = await app["bpmn_models"][model].create_instance(_id, {})
+ asyncio.create_task(instance.run())
+ return web.json_response({"id": _id})
+
+
@routes.post("/instance/{instance_id}/task/{task_id}/form")
async def handle_form(request):
post = await request.json()
instance_id = request.match_info.get("instance_id")
task_id = request.match_info.get("task_id")
- m = get_model_for_instance(instance_id)
+ m = await get_model_for_instance(instance_id)
m.instances[instance_id].in_queue.put_nowait(UserFormMessage(task_id, post))
+ return web.json_response({"status": "OK"})
+
+@routes.post("/instance/{instance_id}/task/{task_id}/receive")
+async def handle_receive_task(request):
+ data = await request.json()
+ instance_id = request.match_info.get("instance_id")
+ task_id = request.match_info.get("task_id")
+ m = await get_model_for_instance(instance_id)
+ m.instances[instance_id].in_queue.put_nowait(ReceiveMessage(task_id, data))
return web.json_response({"status": "OK"})
+@routes.post("/model/{model}/task/{task_id}/receive")
+async def handle_auto_receive(request):
+ _id = str(uuid4()) + str(uuid.uuid1())
+
+ model = request.match_info.get("model")
+ instance = await app["bpmn_models"][model].create_instance(_id, {})
+ asyncio.create_task(instance.run())
+ await asyncio.sleep(0.0000000000000000001)
+ data = await request.json()
+ instance_id = instance._id
+ task_id = request.match_info.get("task_id")
+ m = await get_model_for_instance(instance_id)
+ m.instances[instance_id].in_queue.put_nowait(ReceiveMessage(task_id, data))
+ return web.json_response({"status": "OK", "id_instance": _id})
+
+
@routes.get("/instance")
async def search_instance(request):
params = request.rel_url.query
@@ -114,7 +199,7 @@ async def search_instance(request):
data = []
for _id in ids:
- data.append(get_model_for_instance(_id).instances[_id].to_json())
+ data.append((await get_model_for_instance(_id)).instances[_id].to_json())
return web.json_response({"status": "ok", "results": data})
@@ -123,7 +208,7 @@ async def search_instance(request):
async def handle_task_info(request):
instance_id = request.match_info.get("instance_id")
task_id = request.match_info.get("task_id")
- m = get_model_for_instance(instance_id)
+ m: BpmnModel = get_model_for_instance(instance_id)
if not m:
raise aiohttp.web.HTTPNotFound
instance = m.instances[instance_id]
@@ -135,7 +220,7 @@ async def handle_task_info(request):
@routes.get("/instance/{instance_id}")
async def handle_instance_info(request):
instance_id = request.match_info.get("instance_id")
- m = get_model_for_instance(instance_id)
+ m = await get_model_for_instance(instance_id)
if not m:
raise aiohttp.web.HTTPNotFound
instance = m.instances[instance_id].to_json()
@@ -143,10 +228,53 @@ async def handle_instance_info(request):
return web.json_response(instance)
+@routes.get("/instance/{instance_id}/statews")
+async def handle_instance_state_ws(request):
+ ws: WebSocketResponse = web.WebSocketResponse()
+
+ await ws.prepare(request)
+ state = "running"
+ async for msg in ws:
+ if msg.type == aiohttp.WSMsgType.TEXT:
+ if msg.data == 'close':
+ await ws.close()
+ else:
+ instance_id = request.match_info.get("instance_id")
+
+ while state != "finished" and not ws.closed:
+
+ m = await get_model_for_instance(instance_id)
+ if not m:
+ await ws.close()
+ instance = m.instances[instance_id].to_json()
+
+ await ws.send_json(({"state": instance["state"]}))
+ await asyncio.sleep(3)
+
+ elif msg.type == aiohttp.WSMsgType.ERROR:
+ print('ws connection closed with exception %s' %
+ ws.exception())
+
+ print('websocket connection closed')
+
+ return ws
+
+
+@routes.get("/instance/{instance_id}/state")
+async def handle_instance_state(request):
+ instance_id = request.match_info.get("instance_id")
+ m = await get_model_for_instance(instance_id)
+ if not m:
+ raise aiohttp.web.HTTPNotFound
+ instance = m.instances[instance_id].to_json()
+
+ return web.json_response({"state": instance["state"]})
+
+
app = None
-def run():
+async def run():
global app
app = web.Application()
app.on_startup.append(run_as_server)
@@ -176,4 +304,4 @@ async def serve():
if __name__ == "__main__":
app = run()
- web.run_app(app, port=9000)
+ web.run_app(app, port=os.environ.get('PORT', 9000))
diff --git a/utils/common.py b/utils/common.py
index ff01d73..cdb47bf 100644
--- a/utils/common.py
+++ b/utils/common.py
@@ -1,15 +1,41 @@
+import functools
+from copy import deepcopy
+
+
class SafeDict(dict):
def __missing__(self, key):
return "${" + key + "}"
def parse_expression(expression, process_variables):
- if (key := expression.replace("${", "").replace("}", "")) in process_variables:
+ key = expression.replace("${", "").replace("}", "")
+ if key in process_variables:
return process_variables[key]
+ if "." in key:
+ value = nested_dict_get(process_variables, key)
+ if value is not None:
+ return value
return expression.replace("${", "{").format_map(SafeDict(process_variables))
+def nested_dict_get(dictionary, dotted_key):
+ keys = dotted_key.split('.')
+ return functools.reduce(lambda d, key: d.get(key) if d else None, keys, dictionary)
+
+
+def nested_dict_set(dictionary, dotted_key, value):
+ # not sure if we need this
+ keys = dotted_key.split('.')
+ last = keys.pop()
+ for k in keys:
+ dictionary.setdefault(k, {})
+ dictionary[last] = value
+
+
if __name__ == "__main__":
test = "___${a[nice]}___"
+ dic = {}
+ nested_dict_set(dic, "source.payment.status", "failed")
+ print(dic)
print(parse_expression(test, {"a": {"nice": ["OK"]}}))