diff --git a/.pylintrc b/.pylintrc index 1de5326..05f99d3 100644 --- a/.pylintrc +++ b/.pylintrc @@ -279,6 +279,10 @@ good-names=i, Run, db, assertKml, + assertKmlMetadata, + assertKmlFile, + assertKmlInDb, + assertKmlDbData, _ # Good variable names regexes, separated by a comma. If names match any regex, diff --git a/Makefile b/Makefile index 7fa8467..2c46d75 100644 --- a/Makefile +++ b/Makefile @@ -145,6 +145,7 @@ serve: clean_logs $(LOGS_DIR) .PHONY: gunicornserve gunicornserve: clean_logs $(LOGS_DIR) + mkdir -p /tmp/gunicorn_workers SCRIPT_NAME=$(ROUTE_PREFIX) ENV_FILE=$(ENV_FILE) LOGS_DIR=$(LOGS_DIR) $(PYTHON) wsgi.py diff --git a/Pipfile.lock b/Pipfile.lock index 9d436c3..1e5ab68 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "c64c4bc25b5948d6bfd1c474f32fee6908d5debcde334013bb62d90343950ace" + "sha256": "a3c956e1995782f17da822cf00e831d4501851a229f078abbc6f2c626532b572" }, "pipfile-spec": 6, "requires": { @@ -34,10 +34,10 @@ }, "certifi": { "hashes": [ - "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d", - "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412" + "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14", + "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382" ], - "version": "==2022.6.15" + "version": "==2022.9.24" }, "cffi": { "hashes": [ @@ -124,30 +124,34 @@ }, "cryptography": { "hashes": [ - "sha256:190f82f3e87033821828f60787cfa42bff98404483577b591429ed99bed39d59", - "sha256:2be53f9f5505673eeda5f2736bea736c40f051a739bfae2f92d18aed1eb54596", - "sha256:30788e070800fec9bbcf9faa71ea6d8068f5136f60029759fd8c3efec3c9dcb3", - "sha256:3d41b965b3380f10e4611dbae366f6dc3cefc7c9ac4e8842a806b9672ae9add5", - "sha256:4c590ec31550a724ef893c50f9a97a0c14e9c851c85621c5650d699a7b88f7ab", - "sha256:549153378611c0cca1042f20fd9c5030d37a72f634c9326e225c9f666d472884", - "sha256:63f9c17c0e2474ccbebc9302ce2f07b55b3b3fcb211ded18a42d5764f5c10a82", - "sha256:6bc95ed67b6741b2607298f9ea4932ff157e570ef456ef7ff0ef4884a134cc4b", - "sha256:7099a8d55cd49b737ffc99c17de504f2257e3787e02abe6d1a6d136574873441", - "sha256:75976c217f10d48a8b5a8de3d70c454c249e4b91851f6838a4e48b8f41eb71aa", - "sha256:7bc997818309f56c0038a33b8da5c0bfbb3f1f067f315f9abd6fc07ad359398d", - "sha256:80f49023dd13ba35f7c34072fa17f604d2f19bf0989f292cedf7ab5770b87a0b", - "sha256:91ce48d35f4e3d3f1d83e29ef4a9267246e6a3be51864a5b7d2247d5086fa99a", - "sha256:a958c52505c8adf0d3822703078580d2c0456dd1d27fabfb6f76fe63d2971cd6", - "sha256:b62439d7cd1222f3da897e9a9fe53bbf5c104fff4d60893ad1355d4c14a24157", - "sha256:b7f8dd0d4c1f21759695c05a5ec8536c12f31611541f8904083f3dc582604280", - "sha256:d204833f3c8a33bbe11eda63a54b1aad7aa7456ed769a982f21ec599ba5fa282", - "sha256:e007f052ed10cc316df59bc90fbb7ff7950d7e2919c9757fd42a2b8ecf8a5f67", - "sha256:f2dcb0b3b63afb6df7fd94ec6fbddac81b5492513f7b0436210d390c14d46ee8", - "sha256:f721d1885ecae9078c3f6bbe8a88bc0786b6e749bf32ccec1ef2b18929a05046", - "sha256:f7a6de3e98771e183645181b3627e2563dcde3ce94a9e42a3f427d2255190327", - "sha256:f8c0a6e9e1dd3eb0414ba320f85da6b0dcbd543126e30fcc546e7372a7fbf3b9" - ], - "version": "==37.0.4" + "sha256:0d631744fdd965a6ca7e94106046c62ca26cd55a13c47aa76f9d07aa30806b8b", + "sha256:24cb9cb0ea0bc860250cb494ce59bb8d021c00de3a8ead140c0bb198bd0922ca", + "sha256:32f4ab6652f0630884cc902154f1f26a3a5d8495404250019172dca6fd4abf70", + "sha256:407148dbe633d6f0bb3c6d4c0807d33a50d8dadfb1ca40b368fe72fcac4b2116", + "sha256:55974e634712f7d054886a754a10c67b58e6a9d1c6c3d0d1181919e7fb336d0e", + "sha256:6635b89790a616913ae95977dcd756582a3c5a298a0b8f4071a35ec8809e1cab", + "sha256:6b4c782b5f47751983f5acd29344210d4de36524b78fa4fc96e9e47d31e44654", + "sha256:6ea4cbf5d8e8678dcd87fdb1bb5386d6a91cc8d738866f815c6839751221818c", + "sha256:74ccc297d7cd013ca7faf640afaedb305b265420b342ab32d5fa07ddd19f24a1", + "sha256:7a022ec87c7a8bdad99f516a4ee6ffcb3a2bc31487577f9eccbc9b2edb1a8fd4", + "sha256:7e3040ec05cff2ec32719d2b6428d9c022463c3a97735b7ba524e0283a48c8b4", + "sha256:8526fb97be3bae2977bdd8896a552c9149d04b6b77b36b7dfe026b16136061b2", + "sha256:8c6987de4b656f4d8d70ce422b5e275deedf9bf28d99e0470d50706a1470822c", + "sha256:8fa734b9a7cf555fecddd4ba23e2c5524719bacdd63fd61544166c1352fa5e48", + "sha256:9b99713109d76ad35736dcc4e47d54fbaa36cce761adc0333db75e86621fa68c", + "sha256:a25c5e86d34ec43ea59848afc44ec941da0c6d126fcc9ace72a1360e096e528b", + "sha256:ab4d517e2dc08d862493e727a4411ce6caab8a7ac2089b99a059d938ced5aa8b", + "sha256:bd6ca1f5541420f13250b3335228dc7eb6102761a107442cbfba5de4ccc99891", + "sha256:ca99f9c7599a02cddb878c64a2c81bbe0ffef7424c202acef47dd7c069b7469a", + "sha256:cc7852c5f61c62df783bccdef935d5d64ca0dac7e6ace07f9937eff31690ce20", + "sha256:d14f7e1e6726046c8afd240673cb31828dbd434d710d4ecb2060982e5c76df75", + "sha256:dc8d465c2cf489f12f1168670a4eb90e68701916b15f5a1c6a1dd0f9c0b02e92", + "sha256:e03aaa0bb3783302ea23f0f483222d918f148c65e0f953d1c8d82f5e509a7fab", + "sha256:e553175c49ae31db579342d342e649db36cd91f457f3a90eed47698451479890", + "sha256:e90261b616c0805f0147c50fc69f758d7e321f5c446eea291618f2aa6742c5f3", + "sha256:eb603f1809dd095d07a426d81457f4b8236ff4d7a67a976f9da47e13977d427e" + ], + "version": "==38.0.2" }, "defusedxml": { "hashes": [ @@ -197,64 +201,75 @@ }, "greenlet": { "hashes": [ - "sha256:0051c6f1f27cb756ffc0ffbac7d2cd48cb0362ac1736871399a739b2885134d3", - "sha256:00e44c8afdbe5467e4f7b5851be223be68adb4272f44696ee71fe46b7036a711", - "sha256:013d61294b6cd8fe3242932c1c5e36e5d1db2c8afb58606c5a67efce62c1f5fd", - "sha256:049fe7579230e44daef03a259faa24511d10ebfa44f69411d99e6a184fe68073", - "sha256:14d4f3cd4e8b524ae9b8aa567858beed70c392fdec26dbdb0a8a418392e71708", - "sha256:166eac03e48784a6a6e0e5f041cfebb1ab400b394db188c48b3a84737f505b67", - "sha256:17ff94e7a83aa8671a25bf5b59326ec26da379ace2ebc4411d690d80a7fbcf23", - "sha256:1e12bdc622676ce47ae9abbf455c189e442afdde8818d9da983085df6312e7a1", - "sha256:21915eb821a6b3d9d8eefdaf57d6c345b970ad722f856cd71739493ce003ad08", - "sha256:288c6a76705dc54fba69fbcb59904ae4ad768b4c768839b8ca5fdadec6dd8cfd", - "sha256:2bde6792f313f4e918caabc46532aa64aa27a0db05d75b20edfc5c6f46479de2", - "sha256:32ca72bbc673adbcfecb935bb3fb1b74e663d10a4b241aaa2f5a75fe1d1f90aa", - "sha256:356b3576ad078c89a6107caa9c50cc14e98e3a6c4874a37c3e0273e4baf33de8", - "sha256:40b951f601af999a8bf2ce8c71e8aaa4e8c6f78ff8afae7b808aae2dc50d4c40", - "sha256:572e1787d1460da79590bf44304abbc0a2da944ea64ec549188fa84d89bba7ab", - "sha256:58df5c2a0e293bf665a51f8a100d3e9956febfbf1d9aaf8c0677cf70218910c6", - "sha256:64e6175c2e53195278d7388c454e0b30997573f3f4bd63697f88d855f7a6a1fc", - "sha256:7227b47e73dedaa513cdebb98469705ef0d66eb5a1250144468e9c3097d6b59b", - "sha256:7418b6bfc7fe3331541b84bb2141c9baf1ec7132a7ecd9f375912eca810e714e", - "sha256:7cbd7574ce8e138bda9df4efc6bf2ab8572c9aff640d8ecfece1b006b68da963", - "sha256:7ff61ff178250f9bb3cd89752df0f1dd0e27316a8bd1465351652b1b4a4cdfd3", - "sha256:833e1551925ed51e6b44c800e71e77dacd7e49181fdc9ac9a0bf3714d515785d", - "sha256:8639cadfda96737427330a094476d4c7a56ac03de7265622fcf4cfe57c8ae18d", - "sha256:8c5d5b35f789a030ebb95bff352f1d27a93d81069f2adb3182d99882e095cefe", - "sha256:8c790abda465726cfb8bb08bd4ca9a5d0a7bd77c7ac1ca1b839ad823b948ea28", - "sha256:8d2f1fb53a421b410751887eb4ff21386d119ef9cde3797bf5e7ed49fb51a3b3", - "sha256:903bbd302a2378f984aef528f76d4c9b1748f318fe1294961c072bdc7f2ffa3e", - "sha256:93f81b134a165cc17123626ab8da2e30c0455441d4ab5576eed73a64c025b25c", - "sha256:95e69877983ea39b7303570fa6760f81a3eec23d0e3ab2021b7144b94d06202d", - "sha256:9633b3034d3d901f0a46b7939f8c4d64427dfba6bbc5a36b1a67364cf148a1b0", - "sha256:97e5306482182170ade15c4b0d8386ded995a07d7cc2ca8f27958d34d6736497", - "sha256:9f3cba480d3deb69f6ee2c1825060177a22c7826431458c697df88e6aeb3caee", - "sha256:aa5b467f15e78b82257319aebc78dd2915e4c1436c3c0d1ad6f53e47ba6e2713", - "sha256:abb7a75ed8b968f3061327c433a0fbd17b729947b400747c334a9c29a9af6c58", - "sha256:aec52725173bd3a7b56fe91bc56eccb26fbdff1386ef123abb63c84c5b43b63a", - "sha256:b11548073a2213d950c3f671aa88e6f83cda6e2fb97a8b6317b1b5b33d850e06", - "sha256:b1692f7d6bc45e3200844be0dba153612103db241691088626a33ff1f24a0d88", - "sha256:b336501a05e13b616ef81ce329c0e09ac5ed8c732d9ba7e3e983fcc1a9e86965", - "sha256:b8c008de9d0daba7b6666aa5bbfdc23dcd78cafc33997c9b7741ff6353bafb7f", - "sha256:b92e29e58bef6d9cfd340c72b04d74c4b4e9f70c9fa7c78b674d1fec18896dc4", - "sha256:be5f425ff1f5f4b3c1e33ad64ab994eed12fc284a6ea71c5243fd564502ecbe5", - "sha256:dd0b1e9e891f69e7675ba5c92e28b90eaa045f6ab134ffe70b52e948aa175b3c", - "sha256:e30f5ea4ae2346e62cedde8794a56858a67b878dd79f7df76a0767e356b1744a", - "sha256:e6a36bb9474218c7a5b27ae476035497a6990e21d04c279884eb10d9b290f1b1", - "sha256:e859fcb4cbe93504ea18008d1df98dee4f7766db66c435e4882ab35cf70cac43", - "sha256:eb6ea6da4c787111adf40f697b4e58732ee0942b5d3bd8f435277643329ba627", - "sha256:ec8c433b3ab0419100bd45b47c9c8551248a5aee30ca5e9d399a0b57ac04651b", - "sha256:eff9d20417ff9dcb0d25e2defc2574d10b491bf2e693b4e491914738b7908168", - "sha256:f0214eb2a23b85528310dad848ad2ac58e735612929c8072f6093f3585fd342d", - "sha256:f276df9830dba7a333544bd41070e8175762a7ac20350786b322b714b0e654f5", - "sha256:f3acda1924472472ddd60c29e5b9db0cec629fbe3c5c5accb74d6d6d14773478", - "sha256:f70a9e237bb792c7cc7e44c531fd48f5897961701cdaa06cf22fc14965c496cf", - "sha256:f9d29ca8a77117315101425ec7ec2a47a22ccf59f5593378fc4077ac5b754fce", - "sha256:fa877ca7f6b48054f847b61d6fa7bed5cebb663ebc55e018fda12db09dcc664c", - "sha256:fdcec0b8399108577ec290f55551d926d9a1fa6cad45882093a7a07ac5ec147b" + "sha256:0120a879aa2b1ac5118bce959ea2492ba18783f65ea15821680a256dfad04754", + "sha256:025b8de2273d2809f027d347aa2541651d2e15d593bbce0d5f502ca438c54136", + "sha256:05ae7383f968bba4211b1fbfc90158f8e3da86804878442b4fb6c16ccbcaa519", + "sha256:0914f02fcaa8f84f13b2df4a81645d9e82de21ed95633765dd5cc4d3af9d7403", + "sha256:0971d37ae0eaf42344e8610d340aa0ad3d06cd2eee381891a10fe771879791f9", + "sha256:0a954002064ee919b444b19c1185e8cce307a1f20600f47d6f4b6d336972c809", + "sha256:0aa1845944e62f358d63fcc911ad3b415f585612946b8edc824825929b40e59e", + "sha256:104f29dd822be678ef6b16bf0035dcd43206a8a48668a6cae4d2fe9c7a7abdeb", + "sha256:11fc7692d95cc7a6a8447bb160d98671ab291e0a8ea90572d582d57361360f05", + "sha256:17a69967561269b691747e7f436d75a4def47e5efcbc3c573180fc828e176d80", + "sha256:2794eef1b04b5ba8948c72cc606aab62ac4b0c538b14806d9c0d88afd0576d6b", + "sha256:2c6e942ca9835c0b97814d14f78da453241837419e0d26f7403058e8db3e38f8", + "sha256:2ccdc818cc106cc238ff7eba0d71b9c77be868fdca31d6c3b1347a54c9b187b2", + "sha256:325f272eb997916b4a3fc1fea7313a8adb760934c2140ce13a2117e1b0a8095d", + "sha256:39464518a2abe9c505a727af7c0b4efff2cf242aa168be5f0daa47649f4d7ca8", + "sha256:3a24f3213579dc8459e485e333330a921f579543a5214dbc935bc0763474ece3", + "sha256:3aeac044c324c1a4027dca0cde550bd83a0c0fbff7ef2c98df9e718a5086c194", + "sha256:3c22998bfef3fcc1b15694818fc9b1b87c6cc8398198b96b6d355a7bcb8c934e", + "sha256:467b73ce5dcd89e381292fb4314aede9b12906c18fab903f995b86034d96d5c8", + "sha256:4a8b58232f5b72973350c2b917ea3df0bebd07c3c82a0a0e34775fc2c1f857e9", + "sha256:4f74aa0092602da2069df0bc6553919a15169d77bcdab52a21f8c5242898f519", + "sha256:5662492df0588a51d5690f6578f3bbbd803e7f8d99a99f3bf6128a401be9c269", + "sha256:5c2d21c2b768d8c86ad935e404cc78c30d53dea009609c3ef3a9d49970c864b5", + "sha256:5edf75e7fcfa9725064ae0d8407c849456553a181ebefedb7606bac19aa1478b", + "sha256:60839ab4ea7de6139a3be35b77e22e0398c270020050458b3d25db4c7c394df5", + "sha256:62723e7eb85fa52e536e516ee2ac91433c7bb60d51099293671815ff49ed1c21", + "sha256:64e10f303ea354500c927da5b59c3802196a07468332d292aef9ddaca08d03dd", + "sha256:66aa4e9a726b70bcbfcc446b7ba89c8cec40f405e51422c39f42dfa206a96a05", + "sha256:695d0d8b5ae42c800f1763c9fce9d7b94ae3b878919379150ee5ba458a460d57", + "sha256:70048d7b2c07c5eadf8393e6398595591df5f59a2f26abc2f81abca09610492f", + "sha256:7afa706510ab079fd6d039cc6e369d4535a48e202d042c32e2097f030a16450f", + "sha256:7cf37343e43404699d58808e51f347f57efd3010cc7cee134cdb9141bd1ad9ea", + "sha256:8149a6865b14c33be7ae760bcdb73548bb01e8e47ae15e013bf7ef9290ca309a", + "sha256:814f26b864ed2230d3a7efe0336f5766ad012f94aad6ba43a7c54ca88dd77cba", + "sha256:82a38d7d2077128a017094aff334e67e26194f46bd709f9dcdacbf3835d47ef5", + "sha256:83a7a6560df073ec9de2b7cb685b199dfd12519bc0020c62db9d1bb522f989fa", + "sha256:8415239c68b2ec9de10a5adf1130ee9cb0ebd3e19573c55ba160ff0ca809e012", + "sha256:88720794390002b0c8fa29e9602b395093a9a766b229a847e8d88349e418b28a", + "sha256:890f633dc8cb307761ec566bc0b4e350a93ddd77dc172839be122be12bae3e10", + "sha256:8926a78192b8b73c936f3e87929931455a6a6c6c385448a07b9f7d1072c19ff3", + "sha256:8c0581077cf2734569f3e500fab09c0ff6a2ab99b1afcacbad09b3c2843ae743", + "sha256:8fda1139d87ce5f7bd80e80e54f9f2c6fe2f47983f1a6f128c47bf310197deb6", + "sha256:91a84faf718e6f8b888ca63d0b2d6d185c8e2a198d2a7322d75c303e7097c8b7", + "sha256:924df1e7e5db27d19b1359dc7d052a917529c95ba5b8b62f4af611176da7c8ad", + "sha256:949c9061b8c6d3e6e439466a9be1e787208dec6246f4ec5fffe9677b4c19fcc3", + "sha256:9649891ab4153f217f319914455ccf0b86986b55fc0573ce803eb998ad7d6854", + "sha256:96656c5f7c95fc02c36d4f6ef32f4e94bb0b6b36e6a002c21c39785a4eec5f5d", + "sha256:a812df7282a8fc717eafd487fccc5ba40ea83bb5b13eb3c90c446d88dbdfd2be", + "sha256:a8d24eb5cb67996fb84633fdc96dbc04f2d8b12bfcb20ab3222d6be271616b67", + "sha256:bef49c07fcb411c942da6ee7d7ea37430f830c482bf6e4b72d92fd506dd3a427", + "sha256:bffba15cff4802ff493d6edcf20d7f94ab1c2aee7cfc1e1c7627c05f1102eee8", + "sha256:c0643250dd0756f4960633f5359884f609a234d4066686754e834073d84e9b51", + "sha256:c6f90234e4438062d6d09f7d667f79edcc7c5e354ba3a145ff98176f974b8132", + "sha256:c8c9301e3274276d3d20ab6335aa7c5d9e5da2009cccb01127bddb5c951f8870", + "sha256:c8ece5d1a99a2adcb38f69af2f07d96fb615415d32820108cd340361f590d128", + "sha256:cb863057bed786f6622982fb8b2c122c68e6e9eddccaa9fa98fd937e45ee6c4f", + "sha256:ccbe7129a282ec5797df0451ca1802f11578be018a32979131065565da89b392", + "sha256:d25cdedd72aa2271b984af54294e9527306966ec18963fd032cc851a725ddc1b", + "sha256:d75afcbb214d429dacdf75e03a1d6d6c5bd1fa9c35e360df8ea5b6270fb2211c", + "sha256:d7815e1519a8361c5ea2a7a5864945906f8e386fa1bc26797b4d443ab11a4589", + "sha256:eb6ac495dccb1520667cfea50d89e26f9ffb49fa28496dea2b95720d8b45eb54", + "sha256:ec615d2912b9ad807afd3be80bf32711c0ff9c2b00aa004a45fd5d5dde7853d9", + "sha256:f5e09dc5c6e1796969fd4b775ea1417d70e49a5df29aaa8e5d10675d9e11872c", + "sha256:f6661b58412879a2aa099abb26d3c93e91dedaba55a6394d1fb1512a77e85de9", + "sha256:f7d20c3267385236b4ce54575cc8e9f43e7673fc761b069c820097092e318e3b", + "sha256:fe7c51f8a2ab616cb34bc33d810c887e89117771028e1e3d3b77ca25ddeace04" ], "markers": "platform_python_implementation == 'CPython'", - "version": "==1.1.2" + "version": "==1.1.3.post0" }, "gunicorn": { "hashes": [ @@ -266,18 +281,18 @@ }, "idna": { "hashes": [ - "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", - "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" + "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", + "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" ], - "version": "==3.3" + "version": "==3.4" }, "importlib-metadata": { "hashes": [ - "sha256:637245b8bab2b6502fcbc752cc4b7a6f6243bb02b31c5c26156ad103d3d45670", - "sha256:7401a975809ea1fdc658c3aa4f78cc2195a0e019c5cbc4c06122884e9ae80c23" + "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab", + "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43" ], "markers": "python_version < '3.10'", - "version": "==4.12.0" + "version": "==5.0.0" }, "itsdangerous": { "hashes": [ @@ -302,11 +317,11 @@ }, "logging-utilities": { "hashes": [ - "sha256:2f82c797370dd2eb03efb71abe70008ba5902205b76c744b6e331b43b95e897a", - "sha256:915c281aa86b1e151ba8d8652345e1ecf2becaca1a3594c3cf6fbc1a62c612e2" + "sha256:39ca6b4d840a17c81cfbd21540cf57d4a1c134ae307ffa538c6a619565967284", + "sha256:5545d2208b4ffe72ebc50d469297f0b40bd000765bfb6f4a9b6976335e82bc27" ], "index": "pypi", - "version": "==2.0.0" + "version": "==3.1.3" }, "markupsafe": { "hashes": [ @@ -355,11 +370,11 @@ }, "moto": { "hashes": [ - "sha256:742567fa300b9d51cf63f7b1d0524c70b975e85c6a50e3d94346a6984c19d6e0", - "sha256:82d590021a7ef2bdbd83ee74a01b2ecc65c216915d117d7ae88778b79f81887c" + "sha256:3bd8a72dc385819c84ed3f9d18c386985634041c6ae544d957bd8ab88c6c15f1", + "sha256:8761880f5f3c3af27daac3882a56aae7e21fa2121f430cf917e55e977bddaf6b" ], "index": "pypi", - "version": "==4.0.0" + "version": "==4.0.8" }, "pycparser": { "hashes": [ @@ -385,13 +400,14 @@ }, "pytz": { "hashes": [ - "sha256:220f481bdafa09c3955dfbdddb7b57780e9a94f5127e35456a48589b9e0c0197", - "sha256:cea221417204f2d1a2aa03ddae3e867921971d0d76f14d87abb4414415bbdcf5" + "sha256:335ab46900b1465e714b4fda4963d87363264eb662aab5e65da039c25f1f5b22", + "sha256:c4d88f472f54d615e9cd582a5004d1e5f624854a6a27a6211591c251f22a6914" ], - "version": "==2022.2.1" + "version": "==2022.5" }, "pyyaml": { "hashes": [ + "sha256:01b45c0191e6d66c470b6cf1b9531a771a83c1c4208272ead47a3ae4f2f603bf", "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293", "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b", "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57", @@ -403,26 +419,32 @@ "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287", "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513", "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0", + "sha256:432557aa2c09802be39460360ddffd48156e30721f5e8d917f01d31694216782", "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0", "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92", "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f", "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2", "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc", + "sha256:81957921f441d50af23654aa6c5e5eaf9b06aba7f0a19c18a538dc7ef291c5a1", "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c", "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86", "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4", "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c", "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34", "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b", + "sha256:afa17f5bc4d1b10afd4466fd3a44dc0e245382deca5b3c353d8b757f9e3ecb8d", "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c", "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb", + "sha256:bfaef573a63ba8923503d27530362590ff4f576c626d86a9fed95822a8255fd7", "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737", "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3", "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d", + "sha256:d4b0ba9512519522b118090257be113b9468d804b19d63c71dbcf4a48fa32358", "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53", "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78", "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803", "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a", + "sha256:dbad0e9d368bb989f4515da330b88a057617d16b6a8245084f1b05400f24609f", "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174", "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5" ], @@ -438,10 +460,10 @@ }, "responses": { "hashes": [ - "sha256:2dcc863ba63963c0c3d9ee3fa9507cbe36b7d7b0fccb4f0bdfd9e96c539b1487", - "sha256:b82502eb5f09a0289d8e209e7bad71ef3978334f56d09b444253d5ad67bf5253" + "sha256:396acb2a13d25297789a5866b4881cf4e46ffd49cc26c43ab1117f40b973102e", + "sha256:dcf294d204d14c436fddcc74caefdbc5764795a40ff4e6a7740ed8ddbf3294be" ], - "version": "==0.21.0" + "version": "==0.22.0" }, "s3transfer": { "hashes": [ @@ -457,19 +479,33 @@ ], "version": "==1.16.0" }, + "toml": { + "hashes": [ + "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", + "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" + ], + "version": "==0.10.2" + }, + "types-toml": { + "hashes": [ + "sha256:8300fd093e5829eb9c1fba69cee38130347d4b74ddf32d0a7df650ae55c2b599", + "sha256:b7e7ea572308b1030dc86c3ba825c5210814c2825612ec679eb7814f8dd9295a" + ], + "version": "==0.10.8" + }, "urllib3": { "hashes": [ - "sha256:c33ccba33c819596124764c23a97d25f32b28433ba0dedeb77d873a38722c9bc", - "sha256:ea6e8fb210b19d950fab93b60c9009226c63a28808bc8386e05301e25883ac0a" + "sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e", + "sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997" ], - "version": "==1.26.11" + "version": "==1.26.12" }, "werkzeug": { "hashes": [ - "sha256:1ce08e8093ed67d638d63879fd1ba3735817f7a80de3674d293f5984f25fb6e6", - "sha256:72a4b735692dd3135217911cbeaa1be5fa3f62bffb8745c5215420a03dc55255" + "sha256:7ea2d48322cc7c0f8b3a215ed73eabd7b5d75d0b50e31ab006286ccff9e00b8f", + "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5" ], - "version": "==2.1.2" + "version": "==2.2.2" }, "xmltodict": { "hashes": [ @@ -480,10 +516,10 @@ }, "zipp": { "hashes": [ - "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2", - "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009" + "sha256:4fcb6f278987a6605757302a6e40e896257570d11c51628968ccb2a47e80c6c1", + "sha256:7a7262fd930bd3e36c50b9a64897aec3fafff3dfdeec9623ae22b40e93f99bb8" ], - "version": "==3.8.1" + "version": "==3.10.0" }, "zope.event": { "hashes": [ @@ -494,75 +530,61 @@ }, "zope.interface": { "hashes": [ - "sha256:08f9636e99a9d5410181ba0729e0408d3d8748026ea938f3b970a0249daa8192", - "sha256:0b465ae0962d49c68aa9733ba92a001b2a0933c317780435f00be7ecb959c702", - "sha256:0cba8477e300d64a11a9789ed40ee8932b59f9ee05f85276dbb4b59acee5dd09", - "sha256:0cee5187b60ed26d56eb2960136288ce91bcf61e2a9405660d271d1f122a69a4", - "sha256:0ea1d73b7c9dcbc5080bb8aaffb776f1c68e807767069b9ccdd06f27a161914a", - "sha256:0f91b5b948686659a8e28b728ff5e74b1be6bf40cb04704453617e5f1e945ef3", - "sha256:15e7d1f7a6ee16572e21e3576d2012b2778cbacf75eb4b7400be37455f5ca8bf", - "sha256:17776ecd3a1fdd2b2cd5373e5ef8b307162f581c693575ec62e7c5399d80794c", - "sha256:194d0bcb1374ac3e1e023961610dc8f2c78a0f5f634d0c737691e215569e640d", - "sha256:1c0e316c9add0db48a5b703833881351444398b04111188069a26a61cfb4df78", - "sha256:205e40ccde0f37496904572035deea747390a8b7dc65146d30b96e2dd1359a83", - "sha256:273f158fabc5ea33cbc936da0ab3d4ba80ede5351babc4f577d768e057651531", - "sha256:2876246527c91e101184f63ccd1d716ec9c46519cc5f3d5375a3351c46467c46", - "sha256:2c98384b254b37ce50eddd55db8d381a5c53b4c10ee66e1e7fe749824f894021", - "sha256:2e5a26f16503be6c826abca904e45f1a44ff275fdb7e9d1b75c10671c26f8b94", - "sha256:334701327f37c47fa628fc8b8d28c7d7730ce7daaf4bda1efb741679c2b087fc", - "sha256:3748fac0d0f6a304e674955ab1365d515993b3a0a865e16a11ec9d86fb307f63", - "sha256:3c02411a3b62668200910090a0dff17c0b25aaa36145082a5a6adf08fa281e54", - "sha256:3dd4952748521205697bc2802e4afac5ed4b02909bb799ba1fe239f77fd4e117", - "sha256:3f24df7124c323fceb53ff6168da70dbfbae1442b4f3da439cd441681f54fe25", - "sha256:469e2407e0fe9880ac690a3666f03eb4c3c444411a5a5fddfdabc5d184a79f05", - "sha256:4de4bc9b6d35c5af65b454d3e9bc98c50eb3960d5a3762c9438df57427134b8e", - "sha256:5208ebd5152e040640518a77827bdfcc73773a15a33d6644015b763b9c9febc1", - "sha256:52de7fc6c21b419078008f697fd4103dbc763288b1406b4562554bd47514c004", - "sha256:5bb3489b4558e49ad2c5118137cfeaf59434f9737fa9c5deefc72d22c23822e2", - "sha256:5dba5f530fec3f0988d83b78cc591b58c0b6eb8431a85edd1569a0539a8a5a0e", - "sha256:5dd9ca406499444f4c8299f803d4a14edf7890ecc595c8b1c7115c2342cadc5f", - "sha256:5f931a1c21dfa7a9c573ec1f50a31135ccce84e32507c54e1ea404894c5eb96f", - "sha256:63b82bb63de7c821428d513607e84c6d97d58afd1fe2eb645030bdc185440120", - "sha256:66c0061c91b3b9cf542131148ef7ecbecb2690d48d1612ec386de9d36766058f", - "sha256:6f0c02cbb9691b7c91d5009108f975f8ffeab5dff8f26d62e21c493060eff2a1", - "sha256:71aace0c42d53abe6fc7f726c5d3b60d90f3c5c055a447950ad6ea9cec2e37d9", - "sha256:7d97a4306898b05404a0dcdc32d9709b7d8832c0c542b861d9a826301719794e", - "sha256:7df1e1c05304f26faa49fa752a8c690126cf98b40b91d54e6e9cc3b7d6ffe8b7", - "sha256:8270252effc60b9642b423189a2fe90eb6b59e87cbee54549db3f5562ff8d1b8", - "sha256:867a5ad16892bf20e6c4ea2aab1971f45645ff3102ad29bd84c86027fa99997b", - "sha256:877473e675fdcc113c138813a5dd440da0769a2d81f4d86614e5d62b69497155", - "sha256:8892f89999ffd992208754851e5a052f6b5db70a1e3f7d54b17c5211e37a98c7", - "sha256:9a9845c4c6bb56e508651f005c4aeb0404e518c6f000d5a1123ab077ab769f5c", - "sha256:a1e6e96217a0f72e2b8629e271e1b280c6fa3fe6e59fa8f6701bec14e3354325", - "sha256:a8156e6a7f5e2a0ff0c5b21d6bcb45145efece1909efcbbbf48c56f8da68221d", - "sha256:a9506a7e80bcf6eacfff7f804c0ad5350c8c95b9010e4356a4b36f5322f09abb", - "sha256:af310ec8335016b5e52cae60cda4a4f2a60a788cbb949a4fbea13d441aa5a09e", - "sha256:b0297b1e05fd128d26cc2460c810d42e205d16d76799526dfa8c8ccd50e74959", - "sha256:bf68f4b2b6683e52bec69273562df15af352e5ed25d1b6641e7efddc5951d1a7", - "sha256:d0c1bc2fa9a7285719e5678584f6b92572a5b639d0e471bb8d4b650a1a910920", - "sha256:d4d9d6c1a455d4babd320203b918ccc7fcbefe308615c521062bc2ba1aa4d26e", - "sha256:db1fa631737dab9fa0b37f3979d8d2631e348c3b4e8325d6873c2541d0ae5a48", - "sha256:dd93ea5c0c7f3e25335ab7d22a507b1dc43976e1345508f845efc573d3d779d8", - "sha256:f44e517131a98f7a76696a7b21b164bcb85291cee106a23beccce454e1f433a4", - "sha256:f7ee479e96f7ee350db1cf24afa5685a5899e2b34992fb99e1f7c1b0b758d263" - ], - "version": "==5.4.0" + "sha256:006f8dd81fae28027fc28ada214855166712bf4f0bfbc5a8788f9b70982b9437", + "sha256:03f5ae315db0d0de668125d983e2a819a554f3fdb2d53b7e934e3eb3c3c7375d", + "sha256:0eb2b3e84f48dd9cfc8621c80fba905d7e228615c67f76c7df7c716065669bb6", + "sha256:1e3495bb0cdcea212154e558082c256f11b18031f05193ae2fb85d048848db14", + "sha256:26c1456520fdcafecc5765bec4783eeafd2e893eabc636908f50ee31fe5c738c", + "sha256:2cb3003941f5f4fa577479ac6d5db2b940acb600096dd9ea9bf07007f5cab46f", + "sha256:37ec9ade9902f412cc7e7a32d71f79dec3035bad9bd0170226252eed88763c48", + "sha256:3eedf3d04179774d750e8bb4463e6da350956a50ed44d7b86098e452d7ec385e", + "sha256:3f68404edb1a4fb6aa8a94675521ca26c83ebbdbb90e894f749ae0dc4ca98418", + "sha256:423c074e404f13e6fa07f4454f47fdbb38d358be22945bc812b94289d9142374", + "sha256:43490ad65d4c64e45a30e51a2beb7a6b63e1ff395302ad22392224eb618476d6", + "sha256:47ff078734a1030c48103422a99e71a7662d20258c00306546441adf689416f7", + "sha256:58a66c2020a347973168a4a9d64317bac52f9fdfd3e6b80b252be30da881a64e", + "sha256:58a975f89e4584d0223ab813c5ba4787064c68feef4b30d600f5e01de90ae9ce", + "sha256:5c6023ae7defd052cf76986ce77922177b0c2f3913bea31b5b28fbdf6cb7099e", + "sha256:6566b3d2657e7609cd8751bcb1eab1202b1692a7af223035a5887d64bb3a2f3b", + "sha256:687cab7f9ae18d2c146f315d0ca81e5ffe89a139b88277afa70d52f632515854", + "sha256:700ebf9662cf8df70e2f0cb4988e078c53f65ee3eefd5c9d80cf988c4175c8e3", + "sha256:740f3c1b44380658777669bcc42f650f5348e53797f2cee0d93dc9b0f9d7cc69", + "sha256:7bdcec93f152e0e1942102537eed7b166d6661ae57835b20a52a2a3d6a3e1bf3", + "sha256:7d9ec1e6694af39b687045712a8ad14ddcb568670d5eb1b66b48b98b9312afba", + "sha256:85dd6dd9aaae7a176948d8bb62e20e2968588fd787c29c5d0d964ab475168d3d", + "sha256:8b9f153208d74ccfa25449a0c6cb756ab792ce0dc99d9d771d935f039b38740c", + "sha256:8c791f4c203ccdbcda588ea4c8a6e4353e10435ea48ddd3d8734a26fe9714cba", + "sha256:970661ece2029915b8f7f70892e88404340fbdefd64728380cad41c8dce14ff4", + "sha256:9cdc4e898d3b1547d018829fd4a9f403e52e51bba24be0fbfa37f3174e1ef797", + "sha256:9dc4493aa3d87591e3d2bf1453e25b98038c839ca8e499df3d7106631b66fe83", + "sha256:a69c28d85bb7cf557751a5214cb3f657b2b035c8c96d71080c1253b75b79b69b", + "sha256:aeac590cce44e68ee8ad0b8ecf4d7bf15801f102d564ca1b0eb1f12f584ee656", + "sha256:be11fce0e6af6c0e8d93c10ef17b25aa7c4acb7ec644bff2596c0d639c49e20f", + "sha256:cbbf83914b9a883ab324f728de869f4e406e0cbcd92df7e0a88decf6f9ab7d5a", + "sha256:cfa614d049667bed1c737435c609c0956c5dc0dbafdc1145ee7935e4658582cb", + "sha256:d18fb0f6c8169d26044128a2e7d3c39377a8a151c564e87b875d379dbafd3930", + "sha256:d80f6236b57a95eb19d5e47eb68d0296119e1eff6deaa2971ab8abe3af918420", + "sha256:da7912ae76e1df6a1fb841b619110b1be4c86dfb36699d7fd2f177105cdea885", + "sha256:df6593e150d13cfcce69b0aec5df7bc248cb91e4258a7374c129bb6d56b4e5ca", + "sha256:f70726b60009433111fe9928f5d89cbb18962411d33c45fb19eb81b9bbd26fcd" + ], + "version": "==5.5.0" } }, "develop": { "astroid": { "hashes": [ - "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b", - "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946" + "sha256:1c00a14f5a3ed0339d38d2e2e5b74ea2591df5861c0936bb292b84ccf3a78d83", + "sha256:72702205200b2a638358369d90c222d74ebc376787af8fb2f7f2a86f7b5cc85f" ], - "version": "==2.11.7" + "version": "==2.12.12" }, "dill": { "hashes": [ - "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302", - "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86" + "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0", + "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373" ], - "version": "==0.3.5.1" + "version": "==0.3.6" }, "isort": { "hashes": [ @@ -637,11 +659,11 @@ }, "pylint": { "hashes": [ - "sha256:487ce2192eee48211269a0e976421f334cf94de1806ca9d0a99449adcdf0285e", - "sha256:fabe30000de7d07636d2e82c9a518ad5ad7908590fe135ace169b44839c15f90" + "sha256:3b120505e5af1d06a5ad76b55d8660d44bf0f2fc3c59c2bdd94e39188ee3a4df", + "sha256:c2108037eb074334d9e874dc3c783752cc03d0796c88c9a9af282d0f161a1004" ], "index": "pypi", - "version": "==2.14.5" + "version": "==2.15.5" }, "pylint-flask": { "hashes": [ @@ -667,18 +689,18 @@ }, "tomlkit": { "hashes": [ - "sha256:25d4e2e446c453be6360c67ddfb88838cfc42026322770ba13d1fbd403a93a5c", - "sha256:3235a9010fae54323e727c3ac06fb720752fe6635b3426e379daec60fbd44a83" + "sha256:571854ebbb5eac89abcb4a2e47d7ea27b89bf29e09c35395da6f03dd4ae23d1c", + "sha256:f2ef9da9cef846ee027947dc99a45d6b68a63b0ebc21944649505bf2e8bc5fe7" ], - "version": "==0.11.4" + "version": "==0.11.5" }, "typing-extensions": { "hashes": [ - "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02", - "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6" + "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", + "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" ], "markers": "python_version < '3.10'", - "version": "==4.3.0" + "version": "==4.4.0" }, "wrapt": { "hashes": [ @@ -747,6 +769,7 @@ "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015", "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af" ], + "markers": "python_version < '3.11'", "version": "==1.14.1" }, "yapf": { diff --git a/README.md b/README.md index 193c986..87db4db 100644 --- a/README.md +++ b/README.md @@ -216,3 +216,4 @@ The service is configured by Environment Variable: | SCRIPT_NAME | `''` | If the service is behind a reverse proxy and not served at the root, the route prefix must be set in `SCRIPT_NAME`. | | CACHE_CONTROL | `no-cache, no-store, must-revalidate` | Cache Control header value of the GET endpoint(s) | | CACHE_CONTROL_4XX | `public, max-age=3600` | Cache Control header for 4XX responses | +| GUNICORN_WORKER_TMP_DIR | `/tmp/gunicorn_workers` | Gunicorn worker tmp directory. :warning: This directory should be on **TMPFS** for better performance. | diff --git a/app/helpers/dynamodb.py b/app/helpers/dynamodb.py index 7bb0422..8303d17 100644 --- a/app/helpers/dynamodb.py +++ b/app/helpers/dynamodb.py @@ -43,28 +43,29 @@ def __init__(self, table_name, bucket_name, endpoint_url, table_region): self.endpoint = endpoint_url def save_item( - self, kml_id, kml_admin_id, file_key, file_length, timestamp, empty=False, author='' + self, kml_id, kml_admin_id, file_key, file_length, timestamp, author, author_version, empty ): logger.debug('Saving dynamodb item with primary key %s', kml_id) + db_item = { + 'kml_id': kml_id, + 'admin_id': kml_admin_id, + 'created': timestamp, + 'updated': timestamp, + 'bucket': self.bucket_name, + 'file_key': file_key, + 'empty': empty, + 'length': file_length, + 'encoding': KML_FILE_CONTENT_ENCODING, + 'content_type': KML_FILE_CONTENT_TYPE, + 'author': author, + 'author_version': author_version + } try: - self.table.put_item( - Item={ - 'kml_id': kml_id, - 'admin_id': kml_admin_id, - 'created': timestamp, - 'updated': timestamp, - 'bucket': self.bucket_name, - 'file_key': file_key, - 'empty': empty, - 'length': file_length, - 'encoding': KML_FILE_CONTENT_ENCODING, - 'content_type': KML_FILE_CONTENT_TYPE, - 'author': author - } - ) + self.table.put_item(Item=db_item) except EndpointConnectionError as error: logger.exception('Failed to connect to DynamoDB: %s', error) abort(502, 'Backend DB connection error, please consult logs') + return db_item def get_item(self, kml_id): logger.debug('Get dynamodb item with primary key %s', kml_id) @@ -106,27 +107,33 @@ def get_item_by_admin_id(self, admin_id): return items[0] - def update_item(self, kml_id, file_length, timestamp, empty): + def update_item(self, kml_id, db_item, file_length, timestamp, empty, author_version=None): logger.debug('Updating dynamodb item with primary key %s', kml_id) + db_item['updated'] = timestamp + db_item['empty'] = empty + db_item['length'] = file_length + attribute_updates = { + 'updated': { + 'Value': timestamp, 'Action': 'PUT' + }, + 'empty': { + 'Value': empty, 'Action': 'PUT' + }, + 'length': { + 'Value': file_length, 'Action': 'PUT' + } + } + if author_version is not None: + attribute_updates['author_version'] = {'Value': author_version, 'Action': 'PUT'} + db_item['author_version'] = author_version try: - self.table.update_item( - Key={'kml_id': kml_id}, - AttributeUpdates={ - 'updated': { - 'Value': timestamp, 'Action': 'PUT' - }, - 'empty': { - 'Value': empty, 'Action': 'PUT' - }, - 'length': { - 'Value': file_length, 'Action': 'PUT' - } - } - ) + self.table.update_item(Key={'kml_id': kml_id}, AttributeUpdates=attribute_updates) except EndpointConnectionError as error: logger.exception('Failed to connect to DynamoDB: %s', error) abort(502, 'Backend DB connection error, please consult logs') + return db_item + def delete_item(self, kml_id): logger.debug('Deleting dynamodb item with primary key %s', kml_id) try: diff --git a/app/helpers/utils.py b/app/helpers/utils.py index df5b369..6369873 100644 --- a/app/helpers/utils.py +++ b/app/helpers/utils.py @@ -16,7 +16,9 @@ from flask import jsonify from flask import make_response from flask import request +from flask.helpers import url_for +from app.settings import DEFAULT_AUTHOR_VERSION from app.settings import KML_FILE_CONTENT_TYPE from app.settings import KML_MAX_SIZE from app.settings import KML_STORAGE_HOST_URL @@ -179,6 +181,13 @@ def validate_kml_file(): return gzip_string(kml_string), empty +def validate_author(): + author = request.form.get('author', None) + if author is None: + abort(400, "Missing author field") + return author + + def get_kml_file_link(file_key): if KML_STORAGE_HOST_URL: return f'{KML_STORAGE_HOST_URL}/{file_key}' @@ -228,3 +237,24 @@ def decompress_if_gzipped(file_content): logger.error("Error when trying to decompress kml file: %s", error) raise error return ret + + +def get_json_metadata(db_item, with_admin_id=False): + '''Return a json metadata output of a DB entry''' + metadata = { + 'id': db_item['kml_id'], + 'success': True, + 'created': db_item['created'], + 'updated': db_item['updated'], + 'empty': db_item['empty'], + 'author': db_item['author'], + 'author_version': db_item.get('author_version', DEFAULT_AUTHOR_VERSION), + 'links': + { + 'self': url_for('get_kml_metadata', kml_id=db_item['kml_id'], _external=True), + 'kml': get_kml_file_link(db_item['file_key']), + } + } + if with_admin_id: + metadata['admin_id'] = db_item['admin_id'] + return metadata diff --git a/app/routes.py b/app/routes.py index 1148879..5e60679 100644 --- a/app/routes.py +++ b/app/routes.py @@ -8,16 +8,17 @@ from flask import jsonify from flask import make_response from flask import request -from flask.helpers import url_for from app import app from app.helpers.dynamodb import get_db from app.helpers.s3 import get_storage -from app.helpers.utils import get_kml_file_link +from app.helpers.utils import get_json_metadata +from app.helpers.utils import validate_author from app.helpers.utils import validate_content_length from app.helpers.utils import validate_content_type from app.helpers.utils import validate_kml_file from app.helpers.utils import validate_permissions +from app.settings import DEFAULT_AUTHOR_VERSION from app.settings import SCRIPT_NAME from app.version import APP_VERSION @@ -39,7 +40,9 @@ def create_kml(): # Get the kml file data kml_string_gzip, empty = validate_kml_file() # Get the author - author = request.form.get('author', 'unknown') + author = validate_author() + # Get the client version + author_version = request.form.get('author_version', DEFAULT_AUTHOR_VERSION) kml_admin_id = urlsafe_b64encode(uuid4().bytes).decode('utf8').replace('=', '') kml_id = urlsafe_b64encode(uuid4().bytes).decode('utf8').replace('=', '') @@ -50,27 +53,19 @@ def create_kml(): storage.upload_object_to_bucket(file_key, kml_string_gzip) db = get_db() - db.save_item(kml_id, kml_admin_id, file_key, len(kml_string_gzip), timestamp, empty, author) - - return make_response( - jsonify( - { - 'id': kml_id, - 'admin_id': kml_admin_id, - 'success': True, - 'created': timestamp, - 'updated': timestamp, - 'empty': empty, - 'links': - { - 'self': url_for('get_kml_metadata', kml_id=kml_id, _external=True), - 'kml': get_kml_file_link(file_key), - } - } - ), - 201 + db_item = db.save_item( + kml_id, + kml_admin_id, + file_key, + len(kml_string_gzip), + timestamp, + author, + author_version, + empty ) + return make_response(jsonify(get_json_metadata(db_item, with_admin_id=True)), 201) + @app.route('/admin', methods=['GET']) def get_kml_metadata_by_admin_id(): @@ -78,47 +73,14 @@ def get_kml_metadata_by_admin_id(): if not admin_id: logger.error("Query parameter admin_id is required: query=%s", request.args) abort(400, "Query parameter admin_id is required") - item = get_db().get_item_by_admin_id(admin_id) - return make_response( - jsonify( - { - 'id': item['kml_id'], - 'admin_id': admin_id, - 'success': True, - 'created': item['created'], - 'updated': item['updated'], - 'empty': item['empty'], - 'links': - { - 'self': url_for('get_kml_metadata', kml_id=item['kml_id'], _external=True), - 'kml': get_kml_file_link(item['file_key']), - } - } - ), - 200 - ) + db_item = get_db().get_item_by_admin_id(admin_id) + return make_response(jsonify(get_json_metadata(db_item, with_admin_id=True)), 200) @app.route('/admin/', methods=['GET']) def get_kml_metadata(kml_id): - item = get_db().get_item(kml_id) - return make_response( - jsonify( - { - 'id': kml_id, - 'success': True, - 'created': item['created'], - 'updated': item['updated'], - 'empty': item['empty'], - 'links': - { - 'self': url_for('get_kml_metadata', kml_id=kml_id, _external=True), - 'kml': get_kml_file_link(item['file_key']), - } - } - ), - 200 - ) + db_item = get_db().get_item(kml_id) + return make_response(jsonify(get_json_metadata(db_item, with_admin_id=False)), 200) @app.route('/admin/', methods=['PUT']) @@ -127,37 +89,25 @@ def get_kml_metadata(kml_id): def update_kml(kml_id): db = get_db() - item = db.get_item(kml_id) - admin_id = validate_permissions(item) + db_item = db.get_item(kml_id) + admin_id = validate_permissions(db_item) + + # Get the client version + author_version = request.form.get('author_version', None) # Get the kml file data kml_string_gzip, empty = validate_kml_file() storage = get_storage() - storage.upload_object_to_bucket(item['file_key'], kml_string_gzip) + storage.upload_object_to_bucket(db_item['file_key'], kml_string_gzip) timestamp = datetime.utcnow().replace(tzinfo=timezone.utc).isoformat(timespec='milliseconds') - db.update_item(kml_id, len(kml_string_gzip), timestamp, empty) - - return make_response( - jsonify( - { - 'id': kml_id, - 'admin_id': admin_id, - 'success': True, - 'created': item['created'], - 'updated': timestamp, - 'empty': empty, - 'links': - { - 'self': url_for('get_kml_metadata', kml_id=kml_id, _external=True), - 'kml': get_kml_file_link(item['file_key']), - } - } - ), - 200 + db_item = db.update_item( + kml_id, db_item, len(kml_string_gzip), timestamp, empty, author_version ) + return make_response(jsonify(get_json_metadata(db_item, with_admin_id=True)), 200) + @app.route('/admin/', methods=['DELETE']) @validate_content_type("multipart/form-data") diff --git a/app/settings.py b/app/settings.py index 31f4d30..3560c85 100644 --- a/app/settings.py +++ b/app/settings.py @@ -34,3 +34,5 @@ CACHE_CONTROL = os.getenv('CACHE_CONTROL', 'no-cache, no-store, must-revalidate') CACHE_CONTROL_4XX = os.getenv('CACHE_CONTROL_4XX', 'public, max-age=3600') + +DEFAULT_AUTHOR_VERSION = '0.0.0' diff --git a/tests/unit_tests/base.py b/tests/unit_tests/base.py index 7c4e9ac..877954b 100644 --- a/tests/unit_tests/base.py +++ b/tests/unit_tests/base.py @@ -20,6 +20,7 @@ from app.settings import AWS_DB_TABLE_NAME from app.settings import AWS_S3_BUCKET_NAME from app.settings import AWS_S3_REGION_NAME +from app.settings import DEFAULT_AUTHOR_VERSION from app.settings import KML_FILE_CONTENT_ENCODING from app.settings import KML_FILE_CONTENT_TYPE @@ -88,21 +89,31 @@ def create_dynamodb(): def prepare_kml_payload( - kml_data=None, admin_id=None, kml_file=None, content_type=KML_FILE_CONTENT_TYPE + kml_data=None, + admin_id=None, + kml_file=None, + content_type=KML_FILE_CONTENT_TYPE, + author=None, + author_version=None ): - author = 'unittest' if kml_file and kml_data is None: with open(f'./tests/samples/{kml_file}', 'rb') as file: kml_data = file.read() if admin_id and kml_data: - return dict( - admin_id=admin_id, kml=(io.BytesIO(kml_data), 'kml.xml', content_type), author=author - ) - if kml_data: - return dict(kml=(io.BytesIO(kml_data), 'kml.xml', content_type), author=author) - if admin_id: - return dict(admin_id=admin_id) - raise ValueError('No admin_id and no kml_string given') + data = dict(admin_id=admin_id, kml=(io.BytesIO(kml_data), 'kml.xml', content_type)) + elif kml_data: + data = dict(kml=(io.BytesIO(kml_data), 'kml.xml', content_type)) + elif admin_id: + data = dict(admin_id=admin_id) + else: + raise ValueError('No admin_id and no kml_string given') + + if author is not None: + data['author'] = author + + if author_version is not None: + data['author_version'] = author_version + return data class BaseRouteTestCase(unittest.TestCase): @@ -159,10 +170,12 @@ def assertCors(self, response, expected_allowed_methods): # pylint: disable=inv self.assertIn('Access-Control-Allow-Headers', response.headers) self.assertEqual(response.headers['Access-Control-Allow-Headers'], '*') - def create_test_kml(self, file_name): + def create_test_kml(self, file_name, author=None, author_version=None): response = self.app.post( url_for('create_kml'), - data=prepare_kml_payload(kml_file=file_name), + data=prepare_kml_payload( + kml_file=file_name, author=author, author_version=author_version + ), content_type="multipart/form-data", headers=self.origin_headers["allowed"] ) @@ -182,7 +195,14 @@ def delete_test_kml(self, kml_id, admin_id): ) return response - def assertKml(self, response, expected_kml_file): + def assertKml( + self, + response, + expected_kml_file, + author="mf-geoadmin3", + with_admin_id=False, + author_version=DEFAULT_AUTHOR_VERSION + ): '''Check content of kml on s3 bucket and kml DB entry in DynamoDB. A request has created/updated a kml on s3. The corresponding response is passed to this @@ -196,44 +216,80 @@ def assertKml(self, response, expected_kml_file): expected_kml_file: string Original kml file name. ''' + self.assertKmlMetadata( + response.json, + author=author, + with_admin_id=with_admin_id, + author_version=author_version + ) + db_item = self.assertKmlInDb(response) + self.assertKmlFile(response, expected_kml_file, db_item) + expected_kml_size = self.assertKmlFile(response, expected_kml_file, db_item) + self.assertKmlDbData(response, db_item, expected_kml_size, author, author_version) + + def assertKmlFile(self, response, expected_kml_file, db_item): expected_kml_path = f'./tests/samples/{expected_kml_file}' # read the expected kml file with open(expected_kml_path, 'rb') as fd: content = fd.read() expected_kml = decompress_if_gzipped(content).decode('utf-8') - kml_id = response.json['id'] - item = self.dynamodb.Table(AWS_DB_TABLE_NAME).get_item(Key={ - 'kml_id': kml_id - }).get('Item', None) - if item is None: - self.fail(f"Could not find the following kml id in the database: {kml_id}") - - self.assertIn('length', item) expected_kml_size = os.path.getsize(expected_kml_path) if expected_kml_file.endswith('.xml'): # original file is not compressed get the compressed size expected_kml_size = len(gzip_string(expected_kml)) - self.assertEqual(int(item['length']), expected_kml_size) - self.assertIn('encoding', item) - self.assertEqual(item['encoding'], KML_FILE_CONTENT_ENCODING) - self.assertIn('content_type', item) - self.assertEqual(item['content_type'], KML_FILE_CONTENT_TYPE) - self.assertEqual(item['author'], 'unittest') - try: obj = self.s3bucket.meta.client.get_object( - Bucket=AWS_S3_BUCKET_NAME, Key=item['file_key'] + Bucket=AWS_S3_BUCKET_NAME, Key=db_item['file_key'] ) except EndpointConnectionError as error: self.fail(f'Failed to connect to S3: {error}') except ClientError as error: if error.response['Error']['Code'] == "NoSuchKey": - self.fail(f'Object with the given key {kml_id} not found in s3 bucket.') + self.fail(f'Object with the given key {db_item["id"]} not found in s3 bucket.') else: self.fail(f'S3 client error: {error}') body = decompress_if_gzipped((obj['Body'].read())) self.assertEqual(body.decode('utf-8'), expected_kml) + return expected_kml_size + + def assertKmlInDb(self, response): + db_item = self.dynamodb.Table(AWS_DB_TABLE_NAME).get_item( + Key={ + 'kml_id': response.json['id'] + } + ).get('Item', None) + if db_item is None: + self.fail(f"Could not find the following kml id in the database: {response.json['id']}") + return db_item + + def assertKmlDbData(self, response, db_item, expected_kml_size, author, author_version=None): + self.assertIn('length', db_item) + self.assertEqual(int(db_item['length']), expected_kml_size) + self.assertIn('encoding', db_item) + self.assertEqual(db_item['encoding'], KML_FILE_CONTENT_ENCODING) + self.assertIn('content_type', db_item) + self.assertEqual(db_item['content_type'], KML_FILE_CONTENT_TYPE) + self.assertEqual(db_item['author'], author) + if author_version is not None: + self.assertEqual( + db_item['author_version'], author_version, msg="Wrong author_version in DB" + ) + + def assertKmlMetadata(self, data, author=None, with_admin_id=False, author_version=None): + expected_keys = [ + 'id', 'success', 'created', 'updated', 'empty', 'author', 'author_version', 'links' + ] + if with_admin_id: + expected_keys.append('admin_id') + self.assertListEqual(sorted(list(data.keys())), sorted(expected_keys)) + self.assertListEqual(sorted(data['links'].keys()), sorted(['self', 'kml'])) + if author is not None: + self.assertEqual(data['author'], author, msg="Wrong author in response") + if author_version is not None: + self.assertEqual( + data['author_version'], author_version, msg="Wrong author_version in response" + ) def get_s3_object(self, file_key): try: diff --git a/tests/unit_tests/test_routes.py b/tests/unit_tests/test_routes.py index 51bb9f5..3236ab6 100644 --- a/tests/unit_tests/test_routes.py +++ b/tests/unit_tests/test_routes.py @@ -38,26 +38,48 @@ class TestPostEndpoint(BaseRouteTestCase): def test_valid_kml_post(self): kml_file = 'valid-kml.xml' - response = self.create_test_kml(kml_file) + response = self.create_test_kml(kml_file, author="mf-geoadmin3") self.assertEqual(response.status_code, 201) self.assertCors(response, ['GET', 'HEAD', 'POST', 'OPTIONS']) self.assertEqual(response.content_type, "application/json") # pylint: disable=no-member - self.assertKml(response, kml_file) + self.assertKml(response, kml_file, with_admin_id=True) + + def test_valid_kml_post_author_missing(self): + kml_file = 'valid-kml.xml' + response = self.app.post( + url_for('create_kml'), + data=prepare_kml_payload(kml_file=kml_file), + content_type="multipart/form-data", + headers=self.origin_headers["allowed"] + ) + self.assertEqual(response.status_code, 400) + self.assertCors(response, ['GET', 'HEAD', 'POST', 'OPTIONS']) + self.assertEqual(response.content_type, "application/json") # pylint: disable=no-member + + def test_valid_kml_post_author_version(self): + kml_file = 'valid-kml.xml' + response = self.create_test_kml(kml_file, author='web-mapviewer', author_version='1.0.0') + self.assertEqual(response.status_code, 201) + self.assertCors(response, ['GET', 'HEAD', 'POST', 'OPTIONS']) + self.assertEqual(response.content_type, "application/json") # pylint: disable=no-member + self.assertKml( + response, kml_file, author="web-mapviewer", with_admin_id=True, author_version='1.0.0' + ) def test_valid_gzipped_kml_post(self): kml_file = 'valid-kml.xml.gz' - response = self.create_test_kml(kml_file) + response = self.create_test_kml(kml_file, author="mf-geoadmin3") self.assertEqual(response.status_code, 201) self.assertCors(response, ['GET', 'HEAD', 'POST', 'OPTIONS']) self.assertEqual(response.content_type, "application/json") # pylint: disable=no-member - self.assertKml(response, kml_file) + self.assertKml(response, kml_file, with_admin_id=True) @patch('app.helpers.utils.KML_MAX_SIZE', 10) def test_too_big_kml_post(self): kml_file = 'valid-kml.xml' response = self.app.post( url_for('create_kml'), - data=prepare_kml_payload(kml_file=kml_file), + data=prepare_kml_payload(kml_file=kml_file, author="mf-geoadmin3"), content_type="multipart/form-data", headers=self.origin_headers["allowed"] ) @@ -68,7 +90,7 @@ def test_too_big_kml_post(self): def test_invalid_kml_post(self): response = self.app.post( url_for('create_kml'), - data=prepare_kml_payload(kml_file='invalid-kml.xml'), + data=prepare_kml_payload(kml_file='invalid-kml.xml', author="mf-geoadmin3"), content_type="multipart/form-data", headers=self.origin_headers["allowed"] ) @@ -80,7 +102,7 @@ def test_invalid_kml_post(self): def test_invalid_gzipped_kml_post(self): response = self.app.post( url_for('create_kml'), - data=prepare_kml_payload(kml_file='invalid-kml.xml.gz'), + data=prepare_kml_payload(kml_file='invalid-kml.xml.gz', author="mf-geoadmin3"), content_type="multipart/form-data", headers=self.origin_headers["allowed"] ) @@ -92,7 +114,7 @@ def test_invalid_gzipped_kml_post(self): def test_valid_kml_post_non_allowed_origin(self): response = self.app.post( url_for('create_kml'), - data=prepare_kml_payload(kml_file='valid-kml.xml'), + data=prepare_kml_payload(kml_file='valid-kml.xml', author="mf-geoadmin3"), content_type="multipart/form-data", headers=self.origin_headers["bad"] ) @@ -117,7 +139,9 @@ def test_kml_post_invalid_content_type(self): response = self.app.post( url_for('create_kml'), - data=prepare_kml_payload(kml_file='valid-kml.xml', content_type='application/json'), + data=prepare_kml_payload( + kml_file='valid-kml.xml', content_type='application/json', author="mf-geoadmin3" + ), content_type="multipart/form-data", headers=self.origin_headers["allowed"] ) @@ -131,7 +155,7 @@ class TestGetEndpoint(BaseRouteTestCase): def setUp(self): super().setUp() - self.sample_kml = self.create_test_kml('valid-kml.xml.gz').json + self.sample_kml = self.create_test_kml('valid-kml.xml.gz', "mf-geoadmin3").json def test_get_metadata(self): id_to_fetch = self.sample_kml['id'] @@ -151,6 +175,28 @@ def test_get_metadata(self): self.assertEqual(stored_kml_admin_link, response.json['links']['self']) self.assertKml(response, 'valid-kml.xml') + def test_get_metadata_author_version(self): + sample_kml = self.create_test_kml( + 'valid-kml.xml.gz', author="web-mapviewer", author_version='1.1.1' + ).json + + id_to_fetch = sample_kml['id'] + stored_geoadmin_link = sample_kml['links']['kml'] + stored_kml_admin_link = sample_kml['links']['self'] + response = self.app.get( + url_for('get_kml_metadata', kml_id=id_to_fetch), headers=self.origin_headers["allowed"] + ) + self.assertEqual(response.status_code, 200) + self.assertCors(response, ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT']) + self.assertIn('Cache-Control', response.headers) + self.assertIn('no-cache', response.headers['Cache-Control']) + self.assertIn('Expire', response.headers) + self.assertEqual(response.headers['Expire'], '0') + self.assertEqual(response.content_type, "application/json") + self.assertEqual(stored_geoadmin_link, response.json['links']['kml']) + self.assertEqual(stored_kml_admin_link, response.json['links']['self']) + self.assertKml(response, 'valid-kml.xml', author="web-mapviewer", author_version='1.1.1') + def test_get_metadata_by_admin_id(self): admin_id = self.sample_kml['admin_id'] stored_geoadmin_link = self.sample_kml['links']['kml'] @@ -168,7 +214,7 @@ def test_get_metadata_by_admin_id(self): self.assertEqual(response.content_type, "application/json") self.assertEqual(stored_geoadmin_link, response.json['links']['kml']) self.assertEqual(stored_kml_admin_link, response.json['links']['self']) - self.assertKml(response, 'valid-kml.xml') + self.assertKml(response, 'valid-kml.xml', with_admin_id=True) def test_get_metadata_by_admin_id_invalid(self): response = self.app.get( @@ -281,7 +327,7 @@ class TestPutEndpoint(BaseRouteTestCase): def setUp(self): super().setUp() - self.sample_kml = self.create_test_kml('valid-kml.xml.gz').json + self.sample_kml = self.create_test_kml('valid-kml.xml.gz', author='mf-geoadmin3').json def test_valid_kml_put(self): updated_file = 'updated-kml.xml' @@ -309,7 +355,40 @@ def test_valid_kml_put(self): datetime.datetime.utcnow(), delta=timedelta(seconds=0.3) ) - self.assertKml(response, updated_file) + self.assertKml(response, updated_file, with_admin_id=True) + + def test_valid_kml_put_update_author_version(self): + updated_file = 'updated-kml.xml' + id_to_put = self.sample_kml['id'] + response = self.app.put( + url_for('update_kml', kml_id=id_to_put), + data=prepare_kml_payload( + kml_file=updated_file, admin_id=self.sample_kml['admin_id'], author_version='1.1.1' + ), + content_type="multipart/form-data", + headers=self.origin_headers["allowed"] + ) + self.assertEqual(response.status_code, 200) + self.assertCors(response, ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT']) + self.assertEqual(response.content_type, "application/json") + for key in self.sample_kml: + # values for "updated" should and may differ, so ignore them in + # this assertion + if key == 'author_version': + self.assertNotEqual(self.sample_kml[key], response.json[key]) + self.assertEqual(response.json[key], '1.1.1') + elif key != "updated": + self.assertEqual(self.sample_kml[key], response.json[key]) + + updated_item = self.dynamodb.Table(AWS_DB_TABLE_NAME).get_item(Key={ + 'kml_id': id_to_put + }).get('Item', None) + self.assertAlmostEqual( + datetime.datetime.fromisoformat(updated_item["updated"]).replace(tzinfo=None), + datetime.datetime.utcnow(), + delta=timedelta(seconds=0.3) + ) + self.assertKml(response, updated_file, with_admin_id=True, author_version='1.1.1') def test_valid_gzipped_kml_put(self): updated_file = 'updated-kml.xml.gz' @@ -337,7 +416,7 @@ def test_valid_gzipped_kml_put(self): datetime.datetime.utcnow(), delta=timedelta(seconds=0.3) ) - self.assertKml(response, updated_file) + self.assertKml(response, updated_file, with_admin_id=True) def test_invalid_kml_put(self): id_to_put = self.sample_kml['id'] @@ -435,7 +514,7 @@ class TestDeleteEndpoint(BaseRouteTestCase): def setUp(self): super().setUp() - self.sample_kml = self.create_test_kml('valid-kml.xml.gz').json + self.sample_kml = self.create_test_kml('valid-kml.xml.gz', author="mf-geoadmin3").json def test_kml_delete(self): id_to_delete = self.sample_kml['id'] diff --git a/wsgi.py b/wsgi.py index 62f99a4..bdf8591 100644 --- a/wsgi.py +++ b/wsgi.py @@ -50,6 +50,7 @@ def load(self): 'timeout': 60, 'logconfig_dict': get_logging_cfg(), 'forwarded_allow_ips': os.getenv('FORWARED_ALLOW_IPS', '*'), + 'worker_tmp_dir': os.getenv("GUNICORN_WORKER_TMP_DIR", "/tmp/gunicorn_workers"), 'secure_scheme_headers': { os.getenv('FORWARDED_PROTO_HEADER_NAME', 'X-Forwarded-Proto').upper(): 'https'