exception decorator and mail send for errors and changes to rec state checker

This commit is contained in:
2019-11-14 14:15:36 +01:00
parent 6081486a35
commit e19ce060d8
12 changed files with 305 additions and 136 deletions

View File

@@ -27,6 +27,8 @@ html5lib = "*"
beautifulsoup4 = "*"
flask-socketio = "*"
eventlet = "*"
ics = "*"
coloredlogs = "*"
[dev-packages]

244
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "1eb275e98d59f5fec7c926d01669aafaa57050844b8a5f35aebf396bcbdaeaa5"
"sha256": "f202c24683975df8c5539037b48a09753cfdfcab4669da6c6d35ffef97a4eb63"
},
"pipfile-spec": 6,
"requires": {
@@ -25,9 +25,9 @@
},
"alembic": {
"hashes": [
"sha256:9f907d7e8b286a1cfb22db9084f9ce4fde7ad7956bb496dc7c952e10ac90e36a"
"sha256:e6c6a4243e89c8d3e2342a1562b2388f3b524c9cac2fccc4d2c461a1320cc1c1"
],
"version": "==1.2.1"
"version": "==1.3.0"
},
"aniso8601": {
"hashes": [
@@ -38,10 +38,17 @@
},
"apispec": {
"hashes": [
"sha256:5fdaa1173b32515cc83f9d413a49a6c37fafc2b87f6b40e95923d3e85f0942c5",
"sha256:9e88c51517a6515612e818459f61c1bc06c00f2313e5187828bdbabaa7461473"
"sha256:cf8e1f3b56949710f8cf23797b7f40215e9dae8bac583789a3f2c13dc56349fa",
"sha256:fe5cf5fc89b1c4a73acd5af3a10ede02b31ec116f215ed02271cb905d3172367"
],
"version": "==3.0.0"
"version": "==3.1.0"
},
"arrow": {
"hashes": [
"sha256:4bfacea734ead51495dc47df00421ecfd4ca1f2c0fbe58b9a26eaeddedc31caf",
"sha256:67f8be7c0cf420424bc62d8d7dc40b44e4bb2f7b515f9cc2954fb36e35797656"
],
"version": "==0.14.7"
},
"attrs": {
"hashes": [
@@ -74,38 +81,41 @@
},
"cffi": {
"hashes": [
"sha256:00d890313797d9fe4420506613384b43099ad7d2b905c0752dbcc3a6f14d80fa",
"sha256:0cf9e550ac6c5e57b713437e2f4ac2d7fd0cd10336525a27224f5fc1ec2ee59a",
"sha256:0ea23c9c0cdd6778146a50d867d6405693ac3b80a68829966c98dd5e1bbae400",
"sha256:193697c2918ecdb3865acf6557cddf5076bb39f1f654975e087b67efdff83365",
"sha256:1ae14b542bf3b35e5229439c35653d2ef7d8316c1fffb980f9b7647e544baa98",
"sha256:1e389e069450609c6ffa37f21f40cce36f9be7643bbe5051ab1de99d5a779526",
"sha256:263242b6ace7f9cd4ea401428d2d45066b49a700852334fd55311bde36dcda14",
"sha256:33142ae9807665fa6511cfa9857132b2c3ee6ddffb012b3f0933fc11e1e830d5",
"sha256:364f8404034ae1b232335d8c7f7b57deac566f148f7222cef78cf8ae28ef764e",
"sha256:47368f69fe6529f8f49a5d146ddee713fc9057e31d61e8b6dc86a6a5e38cecc1",
"sha256:4895640844f17bec32943995dc8c96989226974dfeb9dd121cc45d36e0d0c434",
"sha256:558b3afef987cf4b17abd849e7bedf64ee12b28175d564d05b628a0f9355599b",
"sha256:5ba86e1d80d458b338bda676fd9f9d68cb4e7a03819632969cf6d46b01a26730",
"sha256:63424daa6955e6b4c70dc2755897f5be1d719eabe71b2625948b222775ed5c43",
"sha256:6381a7d8b1ebd0bc27c3bc85bc1bfadbb6e6f756b4d4db0aa1425c3719ba26b4",
"sha256:6381ab708158c4e1639da1f2a7679a9bbe3e5a776fc6d1fd808076f0e3145331",
"sha256:6fd58366747debfa5e6163ada468a90788411f10c92597d3b0a912d07e580c36",
"sha256:728ec653964655d65408949b07f9b2219df78badd601d6c49e28d604efe40599",
"sha256:7cfcfda59ef1f95b9f729c56fe8a4041899f96b72685d36ef16a3440a0f85da8",
"sha256:819f8d5197c2684524637f940445c06e003c4a541f9983fd30d6deaa2a5487d8",
"sha256:825ecffd9574557590e3225560a8a9d751f6ffe4a49e3c40918c9969b93395fa",
"sha256:9009e917d8f5ef780c2626e29b6bc126f4cb2a4d43ca67aa2b40f2a5d6385e78",
"sha256:9c77564a51d4d914ed5af096cd9843d90c45b784b511723bd46a8a9d09cf16fc",
"sha256:a19089fa74ed19c4fe96502a291cfdb89223a9705b1d73b3005df4256976142e",
"sha256:a40ed527bffa2b7ebe07acc5a3f782da072e262ca994b4f2085100b5a444bbb2",
"sha256:bb75ba21d5716abc41af16eac1145ab2e471deedde1f22c6f99bd9f995504df0",
"sha256:e22a00c0c81ffcecaf07c2bfb3672fa372c50e2bd1024ffee0da191c1b27fc71",
"sha256:e55b5a746fb77f10c83e8af081979351722f6ea48facea79d470b3731c7b2891",
"sha256:ec2fa3ee81707a5232bf2dfbd6623fdb278e070d596effc7e2d788f2ada71a05",
"sha256:fd82eb4694be712fcae03c717ca2e0fc720657ac226b80bbb597e971fc6928c2"
"sha256:0b49274afc941c626b605fb59b59c3485c17dc776dc3cc7cc14aca74cc19cc42",
"sha256:0e3ea92942cb1168e38c05c1d56b0527ce31f1a370f6117f1d490b8dcd6b3a04",
"sha256:135f69aecbf4517d5b3d6429207b2dff49c876be724ac0c8bf8e1ea99df3d7e5",
"sha256:19db0cdd6e516f13329cba4903368bff9bb5a9331d3410b1b448daaadc495e54",
"sha256:2781e9ad0e9d47173c0093321bb5435a9dfae0ed6a762aabafa13108f5f7b2ba",
"sha256:291f7c42e21d72144bb1c1b2e825ec60f46d0a7468f5346841860454c7aa8f57",
"sha256:2c5e309ec482556397cb21ede0350c5e82f0eb2621de04b2633588d118da4396",
"sha256:2e9c80a8c3344a92cb04661115898a9129c074f7ab82011ef4b612f645939f12",
"sha256:32a262e2b90ffcfdd97c7a5e24a6012a43c61f1f5a57789ad80af1d26c6acd97",
"sha256:3c9fff570f13480b201e9ab69453108f6d98244a7f495e91b6c654a47486ba43",
"sha256:415bdc7ca8c1c634a6d7163d43fb0ea885a07e9618a64bda407e04b04333b7db",
"sha256:42194f54c11abc8583417a7cf4eaff544ce0de8187abaf5d29029c91b1725ad3",
"sha256:4424e42199e86b21fc4db83bd76909a6fc2a2aefb352cb5414833c030f6ed71b",
"sha256:4a43c91840bda5f55249413037b7a9b79c90b1184ed504883b72c4df70778579",
"sha256:599a1e8ff057ac530c9ad1778293c665cb81a791421f46922d80a86473c13346",
"sha256:5c4fae4e9cdd18c82ba3a134be256e98dc0596af1e7285a3d2602c97dcfa5159",
"sha256:5ecfa867dea6fabe2a58f03ac9186ea64da1386af2159196da51c4904e11d652",
"sha256:62f2578358d3a92e4ab2d830cd1c2049c9c0d0e6d3c58322993cc341bdeac22e",
"sha256:6471a82d5abea994e38d2c2abc77164b4f7fbaaf80261cb98394d5793f11b12a",
"sha256:6d4f18483d040e18546108eb13b1dfa1000a089bcf8529e30346116ea6240506",
"sha256:71a608532ab3bd26223c8d841dde43f3516aa5d2bf37b50ac410bb5e99053e8f",
"sha256:74a1d8c85fb6ff0b30fbfa8ad0ac23cd601a138f7509dc617ebc65ef305bb98d",
"sha256:7b93a885bb13073afb0aa73ad82059a4c41f4b7d8eb8368980448b52d4c7dc2c",
"sha256:7d4751da932caaec419d514eaa4215eaf14b612cff66398dd51129ac22680b20",
"sha256:7f627141a26b551bdebbc4855c1157feeef18241b4b8366ed22a5c7d672ef858",
"sha256:8169cf44dd8f9071b2b9248c35fc35e8677451c52f795daa2bb4643f32a540bc",
"sha256:aa00d66c0fab27373ae44ae26a66a9e43ff2a678bf63a9c7c1a9a4d61172827a",
"sha256:ccb032fda0873254380aa2bfad2582aedc2959186cce61e3a17abc1a55ff89c3",
"sha256:d754f39e0d1603b5b24a7f8484b22d2904fa551fe865fd0d4c3332f078d20d4e",
"sha256:d75c461e20e29afc0aee7172a0950157c704ff0dd51613506bd7d82b718e7410",
"sha256:dcd65317dd15bc0451f3e01c80da2216a31916bdcffd6221ca1202d96584aa25",
"sha256:e570d3ab32e2c2861c4ebe6ffcad6a8abf9347432a37608fe1fbd157b3f0036b",
"sha256:fd43a88e045cf992ed09fa724b5315b790525f2676883a6ea64e3263bae6549d"
],
"version": "==1.13.1"
"version": "==1.13.2"
},
"chardet": {
"hashes": [
@@ -121,6 +131,22 @@
],
"version": "==7.0"
},
"colorama": {
"hashes": [
"sha256:05eed71e2e327246ad6b38c540c4a3117230b19679b875190486ddd2d721422d",
"sha256:f8ac84de7840f5b9c4e3347b3c1eaa50f7e49c2b07596221daec5edaabbd7c48"
],
"markers": "sys_platform == 'win32'",
"version": "==0.4.1"
},
"coloredlogs": {
"hashes": [
"sha256:34fad2e342d5a559c31b6c889e8d14f97cb62c47d9a2ae7b5ed14ea10a79eff8",
"sha256:b869a2dda3fa88154b9dd850e27828d8755bfab5a838a1c97fbc850c6e377c36"
],
"index": "pypi",
"version": "==10.0"
},
"coverage": {
"hashes": [
"sha256:08907593569fe59baca0bf152c43f3863201efb6113ecb38ce7e97ce339805a6",
@@ -187,10 +213,10 @@
},
"decorator": {
"hashes": [
"sha256:86156361c50488b84a3f148056ea716ca587df2f0de1d34750d35c21312725de",
"sha256:f069f3a01830ca754ba5258fde2278454a0b5b79e0d7f5c13b3b97e57d4acff6"
"sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce",
"sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"
],
"version": "==4.4.0"
"version": "==4.4.1"
},
"dnspython": {
"hashes": [
@@ -201,10 +227,10 @@
},
"ecdsa": {
"hashes": [
"sha256:163c80b064a763ea733870feb96f9dd9b92216cfcacd374837af18e4e8ec3d4d",
"sha256:9814e700890991abeceeb2242586024d4758c8fc18445b194a49bd62d85861db"
"sha256:64c613005f13efec6541bb0a33290d0d03c27abab5f15fbab20fb0ee162bdd8e",
"sha256:e108a5fe92c67639abae3260e43561af914e7fd0d27bae6d2ec1312ae7934dfe"
],
"version": "==0.13.3"
"version": "==0.14.1"
},
"eventlet": {
"hashes": [
@@ -320,9 +346,9 @@
},
"future": {
"hashes": [
"sha256:858e38522e8fd0d3ce8f0c1feaf0603358e366d5403209674c7b617fa0c24093"
"sha256:b1bead90b70cf6ec3f0710ae53a525360fa360d306a86583adc6bf83a4db537d"
],
"version": "==0.18.1"
"version": "==0.18.2"
},
"greenlet": {
"hashes": [
@@ -356,6 +382,20 @@
"index": "pypi",
"version": "==1.0.1"
},
"humanfriendly": {
"hashes": [
"sha256:23057b10ad6f782e7bc3a20e3cb6768ab919f619bbdc0dd75691121bbde5591d",
"sha256:33ee8ceb63f1db61cce8b5c800c531e1a61023ac5488ccde2ba574a85be00a85"
],
"version": "==4.18"
},
"ics": {
"hashes": [
"sha256:12cf34aed0dafa1bf99d79ca58e99949d6721511b856386e118015fe5f5d6e3a"
],
"index": "pypi",
"version": "==0.6"
},
"idna": {
"hashes": [
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
@@ -432,10 +472,10 @@
},
"marshmallow": {
"hashes": [
"sha256:077b4612f5d3b9333b736fdc6b963d2b46d409070f44ff3e6c4109645c673e83",
"sha256:9a2f3e8ea5f530a9664e882d7d04b58650f46190178b2264c72b7d20399d28f0"
"sha256:1a358beb89c2b4d5555272065a9533591a3eb02f1b854f3c4002d88d8f2a1ddb",
"sha256:eb97c42c5928b5720812c9268865fe863d4807bc1a8b48ddd7d5c9e1779a6af0"
],
"version": "==3.2.1"
"version": "==3.2.2"
},
"monotonic": {
"hashes": [
@@ -487,36 +527,40 @@
},
"pycryptodomex": {
"hashes": [
"sha256:020928b2831b2047288c9143f41c6690eb669d60761c7ca8c5ca743a2c51517c",
"sha256:0ce1950ba6544eca4d6fd7386e2502d4bd871fcbd5e5b977604f48ea37b29fc6",
"sha256:0d5b1159a24a56fd3359b7b1aa1e4331c394033eababb2972bb923d6767968db",
"sha256:11453e8628cdccbcb08e04405298d659c0c0458cf9bf23eaaa3c201f8d635389",
"sha256:22e050089f60e70b97909fe62612ee9589f0be1c928c2aa637f2534eddf61632",
"sha256:27317f1e8e496a2f208b1c40da425d5fe760b494f95c847bb7c3074c95a8edcb",
"sha256:32e2fe1d0c5fada45b22b647f88367b210dfea40a5cc849b142b4e9fa497c488",
"sha256:3a998b390a80fd0d22c7d9fbaf49a9a11772ef90495a8baecdea2e6d09929937",
"sha256:46dda35fbed5426794ab64d483d6257dc43f52e78ba934563492df7cb89f7de6",
"sha256:4846ca0f2363bdb934c556667b056331d4aabd48f20924b0c5583a49d764d3fc",
"sha256:550f5e6f07b091f986023f871fa8a2bde9875ccae51d4bd07b31fa9855fe994f",
"sha256:561905b459de41c3ad19912cdcd88c8e24295d01e97b7b2a63d4188c8e4e0dbc",
"sha256:5745ca86a4e88a775b7cace28b947a86661d5cc09ecc1c8d97293a7d20c1bb79",
"sha256:5c2a3bb28dde992f97d856937e973dda0462bf3acb7d0009308a81159a35323b",
"sha256:73a8acc8ff7f09d482e481757d92a250f803e66e0f248019df90a69e61840180",
"sha256:8601613ebc329b853e466f581ad1156638989926e0dcdf52952542a89883836c",
"sha256:8b604f4fa1de456d6d19771b01c2823675a75a2c60e51a6b738f71fdfe865370",
"sha256:96f8622cb8061f4aca95e52cc835659f024bc2e237ee6a9d01117873b7490b98",
"sha256:a01c99532c5f7ab96274b5c9f3e135315b79b55ba5c8233fc4d029e0369e94df",
"sha256:c63040e0313e27b62b0f4295f41adecf96cde7ff4d49f653b81b1958cb1180bf",
"sha256:c812cb9f3af63da8eaa251e7e48f8b38c4e40974d2bdae2f0ca7a7a12549727a",
"sha256:cb9e8ef672b7a961f90e0a497718e0f052f76324f216840a4ec30248e4d19f20",
"sha256:ce8edda46374c344de87089f9887ad4dd317bb4a22f91f1844202eaf14b08de0",
"sha256:de58de0d5f2fb9253707ee718e1378f2194fdd394cdbed1b6464ab44642f5217",
"sha256:e0100f9b93d0119d846a33e6cb5001ee208519b81c6acf76da614b71de75885b",
"sha256:e530b77bdff5c2bf3065e6a088e1602ad193b43e285bac196d4b8820308ec6bb",
"sha256:f048069aa7b530f1c5e84d55c2b28ca7a7272bb3b8d28829d454a94bec6529a8",
"sha256:f6a9271c842e93c349b6007676a62d03dca712c9f4dff66c3270d50504ca9014"
"sha256:0ab2251a386c065331115c408c23274e8aea7ddf5452f2e92120b88fa09aba23",
"sha256:0da48ccd0944a952cbaac623bf0e1139969078551a213c019ca885ed66771539",
"sha256:1d98214b7bc6f9ceb68eb5cdbd4237f23485b4b746e7e582990be492b6c4797b",
"sha256:275e8f0f7fd03ec4b9f7fecfeac3dad8e5a1fe389369efda1e365e8c5795c1ac",
"sha256:30975ac3ee7c632eb34a05d2aa0e9933cab9a0746b77d44612a3b61c56ecfa3c",
"sha256:37f84bef86e935e10a2ccb22f6cd2cebac274dff8867f16f7c2d5da9aa27665d",
"sha256:3b80f06556552a515ff9f1052ea41895e34745558a5ddbab46e300ba43384a35",
"sha256:3b9f81fd0c897c493ff8367cca41b9b93f6c9277990c8c4c2756538ed1aa4a99",
"sha256:6d58f13c8ca6bac3bf0d64e7474725ff55c2d6db60ed03d5b98b81c757bf1f4c",
"sha256:6f86a6d668d4f918b21452fcf8bb24dc9c135b6564cbd4ff7b954b1d35fe7527",
"sha256:7c462632ff441203fc30f11cab9cf12e2eb00417b4a1ea3c5208e875d81cb160",
"sha256:87d278909c7fabd303d87268eeda7350641f094792ecd023965f960ae6d2d3da",
"sha256:87d3f7357789171a0f05e3b1bac782989619043693e4200518c678245856ca7c",
"sha256:8913f185eccb2f270030a0347161d2cd47ef691f12a4b9af9772319e5a6a717b",
"sha256:8ac49b6ad1e57a0914d8d5e0267e4df5fbdf4e62abdf982bd5493d634cd3a686",
"sha256:8d8b071a159e9b46734cbb802282719a0d0d0e40523c8648fab0b6739f98a882",
"sha256:a06a1f927d02c1fea1f7656e32bf36149d0f6cab750313a03a085e43632163e8",
"sha256:adb6ca0aee7fd2807628d1cb77fc9be8a82f493240e2349da06419221b1f6b19",
"sha256:b3503841cb5185b210876d7ff8f541e2c2ea0915c83f6330be6d7026a34828ca",
"sha256:b90ecc35567d77e7dc9f70817826f077c9dbb37abdd16e2c2d57887c21053e53",
"sha256:ba18a7dfef6d89605ca76f077d033143fab8f2d6948620d09337567402f1c0c4",
"sha256:be635b1f9ee9615243dc706c11047015d22312e7425c9009dd6447c229370e1a",
"sha256:d1db857b0ac6bac6d4d4758250d548d7146d63cb36c6c50b7481837f02d38ef7",
"sha256:d9537841af488a4b83977aeebfd4aebe011b7d1d19e9d45ad32a1f8dfca7eec8",
"sha256:e413457859d3c3e4a4263ef24ccaefe4107b3e3e219c4fb87215cfc34ff8dba0",
"sha256:e87c272263559d657ab3b990be8174c0d492cbc2f4f8d0bddfaef82dfe05d54c",
"sha256:eb5aef32e65d7802e04c78074af1ba8e7a5b4c0482d3a110f236082fadac6859",
"sha256:ee03dc6124287e27738e5f1d1150031d706f7fb96f1770859cb3cebe64c191ea",
"sha256:f792b5deca98bee676912d27bc1aba96b614986a9a89df7cf15e95d7bd480768",
"sha256:f84e6e66af8805703b5f4d1243747accf519cba0223d598b58e85edbec8583d7",
"sha256:fbd9e3ba9437b087b16481d1e34ec4f495ffabb4bee7e2c150b50d28ebe00e44",
"sha256:fbfaf65e610089f37c46e2cb2ff2dbf9a04bbcecd3a2beaa85494094e9987aff"
],
"version": "==3.9.0"
"version": "==3.9.3"
},
"pyjwkest": {
"hashes": [
@@ -539,18 +583,25 @@
],
"version": "==19.0.0"
},
"pyreadline": {
"hashes": [
"sha256:4530592fc2e85b25b1a9f79664433da09237c1a270e4d78ea5aa3a2c7229e2d1"
],
"markers": "sys_platform == 'win32'",
"version": "==2.1"
},
"pyrsistent": {
"hashes": [
"sha256:34b47fa169d6006b32e99d4b3c4031f155e6e68ebcc107d6454852e8e0ee6533"
"sha256:eb6545dbeb1aa69ab1fb4809bfbf5a8705e44d92ef8fc7c2361682a47c46c778"
],
"version": "==0.15.4"
"version": "==0.15.5"
},
"python-dateutil": {
"hashes": [
"sha256:7e6584c74aeed623791615e26efd690f29817a27c73085b78e4bad02493df2fb",
"sha256:c89805f6f4d64db21ed966fda138f8a5ed7a4fdbc1a8ee329ce1b74e3c74da9e"
"sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
"sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"
],
"version": "==2.8.0"
"version": "==2.8.1"
},
"python-editor": {
"hashes": [
@@ -605,24 +656,24 @@
},
"six": {
"hashes": [
"sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
"sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
"sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
"sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
],
"version": "==1.12.0"
"version": "==1.13.0"
},
"soupsieve": {
"hashes": [
"sha256:605f89ad5fdbfefe30cdc293303665eff2d188865d4dbe4eb510bba1edfbfce3",
"sha256:b91d676b330a0ebd5b21719cb6e9b57c57d433671f65b9c28dd3461d9a1ed0b6"
"sha256:bdb0d917b03a1369ce964056fc195cfdff8819c40de04695a80bc813c3cfa1f5",
"sha256:e2c1c5dee4a1c36bcb790e0fabd5492d874b8ebd4617622c4f6a731701060dda"
],
"version": "==1.9.4"
"version": "==1.9.5"
},
"sqlalchemy": {
"hashes": [
"sha256:0f0768b5db594517e1f5e1572c73d14cf295140756431270d89496dc13d5e46c"
"sha256:afa5541e9dea8ad0014251bc9d56171ca3d8b130c9627c6cb3681cff30be3f8a"
],
"index": "pypi",
"version": "==1.3.10"
"version": "==1.3.11"
},
"sqlalchemy-migrate": {
"hashes": [
@@ -672,6 +723,13 @@
],
"version": "==1.1.0"
},
"tatsu": {
"hashes": [
"sha256:80713413473a009f2081148d0f494884cabaf9d6866b71f2a68a92b6442f343d",
"sha256:c9211eeee9a2d4c90f69879ec0b518b1aa0d9450249cb0dd181f5f5b18be0a92"
],
"version": "==4.4.0"
},
"tempita": {
"hashes": [
"sha256:cacecf0baa674d356641f1d406b8bff1d756d739c46b869a54de515d08e6fc9c"
@@ -687,10 +745,10 @@
},
"urllib3": {
"hashes": [
"sha256:3de946ffbed6e6746608990594d08faac602528ac7015ac28d33cee6a45b7398",
"sha256:9a107b99a5393caf59c7aa3c1249c16e6879447533d0887f4336dde834c7be86"
"sha256:a8a318824cc77d1fd4b2bec2ded92646630d7fe8619497b142c84a9e6f5a7293",
"sha256:f3c5fd51747d450d4dcf6f923c81f78f811aab8205fda64b0aba34a4e48b0745"
],
"version": "==1.25.6"
"version": "==1.25.7"
},
"webargs": {
"hashes": [

View File

@@ -3,7 +3,10 @@
Backend base module
"""
import logging
from io import StringIO
from logging.config import dictConfig
from typing import Union
import coloredlogs as coloredlogs
import jwt
import requests
@@ -25,7 +28,6 @@ __email__ = "it@t-kurze.de"
# __status__ = "Production"
__status__ = "Development"
dictConfig({
'version': 1,
'formatters': {
@@ -66,7 +68,7 @@ dictConfig({
},
},
'loggers': {
'mal': {
'lrc': {
'level': Config.LOG_LEVEL,
'handlers': ['wsgi', 'file', 'errors_file']
}
@@ -78,18 +80,34 @@ dictConfig({
})
main_logger = logging.getLogger("lrc")
# following might be dangerous, as buffer might be filled without a mechanism to empty it
# error_log_stream = StringIO()
# error_log_stream_handler = logging.StreamHandler(stream=error_log_stream)
# error_log_stream_handler.setLevel(logging.ERROR)
# main_logger.addHandler(error_log_stream_handler)
coloredlogs.install(level='DEBUG', logger=main_logger)
class LrcException(Exception):
def __init__(self, message: str, html_code: int = None):
super().__init__(message)
def __init__(self, message_or_exception: Union[str, Exception], html_code: int = None):
if isinstance(message_or_exception, str):
super().__init__(message_or_exception)
self.type = None
else:
super().__init__(str(message_or_exception))
self.type = type(message_or_exception)
self.html_code = html_code
def __repr__(self):
if self.type is None:
msg = "LRC Exception: \"{}\"".format(', '.join(super().args))
else:
msg = "LRC Exception: (original Exception: {}) \"{}\"".format(self.type, ', '.join(super().args))
if self.html_code is not None:
return "LRC Exception: \"{}\" (HTML Code: {})".format(', '.join(super().args), self.html_code)
return ', '.join(super().args)
msg += " (HTML Code: {})".format(self.html_code)
return msg
def __str__(self):
return self.__repr__()

Binary file not shown.

View File

@@ -104,6 +104,9 @@ class RecorderAdapter:
def is_recording(self) -> bool:
pass
def get_recording_status(self) -> str:
pass
def get_defined_recorder_adapters():
models = []

View File

@@ -6,11 +6,14 @@ from pprint import pprint
import requests
from requests.auth import HTTPBasicAuth
from requests.exceptions import ConnectionError
from backend import LrcException
from backend.recorder_adapters import RecorderAdapter
# HOST = "localhost"
from backend.tools.exception_decorator import exception_decorator
BASE_URL = "http://172.23.8.102" # Audimax SMP 351
USER = "admin"
@@ -34,12 +37,14 @@ class EpiphanV1(RecorderAdapter):
def _get_version(self):
pass
def get_status(self) -> dict:
@exception_decorator(ConnectionError)
def get_recording_status(self) -> dict:
res = self.session.get(self.url + "/admin/ajax/recorder_status.cgi")
if res.ok:
return res.json()
raise LrcException(res.text, res.status_code)
@exception_decorator(ConnectionError)
def get_sysinfo(self) -> dict:
res = self.session.get(self.url + "/ajax/sysinfo.cgi")
if res.ok:
@@ -47,7 +52,7 @@ class EpiphanV1(RecorderAdapter):
raise LrcException(res.text, res.status_code)
def is_recording(self) -> bool:
state = self.get_status().get('state', None)
state = self.get_recording_status().get('state', None)
return state == "up"
def get_recording_time(self):
@@ -55,7 +60,7 @@ class EpiphanV1(RecorderAdapter):
Returns recording time in seconds. Also returns 0 if not recording.
:return:
"""
return self.get_status().get('seconds', None)
return self.get_recording_status().get('seconds', None)
def start_recording(self):
res = self.session.get(self.url + "/admin/ajax/start_recorder.cgi")

View File

@@ -2,8 +2,9 @@ import logging
from backend import LrcException
from backend.recorder_adapters import telnetlib, TelnetAdapter, RecorderAdapter
from backend.tools.exception_decorator import exception_decorator
logger = logging.getLogger()
logger = logging.getLogger("lrc.recorder_adapters.extron_smp")
RECORDER_MODEL_NAME = "SMP 351 / 352"
VERSION = "0.9.0"
@@ -28,11 +29,13 @@ class SMP(TelnetAdapter, RecorderAdapter):
self._login()
def _login(self):
print("Connecting to {} ...".format(self.address))
logger.info("Connecting to {} ...".format(self.address))
try:
self.tn = telnetlib.Telnet(self.address)
except TimeoutError as e:
raise LrcException(str(e))
except ConnectionRefusedError as e:
raise LrcException(str(e))
self.tn.read_until("\r\nPassword:")
# password = getpass.getpass()
password = self.admin_pw
@@ -371,6 +374,7 @@ class SMP(TelnetAdapter, RecorderAdapter):
self.tn.write("{}Y2RCDR\n".format(self.esc_char))
return TelnetAdapter._get_response_str(self.tn.read_until_non_empty_line())
@exception_decorator(ConnectionError)
def get_recording_status(self):
"""
Status may be one of:

View File

@@ -16,6 +16,7 @@ if not os.path.exists(fe_path) or not os.path.exists(os.path.join(fe_path, "inde
app.logger.critical(
"Frontend path and/or index.html does not exist! Please build frontend before continuing! "
"You might want to go to ../frontend and continue from there.")
print("FATAL: Frontend path wrong or index.html missing -> EXITING!")
exit()
fe_bp = Blueprint('frontend', __name__, url_prefix='/', template_folder=os.path.join(fe_path, ""))

View File

@@ -0,0 +1,13 @@
from backend import LrcException
def exception_decorator(*exceptions):
def decorator(func):
def new_func(*args, **kwargs):
try:
ret = func(*args, **kwargs)
return ret
except exceptions as e:
raise LrcException(e)
return new_func
return decorator

View File

@@ -0,0 +1,45 @@
import smtplib
import traceback
from email.message import EmailMessage
from typing import List, Union
from backend import main_logger, Config
def send_mail(subject: str, msg_body: str, to_mail: List, from_mail: str = Config.FROM_MAIL):
subject = subject.strip().replace("\r", "").split("\n")[0] # remove breaks resp. cut after line break
try:
msg = EmailMessage()
msg.set_content(msg_body)
msg["Subject"] = subject
msg["From"] = from_mail
msg["To"] = to_mail
s = smtplib.SMTP(Config.SMTP_SERVER)
s.send_message(msg)
s.quit()
except Exception as e:
main_logger.error(
"Could not send E-Mail (Exception: {})".format(str(e)))
def send_error_mail(message_or_exception: Union[str, Exception], subject: str = None,
subject_prefix: str = "[LRC] Error: ",
receiver_mail_addresses=Config.ERROR_E_MAIL_TO):
if isinstance(message_or_exception, Exception):
if subject is None:
subject = subject_prefix + str(type(message_or_exception))
else:
subject = subject_prefix + subject
msg_body = str(type(message_or_exception)) + ": " + str(message_or_exception) + "\n\n" + traceback.format_exc()
else:
if subject is None:
subject = str(message_or_exception)
else:
subject = subject_prefix + subject
msg_body = str(message_or_exception)
send_mail(subject, msg_body, receiver_mail_addresses)
def send_warning_mail():
pass

View File

@@ -1,23 +1,31 @@
import json
import os
import logging
from io import StringIO
import requests
from requests.auth import HTTPBasicAuth
from multiprocessing.pool import ThreadPool
from pprint import pprint
import requests
from requests.auth import HTTPBasicAuth
from ics import Calendar
from backend import LrcException
from backend.config import Config
from backend.recorder_adapters import RecorderAdapter
from backend.recorder_adapters.epiphan_base import EpiphanV1
from backend.recorder_adapters.extron_smp import SMP
from backend.tools.send_mail import send_error_mail
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.DEBUG)
logger.addHandler(stream_handler)
logger = logging.getLogger("lrc.tools.simple_state_checker")
rec_err_state_log_stream = StringIO()
rec_err_state_log_stream_handler = logging.StreamHandler(stream=rec_err_state_log_stream)
rec_err_state_log_stream_handler.setLevel(logging.ERROR)
logger.addHandler(rec_err_state_log_stream_handler)
base_url = "https://opencast.bibliothek.kit.edu"
@@ -46,7 +54,6 @@ def get_service_url(service_type: str):
def get_calender(rec_id):
params = {'agentid': rec_id}
url = get_service_url('org.opencastproject.scheduler') + "/calendars"
print(url)
res = session.get(url, params=params)
if res.ok:
return Calendar(res.text)
@@ -80,41 +87,49 @@ def notify_users_of_problem(msg: str):
pass
def get_recorder_adapter(recorder_info:dict) -> RecorderAdapter:
if "SMP" in recorder_info["type"]:
rec = SMP(recorder_info['ip'], recorder_info['password'])
else:
rec = EpiphanV1(recorder_info['ip'], recorder_info["username"], recorder_info["password"])
return rec
def check_capture_agent_state(a: dict):
logger.debug("Checking Agent {}".format(a['name']))
c = get_calender(a['name'])
is_recording_in_calendar = len(list(c.timeline.now())) >= 1
if is_recording_in_calendar:
logger.info("{} has entry in Calender and should therfor be recording... checking now!".format(a['name']))
if a['state'] == "capturing":
print(
logger.info(
"{} is in capturing state, so there should be an entry in the calendar of the recorder, right? -> {}".format(
a['name'], is_recording_in_calendar
))
rec = get_recorder_by_name(a['name'])
print(rec)
if "SMP" in rec["type"]:
print("using SMP adapter")
rec = SMP(rec['ip'], rec['password'])
else:
rec = EpiphanV1(rec['ip'], rec["username"], rec["password"])
if rec.is_recording():
print("OK recorder is recording :)")
else:
logger.info(rec.get_recording_status())
logger.error("FATAL - recorder {} must be recording!!!!".format(a['name']))
recorder_info = get_recorder_by_name(a['name'])
try:
rec = get_recorder_adapter(recorder_info)
if rec.is_recording():
logger.info("OK recorder {} is recording :)".format(a['name']))
else:
logger.info(rec.get_recording_status())
logger.error("FATAL - recorder {} must be recording but is not!!!!".format(a['name']))
except LrcException as e:
logger.fatal("Exception occurred: {}".format(str(e)))
logger.error("Could not check state of recorder {}, Address: {}".format(a['name'], recorder_info['ip']))
else:
print("FATAL: {} is not in capturing state...but should be!!".format(a['name']))
logger.error("FATAL: {} is not in capturing state...but should be!!".format(a['name']))
else:
rec = get_recorder_by_name(a['name'])
if "SMP" in rec["type"]:
logger.debug("using SMP adapter")
rec = SMP(rec['ip'], rec['password'])
else:
rec = EpiphanV1(rec['ip'], rec["username"], rec["password"])
if rec.is_recording():
logger.error("FATAL - recorder must not be recording!!!!")
else:
logger.info("OK recorder is not recording :)")
recorder_info = get_recorder_by_name(a['name'])
try:
rec = get_recorder_adapter(recorder_info)
if rec.is_recording():
logger.error("FATAL - recorder must not be recording!!!!")
else:
logger.info("OK recorder is not recording :)")
except LrcException as e:
logger.fatal("Exception occurred: {}".format(str(e)))
logger.error("Could not check state of recorder {}, Address: {}".format(a['name'], recorder_info['ip']))
agents = get_capture_agents()
@@ -123,6 +138,11 @@ logger.info("Got {} capture agents that will be checked...".format(len(agents)))
pool = ThreadPool(5)
pool.map(check_capture_agent_state, agents)
pool.close()
pool.join()
logged_events = rec_err_state_log_stream.getvalue()
if len(logged_events) > 0:
send_error_mail(logged_events, "Errors have been detected while checking recorder states!")
exit()
c = get_calender('CS 30.46 Chemie Neuer Hoersaal')

0
logs/app.log.2019-11-13 Normal file
View File