From 119604afceba373e854b8b1c0d3dc8d7c7d3277b Mon Sep 17 00:00:00 2001 From: Domenico DiNicola Date: Wed, 22 Mar 2023 13:00:20 -0600 Subject: [PATCH 1/6] partial --- CHANGES | 9 +- Pipfile | 4 +- Pipfile.lock | 1441 ++++++++++------- docker/Dockerfile | 2 +- docker/Dockerfile.base | 6 +- docker/Dockerfile.flat | 6 +- docker/Makefile | 2 +- .../api/serializers/utils.py | 5 +- .../api/views/sharepoint.py | 30 + .../apps/roles/tasks.py | 4 +- 10 files changed, 892 insertions(+), 617 deletions(-) diff --git a/CHANGES b/CHANGES index fc2afa5d..081ebc3a 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,13 @@ +Release 2.1 +---------------- +* updated to python 3.11 +* updated to django 4.2 +* updated office365 2.4 + + Release 2.0.3 ---------------- -* update vaccine type metadata +* updated vaccine type metadata Release 2.0.2 diff --git a/Pipfile b/Pipfile index 9e32d6a0..901b6167 100644 --- a/Pipfile +++ b/Pipfile @@ -33,7 +33,7 @@ bleach = {extras = ["css"],version = "*"} celery = "*" dj-database-url = "*" dj-static = "*" -Django = "<4.1" +Django = "*" django-adminactions = "*" django-celery-beat = "*" django-celery-email = "*" @@ -56,7 +56,7 @@ newrelic = "*" psycopg2-binary = "*" sentry-sdk = "*" requests = "*" -sharepoint-rest-api = "0.15" +sharepoint-rest-api = "*" social-auth-app-django = "*" social-auth-core = {extras = ["azuread"],version = "*"} unicef-djangolib = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 7b18c699..1fa0c748 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2a075f1711d7f2164b16e42f630238a1413f8761c6120a7054581c8ee867d311" + "sha256": "e00111ec5f0549cde944b6cf6e28e046c5cd65272524a3f15e95dfbafec42cd1" }, "pipfile-spec": 6, "requires": { @@ -26,11 +26,11 @@ }, "asgiref": { "hashes": [ - "sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4", - "sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424" + "sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac", + "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506" ], "markers": "python_version >= '3.7'", - "version": "==3.5.2" + "version": "==3.6.0" }, "billiard": { "hashes": [ @@ -44,11 +44,11 @@ "css" ], "hashes": [ - "sha256:085f7f33c15bd408dd9b17a4ad77c577db66d76203e5984b1bd59baeee948b2a", - "sha256:0d03255c47eb9bd2f26aa9bb7f2107732e7e8fe195ca2f64709fcf3b0a4a085c" + "sha256:1a1a85c1595e07d8db14c5f09f09e6433502c51c595970edc090551f0db99414", + "sha256:33c16e3353dbd13028ab4799a0f89a83f113405c766e9c122df8a06f5b85b3f4" ], "index": "pypi", - "version": "==5.0.1" + "version": "==6.0.0" }, "celery": { "hashes": [ @@ -60,11 +60,11 @@ }, "certifi": { "hashes": [ - "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14", - "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382" + "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", + "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" ], "markers": "python_version >= '3.6'", - "version": "==2022.9.24" + "version": "==2022.12.7" }, "cffi": { "hashes": [ @@ -137,11 +137,84 @@ }, "charset-normalizer": { "hashes": [ - "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", - "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" + "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6", + "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1", + "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e", + "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373", + "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62", + "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230", + "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be", + "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c", + "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0", + "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448", + "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f", + "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649", + "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d", + "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0", + "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706", + "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a", + "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59", + "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23", + "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5", + "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb", + "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e", + "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e", + "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c", + "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28", + "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d", + "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41", + "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974", + "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce", + "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f", + "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1", + "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d", + "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8", + "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017", + "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31", + "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7", + "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8", + "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e", + "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14", + "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd", + "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d", + "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795", + "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b", + "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b", + "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b", + "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203", + "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f", + "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19", + "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1", + "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a", + "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac", + "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9", + "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0", + "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137", + "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f", + "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6", + "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5", + "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909", + "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f", + "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0", + "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324", + "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755", + "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb", + "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854", + "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c", + "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60", + "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84", + "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0", + "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b", + "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1", + "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531", + "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1", + "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11", + "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326", + "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df", + "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab" ], - "markers": "python_full_version >= '3.6.0'", - "version": "==2.1.1" + "markers": "python_full_version >= '3.7.0'", + "version": "==3.1.0" }, "click": { "hashes": [ @@ -173,37 +246,40 @@ ], "version": "==0.2.0" }, + "cron-descriptor": { + "hashes": [ + "sha256:7b6fc5e07f3e505d247f35ef432a098d75769efdaf01b04ab8e42a528c75266d" + ], + "version": "==1.2.35" + }, "cryptography": { "hashes": [ - "sha256:0e70da4bdff7601b0ef48e6348339e490ebfb0cbe638e083c9c41fb49f00c8bd", - "sha256:10652dd7282de17990b88679cb82f832752c4e8237f0c714be518044269415db", - "sha256:175c1a818b87c9ac80bb7377f5520b7f31b3ef2a0004e2420319beadedb67290", - "sha256:1d7e632804a248103b60b16fb145e8df0bc60eed790ece0d12efe8cd3f3e7744", - "sha256:1f13ddda26a04c06eb57119caf27a524ccae20533729f4b1e4a69b54e07035eb", - "sha256:2ec2a8714dd005949d4019195d72abed84198d877112abb5a27740e217e0ea8d", - "sha256:2fa36a7b2cc0998a3a4d5af26ccb6273f3df133d61da2ba13b3286261e7efb70", - "sha256:2fb481682873035600b5502f0015b664abc26466153fab5c6bc92c1ea69d478b", - "sha256:3178d46f363d4549b9a76264f41c6948752183b3f587666aff0555ac50fd7876", - "sha256:4367da5705922cf7070462e964f66e4ac24162e22ab0a2e9d31f1b270dd78083", - "sha256:4eb85075437f0b1fd8cd66c688469a0c4119e0ba855e3fef86691971b887caf6", - "sha256:50a1494ed0c3f5b4d07650a68cd6ca62efe8b596ce743a5c94403e6f11bf06c1", - "sha256:53049f3379ef05182864d13bb9686657659407148f901f3f1eee57a733fb4b00", - "sha256:6391e59ebe7c62d9902c24a4d8bcbc79a68e7c4ab65863536127c8a9cd94043b", - "sha256:67461b5ebca2e4c2ab991733f8ab637a7265bb582f07c7c88914b5afb88cb95b", - "sha256:78e47e28ddc4ace41dd38c42e6feecfdadf9c3be2af389abbfeef1ff06822285", - "sha256:80ca53981ceeb3241998443c4964a387771588c4e4a5d92735a493af868294f9", - "sha256:8a4b2bdb68a447fadebfd7d24855758fe2d6fecc7fed0b78d190b1af39a8e3b0", - "sha256:8e45653fb97eb2f20b8c96f9cd2b3a0654d742b47d638cf2897afbd97f80fa6d", - "sha256:998cd19189d8a747b226d24c0207fdaa1e6658a1d3f2494541cb9dfbf7dcb6d2", - "sha256:a10498349d4c8eab7357a8f9aa3463791292845b79597ad1b98a543686fb1ec8", - "sha256:b4cad0cea995af760f82820ab4ca54e5471fc782f70a007f31531957f43e9dee", - "sha256:bfe6472507986613dc6cc00b3d492b2f7564b02b3b3682d25ca7f40fa3fd321b", - "sha256:c9e0d79ee4c56d841bd4ac6e7697c8ff3c8d6da67379057f29e66acffcd1e9a7", - "sha256:ca57eb3ddaccd1112c18fc80abe41db443cc2e9dcb1917078e02dfa010a4f353", - "sha256:ce127dd0a6a0811c251a6cddd014d292728484e530d80e872ad9806cfb1c5b3c" + "sha256:103e8f7155f3ce2ffa0049fe60169878d47a4364b277906386f8de21c9234aa1", + "sha256:23df8ca3f24699167daf3e23e51f7ba7334d504af63a94af468f468b975b7dd7", + "sha256:2725672bb53bb92dc7b4150d233cd4b8c59615cd8288d495eaa86db00d4e5c06", + "sha256:30b1d1bfd00f6fc80d11300a29f1d8ab2b8d9febb6ed4a38a76880ec564fae84", + "sha256:35d658536b0a4117c885728d1a7032bdc9a5974722ae298d6c533755a6ee3915", + "sha256:50cadb9b2f961757e712a9737ef33d89b8190c3ea34d0fb6675e00edbe35d074", + "sha256:5f8c682e736513db7d04349b4f6693690170f95aac449c56f97415c6980edef5", + "sha256:6236a9610c912b129610eb1a274bdc1350b5df834d124fa84729ebeaf7da42c3", + "sha256:788b3921d763ee35dfdb04248d0e3de11e3ca8eb22e2e48fef880c42e1f3c8f9", + "sha256:8bc0008ef798231fac03fe7d26e82d601d15bd16f3afaad1c6113771566570f3", + "sha256:8f35c17bd4faed2bc7797d2a66cbb4f986242ce2e30340ab832e5d99ae60e011", + "sha256:b49a88ff802e1993b7f749b1eeb31134f03c8d5c956e3c125c75558955cda536", + "sha256:bc0521cce2c1d541634b19f3ac661d7a64f9555135e9d8af3980965be717fd4a", + "sha256:bc5b871e977c8ee5a1bbc42fa8d19bcc08baf0c51cbf1586b0e87a2694dde42f", + "sha256:c43ac224aabcbf83a947eeb8b17eaf1547bce3767ee2d70093b461f31729a480", + "sha256:d15809e0dbdad486f4ad0979753518f47980020b7a34e9fc56e8be4f60702fac", + "sha256:d7d84a512a59f4412ca8549b01f94be4161c94efc598bf09d027d67826beddc0", + "sha256:e029b844c21116564b8b61216befabca4b500e6816fa9f0ba49527653cae2108", + "sha256:e8a0772016feeb106efd28d4a328e77dc2edae84dfbac06061319fdb669ff828", + "sha256:e944fe07b6f229f4c1a06a7ef906a19652bdd9fd54c761b0ff87e83ae7a30354", + "sha256:eb40fe69cfc6f5cdab9a5ebd022131ba21453cf7b8a7fd3631f45bbf52bed612", + "sha256:fa507318e427169ade4e9eccef39e9011cdc19534f55ca2f36ec3f388c1f70f3", + "sha256:ffd394c7896ed7821a6d13b24657c6a34b6e2650bd84ae063cf11ccffa4f1a97" ], "markers": "python_version >= '3.6'", - "version": "==38.0.4" + "version": "==39.0.2" }, "defusedxml": { "hashes": [ @@ -223,11 +299,11 @@ }, "dj-database-url": { "hashes": [ - "sha256:ccf3e8718f75ddd147a1e212fca88eecdaa721759ee48e38b485481c77bca3dc", - "sha256:cd354a3b7a9136d78d64c17b2aec369e2ae5616fbca6bfbe435ef15bb372ce39" + "sha256:5c2993b91801c0f78a8b19e642b497b90831124cbade0c265900d4c1037b4730", + "sha256:b23b15046cb38180e0c95207bcc90fe5e9dbde8eef16065907dd85cf4ca7036c" ], "index": "pypi", - "version": "==1.0.0" + "version": "==1.2.0" }, "dj-static": { "hashes": [ @@ -238,17 +314,17 @@ }, "django": { "hashes": [ - "sha256:07e6433f263c3839939cfabeb6d7557841e0419e47759a7b7d37f6d44d40adcb", - "sha256:27cb08fa6458c1eff8b97c4c2d03774646fb26feeaa4587dca10c49e6d4fc6a3" + "sha256:44f714b81c5f190d9d2ddad01a532fe502fa01c4cb8faf1d081f4264ed15dcd8", + "sha256:f2f431e75adc40039ace496ad3b9f17227022e8b11566f4b363da44c7e44761e" ], "index": "pypi", - "version": "==4.0.8" + "version": "==4.1.7" }, "django-admin-extra-buttons": { "hashes": [ - "sha256:38839490d93c100c0e82549e6d6c2245cfaeec04e95b51a255be29b39270ba4f" + "sha256:9616ae96e51cbdd60428bd5e1d2803ae0760a274ed777a56c2c3b2f23ffb872a" ], - "version": "==1.5.5" + "version": "==1.5.6" }, "django-adminactions": { "hashes": [ @@ -274,11 +350,11 @@ }, "django-celery-beat": { "hashes": [ - "sha256:58efe9460e4373a241c2b3d839518f29a28ae19bc80a8dba20da204c7ea50613", - "sha256:a20b7a7857daaa2eea1f4cfefb2a965456800216f5763c6cf918c2e21372b3c8" + "sha256:ae460faa5ea142fba0875409095d22f6bd7bcc7377889b85e8cab5c0dfb781fe", + "sha256:cd0a47f5958402f51ac0c715bc942ae33d7b50b4e48cba91bc3f2712be505df1" ], "index": "pypi", - "version": "==2.4.0" + "version": "==2.5.0" }, "django-celery-email": { "hashes": [ @@ -290,11 +366,11 @@ }, "django-celery-results": { "hashes": [ - "sha256:75aa51970db5691cbf242c6a0ff50c8cdf419e265cd0e9b772335d06436c4b99", - "sha256:be91307c02fbbf0dda21993c3001c60edb74595444ccd6ad696552fe3689e85b" + "sha256:8631fd68158c41afddfc378840ecee2f10ddd7d4879e964f2597f483e4203269", + "sha256:efb68932bde8938794068a9d0929bea8601ec5f6a4150a7f7ab6e2a83a735938" ], "index": "pypi", - "version": "==2.4.0" + "version": "==2.5.0" }, "django-constance": { "hashes": [ @@ -306,34 +382,34 @@ }, "django-cors-headers": { "hashes": [ - "sha256:37e42883b5f1f2295df6b4bba96eb2417a14a03270cb24b2a07f021cd4487cf4", - "sha256:f9dc6b4e3f611c3199700b3e5f3398c28757dcd559c2f82932687f3d0443cfdf" + "sha256:5fbd58a6fb4119d975754b2bc090f35ec160a8373f276612c675b00e8a138739", + "sha256:684180013cc7277bdd8702b80a3c5a4b3fcae4abb2bf134dceb9f5dfe300228e" ], "index": "pypi", - "version": "==3.13.0" + "version": "==3.14.0" }, "django-countries": { "hashes": [ - "sha256:2eadbe91578fe7b5a0c7782c07487b2ceb4bde9bc5c76eb43458929969f25c62", - "sha256:9d553531de8eaf384fec7fdd5867f3cb9b922d384984c3e613b6b29031e5c3c2" + "sha256:22915d9b9403932b731622619940a54894a3eb0da9a374e7249c8fc453c122d7", + "sha256:2df707aca7a5e677254bed116cf6021a136ebaccd5c2f46860abd6452bb45521" ], - "version": "==7.4.2" + "version": "==7.5.1" }, "django-debug-toolbar": { "hashes": [ - "sha256:1e3acad24e3d351ba45c6fa2072e4164820307332a776b16c9f06d1f89503465", - "sha256:80de23066b624d3970fd296cf02d61988e5d56c31aa0dc4a428970b46e2883a8" + "sha256:24ef1a7d44d25e60d7951e378454c6509bf536dce7e7d9d36e7c387db499bc27", + "sha256:879f8a4672d41621c06a4d322dcffa630fc4df056cada6e417ed01db0e5e0478" ], "index": "pypi", - "version": "==3.7.0" + "version": "==3.8.1" }, "django-environ": { "hashes": [ - "sha256:bff5381533056328c9ac02f71790bd5bf1cea81b1beeb648f28b81c9e83e0a21", - "sha256:f21a5ef8cc603da1870bbf9a09b7e5577ab5f6da451b843dbcc721a7bca6b3d9" + "sha256:510f8c9c1d0a38b0815f91504270c29440a0cf44fab07f55942fa8d31bbb9be6", + "sha256:b3559a91439c9d774a9e0c1ced872364772c612cdf6dc919506a2b13f7a77225" ], "index": "pypi", - "version": "==0.9.0" + "version": "==0.10.0" }, "django-extensions": { "hashes": [ @@ -360,10 +436,10 @@ }, "django-impersonate": { "hashes": [ - "sha256:cdf9ba7d246bb528d7caa70f29a9bc1bfdd084c5e94f0312fd9080f6d539fec9" + "sha256:0befdb096198b458507239a6f21574c9e0f608ab01fad352d71eb9284e5bb9c9" ], "index": "pypi", - "version": "==1.8.2" + "version": "==1.9.1" }, "django-model-utils": { "hashes": [ @@ -497,31 +573,31 @@ }, "msal": { "hashes": [ - "sha256:78344cd4c91d6134a593b5e3e45541e666e37b747ff8a6316c3668dd1e6ab6b2", - "sha256:d2f1c26368ecdc28c8657d457352faa0b81b1845a7b889d8676787721ba86792" + "sha256:96b5c867830fd116e5f7d0ec8ef1b238b4cda4d1aea86d8fecf518260e136fbf", + "sha256:e8444617c1eccdff7bb73f5d4f94036002accea4a2c05f8f39c9efb5bd2b0c6a" ], - "version": "==1.20.0" + "version": "==1.21.0" }, "newrelic": { "hashes": [ - "sha256:01b37112a6f48d2da8e98268dfc273a33981297a2b43ac7674d5993dee31885d", - "sha256:0c465d7366cb081498bb6918f4b91157b54e70b446639d1a3ec86fc72062e6c3", - "sha256:20ea8850cc5c05edba753cd85800bb6d3411bcd7425614c59e5550f35c4f2cc6", - "sha256:385829c819bccde7edc002ea73b784194312824c3b3d9511c1015194498f2658", - "sha256:492a06949af21b82072095c1055051985cddadc9458f1752a2c040228918fabc", - "sha256:4abf147b5148ac1d284aba46582c92840a521bf5086a29af36494bd53778136f", - "sha256:592b622945e4ff4f14cca0e01dd08553a1f1e29cea25826b9e30101133296993", - "sha256:88063cd39672a93d2201f9f6568e9b996b1a1b9ca052f83eac9a4ca0a36fa7a9", - "sha256:8ec531aa73f1ae12724031a965805a535585fd06c617acb68b8b1a4534912e31", - "sha256:97f8f288dc131b3260220aef3716ae5e78aeb08edcd2e43e947a675a0d08d21b", - "sha256:ba0b9fcf84b3735b7d699df9e27822ab5a62a1ed12c39540140e2d40be3be8e9", - "sha256:c4c831a8f084b8168afdc4e9770ac062d6fdac16f41aa7a122ce87e5e448bbe9", - "sha256:dc095f45496c03681bcf01692c85817243ccb500a5281410cdf7194be9308444", - "sha256:edbedd2040a003e2f712184fab672e2987cf34da59f64f548d121c1a02ea1f4c", - "sha256:ede2b43cf395fef31c3a43bd8d6db6cb56496516c54123b534f0027d582446ef" + "sha256:15d3088d9ab4d708e7b3826e651c2402f2cb9c72689e47a0badc8281ab20bfe9", + "sha256:2249a25b1ce967267604cb0ce3268256fb25da481312f3c7b04df90245708131", + "sha256:2fc9807a1e3277e1dbddb7cd84e00b1f70faea602f0bbe53109e0e68b0c20e3c", + "sha256:432a6fa9c0051154f4110f4203831f464c8ba5bc842e709639391175d4ba50e6", + "sha256:4f48e481ebb7d873fd16a7fe0df30383c834e75daa6b0b514e147b8d683d922d", + "sha256:69a7ed5788fb6347e96f7df18a641ea242d5dac7ccb76bbaa869851cade335c4", + "sha256:6fc4169f66e80f4b497d16be3759feaf5be08ec389b8f42b8b62ce632de9eb3f", + "sha256:95484f2ca36952831b47e3b054e808317a0a12597ca9ef5166789a425545de44", + "sha256:b5c53a5922c92d742eff37da87c113a18762cd06e310bfc430df02603298def9", + "sha256:d02acde140c6d4f549f36a2bda64025a18efc5b6457c8fa505146c7bcaaac23b", + "sha256:d39f6f3ffc458337e22ef4d4e7bacf5b0b2712feb7668538299d029bc87f9b7a", + "sha256:d7b510f3889fe57330bb85de78abcac2d0711b49e9da74fcd1b936a57b139238", + "sha256:eb3a27fd7b9d51941fb20c452aa3b3b2dd52fe652cda2d5d269dcc14f64ade6e", + "sha256:ec8d38d9f7c30c464cddd594cb390cf66a2b573d08e09ac231d3d349a26e0f96", + "sha256:f79a599b53894870dfdfcd88fa7ca7e81cac77f4a253ca0c08c58f400bb0a5ab" ], "index": "pypi", - "version": "==8.4.0" + "version": "==8.7.1" }, "oauthlib": { "hashes": [ @@ -533,18 +609,18 @@ }, "office365-rest-python-client": { "hashes": [ - "sha256:406310f7ab819a78723c22466c096b054b8f8e2cf3600206649b24dda7bfb2bd", - "sha256:a5c97a7ca0a3b9315dc1ac7210e110a00a539d67eb7617d4afb633219de578c2" + "sha256:6fbc1c53fd71359b51dd58e147bda7f20e348bba0ae1493fb8c6d5ff03a255bb", + "sha256:c261ac23ac3b8b373f337219e6e9da312f2b5d29abcf9095b642b657e9d0d05a" ], - "version": "==2.3.16" + "version": "==2.4.0" }, "prompt-toolkit": { "hashes": [ - "sha256:535c29c31216c77302877d5120aef6c94ff573748a5b5ca5b1b1f76f5e700c73", - "sha256:ced598b222f6f4029c0800cefaa6a17373fb580cd093223003475ce32805c35b" + "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b", + "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f" ], - "markers": "python_full_version >= '3.6.2'", - "version": "==3.0.33" + "markers": "python_full_version >= '3.7.0'", + "version": "==3.0.38" }, "psycopg2-binary": { "hashes": [ @@ -640,16 +716,17 @@ }, "python-crontab": { "hashes": [ - "sha256:1e35ed7a3cdc3100545b43e196d34754e6551e7f95e4caebbe0e1c0ca41c2f1b" + "sha256:9c374d1c9d401afdd8dd958f20077f74c158ab3fffb9604296802715e887fe48", + "sha256:b21af4647c7bbb848fef2f020616c6b0289dcb9f94b4f991a55310ff9bec5749" ], - "version": "==2.6.0" + "version": "==2.7.1" }, "python-dateutil": { "hashes": [ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.2" }, "python3-openid": { @@ -661,10 +738,10 @@ }, "pytz": { "hashes": [ - "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427", - "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2" + "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0", + "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a" ], - "version": "==2022.6" + "version": "==2022.7.1" }, "redis": { "hashes": [ @@ -676,11 +753,11 @@ }, "requests": { "hashes": [ - "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", - "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" + "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa", + "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf" ], "index": "pypi", - "version": "==2.28.1" + "version": "==2.28.2" }, "requests-oauthlib": { "hashes": [ @@ -692,54 +769,54 @@ }, "sentry-sdk": { "hashes": [ - "sha256:675f6279b6bb1fea09fd61751061f9a90dca3b5929ef631dd50dc8b3aeb245e9", - "sha256:8b4ff696c0bdcceb3f70bbb87a57ba84fd3168b1332d493fcd16c137f709578c" + "sha256:3c4e898f7a3edf5a2042cd0dcab6ee124e2112189228c272c08ad15d3850c201", + "sha256:ad40860325c94d1a656da70fba5a7c4dbb2f6809d3cc2d00f74ca0b608330f14" ], "index": "pypi", - "version": "==1.11.1" + "version": "==1.17.0" }, "setuptools": { "hashes": [ - "sha256:57f6f22bde4e042978bcd50176fdb381d7c21a9efa4041202288d3737a0c6a54", - "sha256:a7620757bf984b58deaf32fc8a4577a9bbc0850cf92c20e1ce41c38c19e5fb75" + "sha256:2ee892cd5f29f3373097f5a814697e397cf3ce313616df0af11231e2ad118077", + "sha256:b78aaa36f6b90a074c1fa651168723acbf45d14cb1196b6f02c0fd07f17623b2" ], "markers": "python_version >= '3.7'", - "version": "==65.6.3" + "version": "==67.6.0" }, "sharepoint-rest-api": { "hashes": [ - "sha256:302be3a93421f68e239a9e9f693664b32f5fa85d42cd107fb147209cc4fc896d", - "sha256:880f344d0582a225ae34b679383302bd9016603ff3e82436a3fada0a8679f889" + "sha256:2375215ce898ae45e44095b636f3d0595fc23469d98589deb0c04da5464045b2", + "sha256:3749db4dcaedd4e113f0ec1261c586851b6ed02a6745c1971af3932fed8b7c05" ], "index": "pypi", - "version": "==0.15" + "version": "==0.16" }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "social-auth-app-django": { "hashes": [ - "sha256:52241a25445a010ab1c108bafff21fc5522d5c8cd0d48a92c39c7371824b065d", - "sha256:b6e3132ce087cdd6e1707aeb1b588be41d318408fcf6395435da0bc6fe9a9795" + "sha256:e4e9eb2c8c1258f443d4f1c04cb6693c0303e8ee2fa0981ba1b371546195a939", + "sha256:fdf1dc6bcb8b457001d88d2279f637bc9955f1aedf750c627784bb5104601b1c" ], "index": "pypi", - "version": "==5.0.0" + "version": "==5.1.0" }, "social-auth-core": { "extras": [ "azuread" ], "hashes": [ - "sha256:1e3440d104f743b02dfe258c9d4dba5b4065abf24b2f7eb362b47054d21797df", - "sha256:4686f0e43cf12954216875a32e944847bb1dc69e7cd9573d16a9003bb05ca477" + "sha256:359f6be5bb2d4caef6500eb6e1b40821a40dde9add8d339d539b1adbba2c9bf7", + "sha256:89536f218fa1a769caeaa56ef90f965ea50a81b9a7e3e5a2c5a61b832df11bde" ], "index": "pypi", - "version": "==4.3.0" + "version": "==4.4.0" }, "sqlparse": { "hashes": [ @@ -764,11 +841,11 @@ }, "typing-extensions": { "hashes": [ - "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa", - "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e" + "sha256:5cb5f4a79139d699607b3ef622a1dedafa84e115ab0024e0d9c044a9479ca7cb", + "sha256:fb33085c39dd998ac16d1431ebc293a8b3eedd00fd4a32de0ff79002c19511b4" ], "markers": "python_version >= '3.7'", - "version": "==4.4.0" + "version": "==4.5.0" }, "tzdata": { "hashes": [ @@ -788,11 +865,11 @@ }, "unicef-notification": { "hashes": [ - "sha256:5517a2d9f662f9e953df44369b80b1f532eaca471ab7bbef4a6cabc23ae24882", - "sha256:bb697a9f60cb9b26fd5fa7205a1c94ce8d20dbc472f251b8c5d4dd17bd52b948" + "sha256:001b8624e600e3b7453447f9543e8a331bc18f5bbf6d5198eff95c905258ffc8", + "sha256:a9f4c437114f3fa785c3cdef711c6191818a80c19eee6871ad2c8c1d7f5946d3" ], "index": "pypi", - "version": "==1.1" + "version": "==1.2" }, "unicef-realm": { "hashes": [ @@ -804,11 +881,11 @@ }, "unicef-security": { "hashes": [ - "sha256:20452f33bd7196a871d9f0f9aaf3c2d81cdba9e1906042fe7dd54d3851a60075", - "sha256:a996521062f889aa5e9cf112da0bfdd17dcb4c72d8f86ce0fdb738cbb2bb76dd" + "sha256:20c03f7ae96cedb670e53431107a331488bdf9cd89a55965f602eb4293ef9880", + "sha256:52ab668ea34c5f145d91c5517f9631ef009a14be852b50fe1bb70281c5937b4e" ], "index": "pypi", - "version": "==1.2.1" + "version": "==1.3" }, "unicef-vision": { "hashes": [ @@ -826,11 +903,11 @@ }, "urllib3": { "hashes": [ - "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc", - "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8" + "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305", + "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.13" + "version": "==1.26.15" }, "uwsgi": { "hashes": [ @@ -849,10 +926,10 @@ }, "wcwidth": { "hashes": [ - "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784", - "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83" + "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e", + "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0" ], - "version": "==0.2.5" + "version": "==0.2.6" }, "webencodings": { "hashes": [ @@ -863,73 +940,84 @@ }, "wrapt": { "hashes": [ - "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3", - "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b", - "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4", - "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2", - "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656", - "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3", - "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff", - "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310", - "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a", - "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57", - "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069", - "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383", - "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe", - "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87", - "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d", - "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b", - "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907", - "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f", - "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0", - "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28", - "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1", - "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853", - "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc", - "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3", - "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3", - "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164", - "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1", - "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c", - "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1", - "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7", - "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1", - "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320", - "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed", - "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1", - "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248", - "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c", - "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456", - "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77", - "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef", - "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1", - "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7", - "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86", - "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4", - "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d", - "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d", - "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8", - "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5", - "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471", - "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00", - "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68", - "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3", - "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d", - "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735", - "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d", - "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569", - "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7", - "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59", - "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5", - "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb", - "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b", - "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f", - "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462", - "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015", - "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af" + "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0", + "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420", + "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a", + "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c", + "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079", + "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923", + "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f", + "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1", + "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8", + "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86", + "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0", + "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364", + "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e", + "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c", + "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e", + "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c", + "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727", + "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff", + "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e", + "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29", + "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7", + "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72", + "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475", + "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a", + "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317", + "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2", + "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd", + "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640", + "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98", + "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248", + "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e", + "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d", + "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec", + "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1", + "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e", + "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9", + "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92", + "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb", + "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094", + "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46", + "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29", + "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd", + "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705", + "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8", + "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975", + "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb", + "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e", + "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b", + "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418", + "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019", + "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1", + "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba", + "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6", + "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2", + "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3", + "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7", + "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752", + "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416", + "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f", + "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1", + "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc", + "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145", + "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee", + "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a", + "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7", + "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b", + "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653", + "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0", + "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90", + "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29", + "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6", + "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034", + "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09", + "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559", + "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.14.1" + "version": "==1.15.0" }, "xlrd": { "hashes": [ @@ -950,10 +1038,11 @@ "develop": { "alabaster": { "hashes": [ - "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", - "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3", + "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2" ], - "version": "==0.7.12" + "markers": "python_version >= '3.6'", + "version": "==0.7.13" }, "appnope": { "hashes": [ @@ -965,34 +1054,34 @@ }, "asgiref": { "hashes": [ - "sha256:1d2880b792ae8757289136f1db2b7b99100ce959b2aa57fd69dab783d05afac4", - "sha256:4a29362a6acebe09bf1d6640db38c1dc3d9217c68e6f9f6204d72667fc19a424" + "sha256:71e68008da809b957b7ee4b43dbccff33d1b23519fb8344e33f049897077afac", + "sha256:9567dfe7bd8d3c8c892227827c41cce860b368104c3431da67a0c5a65a949506" ], "markers": "python_version >= '3.7'", - "version": "==3.5.2" + "version": "==3.6.0" }, "asttokens": { "hashes": [ - "sha256:c56caef774a929923696f09ceea0eadcb95c94b30e8ee4f9fc4f5867096caaeb", - "sha256:e27b1f115daebfafd4d1826fc75f9a72f0b74bd3ae4ee4d9380406d74d35e52c" + "sha256:4622110b2a6f30b77e1473affaa97e711bc2f07d3f10848420ff1898edbe94f3", + "sha256:6b0ac9e93fb0335014d382b8fa9b3afa7df546984258005da0b9e7095b3deb1c" ], - "version": "==2.2.0" + "version": "==2.2.1" }, "attrs": { "hashes": [ - "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6", - "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c" + "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836", + "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99" ], - "markers": "python_version >= '3.5'", - "version": "==22.1.0" + "markers": "python_version >= '3.6'", + "version": "==22.2.0" }, "babel": { "hashes": [ - "sha256:1ad3eca1c885218f6dce2ab67291178944f810a10a9b5f3cb8382a5a232b64fe", - "sha256:5ef4b3226b0180dedded4229651c8b0e1a3a6a2837d45a073272f313e4cf97f6" + "sha256:b4246fb7677d3b98f501a39d43396d3cafdc8eadb045f4a31be01863f655c610", + "sha256:cc2d99999cd01d44420ae725a21c9e3711b3aadc7976d6147f622d8581963455" ], - "markers": "python_version >= '3.6'", - "version": "==2.11.0" + "markers": "python_version >= '3.7'", + "version": "==2.12.1" }, "backcall": { "hashes": [ @@ -1003,83 +1092,181 @@ }, "beautifulsoup4": { "hashes": [ - "sha256:58d5c3d29f5a36ffeb94f02f0d786cd53014cf9b3b3951d42e0080d8a9498d30", - "sha256:ad9aa55b65ef2808eb405f46cf74df7fcb7044d5cbc26487f96eb2ef2e436693" + "sha256:2130a5ad7f513200fae61a17abb5e338ca980fa28c439c0571014bc0217e9591", + "sha256:c5fceeaec29d09c84970e47c65f2f0efe57872f7cff494c9691a26ec0ff13234" ], "markers": "python_full_version >= '3.6.0'", - "version": "==4.11.1" + "version": "==4.12.0" + }, + "cachetools": { + "hashes": [ + "sha256:13dfddc7b8df938c21a940dfa6557ce6e94a2f1cdfa58eb90c805721d58f2c14", + "sha256:429e1a1e845c008ea6c85aa35d4b98b65d6a9763eeef3e37e92728a12d1de9d4" + ], + "markers": "python_version ~= '3.7'", + "version": "==5.3.0" }, "certifi": { "hashes": [ - "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14", - "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382" + "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3", + "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18" ], "markers": "python_version >= '3.6'", - "version": "==2022.9.24" + "version": "==2022.12.7" + }, + "chardet": { + "hashes": [ + "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5", + "sha256:362777fb014af596ad31334fde1e8c327dfdb076e1960d1694662d46a6917ab9" + ], + "markers": "python_version >= '3.7'", + "version": "==5.1.0" }, "charset-normalizer": { "hashes": [ - "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845", - "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f" + "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6", + "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1", + "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e", + "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373", + "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62", + "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230", + "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be", + "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c", + "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0", + "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448", + "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f", + "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649", + "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d", + "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0", + "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706", + "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a", + "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59", + "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23", + "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5", + "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb", + "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e", + "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e", + "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c", + "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28", + "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d", + "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41", + "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974", + "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce", + "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f", + "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1", + "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d", + "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8", + "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017", + "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31", + "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7", + "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8", + "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e", + "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14", + "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd", + "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d", + "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795", + "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b", + "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b", + "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b", + "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203", + "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f", + "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19", + "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1", + "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a", + "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac", + "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9", + "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0", + "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137", + "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f", + "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6", + "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5", + "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909", + "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f", + "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0", + "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324", + "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755", + "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb", + "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854", + "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c", + "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60", + "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84", + "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0", + "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b", + "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1", + "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531", + "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1", + "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11", + "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326", + "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df", + "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab" ], - "markers": "python_full_version >= '3.6.0'", - "version": "==2.1.1" + "markers": "python_full_version >= '3.7.0'", + "version": "==3.1.0" + }, + "colorama": { + "hashes": [ + "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", + "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==0.4.6" }, "coverage": { "hashes": [ - "sha256:027018943386e7b942fa832372ebc120155fd970837489896099f5cfa2890f79", - "sha256:11b990d520ea75e7ee8dcab5bc908072aaada194a794db9f6d7d5cfd19661e5a", - "sha256:12adf310e4aafddc58afdb04d686795f33f4d7a6fa67a7a9d4ce7d6ae24d949f", - "sha256:1431986dac3923c5945271f169f59c45b8802a114c8f548d611f2015133df77a", - "sha256:1ef221513e6f68b69ee9e159506d583d31aa3567e0ae84eaad9d6ec1107dddaa", - "sha256:20c8ac5386253717e5ccc827caad43ed66fea0efe255727b1053a8154d952398", - "sha256:2198ea6fc548de52adc826f62cb18554caedfb1d26548c1b7c88d8f7faa8f6ba", - "sha256:255758a1e3b61db372ec2736c8e2a1fdfaf563977eedbdf131de003ca5779b7d", - "sha256:265de0fa6778d07de30bcf4d9dc471c3dc4314a23a3c6603d356a3c9abc2dfcf", - "sha256:33a7da4376d5977fbf0a8ed91c4dffaaa8dbf0ddbf4c8eea500a2486d8bc4d7b", - "sha256:42eafe6778551cf006a7c43153af1211c3aaab658d4d66fa5fcc021613d02518", - "sha256:4433b90fae13f86fafff0b326453dd42fc9a639a0d9e4eec4d366436d1a41b6d", - "sha256:4a5375e28c5191ac38cca59b38edd33ef4cc914732c916f2929029b4bfb50795", - "sha256:4a8dbc1f0fbb2ae3de73eb0bdbb914180c7abfbf258e90b311dcd4f585d44bd2", - "sha256:59f53f1dc5b656cafb1badd0feb428c1e7bc19b867479ff72f7a9dd9b479f10e", - "sha256:5dbec3b9095749390c09ab7c89d314727f18800060d8d24e87f01fb9cfb40b32", - "sha256:633713d70ad6bfc49b34ead4060531658dc6dfc9b3eb7d8a716d5873377ab745", - "sha256:6b07130585d54fe8dff3d97b93b0e20290de974dc8177c320aeaf23459219c0b", - "sha256:6c4459b3de97b75e3bd6b7d4b7f0db13f17f504f3d13e2a7c623786289dd670e", - "sha256:6d4817234349a80dbf03640cec6109cd90cba068330703fa65ddf56b60223a6d", - "sha256:723e8130d4ecc8f56e9a611e73b31219595baa3bb252d539206f7bbbab6ffc1f", - "sha256:784f53ebc9f3fd0e2a3f6a78b2be1bd1f5575d7863e10c6e12504f240fd06660", - "sha256:7b6be138d61e458e18d8e6ddcddd36dd96215edfe5f1168de0b1b32635839b62", - "sha256:7ccf362abd726b0410bf8911c31fbf97f09f8f1061f8c1cf03dfc4b6372848f6", - "sha256:83516205e254a0cb77d2d7bb3632ee019d93d9f4005de31dca0a8c3667d5bc04", - "sha256:851cf4ff24062c6aec510a454b2584f6e998cada52d4cb58c5e233d07172e50c", - "sha256:8f830ed581b45b82451a40faabb89c84e1a998124ee4212d440e9c6cf70083e5", - "sha256:94e2565443291bd778421856bc975d351738963071e9b8839ca1fc08b42d4bef", - "sha256:95203854f974e07af96358c0b261f1048d8e1083f2de9b1c565e1be4a3a48cfc", - "sha256:97117225cdd992a9c2a5515db1f66b59db634f59d0679ca1fa3fe8da32749cae", - "sha256:98e8a10b7a314f454d9eff4216a9a94d143a7ee65018dd12442e898ee2310578", - "sha256:a1170fa54185845505fbfa672f1c1ab175446c887cce8212c44149581cf2d466", - "sha256:a6b7d95969b8845250586f269e81e5dfdd8ff828ddeb8567a4a2eaa7313460c4", - "sha256:a8fb6cf131ac4070c9c5a3e21de0f7dc5a0fbe8bc77c9456ced896c12fcdad91", - "sha256:af4fffaffc4067232253715065e30c5a7ec6faac36f8fc8d6f64263b15f74db0", - "sha256:b4a5be1748d538a710f87542f22c2cad22f80545a847ad91ce45e77417293eb4", - "sha256:b5604380f3415ba69de87a289a2b56687faa4fe04dbee0754bfcae433489316b", - "sha256:b9023e237f4c02ff739581ef35969c3739445fb059b060ca51771e69101efffe", - "sha256:bc8ef5e043a2af066fa8cbfc6e708d58017024dc4345a1f9757b329a249f041b", - "sha256:c4ed2820d919351f4167e52425e096af41bfabacb1857186c1ea32ff9983ed75", - "sha256:cca4435eebea7962a52bdb216dec27215d0df64cf27fc1dd538415f5d2b9da6b", - "sha256:d900bb429fdfd7f511f868cedd03a6bbb142f3f9118c09b99ef8dc9bf9643c3c", - "sha256:d9ecf0829c6a62b9b573c7bb6d4dcd6ba8b6f80be9ba4fc7ed50bf4ac9aecd72", - "sha256:dbdb91cd8c048c2b09eb17713b0c12a54fbd587d79adcebad543bc0cd9a3410b", - "sha256:de3001a203182842a4630e7b8d1a2c7c07ec1b45d3084a83d5d227a3806f530f", - "sha256:e07f4a4a9b41583d6eabec04f8b68076ab3cd44c20bd29332c6572dda36f372e", - "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53", - "sha256:f4f05d88d9a80ad3cac6244d36dd89a3c00abc16371769f1340101d3cb899fc3", - "sha256:f642e90754ee3e06b0e7e51bce3379590e76b7f76b708e1a71ff043f87025c84", - "sha256:fc2af30ed0d5ae0b1abdb4ebdce598eafd5b35397d4d75deb341a614d333d987" + "sha256:006ed5582e9cbc8115d2e22d6d2144a0725db542f654d9d4fda86793832f873d", + "sha256:046936ab032a2810dcaafd39cc4ef6dd295df1a7cbead08fe996d4765fca9fe4", + "sha256:0484d9dd1e6f481b24070c87561c8d7151bdd8b044c93ac99faafd01f695c78e", + "sha256:0ce383d5f56d0729d2dd40e53fe3afeb8f2237244b0975e1427bfb2cf0d32bab", + "sha256:186e0fc9cf497365036d51d4d2ab76113fb74f729bd25da0975daab2e107fd90", + "sha256:2199988e0bc8325d941b209f4fd1c6fa007024b1442c5576f1a32ca2e48941e6", + "sha256:299bc75cb2a41e6741b5e470b8c9fb78d931edbd0cd009c58e5c84de57c06731", + "sha256:3668291b50b69a0c1ef9f462c7df2c235da3c4073f49543b01e7eb1dee7dd540", + "sha256:36dd42da34fe94ed98c39887b86db9d06777b1c8f860520e21126a75507024f2", + "sha256:38004671848b5745bb05d4d621526fca30cee164db42a1f185615f39dc997292", + "sha256:387fb46cb8e53ba7304d80aadca5dca84a2fbf6fe3faf6951d8cf2d46485d1e5", + "sha256:3eb55b7b26389dd4f8ae911ba9bc8c027411163839dea4c8b8be54c4ee9ae10b", + "sha256:420f94a35e3e00a2b43ad5740f935358e24478354ce41c99407cddd283be00d2", + "sha256:4ac0f522c3b6109c4b764ffec71bf04ebc0523e926ca7cbe6c5ac88f84faced0", + "sha256:4c752d5264053a7cf2fe81c9e14f8a4fb261370a7bb344c2a011836a96fb3f57", + "sha256:4f01911c010122f49a3e9bdc730eccc66f9b72bd410a3a9d3cb8448bb50d65d3", + "sha256:4f68ee32d7c4164f1e2c8797535a6d0a3733355f5861e0f667e37df2d4b07140", + "sha256:4fa54fb483decc45f94011898727802309a109d89446a3c76387d016057d2c84", + "sha256:507e4720791977934bba016101579b8c500fb21c5fa3cd4cf256477331ddd988", + "sha256:53d0fd4c17175aded9c633e319360d41a1f3c6e352ba94edcb0fa5167e2bad67", + "sha256:55272f33da9a5d7cccd3774aeca7a01e500a614eaea2a77091e9be000ecd401d", + "sha256:5764e1f7471cb8f64b8cda0554f3d4c4085ae4b417bfeab236799863703e5de2", + "sha256:57b77b9099f172804e695a40ebaa374f79e4fb8b92f3e167f66facbf92e8e7f5", + "sha256:5afdad4cc4cc199fdf3e18088812edcf8f4c5a3c8e6cb69127513ad4cb7471a9", + "sha256:5cc0783844c84af2522e3a99b9b761a979a3ef10fb87fc4048d1ee174e18a7d8", + "sha256:5e1df45c23d4230e3d56d04414f9057eba501f78db60d4eeecfcb940501b08fd", + "sha256:6146910231ece63facfc5984234ad1b06a36cecc9fd0c028e59ac7c9b18c38c6", + "sha256:797aad79e7b6182cb49c08cc5d2f7aa7b2128133b0926060d0a8889ac43843be", + "sha256:7c20b731211261dc9739bbe080c579a1835b0c2d9b274e5fcd903c3a7821cf88", + "sha256:817295f06eacdc8623dc4df7d8b49cea65925030d4e1e2a7c7218380c0072c25", + "sha256:81f63e0fb74effd5be736cfe07d710307cc0a3ccb8f4741f7f053c057615a137", + "sha256:872d6ce1f5be73f05bea4df498c140b9e7ee5418bfa2cc8204e7f9b817caa968", + "sha256:8c99cb7c26a3039a8a4ee3ca1efdde471e61b4837108847fb7d5be7789ed8fd9", + "sha256:8dbe2647bf58d2c5a6c5bcc685f23b5f371909a5624e9f5cd51436d6a9f6c6ef", + "sha256:8efb48fa743d1c1a65ee8787b5b552681610f06c40a40b7ef94a5b517d885c54", + "sha256:92ebc1619650409da324d001b3a36f14f63644c7f0a588e331f3b0f67491f512", + "sha256:9d22e94e6dc86de981b1b684b342bec5e331401599ce652900ec59db52940005", + "sha256:ba279aae162b20444881fc3ed4e4f934c1cf8620f3dab3b531480cf602c76b7f", + "sha256:bc4803779f0e4b06a2361f666e76f5c2e3715e8e379889d02251ec911befd149", + "sha256:bfe7085783cda55e53510482fa7b5efc761fad1abe4d653b32710eb548ebdd2d", + "sha256:c448b5c9e3df5448a362208b8d4b9ed85305528313fca1b479f14f9fe0d873b8", + "sha256:c90e73bdecb7b0d1cea65a08cb41e9d672ac6d7995603d6465ed4914b98b9ad7", + "sha256:d2b96123a453a2d7f3995ddb9f28d01fd112319a7a4d5ca99796a7ff43f02af5", + "sha256:d52f0a114b6a58305b11a5cdecd42b2e7f1ec77eb20e2b33969d702feafdd016", + "sha256:d530191aa9c66ab4f190be8ac8cc7cfd8f4f3217da379606f3dd4e3d83feba69", + "sha256:d683d230b5774816e7d784d7ed8444f2a40e7a450e5720d58af593cb0b94a212", + "sha256:db45eec1dfccdadb179b0f9ca616872c6f700d23945ecc8f21bb105d74b1c5fc", + "sha256:db8c2c5ace167fd25ab5dd732714c51d4633f58bac21fb0ff63b0349f62755a8", + "sha256:e2926b8abedf750c2ecf5035c07515770944acf02e1c46ab08f6348d24c5f94d", + "sha256:e627dee428a176ffb13697a2c4318d3f60b2ccdde3acdc9b3f304206ec130ccd", + "sha256:efe1c0adad110bf0ad7fb59f833880e489a61e39d699d37249bdf42f80590169" ], "index": "pypi", - "version": "==6.5.0" + "version": "==7.2.2" }, "decorator": { "hashes": [ @@ -1098,11 +1285,11 @@ }, "django": { "hashes": [ - "sha256:07e6433f263c3839939cfabeb6d7557841e0419e47759a7b7d37f6d44d40adcb", - "sha256:27cb08fa6458c1eff8b97c4c2d03774646fb26feeaa4587dca10c49e6d4fc6a3" + "sha256:44f714b81c5f190d9d2ddad01a532fe502fa01c4cb8faf1d081f4264ed15dcd8", + "sha256:f2f431e75adc40039ace496ad3b9f17227022e8b11566f4b363da44c7e44761e" ], "index": "pypi", - "version": "==4.0.8" + "version": "==4.1.7" }, "django-webtest": { "hashes": [ @@ -1152,11 +1339,11 @@ }, "faker": { "hashes": [ - "sha256:2d5443724f640ce07658ca8ca8bbd40d26b58914e63eec6549727869aa67e2cc", - "sha256:c2a2ff9dd8dfd991109b517ab98d5cb465e857acb45f6b643a0e284a9eb2cc76" + "sha256:2deeee8fed3d1b8ae5f87d172d4569ddc859aab8693f7cd68eddc5d20400563a", + "sha256:e7c058e1f360f245f265625b32d3189d7229398ad80a8b6bac459891745de052" ], "markers": "python_version >= '3.7'", - "version": "==15.3.4" + "version": "==18.3.0" }, "fancycompleter": { "hashes": [ @@ -1167,11 +1354,11 @@ }, "filelock": { "hashes": [ - "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc", - "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4" + "sha256:3199fd0d3faea8b911be52b663dfccceb84c95949dd13179aa21436d1a79c4ce", + "sha256:e90b34656470756edf8b19656785c5fea73afa1953f3e1b0d645cef11cab3182" ], "markers": "python_version >= '3.7'", - "version": "==3.8.0" + "version": "==3.10.0" }, "flake8": { "hashes": [ @@ -1183,11 +1370,11 @@ }, "flake8-html": { "hashes": [ - "sha256:5db0439169987509690ef8c90efb00346009bcc5cffb8b94fe0ad30cd655b88c", - "sha256:6d3f2cbae8a0092d922ca5acf88f971d85a2bd69723d0dceba65e57bcaa0adba" + "sha256:8b870299620cc4a06f73644a1b4d457799abeca1cc914c62ae71ec5bf65c79a5", + "sha256:8f126748b1b0edd6cd39e87c6192df56e2f8655b0aa2bb00ffeac8cf27be4325" ], "index": "pypi", - "version": "==0.4.2" + "version": "==0.4.3" }, "freezegun": { "hashes": [ @@ -1215,34 +1402,35 @@ }, "importlib-metadata": { "hashes": [ - "sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b", - "sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313" + "sha256:43ce9281e097583d758c2c708c4376371261a02c34682491a8e98352365aad20", + "sha256:ff80f3b5394912eb1b108fcfd444dc78b7f1f3e16b16188054bd01cb9cb86f09" ], "markers": "python_version < '3.10'", - "version": "==5.1.0" + "version": "==6.1.0" }, "iniconfig": { "hashes": [ - "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3", - "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32" + "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", + "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" ], - "version": "==1.1.1" + "markers": "python_version >= '3.7'", + "version": "==2.0.0" }, "ipython": { "hashes": [ - "sha256:352042ddcb019f7c04e48171b4dd78e4c4bb67bf97030d170e154aac42b656d9", - "sha256:882899fe78d5417a0aa07f995db298fa28b58faeba2112d2e3a4c95fe14bb738" + "sha256:5b54478e459155a326bf5f42ee4f29df76258c0279c36f21d71ddb560f88b156", + "sha256:735cede4099dbc903ee540307b9171fbfef4aa75cfcacc5a273b2cda2f02be04" ], "index": "pypi", - "version": "==8.7.0" + "version": "==8.11.0" }, "isort": { "hashes": [ - "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7", - "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951" + "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504", + "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6" ], "index": "pypi", - "version": "==5.10.1" + "version": "==5.12.0" }, "jedi": { "hashes": [ @@ -1262,49 +1450,59 @@ }, "markupsafe": { "hashes": [ - "sha256:0212a68688482dc52b2d45013df70d169f542b7394fc744c02a57374a4207003", - "sha256:089cf3dbf0cd6c100f02945abeb18484bd1ee57a079aefd52cffd17fba910b88", - "sha256:10c1bfff05d95783da83491be968e8fe789263689c02724e0c691933c52994f5", - "sha256:33b74d289bd2f5e527beadcaa3f401e0df0a89927c1559c8566c066fa4248ab7", - "sha256:3799351e2336dc91ea70b034983ee71cf2f9533cdff7c14c90ea126bfd95d65a", - "sha256:3ce11ee3f23f79dbd06fb3d63e2f6af7b12db1d46932fe7bd8afa259a5996603", - "sha256:421be9fbf0ffe9ffd7a378aafebbf6f4602d564d34be190fc19a193232fd12b1", - "sha256:43093fb83d8343aac0b1baa75516da6092f58f41200907ef92448ecab8825135", - "sha256:46d00d6cfecdde84d40e572d63735ef81423ad31184100411e6e3388d405e247", - "sha256:4a33dea2b688b3190ee12bd7cfa29d39c9ed176bda40bfa11099a3ce5d3a7ac6", - "sha256:4b9fe39a2ccc108a4accc2676e77da025ce383c108593d65cc909add5c3bd601", - "sha256:56442863ed2b06d19c37f94d999035e15ee982988920e12a5b4ba29b62ad1f77", - "sha256:671cd1187ed5e62818414afe79ed29da836dde67166a9fac6d435873c44fdd02", - "sha256:694deca8d702d5db21ec83983ce0bb4b26a578e71fbdbd4fdcd387daa90e4d5e", - "sha256:6a074d34ee7a5ce3effbc526b7083ec9731bb3cbf921bbe1d3005d4d2bdb3a63", - "sha256:6d0072fea50feec76a4c418096652f2c3238eaa014b2f94aeb1d56a66b41403f", - "sha256:6fbf47b5d3728c6aea2abb0589b5d30459e369baa772e0f37a0320185e87c980", - "sha256:7f91197cc9e48f989d12e4e6fbc46495c446636dfc81b9ccf50bb0ec74b91d4b", - "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812", - "sha256:8dc1c72a69aa7e082593c4a203dcf94ddb74bb5c8a731e4e1eb68d031e8498ff", - "sha256:8e3dcf21f367459434c18e71b2a9532d96547aef8a871872a5bd69a715c15f96", - "sha256:8e576a51ad59e4bfaac456023a78f6b5e6e7651dcd383bcc3e18d06f9b55d6d1", - "sha256:96e37a3dc86e80bf81758c152fe66dbf60ed5eca3d26305edf01892257049925", - "sha256:97a68e6ada378df82bc9f16b800ab77cbf4b2fada0081794318520138c088e4a", - "sha256:99a2a507ed3ac881b975a2976d59f38c19386d128e7a9a18b7df6fff1fd4c1d6", - "sha256:a49907dd8420c5685cfa064a1335b6754b74541bbb3706c259c02ed65b644b3e", - "sha256:b09bf97215625a311f669476f44b8b318b075847b49316d3e28c08e41a7a573f", - "sha256:b7bd98b796e2b6553da7225aeb61f447f80a1ca64f41d83612e6139ca5213aa4", - "sha256:b87db4360013327109564f0e591bd2a3b318547bcef31b468a92ee504d07ae4f", - "sha256:bcb3ed405ed3222f9904899563d6fc492ff75cce56cba05e32eff40e6acbeaa3", - "sha256:d4306c36ca495956b6d568d276ac11fdd9c30a36f1b6eb928070dc5360b22e1c", - "sha256:d5ee4f386140395a2c818d149221149c54849dfcfcb9f1debfe07a8b8bd63f9a", - "sha256:dda30ba7e87fbbb7eab1ec9f58678558fd9a6b8b853530e176eabd064da81417", - "sha256:e04e26803c9c3851c931eac40c695602c6295b8d432cbe78609649ad9bd2da8a", - "sha256:e1c0b87e09fa55a220f058d1d49d3fb8df88fbfab58558f1198e08c1e1de842a", - "sha256:e72591e9ecd94d7feb70c1cbd7be7b3ebea3f548870aa91e2732960fa4d57a37", - "sha256:e8c843bbcda3a2f1e3c2ab25913c80a3c5376cd00c6e8c4a86a89a28c8dc5452", - "sha256:efc1913fd2ca4f334418481c7e595c00aad186563bbc1ec76067848c7ca0a933", - "sha256:f121a1420d4e173a5d96e47e9a0c0dcff965afdf1626d28de1460815f7c4ee7a", - "sha256:fc7b548b17d238737688817ab67deebb30e8073c95749d55538ed473130ec0c7" + "sha256:0576fe974b40a400449768941d5d0858cc624e3249dfd1e0c33674e5c7ca7aed", + "sha256:085fd3201e7b12809f9e6e9bc1e5c96a368c8523fad5afb02afe3c051ae4afcc", + "sha256:090376d812fb6ac5f171e5938e82e7f2d7adc2b629101cec0db8b267815c85e2", + "sha256:0b462104ba25f1ac006fdab8b6a01ebbfbce9ed37fd37fd4acd70c67c973e460", + "sha256:137678c63c977754abe9086a3ec011e8fd985ab90631145dfb9294ad09c102a7", + "sha256:1bea30e9bf331f3fef67e0a3877b2288593c98a21ccb2cf29b74c581a4eb3af0", + "sha256:22152d00bf4a9c7c83960521fc558f55a1adbc0631fbb00a9471e097b19d72e1", + "sha256:22731d79ed2eb25059ae3df1dfc9cb1546691cc41f4e3130fe6bfbc3ecbbecfa", + "sha256:2298c859cfc5463f1b64bd55cb3e602528db6fa0f3cfd568d3605c50678f8f03", + "sha256:28057e985dace2f478e042eaa15606c7efccb700797660629da387eb289b9323", + "sha256:2e7821bffe00aa6bd07a23913b7f4e01328c3d5cc0b40b36c0bd81d362faeb65", + "sha256:2ec4f2d48ae59bbb9d1f9d7efb9236ab81429a764dedca114f5fdabbc3788013", + "sha256:340bea174e9761308703ae988e982005aedf427de816d1afe98147668cc03036", + "sha256:40627dcf047dadb22cd25ea7ecfe9cbf3bbbad0482ee5920b582f3809c97654f", + "sha256:40dfd3fefbef579ee058f139733ac336312663c6706d1163b82b3003fb1925c4", + "sha256:4cf06cdc1dda95223e9d2d3c58d3b178aa5dacb35ee7e3bbac10e4e1faacb419", + "sha256:50c42830a633fa0cf9e7d27664637532791bfc31c731a87b202d2d8ac40c3ea2", + "sha256:55f44b440d491028addb3b88f72207d71eeebfb7b5dbf0643f7c023ae1fba619", + "sha256:608e7073dfa9e38a85d38474c082d4281f4ce276ac0010224eaba11e929dd53a", + "sha256:63ba06c9941e46fa389d389644e2d8225e0e3e5ebcc4ff1ea8506dce646f8c8a", + "sha256:65608c35bfb8a76763f37036547f7adfd09270fbdbf96608be2bead319728fcd", + "sha256:665a36ae6f8f20a4676b53224e33d456a6f5a72657d9c83c2aa00765072f31f7", + "sha256:6d6607f98fcf17e534162f0709aaad3ab7a96032723d8ac8750ffe17ae5a0666", + "sha256:7313ce6a199651c4ed9d7e4cfb4aa56fe923b1adf9af3b420ee14e6d9a73df65", + "sha256:7668b52e102d0ed87cb082380a7e2e1e78737ddecdde129acadb0eccc5423859", + "sha256:7df70907e00c970c60b9ef2938d894a9381f38e6b9db73c5be35e59d92e06625", + "sha256:7e007132af78ea9df29495dbf7b5824cb71648d7133cf7848a2a5dd00d36f9ff", + "sha256:835fb5e38fd89328e9c81067fd642b3593c33e1e17e2fdbf77f5676abb14a156", + "sha256:8bca7e26c1dd751236cfb0c6c72d4ad61d986e9a41bbf76cb445f69488b2a2bd", + "sha256:8db032bf0ce9022a8e41a22598eefc802314e81b879ae093f36ce9ddf39ab1ba", + "sha256:99625a92da8229df6d44335e6fcc558a5037dd0a760e11d84be2260e6f37002f", + "sha256:9cad97ab29dfc3f0249b483412c85c8ef4766d96cdf9dcf5a1e3caa3f3661cf1", + "sha256:a4abaec6ca3ad8660690236d11bfe28dfd707778e2442b45addd2f086d6ef094", + "sha256:a6e40afa7f45939ca356f348c8e23048e02cb109ced1eb8420961b2f40fb373a", + "sha256:a6f2fcca746e8d5910e18782f976489939d54a91f9411c32051b4aab2bd7c513", + "sha256:a806db027852538d2ad7555b203300173dd1b77ba116de92da9afbc3a3be3eed", + "sha256:abcabc8c2b26036d62d4c746381a6f7cf60aafcc653198ad678306986b09450d", + "sha256:b8526c6d437855442cdd3d87eede9c425c4445ea011ca38d937db299382e6fa3", + "sha256:bb06feb762bade6bf3c8b844462274db0c76acc95c52abe8dbed28ae3d44a147", + "sha256:c0a33bc9f02c2b17c3ea382f91b4db0e6cde90b63b296422a939886a7a80de1c", + "sha256:c4a549890a45f57f1ebf99c067a4ad0cb423a05544accaf2b065246827ed9603", + "sha256:ca244fa73f50a800cf8c3ebf7fd93149ec37f5cb9596aa8873ae2c1d23498601", + "sha256:cf877ab4ed6e302ec1d04952ca358b381a882fbd9d1b07cccbfd61783561f98a", + "sha256:d9d971ec1e79906046aa3ca266de79eac42f1dbf3612a05dc9368125952bd1a1", + "sha256:da25303d91526aac3672ee6d49a2f3db2d9502a4a60b55519feb1a4c7714e07d", + "sha256:e55e40ff0cc8cc5c07996915ad367fa47da6b3fc091fdadca7f5403239c5fec3", + "sha256:f03a532d7dee1bed20bc4884194a16160a2de9ffc6354b3878ec9682bb623c54", + "sha256:f1cd098434e83e656abf198f103a8207a8187c0fc110306691a2e94a78d0abb2", + "sha256:f2bfb563d0211ce16b63c7cb9395d2c682a23187f54c3d79bfec33e6705473c6", + "sha256:f8ffb705ffcf5ddd0e80b65ddf7bed7ee4f5a441ea7d3419e861a12eaf41af58" ], "markers": "python_version >= '3.7'", - "version": "==2.1.1" + "version": "==2.1.2" }, "matplotlib-inline": { "hashes": [ @@ -1324,84 +1522,99 @@ }, "mock": { "hashes": [ - "sha256:122fcb64ee37cfad5b3f48d7a7d51875d7031aaf3d8be7c42e2bee25044eee62", - "sha256:7d3fbbde18228f4ff2f1f119a45cdffa458b4c0dee32eb4d2bb2f82554bac7bc" + "sha256:c41cfb1e99ba5d341fbcc5308836e7d7c9786d302f995b2c271ce2144dece9eb", + "sha256:e3ea505c03babf7977fd21674a69ad328053d414f05e6433c30d8fa14a534a6b" ], "index": "pypi", - "version": "==4.0.3" + "version": "==5.0.1" }, "multidict": { "hashes": [ - "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" + "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9", + "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8", + "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03", + "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710", + "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161", + "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664", + "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569", + "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067", + "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313", + "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706", + "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2", + "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636", + "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49", + "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93", + "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603", + "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0", + "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60", + "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4", + "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e", + "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1", + "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60", + "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951", + "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc", + "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe", + "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95", + "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d", + "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8", + "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed", + "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2", + "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775", + "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87", + "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c", + "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2", + "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98", + "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3", + "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe", + "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78", + "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660", + "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176", + "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e", + "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988", + "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c", + "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c", + "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0", + "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449", + "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f", + "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde", + "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5", + "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d", + "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac", + "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a", + "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9", + "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca", + "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11", + "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35", + "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063", + "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b", + "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982", + "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258", + "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1", + "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52", + "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480", + "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7", + "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461", + "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d", + "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc", + "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779", + "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a", + "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547", + "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0", + "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171", + "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf", + "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d", + "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba" ], "markers": "python_version >= '3.7'", - "version": "==6.0.2" + "version": "==6.0.4" }, "packaging": { "hashes": [ - "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", - "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" + "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2", + "sha256:b6ad297f8907de0fa2fe1ccbd26fdaf387f5f47c7275fedf8cce89f99446cf97" ], - "markers": "python_version >= '3.6'", - "version": "==21.3" + "markers": "python_version >= '3.7'", + "version": "==23.0" }, "parso": { "hashes": [ @@ -1436,11 +1649,11 @@ }, "platformdirs": { "hashes": [ - "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7", - "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10" + "sha256:024996549ee88ec1a9aa99ff7f8fc819bb59e2c3477b410d90a16d32d6e707aa", + "sha256:e5986afb596e4bb5bde29a79ac9061aa955b94fca2399b7aaac4090860920dd8" ], "markers": "python_version >= '3.7'", - "version": "==2.5.4" + "version": "==3.1.1" }, "pluggy": { "hashes": [ @@ -1452,11 +1665,11 @@ }, "prompt-toolkit": { "hashes": [ - "sha256:535c29c31216c77302877d5120aef6c94ff573748a5b5ca5b1b1f76f5e700c73", - "sha256:ced598b222f6f4029c0800cefaa6a17373fb580cd093223003475ce32805c35b" + "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b", + "sha256:45ea77a2f7c60418850331366c81cf6b5b9cf4c7fd34616f733c5427e6abbb1f" ], - "markers": "python_full_version >= '3.6.2'", - "version": "==3.0.33" + "markers": "python_full_version >= '3.7.0'", + "version": "==3.0.38" }, "ptyprocess": { "hashes": [ @@ -1498,19 +1711,19 @@ }, "pygments": { "hashes": [ - "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1", - "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42" + "sha256:b3ed06a9e8ac9a9aae5a6f5dbe78a8a58655d17b43b93c078f094ddc476ae297", + "sha256:fa7bd7bd2771287c0de303af8bfdfc731f51bd2c6a47ab69d117138893b82717" ], "markers": "python_version >= '3.6'", - "version": "==2.13.0" + "version": "==2.14.0" }, - "pyparsing": { + "pyproject-api": { "hashes": [ - "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb", - "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc" + "sha256:435f46547a9ff22cf4208ee274fca3e2869aeb062a4834adfc99a4dd64af3cf9", + "sha256:4698a3777c2e0f6b624f8a4599131e2a25376d90fe8d146d7ac74c67c6f97c43" ], - "markers": "python_full_version >= '3.6.8'", - "version": "==3.0.9" + "markers": "python_version >= '3.7'", + "version": "==1.5.1" }, "pyrepl": { "hashes": [ @@ -1585,15 +1798,15 @@ "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86", "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.8.2" }, "pytz": { "hashes": [ - "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427", - "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2" + "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0", + "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a" ], - "version": "==2022.6" + "version": "==2022.7.1" }, "pyyaml": { "hashes": [ @@ -1643,26 +1856,26 @@ }, "requests": { "hashes": [ - "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983", - "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349" + "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa", + "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf" ], "index": "pypi", - "version": "==2.28.1" + "version": "==2.28.2" }, "responses": { "hashes": [ - "sha256:396acb2a13d25297789a5866b4881cf4e46ffd49cc26c43ab1117f40b973102e", - "sha256:dcf294d204d14c436fddcc74caefdbc5764795a40ff4e6a7740ed8ddbf3294be" + "sha256:8a3a5915713483bf353b6f4079ba8b2a29029d1d1090a503c70b0dc5d9d0c7bd", + "sha256:c4d9aa9fc888188f0c673eff79a8dadbe2e75b7fe879dc80a221a06e0a68138f" ], "index": "pypi", - "version": "==0.22.0" + "version": "==0.23.1" }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "snowballstemmer": { @@ -1674,27 +1887,27 @@ }, "soupsieve": { "hashes": [ - "sha256:3b2503d3c7084a42b1ebd08116e5f81aadfaea95863628c80a3b774a11b7c759", - "sha256:fc53893b3da2c33de295667a0e19f078c14bf86544af307354de5fcf12a3f30d" + "sha256:49e5368c2cda80ee7e84da9dbe3e110b70a4575f196efb74e51b94549d921955", + "sha256:e28dba9ca6c7c00173e34e4ba57448f0688bb681b7c5e8bf4971daafc093d69a" ], - "markers": "python_version >= '3.6'", - "version": "==2.3.2.post1" + "markers": "python_version >= '3.7'", + "version": "==2.4" }, "sphinx": { "hashes": [ - "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d", - "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5" + "sha256:0dac3b698538ffef41716cf97ba26c1c7788dba73ce6f150c1ff5b4720786dd2", + "sha256:807d1cb3d6be87eb78a381c3e70ebd8d346b9a25f3753e9947e866b2786865fc" ], "index": "pypi", - "version": "==5.3.0" + "version": "==6.1.3" }, "sphinxcontrib-applehelp": { "hashes": [ - "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", - "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228", + "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e" ], - "markers": "python_version >= '3.5'", - "version": "==1.0.2" + "markers": "python_version >= '3.8'", + "version": "==1.0.4" }, "sphinxcontrib-devhelp": { "hashes": [ @@ -1706,11 +1919,11 @@ }, "sphinxcontrib-htmlhelp": { "hashes": [ - "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07", - "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2" + "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff", + "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903" ], - "markers": "python_version >= '3.6'", - "version": "==2.0.0" + "markers": "python_version >= '3.8'", + "version": "==2.0.1" }, "sphinxcontrib-jsmath": { "hashes": [ @@ -1763,7 +1976,7 @@ "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, "tomli": { @@ -1776,34 +1989,34 @@ }, "tox": { "hashes": [ - "sha256:b2a920e35a668cc06942ffd1cf3a4fb221a4d909ca72191fb6d84b0b18a7be04", - "sha256:f52ca66eae115fcfef0e77ef81fd107133d295c97c52df337adedb8dfac6ab84" + "sha256:52c92a96e2c3fd47c5301e9c26f5a871466133d5376958c1ed95ef4ff4629cbe", + "sha256:da10ca1d809b99fae80b706b9dc9656b1daf505a395ac427d130a8a85502d08f" ], "index": "pypi", - "version": "==3.27.1" + "version": "==4.4.7" }, "traitlets": { "hashes": [ - "sha256:10b6ed1c9cedee83e795db70a8b9c2db157bb3778ec4587a349ecb7ef3b1033b", - "sha256:1410755385d778aed847d68deb99b3ba30fbbf489e17a1e8cbb753060d5cce73" + "sha256:9e6ec080259b9a5940c797d58b613b5e31441c2257b87c2e795c5228ae80d2d8", + "sha256:f6cde21a9c68cf756af02035f72d5a723bf607e862e7be33ece505abf4a3bad9" ], "markers": "python_version >= '3.7'", - "version": "==5.6.0" + "version": "==5.9.0" }, - "types-toml": { + "types-pyyaml": { "hashes": [ - "sha256:171bdb3163d79a520560f24ba916a9fc9bff81659c5448a9fea89240923722be", - "sha256:b7b5c4977f96ab7b5ac06d8a6590d17c0bf252a96efc03b109c2711fb3e0eafd" + "sha256:19304869a89d49af00be681e7b267414df213f4eb89634c4495fa62e8f942b9f", + "sha256:5314a4b2580999b2ea06b2e5f9a7763d860d6e09cdf21c0e9561daa9cbd60178" ], - "version": "==0.10.8.1" + "version": "==6.0.12.8" }, "urllib3": { "hashes": [ - "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc", - "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8" + "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305", + "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.26.13" + "version": "==1.26.15" }, "vcrpy": { "hashes": [ @@ -1815,11 +2028,11 @@ }, "virtualenv": { "hashes": [ - "sha256:40a7e06a98728fd5769e1af6fd1a706005b4bb7e16176a272ed4292473180389", - "sha256:7d6a8d55b2f73b617f684ee40fd85740f062e1f2e379412cb1879c7136f05902" + "sha256:31712f8f2a17bd06234fa97fdf19609e789dd4e3e4bf108c3da71d710651adbc", + "sha256:f50e3e60f990a0757c9b68333c9fdaa72d7188caa417f96af9e52407831a3b68" ], - "markers": "python_version >= '3.6'", - "version": "==20.17.0" + "markers": "python_version >= '3.7'", + "version": "==20.21.0" }, "waitress": { "hashes": [ @@ -1831,17 +2044,17 @@ }, "wcwidth": { "hashes": [ - "sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784", - "sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83" + "sha256:795b138f6875577cd91bba52baf9e445cd5118fd32723b460e30a0af30ea230e", + "sha256:a5220780a404dbe3353789870978e472cfe477761f06ee55077256e509b156d0" ], - "version": "==0.2.5" + "version": "==0.2.6" }, "webob": { "hashes": [ "sha256:73aae30359291c14fa3b956f8b5ca31960e420c28c1bec002547fb04928cf89b", "sha256:b64ef5141be559cfade448f044fa45c2260351edcb6a8ef6b7e00c7dcef0c323" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.8.7" }, "webtest": { @@ -1860,146 +2073,172 @@ }, "wrapt": { "hashes": [ - "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3", - "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b", - "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4", - "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2", - "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656", - "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3", - "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff", - "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310", - "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a", - "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57", - "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069", - "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383", - "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe", - "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87", - "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d", - "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b", - "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907", - "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f", - "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0", - "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28", - "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1", - "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853", - "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc", - "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3", - "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3", - "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164", - "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1", - "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c", - "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1", - "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7", - "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1", - "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320", - "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed", - "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1", - "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248", - "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c", - "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456", - "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77", - "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef", - "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1", - "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7", - "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86", - "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4", - "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d", - "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d", - "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8", - "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5", - "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471", - "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00", - "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68", - "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3", - "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d", - "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735", - "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d", - "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569", - "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7", - "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59", - "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5", - "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb", - "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b", - "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f", - "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462", - "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015", - "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af" + "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0", + "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420", + "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a", + "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c", + "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079", + "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923", + "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f", + "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1", + "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8", + "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86", + "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0", + "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364", + "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e", + "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c", + "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e", + "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c", + "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727", + "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff", + "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e", + "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29", + "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7", + "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72", + "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475", + "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a", + "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317", + "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2", + "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd", + "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640", + "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98", + "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248", + "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e", + "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d", + "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec", + "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1", + "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e", + "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9", + "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92", + "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb", + "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094", + "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46", + "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29", + "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd", + "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705", + "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8", + "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975", + "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb", + "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e", + "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b", + "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418", + "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019", + "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1", + "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba", + "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6", + "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2", + "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3", + "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7", + "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752", + "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416", + "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f", + "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1", + "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc", + "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145", + "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee", + "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a", + "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7", + "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b", + "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653", + "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0", + "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90", + "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29", + "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6", + "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034", + "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09", + "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559", + "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.14.1" + "version": "==1.15.0" }, "yarl": { "hashes": [ - "sha256:076eede537ab978b605f41db79a56cad2e7efeea2aa6e0fa8f05a26c24a034fb", - "sha256:07b21e274de4c637f3e3b7104694e53260b5fc10d51fb3ec5fed1da8e0f754e3", - "sha256:0ab5a138211c1c366404d912824bdcf5545ccba5b3ff52c42c4af4cbdc2c5035", - "sha256:0c03f456522d1ec815893d85fccb5def01ffaa74c1b16ff30f8aaa03eb21e453", - "sha256:12768232751689c1a89b0376a96a32bc7633c08da45ad985d0c49ede691f5c0d", - "sha256:19cd801d6f983918a3f3a39f3a45b553c015c5aac92ccd1fac619bd74beece4a", - "sha256:1ca7e596c55bd675432b11320b4eacc62310c2145d6801a1f8e9ad160685a231", - "sha256:1e4808f996ca39a6463f45182e2af2fae55e2560be586d447ce8016f389f626f", - "sha256:205904cffd69ae972a1707a1bd3ea7cded594b1d773a0ce66714edf17833cdae", - "sha256:20df6ff4089bc86e4a66e3b1380460f864df3dd9dccaf88d6b3385d24405893b", - "sha256:21ac44b763e0eec15746a3d440f5e09ad2ecc8b5f6dcd3ea8cb4773d6d4703e3", - "sha256:29e256649f42771829974e742061c3501cc50cf16e63f91ed8d1bf98242e5507", - "sha256:2d800b9c2eaf0684c08be5f50e52bfa2aa920e7163c2ea43f4f431e829b4f0fd", - "sha256:2d93a049d29df172f48bcb09acf9226318e712ce67374f893b460b42cc1380ae", - "sha256:31a9a04ecccd6b03e2b0e12e82131f1488dea5555a13a4d32f064e22a6003cfe", - "sha256:3d1a50e461615747dd93c099f297c1994d472b0f4d2db8a64e55b1edf704ec1c", - "sha256:449c957ffc6bc2309e1fbe67ab7d2c1efca89d3f4912baeb8ead207bb3cc1cd4", - "sha256:4a88510731cd8d4befaba5fbd734a7dd914de5ab8132a5b3dde0bbd6c9476c64", - "sha256:4c322cbaa4ed78a8aac89b2174a6df398faf50e5fc12c4c191c40c59d5e28357", - "sha256:5395da939ffa959974577eff2cbfc24b004a2fb6c346918f39966a5786874e54", - "sha256:5587bba41399854703212b87071c6d8638fa6e61656385875f8c6dff92b2e461", - "sha256:56c11efb0a89700987d05597b08a1efcd78d74c52febe530126785e1b1a285f4", - "sha256:5999c4662631cb798496535afbd837a102859568adc67d75d2045e31ec3ac497", - "sha256:59ddd85a1214862ce7c7c66457f05543b6a275b70a65de366030d56159a979f0", - "sha256:6347f1a58e658b97b0a0d1ff7658a03cb79bdbda0331603bed24dd7054a6dea1", - "sha256:6628d750041550c5d9da50bb40b5cf28a2e63b9388bac10fedd4f19236ef4957", - "sha256:6afb336e23a793cd3b6476c30f030a0d4c7539cd81649683b5e0c1b0ab0bf350", - "sha256:6c8148e0b52bf9535c40c48faebb00cb294ee577ca069d21bd5c48d302a83780", - "sha256:76577f13333b4fe345c3704811ac7509b31499132ff0181f25ee26619de2c843", - "sha256:7c0da7e44d0c9108d8b98469338705e07f4bb7dab96dbd8fa4e91b337db42548", - "sha256:7de89c8456525650ffa2bb56a3eee6af891e98f498babd43ae307bd42dca98f6", - "sha256:7ec362167e2c9fd178f82f252b6d97669d7245695dc057ee182118042026da40", - "sha256:7fce6cbc6c170ede0221cc8c91b285f7f3c8b9fe28283b51885ff621bbe0f8ee", - "sha256:85cba594433915d5c9a0d14b24cfba0339f57a2fff203a5d4fd070e593307d0b", - "sha256:8b0af1cf36b93cee99a31a545fe91d08223e64390c5ecc5e94c39511832a4bb6", - "sha256:9130ddf1ae9978abe63808b6b60a897e41fccb834408cde79522feb37fb72fb0", - "sha256:99449cd5366fe4608e7226c6cae80873296dfa0cde45d9b498fefa1de315a09e", - "sha256:9de955d98e02fab288c7718662afb33aab64212ecb368c5dc866d9a57bf48880", - "sha256:a0fb2cb4204ddb456a8e32381f9a90000429489a25f64e817e6ff94879d432fc", - "sha256:a165442348c211b5dea67c0206fc61366212d7082ba8118c8c5c1c853ea4d82e", - "sha256:ab2a60d57ca88e1d4ca34a10e9fb4ab2ac5ad315543351de3a612bbb0560bead", - "sha256:abc06b97407868ef38f3d172762f4069323de52f2b70d133d096a48d72215d28", - "sha256:af887845b8c2e060eb5605ff72b6f2dd2aab7a761379373fd89d314f4752abbf", - "sha256:b19255dde4b4f4c32e012038f2c169bb72e7f081552bea4641cab4d88bc409dd", - "sha256:b3ded839a5c5608eec8b6f9ae9a62cb22cd037ea97c627f38ae0841a48f09eae", - "sha256:c1445a0c562ed561d06d8cbc5c8916c6008a31c60bc3655cdd2de1d3bf5174a0", - "sha256:d0272228fabe78ce00a3365ffffd6f643f57a91043e119c289aaba202f4095b0", - "sha256:d0b51530877d3ad7a8d47b2fff0c8df3b8f3b8deddf057379ba50b13df2a5eae", - "sha256:d0f77539733e0ec2475ddcd4e26777d08996f8cd55d2aef82ec4d3896687abda", - "sha256:d2b8f245dad9e331540c350285910b20dd913dc86d4ee410c11d48523c4fd546", - "sha256:dd032e8422a52e5a4860e062eb84ac94ea08861d334a4bcaf142a63ce8ad4802", - "sha256:de49d77e968de6626ba7ef4472323f9d2e5a56c1d85b7c0e2a190b2173d3b9be", - "sha256:de839c3a1826a909fdbfe05f6fe2167c4ab033f1133757b5936efe2f84904c07", - "sha256:e80ed5a9939ceb6fda42811542f31c8602be336b1fb977bccb012e83da7e4936", - "sha256:ea30a42dc94d42f2ba4d0f7c0ffb4f4f9baa1b23045910c0c32df9c9902cb272", - "sha256:ea513a25976d21733bff523e0ca836ef1679630ef4ad22d46987d04b372d57fc", - "sha256:ed19b74e81b10b592084a5ad1e70f845f0aacb57577018d31de064e71ffa267a", - "sha256:f5af52738e225fcc526ae64071b7e5342abe03f42e0e8918227b38c9aa711e28", - "sha256:fae37373155f5ef9b403ab48af5136ae9851151f7aacd9926251ab26b953118b" + "sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87", + "sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89", + "sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a", + "sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08", + "sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996", + "sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077", + "sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901", + "sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e", + "sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee", + "sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574", + "sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165", + "sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634", + "sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229", + "sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b", + "sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f", + "sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7", + "sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf", + "sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89", + "sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0", + "sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1", + "sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe", + "sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf", + "sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76", + "sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951", + "sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863", + "sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06", + "sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562", + "sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6", + "sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c", + "sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e", + "sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1", + "sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3", + "sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3", + "sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778", + "sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8", + "sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2", + "sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b", + "sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d", + "sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f", + "sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c", + "sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581", + "sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918", + "sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c", + "sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e", + "sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220", + "sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37", + "sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739", + "sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77", + "sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6", + "sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42", + "sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946", + "sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5", + "sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d", + "sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146", + "sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a", + "sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83", + "sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef", + "sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80", + "sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588", + "sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5", + "sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2", + "sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef", + "sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826", + "sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05", + "sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516", + "sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0", + "sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4", + "sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2", + "sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0", + "sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd", + "sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8", + "sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b", + "sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1", + "sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c" ], "markers": "python_version >= '3.7'", - "version": "==1.8.1" + "version": "==1.8.2" }, "zipp": { "hashes": [ - "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa", - "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766" + "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b", + "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556" ], "markers": "python_version >= '3.7'", - "version": "==3.11.0" + "version": "==3.15.0" } } } diff --git a/docker/Dockerfile b/docker/Dockerfile index 5198ee94..8ba5c993 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -ARG BASE_IMAGE=2.0 +ARG BASE_IMAGE=2.1 FROM unicef/donor-reporting-portal-backend:${BASE_IMAGE}-base diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base index a4f61595..10766734 100644 --- a/docker/Dockerfile.base +++ b/docker/Dockerfile.base @@ -1,4 +1,4 @@ -FROM python:3.9.13-alpine3.16 +FROM python:3.11.2-alpine3.17 ARG PIPENV_ARGS @@ -55,11 +55,11 @@ RUN apk add --no-cache --virtual .postgis-rundeps-edge \ RUN apk add --no-cache --virtual .donor_reporting_portal-build-deps \ freetype-dev \ fontconfig-dev \ - freetype-dev \ jpeg-dev \ lcms2-dev \ libffi-dev \ - libressl-dev \ + libc-dev \ + libressl \ linux-headers \ musl-dev \ openjpeg-dev \ diff --git a/docker/Dockerfile.flat b/docker/Dockerfile.flat index 8469969c..bf68c38c 100644 --- a/docker/Dockerfile.flat +++ b/docker/Dockerfile.flat @@ -1,4 +1,4 @@ -FROM python:3.9.13-alpine3.15 +FROM python:3.11.2-alpine3.17 ARG BUILD_DATE ARG PIPENV_ARGS @@ -41,11 +41,11 @@ RUN apk add --no-cache --virtual .postgis-rundeps-edge \ RUN apk add --no-cache --virtual .donor_reporting_portal-build-deps \ freetype-dev \ fontconfig-dev \ - freetype-dev \ jpeg-dev \ lcms2-dev \ libffi-dev \ - libressl-dev \ + libc-dev \ + libressl \ linux-headers \ musl-dev \ openjpeg-dev \ diff --git a/docker/Makefile b/docker/Makefile index 6c69f1a2..fdaf6a8d 100644 --- a/docker/Makefile +++ b/docker/Makefile @@ -2,7 +2,7 @@ DATABASE_URL?= DOCKER_PASS?= DOCKER_USER?= -TARGET?=2.0.0 +TARGET?=2.1.0 BASE?=$(shell echo "${TARGET}" | sed "s/\([0-9]\)\.\([0-9]\)\.\(.*\)/\1.\2/g" ) # below vars are used internally BUILD_OPTIONS?= diff --git a/src/donor_reporting_portal/api/serializers/utils.py b/src/donor_reporting_portal/api/serializers/utils.py index a4ea2b2a..699e89f3 100644 --- a/src/donor_reporting_portal/api/serializers/utils.py +++ b/src/donor_reporting_portal/api/serializers/utils.py @@ -1,3 +1,2 @@ -def getvalue(values, field_name): - items = [item['Value'] for item in values if item['Key'] == field_name] - return items[0] if items else None +def getvalue(instance, field_name): + return instance.get(field_name, 'N/A') diff --git a/src/donor_reporting_portal/api/views/sharepoint.py b/src/donor_reporting_portal/api/views/sharepoint.py index a0bfd38e..721f686f 100644 --- a/src/donor_reporting_portal/api/views/sharepoint.py +++ b/src/donor_reporting_portal/api/views/sharepoint.py @@ -1,6 +1,12 @@ +import csv + from django.conf import settings +from django.http import HttpResponse +from django.utils import timezone from rest_framework import viewsets +from rest_framework.decorators import action +from sharepoint_rest_api.config import SHAREPOINT_PAGE_SIZE from sharepoint_rest_api.utils import to_camel from sharepoint_rest_api.views.base import SharePointSearchViewSet from sharepoint_rest_api.views.settings_based import ( @@ -130,6 +136,30 @@ def get_filters(self, kwargs): class DRPSharePointSettingsSearchViewSet(DRPViewSet, DRPSharepointSearchViewSet, SharePointSettingsSearchViewSet): """DRP Search Viewset for settings based""" + @action(detail=False, methods=['get']) + def export(self, request, *args, **kwargs): + + exit_condition = True + response = HttpResponse(content_type='text/csv') + filename = 'drp_export_{}.csv'.format(timezone.now().date()) + response['Content-Disposition'] = f'attachment; filename="{filename}"' + + headers = ["CTNNumber", "CTNMOUNumber", "CTNMOUREference", "CTNSentToGAVIDate", "CTNFundsDueDate", + "CTNGAVIWBS", "CTNCountryName", "CTNVaccineType", "CTNPurchaseOrder", "CTNMaterialCode", + "CTNApprovalYear", "CTNPrepaidStatus", "CTNAllocationRound", "CTNVendor", "CTNUrgent", "Title"] + writer = csv.writer(response) + page = 1 + qs = self.get_queryset(page=page) + writer.writerow([str(item['Key']).replace('CTN', "") for item in qs[0] if item['Key'] in headers]) + while exit_condition: + for row in qs: + writer.writerow( + [str(item['Value']) if item['Value'] else '-' for item in row if item['Key'] in headers]) + exit_condition = page * SHAREPOINT_PAGE_SIZE < self.total_rows + page += 1 + qs = self.get_queryset(page=page) + return response + class DRPSharePointUrlSearchViewSet(DRPViewSet, DRPSharepointSearchViewSet, SharePointUrlSearchViewSet): """DRP Search Viewset for url based""" diff --git a/src/donor_reporting_portal/apps/roles/tasks.py b/src/donor_reporting_portal/apps/roles/tasks.py index 1312c24d..67bcedf8 100644 --- a/src/donor_reporting_portal/apps/roles/tasks.py +++ b/src/donor_reporting_portal/apps/roles/tasks.py @@ -206,7 +206,7 @@ def notify_donor(donor_code): @app.task def notify_gavi_donor(donor_code=settings.GAVI_DONOR_CODE): """notify GAVI and spawn one task per group""" - logger.info('Notifing GAVI') + logger.info('Notifying GAVI') for group_name in Group.objects.filter(name__startswith='MOU').values_list('name', flat=True): notify_gavi_donor_ctn.delay(donor_code, group_name) @@ -214,7 +214,7 @@ def notify_gavi_donor(donor_code=settings.GAVI_DONOR_CODE): @app.task def notify_gavi_donor_ctn(donor_code, group_name): """notify a GAVI group""" - logger.info(f'Notifing {donor_code}') + logger.info(f'Notifying {donor_code}') notifier = GaviNotifier(donor_code, group_name) notifier.notify() From ca3406829af8d1a11a9f63a444ca18ac8b3dbfe8 Mon Sep 17 00:00:00 2001 From: Domenico DiNicola Date: Fri, 24 Mar 2023 11:16:01 -0600 Subject: [PATCH 2/6] upgradeone --- .flake8 | 4 + .pre-commit-config.yaml | 20 + .travis.yml | 19 +- CHANGES | 5 +- Pipfile | 6 +- Pipfile.lock | 185 ++++++--- README.rst | 2 +- docker/entrypoint.sh | 8 +- manage.py | 3 +- pyproject.toml | 13 + setup.py | 41 +- src/donor_reporting_portal/__init__.py | 4 +- src/donor_reporting_portal/api/filters.py | 63 ++- src/donor_reporting_portal/api/permissions.py | 18 +- .../api/serializers/fields.py | 6 +- .../api/serializers/metadata.py | 13 +- .../api/serializers/sharepoint.py | 71 +++- .../api/serializers/userrole.py | 74 ++-- .../api/serializers/utils.py | 2 +- src/donor_reporting_portal/api/urls.py | 100 +++-- .../api/views/config.py | 12 +- .../api/views/metadata.py | 35 +- .../api/views/sharepoint.py | 78 ++-- .../api/views/static.py | 220 +++++------ .../api/views/userrole.py | 24 +- src/donor_reporting_portal/apps/core/apps.py | 4 +- .../apps/core/backends.py | 8 +- .../apps/core/checks.py | 16 +- .../commands/{db-isready.py => db_isready.py} | 52 +-- .../core/management/commands/init-setup.py | 85 ---- .../core/management/commands/init_setup.py | 81 ++++ ...eset-migrations.py => reset_migrations.py} | 31 +- .../apps/core/templatetags/core.py | 2 +- .../apps/report_metadata/admin.py | 44 +-- .../apps/report_metadata/apps.py | 4 +- .../migrations/0001_initial.py | 221 +++++++++-- .../migrations/0002_auto_20190920_0330.py | 7 +- .../migrations/0003_auto_20190920_0615.py | 9 +- .../migrations/0004_auto_20191011_0804.py | 15 +- .../migrations/0005_auto_20191014_0955.py | 18 +- .../migrations/0006_donor_us_gov.py | 9 +- .../migrations/0007_auto_20200205_1148.py | 7 +- .../migrations/0008_secondarydonor.py | 44 ++- .../migrations/0009_donor_active.py | 9 +- .../migrations/0010_drpmetadata.py | 61 ++- .../0011_remove_grant_business_areas.py | 7 +- .../migrations/0012_grant_business_areas.py | 15 +- .../migrations/0013_auto_20220608_1003.py | 11 +- .../apps/report_metadata/models.py | 68 ++-- .../notifications/notify_donor.py | 6 +- .../notifications/notify_gavi.py | 6 +- .../notifications/notify_urgent_gavi.py | 6 +- .../apps/report_metadata/synchronizers.py | 67 ++-- .../apps/report_metadata/tasks.py | 4 +- .../apps/roles/admin.py | 12 +- src/donor_reporting_portal/apps/roles/apps.py | 4 +- .../apps/roles/migrations/0001_initial.py | 68 +++- .../migrations/0002_auto_20190920_0339.py | 11 +- .../migrations/0003_auto_20191007_1102.py | 11 +- .../migrations/0004_auto_20200220_1101.py | 23 +- .../migrations/0005_auto_20200302_1609.py | 18 +- .../0006_userrole_notification_period.py | 19 +- ...0007_alter_userrole_notification_period.py | 19 +- .../migrations/0008_auto_20220128_1054.py | 10 +- .../migrations/0009_auto_20220511_1724.py | 35 +- .../0010_alter_userrole_secondary_donor.py | 18 +- .../apps/roles/models.py | 92 +++-- .../roles/notifications/access_grant_email.py | 6 +- .../apps/roles/tasks.py | 173 ++++---- .../apps/sharepoint/admin.py | 6 +- .../apps/sharepoint/apps.py | 4 +- .../sharepoint/migrations/0001_initial.py | 109 +++-- .../migrations/0002_auto_20191105_0444.py | 27 +- .../migrations/0003_auto_20191105_1127.py | 15 +- .../migrations/0004_auto_20191105_1400.py | 15 +- ...repointlibrary_require_donor_permission.py | 11 +- .../migrations/0006_auto_20200124_1045.py | 13 +- .../migrations/0007_auto_20200129_1227.py | 89 +++-- .../migrations/0008_auto_20200206_1518.py | 13 +- .../migrations/0009_auto_20200220_0939.py | 13 +- .../migrations/0010_sharepointgroup.py | 41 +- .../migrations/0011_sharepointgroup_libs.py | 13 +- .../apps/sharepoint/models.py | 10 +- src/donor_reporting_portal/config/celery.py | 6 +- src/donor_reporting_portal/config/settings.py | 374 +++++++++--------- src/donor_reporting_portal/config/urls.py | 22 +- .../libs/impersonate.py | 2 +- ...f18ae6b758e8014a24c7fa039e91.response.json | 18 +- tests/api/test_config.py | 4 +- tests/api/test_metadata.py | 32 +- tests/api/test_security.py | 8 +- tests/api/test_sharepoint.py | 59 ++- tests/api_checker.py | 27 +- tests/apps/test_backends.py | 16 +- tests/apps/test_commands.py | 35 +- tests/apps/test_metadata.py | 12 +- tests/apps/test_roles.py | 15 +- tests/apps/test_security.py | 2 +- tests/apps/test_sharepoint.py | 2 +- tests/apps/test_signals.py | 10 +- tests/apps/test_synchronizers.py | 2 +- tests/apps/test_tasks.py | 2 +- tests/apps/test_wsgi.py | 1 + tests/conftest.py | 8 +- tests/factories/metadata.py | 10 +- tests/factories/roles.py | 20 +- tests/factories/sharepoint.py | 9 +- tests/perms.py | 32 +- tests/vcrpy.py | 14 +- tox.ini | 11 +- 110 files changed, 2161 insertions(+), 1433 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 pyproject.toml rename src/donor_reporting_portal/apps/core/management/commands/{db-isready.py => db_isready.py} (57%) delete mode 100644 src/donor_reporting_portal/apps/core/management/commands/init-setup.py create mode 100644 src/donor_reporting_portal/apps/core/management/commands/init_setup.py rename src/donor_reporting_portal/apps/core/management/commands/{reset-migrations.py => reset_migrations.py} (60%) diff --git a/.flake8 b/.flake8 index 16ca1ec2..0809a4ef 100644 --- a/.flake8 +++ b/.flake8 @@ -3,3 +3,7 @@ max-line-length = 120 exclude = */migrations, + +ignore = + W503, + # line break before binary operator diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..5ff38c8f --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,20 @@ +repos: + - repo: https://github.com/PyCQA/isort + rev: 5.12.0 + hooks: + - id: isort + stages: [commit] + - repo: https://github.com/ambv/black + rev: 23.1.0 + hooks: + - id: black + args: [--config=backend/pyproject.toml] + exclude: "migrations|snapshots" + stages: [commit] + - repo: https://github.com/PyCQA/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + args: [--config=backend/.flake8] + additional_dependencies: [flake8-bugbear==22.9.23] + stages: [ commit ] diff --git a/.travis.yml b/.travis.yml index c5e7b210..59f804be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ -dist: xenial +dist: jammy language: python python: - - 3.9 + - "3.11" env: global: @@ -12,17 +12,18 @@ env: - INSIGHT_URL=https://uniapis.unicef.org/biapi/v1/ - SHAREPOINT_CONNECTION=user jobs: - - DJANGO=4.0 + - DJANGO=4.1 + +services: + - postgres addons: - postgresql: "10" apt: + sources: + - sourceline: 'ppa:chris-lea/redis-server' packages: - - postgresql-10 - - postgresql-client-10 - -services: - - redis + - redis-tools + - redis-server install: - pip install tox codecov diff --git a/CHANGES b/CHANGES index 081ebc3a..8b440646 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,7 @@ Release 2.1 * updated to python 3.11 * updated to django 4.2 * updated office365 2.4 +* introduced black and precommit Release 2.0.3 @@ -189,7 +190,7 @@ Release 0.6 ---------------- * handled not by donor libraries * allowed download of different file extentions (other than pdf) -* tweaked init-setup +* tweaked init_setup * tweaked static-metadata * added retracted field * added tenant model @@ -231,7 +232,7 @@ Release 0.2 * increased coverage * added static endpoint (/api/metadata/static/) * added business area endpoint (/api/roles/business-area/) -* tweaked init-setup +* tweaked init_setup * added my profile API diff --git a/Pipfile b/Pipfile index 901b6167..7abbe9bd 100644 --- a/Pipfile +++ b/Pipfile @@ -4,6 +4,7 @@ url = "https://pypi.org/simple" verify_ssl = true [dev-packages] +black = "*" coverage = "*" drf-api-checker = "*" factory-boy = "*" @@ -14,6 +15,7 @@ ipython = "*" isort = "*" mock = "*" pdbpp = "*" +pre_commit = "*" pytest = "*" pytest-coverage = "*" pytest-django = "*" @@ -53,7 +55,7 @@ djangorestframework-xml = "*" django-rest-framework-social-oauth2 = "*" gunicorn = "*" newrelic = "*" -psycopg2-binary = "*" +psycopg2-binary = "*" # psycopg = "*" sentry-sdk = "*" requests = "*" sharepoint-rest-api = "*" @@ -68,4 +70,4 @@ uwsgi = "*" django-picklefield = "*" [requires] -python_version = "3.9" +python_version = "3.11" diff --git a/Pipfile.lock b/Pipfile.lock index 1fa0c748..6788b409 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "e00111ec5f0549cde944b6cf6e28e046c5cd65272524a3f15e95dfbafec42cd1" + "sha256": "14d2d0ceb9e4792d926529afd49fd90432a1beaa6205bdf0b3f9b1eb20c3a613" }, "pipfile-spec": 6, "requires": { - "python_version": "3.9" + "python_version": "3.11" }, "sources": [ { @@ -254,32 +254,28 @@ }, "cryptography": { "hashes": [ - "sha256:103e8f7155f3ce2ffa0049fe60169878d47a4364b277906386f8de21c9234aa1", - "sha256:23df8ca3f24699167daf3e23e51f7ba7334d504af63a94af468f468b975b7dd7", - "sha256:2725672bb53bb92dc7b4150d233cd4b8c59615cd8288d495eaa86db00d4e5c06", - "sha256:30b1d1bfd00f6fc80d11300a29f1d8ab2b8d9febb6ed4a38a76880ec564fae84", - "sha256:35d658536b0a4117c885728d1a7032bdc9a5974722ae298d6c533755a6ee3915", - "sha256:50cadb9b2f961757e712a9737ef33d89b8190c3ea34d0fb6675e00edbe35d074", - "sha256:5f8c682e736513db7d04349b4f6693690170f95aac449c56f97415c6980edef5", - "sha256:6236a9610c912b129610eb1a274bdc1350b5df834d124fa84729ebeaf7da42c3", - "sha256:788b3921d763ee35dfdb04248d0e3de11e3ca8eb22e2e48fef880c42e1f3c8f9", - "sha256:8bc0008ef798231fac03fe7d26e82d601d15bd16f3afaad1c6113771566570f3", - "sha256:8f35c17bd4faed2bc7797d2a66cbb4f986242ce2e30340ab832e5d99ae60e011", - "sha256:b49a88ff802e1993b7f749b1eeb31134f03c8d5c956e3c125c75558955cda536", - "sha256:bc0521cce2c1d541634b19f3ac661d7a64f9555135e9d8af3980965be717fd4a", - "sha256:bc5b871e977c8ee5a1bbc42fa8d19bcc08baf0c51cbf1586b0e87a2694dde42f", - "sha256:c43ac224aabcbf83a947eeb8b17eaf1547bce3767ee2d70093b461f31729a480", - "sha256:d15809e0dbdad486f4ad0979753518f47980020b7a34e9fc56e8be4f60702fac", - "sha256:d7d84a512a59f4412ca8549b01f94be4161c94efc598bf09d027d67826beddc0", - "sha256:e029b844c21116564b8b61216befabca4b500e6816fa9f0ba49527653cae2108", - "sha256:e8a0772016feeb106efd28d4a328e77dc2edae84dfbac06061319fdb669ff828", - "sha256:e944fe07b6f229f4c1a06a7ef906a19652bdd9fd54c761b0ff87e83ae7a30354", - "sha256:eb40fe69cfc6f5cdab9a5ebd022131ba21453cf7b8a7fd3631f45bbf52bed612", - "sha256:fa507318e427169ade4e9eccef39e9011cdc19534f55ca2f36ec3f388c1f70f3", - "sha256:ffd394c7896ed7821a6d13b24657c6a34b6e2650bd84ae063cf11ccffa4f1a97" + "sha256:14da8c26755ffa5c7863ffa5e8b87cb9596a21b6c34852cb19e0f48c226c64fb", + "sha256:168ded448fb5d82dfa911156ab8b13b1716de65bd50ff977f4657643f998fa05", + "sha256:22e63fb48e2615cfab5a9c4bb457d35e7ae03ea8593996bfbe257e78244d12d0", + "sha256:23c42c59c2b5b9ddc6a85b5c46b8fabc4d63a1714f4dbea4bf20d25690bf2365", + "sha256:34f502619964210939bb7ee7cd5df53178534eb08d3526f941695a8f7aa0efe4", + "sha256:43089be365c0ca4235c6e4e781f3bc125bc1fff576c9dd22cdfb585309b9bb9d", + "sha256:6b36e2864e04c82634879c7e7aad48824b1847fdb06b64cd410d2ec5e51d1b31", + "sha256:7162ae4530958114ca2eee30a56eca46527def33493f622f059dc2e825fd0913", + "sha256:71cb346b9dd1537102e7466a2d629385b01847f8d96cd7405f0e717d91cebc8e", + "sha256:722cfddae79684166840be2cbbae154f44a455519e644b60bf274a50ccb834db", + "sha256:754dc5ab648113dc54197f242db43234a04e4d61193fb5d3ebb42bd569dca571", + "sha256:7cc9fc3ffcb766c313ed0515d77d0deabb4f36bdcff3a9f115c43e5ec611b82a", + "sha256:b05c9f25a1ea42e427085230815bbdebe15a53bb6163c4c06022e5630645046b", + "sha256:e5855a80c77565fe2464e88e0095764e25d8ddb2d24df2b1d31773e80be94435", + "sha256:e917a07094217edeefe8f6ea960b45d7aab650b982e4209da078332cc9d3ac3a", + "sha256:f2c4134d29cdce0735c16abf48fa8435f001a7b0031e68dd9a9ee1c80a29374a", + "sha256:f421f6777592eb199ca8abac7c20b9ecef27c50ad63546e6c614b29771b46d0d", + "sha256:fafa997b9e6818db333ded4b379f5b7679b48bd88ac878428cea2a1aa6e79fd8", + "sha256:fba36ec552794a06a07ac8bdc5ad83a587f6959d98547f373d401975d55c7c9e" ], "markers": "python_version >= '3.6'", - "version": "==39.0.2" + "version": "==40.0.0" }, "defusedxml": { "hashes": [ @@ -849,11 +845,11 @@ }, "tzdata": { "hashes": [ - "sha256:2b88858b0e3120792a3c0635c23daf36a7d7eeeca657c323da299d2094402a0d", - "sha256:fe5f866eddd8b96e9fcba978f8e503c909b19ea7efda11e52e39494bad3a7bfa" + "sha256:905ae9e6744dd9ef5ce94d2aaa2dd00282fee38b670b2133407f23c388f110a1", + "sha256:c3b51b235b07f9f1889089c2264bcbeaaba260a63f89bea09e350ea4205eb95f" ], "markers": "python_version >= '2'", - "version": "==2022.7" + "version": "==2023.2" }, "unicef-djangolib": { "hashes": [ @@ -1098,6 +1094,37 @@ "markers": "python_full_version >= '3.6.0'", "version": "==4.12.0" }, + "black": { + "hashes": [ + "sha256:0052dba51dec07ed029ed61b18183942043e00008ec65d5028814afaab9a22fd", + "sha256:0680d4380db3719ebcfb2613f34e86c8e6d15ffeabcf8ec59355c5e7b85bb555", + "sha256:121ca7f10b4a01fd99951234abdbd97728e1240be89fde18480ffac16503d481", + "sha256:162e37d49e93bd6eb6f1afc3e17a3d23a823042530c37c3c42eeeaf026f38468", + "sha256:2a951cc83ab535d248c89f300eccbd625e80ab880fbcfb5ac8afb5f01a258ac9", + "sha256:2bf649fda611c8550ca9d7592b69f0637218c2369b7744694c5e4902873b2f3a", + "sha256:382998821f58e5c8238d3166c492139573325287820963d2f7de4d518bd76958", + "sha256:49f7b39e30f326a34b5c9a4213213a6b221d7ae9d58ec70df1c4a307cf2a1580", + "sha256:57c18c5165c1dbe291d5306e53fb3988122890e57bd9b3dcb75f967f13411a26", + "sha256:7a0f701d314cfa0896b9001df70a530eb2472babb76086344e688829efd97d32", + "sha256:8178318cb74f98bc571eef19068f6ab5613b3e59d4f47771582f04e175570ed8", + "sha256:8b70eb40a78dfac24842458476135f9b99ab952dd3f2dab738c1881a9b38b753", + "sha256:9880d7d419bb7e709b37e28deb5e68a49227713b623c72b2b931028ea65f619b", + "sha256:9afd3f493666a0cd8f8df9a0200c6359ac53940cbde049dcb1a7eb6ee2dd7074", + "sha256:a29650759a6a0944e7cca036674655c2f0f63806ddecc45ed40b7b8aa314b651", + "sha256:a436e7881d33acaf2536c46a454bb964a50eff59b21b51c6ccf5a40601fbef24", + "sha256:a59db0a2094d2259c554676403fa2fac3473ccf1354c1c63eccf7ae65aac8ab6", + "sha256:a8471939da5e824b891b25751955be52ee7f8a30a916d570a5ba8e0f2eb2ecad", + "sha256:b0bd97bea8903f5a2ba7219257a44e3f1f9d00073d6cc1add68f0beec69692ac", + "sha256:b6a92a41ee34b883b359998f0c8e6eb8e99803aa8bf3123bf2b2e6fec505a221", + "sha256:bb460c8561c8c1bec7824ecbc3ce085eb50005883a6203dcfb0122e95797ee06", + "sha256:bfffba28dc52a58f04492181392ee380e95262af14ee01d4bc7bb1b1c6ca8d27", + "sha256:c1c476bc7b7d021321e7d93dc2cbd78ce103b84d5a4cf97ed535fbc0d6660648", + "sha256:c91dfc2c2a4e50df0026f88d2215e166616e0c80e86004d0003ece0488db2739", + "sha256:e6663f91b6feca5d06f2ccd49a10f254f9298cc1f7f49c46e498a0771b507104" + ], + "index": "pypi", + "version": "==23.1.0" + }, "cachetools": { "hashes": [ "sha256:13dfddc7b8df938c21a940dfa6557ce6e94a2f1cdfa58eb90c805721d58f2c14", @@ -1114,6 +1141,14 @@ "markers": "python_version >= '3.6'", "version": "==2022.12.7" }, + "cfgv": { + "hashes": [ + "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426", + "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736" + ], + "markers": "python_full_version >= '3.6.1'", + "version": "==3.3.1" + }, "chardet": { "hashes": [ "sha256:0d62712b956bc154f85fb0a266e2a3c5913c2967e00348701b32411d6def31e5", @@ -1203,6 +1238,14 @@ "markers": "python_full_version >= '3.7.0'", "version": "==3.1.0" }, + "click": { + "hashes": [ + "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e", + "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.3" + }, "colorama": { "hashes": [ "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", @@ -1339,11 +1382,11 @@ }, "faker": { "hashes": [ - "sha256:2deeee8fed3d1b8ae5f87d172d4569ddc859aab8693f7cd68eddc5d20400563a", - "sha256:e7c058e1f360f245f265625b32d3189d7229398ad80a8b6bac459891745de052" + "sha256:4c98c42984db54be2246d40e6407cd983db7b1511a70eaff64c3f383a51bace6", + "sha256:9bd71833146b844d848791b79720c7806108130c9603c7074123b3f77b4e97a1" ], "markers": "python_version >= '3.7'", - "version": "==18.3.0" + "version": "==18.3.1" }, "fancycompleter": { "hashes": [ @@ -1354,11 +1397,11 @@ }, "filelock": { "hashes": [ - "sha256:3199fd0d3faea8b911be52b663dfccceb84c95949dd13179aa21436d1a79c4ce", - "sha256:e90b34656470756edf8b19656785c5fea73afa1953f3e1b0d645cef11cab3182" + "sha256:6d332dc5c896f18ba93a21d987155e97c434a96d3fe4042ca70d0b3b46e3b470", + "sha256:9fc1734dbddcdcd4aaa02c160dd94db5272b92dfa859b44ec8df28e160b751f0" ], "markers": "python_version >= '3.7'", - "version": "==3.10.0" + "version": "==3.10.4" }, "flake8": { "hashes": [ @@ -1384,6 +1427,14 @@ "index": "pypi", "version": "==1.2.2" }, + "identify": { + "hashes": [ + "sha256:f0faad595a4687053669c112004178149f6c326db71ee999ae4636685753ad2f", + "sha256:f7a93d6cf98e29bd07663c60728e7a4057615068d7a639d132dc883b2d54d31e" + ], + "markers": "python_version >= '3.7'", + "version": "==2.5.22" + }, "idna": { "hashes": [ "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", @@ -1400,14 +1451,6 @@ "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.4.1" }, - "importlib-metadata": { - "hashes": [ - "sha256:43ce9281e097583d758c2c708c4376371261a02c34682491a8e98352365aad20", - "sha256:ff80f3b5394912eb1b108fcfd444dc78b7f1f3e16b16188054bd01cb9cb86f09" - ], - "markers": "python_version < '3.10'", - "version": "==6.1.0" - }, "iniconfig": { "hashes": [ "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", @@ -1608,6 +1651,22 @@ "markers": "python_version >= '3.7'", "version": "==6.0.4" }, + "mypy-extensions": { + "hashes": [ + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, + "nodeenv": { + "hashes": [ + "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e", + "sha256:e0e7f7dfb85fc5394c6fe1e8fa98131a2473e04311a45afb6508f7cf1836fa2b" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", + "version": "==1.7.0" + }, "packaging": { "hashes": [ "sha256:714ac14496c3e68c99c29b00845f7a2b85f3bb6f1078fd9f72fd20f0570002b2", @@ -1624,6 +1683,14 @@ "markers": "python_version >= '3.6'", "version": "==0.8.3" }, + "pathspec": { + "hashes": [ + "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687", + "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293" + ], + "markers": "python_version >= '3.7'", + "version": "==0.11.1" + }, "pdbpp": { "hashes": [ "sha256:79580568e33eb3d6f6b462b1187f53e10cd8e4538f7d31495c9181e2cf9665d1", @@ -1663,6 +1730,14 @@ "markers": "python_version >= '3.6'", "version": "==1.0.0" }, + "pre-commit": { + "hashes": [ + "sha256:818f0d998059934d0f81bb3667e3ccdc32da6ed7ccaac33e43dc231561ddaaa9", + "sha256:f712d3688102e13c8e66b7d7dbd8934a6dda157e58635d89f7d6fecdca39ce8a" + ], + "index": "pypi", + "version": "==3.2.0" + }, "prompt-toolkit": { "hashes": [ "sha256:23ac5d50538a9a38c8bde05fecb47d0b403ecd0662857a86f886f798563d5b9b", @@ -1870,6 +1945,14 @@ "index": "pypi", "version": "==0.23.1" }, + "setuptools": { + "hashes": [ + "sha256:2ee892cd5f29f3373097f5a814697e397cf3ce313616df0af11231e2ad118077", + "sha256:b78aaa36f6b90a074c1fa651168723acbf45d14cb1196b6f02c0fd07f17623b2" + ], + "markers": "python_version >= '3.7'", + "version": "==67.6.0" + }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", @@ -1979,14 +2062,6 @@ "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.10.2" }, - "tomli": { - "hashes": [ - "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc", - "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f" - ], - "markers": "python_version < '3.11'", - "version": "==2.0.1" - }, "tox": { "hashes": [ "sha256:52c92a96e2c3fd47c5301e9c26f5a871466133d5376958c1ed95ef4ff4629cbe", @@ -2231,14 +2306,6 @@ ], "markers": "python_version >= '3.7'", "version": "==1.8.2" - }, - "zipp": { - "hashes": [ - "sha256:112929ad649da941c23de50f356a2b5570c954b65150642bccdd66bf194d224b", - "sha256:48904fc76a60e542af151aded95726c1a5c34ed43ab4134b597665c86d7ad556" - ], - "markers": "python_version >= '3.7'", - "version": "==3.15.0" } } } diff --git a/README.rst b/README.rst index 96778fe7..0c09442c 100644 --- a/README.rst +++ b/README.rst @@ -36,7 +36,7 @@ Troubleshoot Get Started -------------------- * populate your .env file from template .env_template -* python manage.py init-setup --all +* python manage.py init_setup --all Development Release diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 17726551..4f0b8db2 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -25,7 +25,7 @@ elif [[ "$*" == "beat" ]];then --pidfile run/celerybeat.pid elif [[ "$*" == "w2" ]];then - django-admin db-isready --wait --timeout 60 + django-admin db_isready --wait --timeout 60 elif [[ "$*" == "donor_reporting_portal" ]];then rm -f /var/donor_reporting_portal/run/* @@ -33,11 +33,11 @@ elif [[ "$*" == "donor_reporting_portal" ]];then django-admin diffsettings --output unified # django-admin makemigrations --check --dry-run - django-admin db-isready --wait --timeout 60 + django-admin db_isready --wait --timeout 60 django-admin check --deploy django-admin remove_stale_contenttypes --noinput - django-admin init-setup --all --verbosity 2 - django-admin db-isready --wait --timeout 300 + django-admin init_setup --all --verbosity 2 + django-admin db_isready --wait --timeout 300 echo "uwsgi --static-map ${STATIC_URL}=${STATIC_ROOT}" # exec gosu donor_reporting_portal uwsgi --static-map ${STATIC_URL}=${STATIC_ROOT} # newrelic-admin run-program diff --git a/manage.py b/manage.py index 262d9385..e901e127 100755 --- a/manage.py +++ b/manage.py @@ -4,12 +4,11 @@ SRC = os.path.abspath("src") sys.path.insert(0, SRC) -if sys.argv[1] == 'test': +if sys.argv[1] == "test": os.chdir(os.path.join(SRC, "donor_reporting_portal")) if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "donor_reporting_portal.config.settings") from django.core.management import execute_from_command_line diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..5089350d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,13 @@ +[tool.black] +line-length = 120 +exclude = ''' +/( + \.git + | \.tox + | \.venv + | _build + | build + | dist + | migrations +)/ +''' diff --git a/setup.py b/setup.py index 5a9ee9f4..802527e9 100644 --- a/setup.py +++ b/setup.py @@ -8,14 +8,14 @@ from setuptools import find_packages, setup ROOT = os.path.realpath(os.path.dirname(__file__)) -init = os.path.join(ROOT, 'src', 'donor_reporting_portal', '__init__.py') -_version_re = re.compile(r'__version__\s+=\s+(.*)') -_name_re = re.compile(r'NAME\s+=\s+(.*)') +init = os.path.join(ROOT, "src", "donor_reporting_portal", "__init__.py") +_version_re = re.compile(r"__version__\s+=\s+(.*)") +_name_re = re.compile(r"NAME\s+=\s+(.*)") -sys.path.insert(0, os.path.join(ROOT, 'src')) +sys.path.insert(0, os.path.join(ROOT, "src")) -with open(init, 'rb') as f: - content = f.read().decode('utf-8') +with open(init, "rb") as f: + content = f.read().decode("utf-8") VERSION = str(ast.literal_eval(_version_re.search(content).group(1))) NAME = str(ast.literal_eval(_name_re.search(content).group(1))) @@ -24,24 +24,23 @@ setup( name=NAME, version=VERSION, - author='UNICEF', - author_email='donor_reporting_portal@unicef.org', - url='', - description='', - long_description=open(os.path.join(ROOT, 'README.rst')).read(), - package_dir={'': 'src'}, - packages=find_packages('src'), + author="UNICEF", + author_email="donor_reporting_portal@unicef.org", + url="", + description="", + long_description=open(os.path.join(ROOT, "README.rst")).read(), + package_dir={"": "src"}, + packages=find_packages("src"), zip_safe=False, dependency_links=list(dependency_links), - license='BSD', + license="BSD", include_package_data=True, classifiers=[ - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Framework :: Django', - 'Framework :: Django :: 4.0', - 'Framework :: Flake8', + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.11", + "Framework :: Django", + "Framework :: Django :: 4.0", + "Framework :: Flake8", ], ) diff --git a/src/donor_reporting_portal/__init__.py b/src/donor_reporting_portal/__init__.py index 08b6f9e0..f44b2f68 100644 --- a/src/donor_reporting_portal/__init__.py +++ b/src/donor_reporting_portal/__init__.py @@ -1,2 +1,2 @@ -NAME = 'donor-reporting-portal' -VERSION = __version__ = '2.0.3' +NAME = "donor-reporting-portal" +VERSION = __version__ = "2.0.3" diff --git a/src/donor_reporting_portal/api/filters.py b/src/donor_reporting_portal/api/filters.py index ec429249..bbb11bb6 100644 --- a/src/donor_reporting_portal/api/filters.py +++ b/src/donor_reporting_portal/api/filters.py @@ -16,45 +16,41 @@ class GroupFilter(filters.FilterSet): - class Meta: model = Group fields = { - 'name': ['exact', 'icontains'], + "name": ["exact", "icontains"], } class UserFilter(filters.FilterSet): - class Meta: model = get_user_model() fields = { - 'username': ['exact', 'icontains'], - 'last_name': ['exact', 'icontains'], - 'first_name': ['exact', 'icontains'], + "username": ["exact", "icontains"], + "last_name": ["exact", "icontains"], + "first_name": ["exact", "icontains"], } class UserRoleFilter(filters.FilterSet): - class Meta: model = UserRole fields = { - 'donor': ['exact', 'in'], - 'group': ['exact', 'in'], - 'user': ['exact', 'in'], - 'secondary_donor': ['exact', 'in'], - 'notification_period': ['exact', 'in'] + "donor": ["exact", "in"], + "group": ["exact", "in"], + "user": ["exact", "in"], + "secondary_donor": ["exact", "in"], + "notification_period": ["exact", "in"], } class BusinessAreaFilter(filters.FilterSet): - class Meta: model = BusinessArea fields = { - 'region': ['exact', 'in'], - 'country': ['exact', 'in'], + "region": ["exact", "in"], + "country": ["exact", "in"], } @@ -62,7 +58,7 @@ class ThemeFilter(filters.FilterSet): class Meta: model = Theme fields = { - 'name': ['exact', 'in'], + "name": ["exact", "in"], } @@ -70,10 +66,10 @@ class DonorFilter(filters.FilterSet): class Meta: model = Donor fields = { - 'name': ['exact', 'in'], - 'code': ['exact', 'in'], - 'us_gov': ['exact'], - 'active': ['exact'], + "name": ["exact", "in"], + "code": ["exact", "in"], + "us_gov": ["exact"], + "active": ["exact"], } @@ -81,8 +77,8 @@ class ExternalGrantFilter(filters.FilterSet): class Meta: model = ExternalGrant fields = { - 'code': ['exact', 'in'], - 'donor': ['exact', 'in'], + "code": ["exact", "in"], + "donor": ["exact", "in"], } @@ -92,13 +88,13 @@ class GrantFilter(filters.FilterSet): class Meta: model = Grant fields = { - 'donor': ['exact'], - 'code': ['exact', 'in'], - 'year': ['exact', 'in'], - 'theme': ['exact', 'in'], - 'business_areas': ['exact', 'in'], - 'expiry_date': ['lte', 'gte', 'gt', 'lt'], - 'financial_close_date': ['lte', 'gte', 'gt', 'lt'], + "donor": ["exact"], + "code": ["exact", "in"], + "year": ["exact", "in"], + "theme": ["exact", "in"], + "business_areas": ["exact", "in"], + "expiry_date": ["lte", "gte", "gt", "lt"], + "financial_close_date": ["lte", "gte", "gt", "lt"], } @@ -108,16 +104,15 @@ class SecondaryDonorFilter(filters.FilterSet): class Meta: model = SecondaryDonor fields = { - 'name': ['exact', 'in'], - 'code': ['exact', 'in'], + "name": ["exact", "in"], + "code": ["exact", "in"], } class DRPMetadataFilter(filters.FilterSet): - class Meta: model = DRPMetadata fields = { - 'category': ['exact', 'in'], - 'audience': ['exact', 'in'], + "category": ["exact", "in"], + "audience": ["exact", "in"], } diff --git a/src/donor_reporting_portal/api/permissions.py b/src/donor_reporting_portal/api/permissions.py index f006f418..8865dad7 100644 --- a/src/donor_reporting_portal/api/permissions.py +++ b/src/donor_reporting_portal/api/permissions.py @@ -2,28 +2,27 @@ from donor_reporting_portal.apps.report_metadata.models import Donor, SecondaryDonor -NO_DONOR = 'Various' +NO_DONOR = "Various" class DonorPermission(permissions.BasePermission): - @staticmethod def _get_instance(view, query_params, user, mapping_dict, model): instance = None for field_name, qs_param in mapping_dict.items(): values = view.kwargs.get(qs_param, query_params.get(qs_param, None)) - values = values.split(',') if values else [] - filter_dict = {field_name + '__in': values, 'user_roles__user__pk': user.pk} + values = values.split(",") if values else [] + filter_dict = {field_name + "__in": values, "user_roles__user__pk": user.pk} if not instance: instance = model.objects.filter(**filter_dict).first() return instance def _get_donor(self, view, query_params, user): - mapping_dict = {'id': 'donor_id', 'code': 'donor_code'} + mapping_dict = {"id": "donor_id", "code": "donor_code"} return self._get_instance(view, query_params, user, mapping_dict, Donor) def _get_secondary_donor(self, view, query_params, user): - mapping_dict = {'id': 'secondary_donor_id', 'code': 'secondary_donor_code'} + mapping_dict = {"id": "secondary_donor_id", "code": "secondary_donor_code"} return self._get_instance(view, query_params, user, mapping_dict, SecondaryDonor) def has_permission(self, request, view): @@ -33,8 +32,11 @@ def has_permission(self, request, view): donor = self._get_donor(view, request.query_params, user) secondary_donor = self._get_secondary_donor(view, request.query_params, user) context_object = (donor, secondary_donor) if donor and secondary_donor else donor - if donor and user.has_perm('roles.can_view_all_donors') or \ - user.has_perm('report_metadata.view_donor', context_object): + if ( + donor + and user.has_perm("roles.can_view_all_donors") + or user.has_perm("report_metadata.view_donor", context_object) + ): return True return False diff --git a/src/donor_reporting_portal/api/serializers/fields.py b/src/donor_reporting_portal/api/serializers/fields.py index b0e64e93..57f0fa03 100644 --- a/src/donor_reporting_portal/api/serializers/fields.py +++ b/src/donor_reporting_portal/api/serializers/fields.py @@ -13,15 +13,15 @@ def get_attribute(self, instance): class SearchMultiSharePointField(serializers.ReadOnlyField): def get_attribute(self, instance): attrs = super().get_attribute(instance) - return list(filter(None, attrs.split(';'))) if attrs else [] + return list(filter(None, attrs.split(";"))) if attrs else [] class DRPSearchSharePointField(SearchSharePointField): - prefix = 'DRP' + prefix = "DRP" class CTNSearchSharePointField(SearchSharePointField): - prefix = 'CTN' + prefix = "CTN" class DRPSearchMultiSharePointField(SearchMultiSharePointField, DRPSearchSharePointField): diff --git a/src/donor_reporting_portal/api/serializers/metadata.py b/src/donor_reporting_portal/api/serializers/metadata.py index 6f851d77..734a4bb1 100644 --- a/src/donor_reporting_portal/api/serializers/metadata.py +++ b/src/donor_reporting_portal/api/serializers/metadata.py @@ -13,14 +13,13 @@ class ThemeSerializer(serializers.ModelSerializer): class Meta: model = Theme - fields = '__all__' + fields = "__all__" class DonorSerializer(serializers.ModelSerializer): - class Meta: model = Donor - fields = '__all__' + fields = "__all__" class DonorSecondaryDonorSerializer(DonorSerializer): @@ -34,22 +33,22 @@ def get_secondary_donors(self, obj): class ExternalGrantSerializer(serializers.ModelSerializer): class Meta: model = ExternalGrant - fields = '__all__' + fields = "__all__" class GrantSerializer(serializers.ModelSerializer): class Meta: model = Grant - fields = '__all__' + fields = "__all__" class SecondaryDonorSerializer(serializers.ModelSerializer): class Meta: model = SecondaryDonor - fields = '__all__' + fields = "__all__" class DRPMetadataSerializer(serializers.ModelSerializer): class Meta: model = DRPMetadata - fields = ('category', 'code', 'description', 'audience') + fields = ("category", "code", "description", "audience") diff --git a/src/donor_reporting_portal/api/serializers/sharepoint.py b/src/donor_reporting_portal/api/serializers/sharepoint.py index bf771281..9acd5b15 100644 --- a/src/donor_reporting_portal/api/serializers/sharepoint.py +++ b/src/donor_reporting_portal/api/serializers/sharepoint.py @@ -23,15 +23,14 @@ class SharePointGroupSerializer(serializers.ModelSerializer): - libs = serializers.SlugRelatedField(slug_field='name', read_only=True, many=True) + libs = serializers.SlugRelatedField(slug_field="name", read_only=True, many=True) class Meta: model = SharePointGroup - fields = '__all__' + fields = "__all__" class DRPSerializerMixin(serializers.Serializer): - report_generated_by = SharePointPropertyField() year = SharePointPropertyField() donor = SharePointPropertyField() @@ -58,7 +57,7 @@ class DRPSerializerMixin(serializers.Serializer): def get_is_new(self, obj): try: - modified = parse(obj.properties['Modified'][:19], ignoretz=True) + modified = parse(obj.properties["Modified"][:19], ignoretz=True) day_difference = (datetime.now() - modified).days return day_difference <= 3 except (TypeError, ValueError): @@ -66,8 +65,8 @@ def get_is_new(self, obj): def get_download_url(self, obj): base_url = super().get_download_url(obj) - donor_code = obj.properties['DonorCode'].replace(';', ',') - return f'{base_url}?donor_code={donor_code}' + donor_code = obj.properties["DonorCode"].replace(";", ",") + return f"{base_url}?donor_code={donor_code}" class DRPSharePointUrlSerializer(DRPSerializerMixin, SharePointUrlSerializer): @@ -89,8 +88,12 @@ class DRPSharePointBaseSerializer(serializers.Serializer): is_new = serializers.SerializerMethodField() download_url = serializers.SerializerMethodField() + export_headers = [ + "Title", + ] + def get_is_new(self, obj): - modified = getvalue(obj, 'DRPModified') + modified = getvalue(obj, "DRPModified") if modified: try: @@ -101,17 +104,17 @@ def get_is_new(self, obj): def get_download_url(self, obj): try: - path = getvalue(obj, 'Path') - directories = path.split('/') - relative_url = reverse('sharepoint_rest_api:sharepoint-settings-files-download', kwargs={ - 'folder': directories[-2], - 'filename': directories[-1] - }) - base_url = f'{settings.HOST}{relative_url}' - donor_code = getvalue(obj, 'DRPDonorCode') + path = getvalue(obj, "Path") + directories = path.split("/") + relative_url = reverse( + "sharepoint_rest_api:sharepoint-settings-files-download", + kwargs={"folder": directories[-2], "filename": directories[-1]}, + ) + base_url = f"{settings.HOST}{relative_url}" + donor_code = getvalue(obj, "DRPDonorCode") if donor_code: - donor_code = donor_code.replace(';', ',') - base_url = f'{base_url}?donor_code={donor_code}' + donor_code = donor_code.replace(";", ",") + base_url = f"{base_url}?donor_code={donor_code}" return base_url except BaseException: return None @@ -138,6 +141,21 @@ class DRPSharePointSearchSerializer(DRPSharePointBaseSerializer): framework_agreement = DRPSearchSharePointField() award_type = DRPSearchSharePointField() + export_headers = [ + "DRPDonor", + "DRPGrantNumber", + "DRPIssueYear", + "DRPExternalReference", + "DRPRecipientOffice", + "DRPReportType", + "DRPTheme", + "DRPDonorDocument" "DRPReportMethod", + "DRPReportGroup", + "DRPReportStatus" "DRPRetracted", + "DRPFrameworkAgreement", + "DRPAwardType", + ] + class GaviSharePointSearchSerializer(DRPSharePointBaseSerializer): donor_code = DRPSearchSharePointField() @@ -156,3 +174,22 @@ class GaviSharePointSearchSerializer(DRPSharePointBaseSerializer): allocation_round = CTNSearchSharePointField() vendor = CTNSearchSharePointField() urgent = CTNSearchSharePointField() + + export_headers = [ + "CTNNumber", + "CTNMOUNumber", + "CTNMOUREference", + "CTNSentToGAVIDate", + "CTNFundsDueDate", + "CTNGAVIWBS", + "CTNCountryName", + "CTNVaccineType", + "CTNPurchaseOrder", + "CTNMaterialCode", + "CTNApprovalYear", + "CTNPrepaidStatus", + "CTNAllocationRound", + "CTNVendor", + "CTNUrgent", + "Title", + ] diff --git a/src/donor_reporting_portal/api/serializers/userrole.py b/src/donor_reporting_portal/api/serializers/userrole.py index 2c2c5646..c18cd674 100644 --- a/src/donor_reporting_portal/api/serializers/userrole.py +++ b/src/donor_reporting_portal/api/serializers/userrole.py @@ -11,7 +11,7 @@ class GroupSerializer(serializers.ModelSerializer): class Meta: model = Group - fields = '__all__' + fields = "__all__" class UserSerializer(serializers.ModelSerializer): @@ -20,7 +20,7 @@ class UserSerializer(serializers.ModelSerializer): class Meta: model = get_user_model() - fields = ('id', 'username', 'first_name', 'last_name', 'email', 'is_superuser') + fields = ("id", "username", "first_name", "last_name", "email", "is_superuser") def validate_email(self, value): if value != value.lower(): @@ -29,27 +29,39 @@ def validate_email(self, value): class UserRoleSerializer(serializers.ModelSerializer): - user_last_login = serializers.ReadOnlyField(source='user.last_login') - user_email = serializers.ReadOnlyField(source='user.email') - user_first_name = serializers.ReadOnlyField(source='user.first_name') - user_last_name = serializers.ReadOnlyField(source='user.last_name') - group_name = serializers.ReadOnlyField(source='group.name') - donor_name = serializers.ReadOnlyField(source='donor.name') - secondary_donor_name = serializers.ReadOnlyField(source='secondary_donor.name') + user_last_login = serializers.ReadOnlyField(source="user.last_login") + user_email = serializers.ReadOnlyField(source="user.email") + user_first_name = serializers.ReadOnlyField(source="user.first_name") + user_last_name = serializers.ReadOnlyField(source="user.last_name") + group_name = serializers.ReadOnlyField(source="group.name") + donor_name = serializers.ReadOnlyField(source="donor.name") + secondary_donor_name = serializers.ReadOnlyField(source="secondary_donor.name") class Meta: model = UserRole - fields = ('id', 'user', 'group', 'donor', 'secondary_donor', - 'group_name', 'donor_name', 'secondary_donor_name', 'notification_period', - 'user_last_login', 'user_email', 'user_first_name', 'user_last_name') + fields = ( + "id", + "user", + "group", + "donor", + "secondary_donor", + "group_name", + "donor_name", + "secondary_donor_name", + "notification_period", + "user_last_login", + "user_email", + "user_first_name", + "user_last_name", + ) class BusinessAreaSerializer(serializers.ModelSerializer): - country = serializers.ReadOnlyField(source='country.name') + country = serializers.ReadOnlyField(source="country.name") class Meta: model = BusinessArea - fields = ('code', 'name', 'long_name', 'region', 'country') + fields = ("code", "name", "long_name", "region", "country") class UserProfileSerializer(UserSerializer): @@ -60,27 +72,34 @@ class UserProfileSerializer(UserSerializer): is_unicef_user = serializers.SerializerMethodField() def get_is_unicef_user(self, obj): - unicef_user = obj.groups.filter(name='UNICEF User').first() + unicef_user = obj.groups.filter(name="UNICEF User").first() return bool(unicef_user) def get_roles(self, obj): - qs = UserRole.objects.by_permissions(['report_metadata.view_donor', ]).filter(user=obj) + qs = UserRole.objects.by_permissions( + [ + "report_metadata.view_donor", + ] + ).filter(user=obj) return UserRoleSerializer(qs, many=True).data def get_instance(self, obj): # unicef_user = obj.groups.filter(name='UNICEF User').first() # if unicef_user: # return unicef_user, None, None - if UserRole.objects.by_permissions(['report_metadata.view_donor', 'roles.add_userrole']).filter(user=obj): - instance = UserRole.objects.by_permissions(['report_metadata.view_donor', - 'roles.add_userrole']).filter(user=obj).first() + if UserRole.objects.by_permissions(["report_metadata.view_donor", "roles.add_userrole"]).filter(user=obj): + instance = ( + UserRole.objects.by_permissions(["report_metadata.view_donor", "roles.add_userrole"]) + .filter(user=obj) + .first() + ) else: - instance = UserRole.objects.by_permissions('report_metadata.view_donor').filter(user=obj).first() + instance = UserRole.objects.by_permissions("report_metadata.view_donor").filter(user=obj).first() return ( - getattr(instance, 'group', None), - getattr(instance, 'donor', None), - getattr(instance, 'secondary_donor', None) + getattr(instance, "group", None), + getattr(instance, "donor", None), + getattr(instance, "secondary_donor", None), ) def get_group(self, obj): @@ -101,7 +120,14 @@ def get_secondary_donor(self, obj): return serializer.data class Meta(UserSerializer.Meta): - fields = UserSerializer.Meta.fields + ('is_unicef_user', 'pk', 'donor', 'group', 'secondary_donor', 'roles') + fields = UserSerializer.Meta.fields + ( + "is_unicef_user", + "pk", + "donor", + "group", + "secondary_donor", + "roles", + ) # donors = serializers.SerializerMethodField() # admin_donors = serializers.SerializerMethodField() diff --git a/src/donor_reporting_portal/api/serializers/utils.py b/src/donor_reporting_portal/api/serializers/utils.py index 699e89f3..e66bde22 100644 --- a/src/donor_reporting_portal/api/serializers/utils.py +++ b/src/donor_reporting_portal/api/serializers/utils.py @@ -1,2 +1,2 @@ def getvalue(instance, field_name): - return instance.get(field_name, 'N/A') + return instance.get(field_name, "N/A") diff --git a/src/donor_reporting_portal/api/urls.py b/src/donor_reporting_portal/api/urls.py index 813b6da6..b21a0e70 100644 --- a/src/donor_reporting_portal/api/urls.py +++ b/src/donor_reporting_portal/api/urls.py @@ -26,43 +26,77 @@ ) from .views.userrole import BusinessAreaViewSet, GroupViewSet, UserRoleViewSet, UserViewSet -app_name = 'api' +app_name = "api" router = routers.DefaultRouter() -router.register(r'roles/groups', GroupViewSet) -router.register(r'roles/users', UserViewSet) -router.register(r'roles/user-role', UserRoleViewSet) -router.register(r'roles/business-area', BusinessAreaViewSet) -router.register(r'metadata/themes', ThemeViewSet) -router.register(r'metadata/donors', DonorViewSet) -router.register(r'metadata/external_grant/(?P\d+)', ExternalGrantViewSet, basename='external_grant') -router.register(r'metadata/grants/(?P\d+)', GrantViewSet, basename='grant') -router.register(r'metadata/drp-static', DRPMetadataViewSet) -router.register(r'metadata/secondary-donors', SecondaryDonorViewSet, basename='secondary-donor') -router.register(r'sharepoint/groups', SharePointGroupViewSet, basename='sharepoint-group') +router.register(r"roles/groups", GroupViewSet) +router.register(r"roles/users", UserViewSet) +router.register(r"roles/user-role", UserRoleViewSet) +router.register(r"roles/business-area", BusinessAreaViewSet) +router.register(r"metadata/themes", ThemeViewSet) +router.register(r"metadata/donors", DonorViewSet) +router.register( + r"metadata/external_grant/(?P\d+)", + ExternalGrantViewSet, + basename="external_grant", +) +router.register(r"metadata/grants/(?P\d+)", GrantViewSet, basename="grant") +router.register(r"metadata/drp-static", DRPMetadataViewSet) +router.register(r"metadata/secondary-donors", SecondaryDonorViewSet, basename="secondary-donor") +router.register(r"sharepoint/groups", SharePointGroupViewSet, basename="sharepoint-group") -router.register(r'sharepoint/(?P[\w\-]+)/(?P[\w\-]+)/(?P[\w\W]+)/files', - DRPSharePointUrlFileViewSet, basename='sharepoint-url-files') -router.register(r'sharepoint/(?P[\w\-]+)/(?P[\w\-]+)/(?P[\w|\W]+)/rest', - DRPSharePointUrlRestViewSet, basename='sharepoint-url') -router.register(r'sharepoint/(?P[\w\-]+)/(?P[\w\-]+)/(?P[\w|\W]+)/caml', - DRPSharePointUrlCamlViewSet, basename='sharepoint-url-caml') -router.register(r'sharepoint/(?P[\w\-]+)/(?P[\w\-]+)/search', - DRPSharePointUrlSearchViewSet, basename='sharepoint-url-search') +router.register( + r"sharepoint/(?P[\w\-]+)/(?P[\w\-]+)/(?P[\w\W]+)/files", + DRPSharePointUrlFileViewSet, + basename="sharepoint-url-files", +) +router.register( + r"sharepoint/(?P[\w\-]+)/(?P[\w\-]+)/(?P[\w|\W]+)/rest", + DRPSharePointUrlRestViewSet, + basename="sharepoint-url", +) +router.register( + r"sharepoint/(?P[\w\-]+)/(?P[\w\-]+)/(?P[\w|\W]+)/caml", + DRPSharePointUrlCamlViewSet, + basename="sharepoint-url-caml", +) +router.register( + r"sharepoint/(?P[\w\-]+)/(?P[\w\-]+)/search", + DRPSharePointUrlSearchViewSet, + basename="sharepoint-url-search", +) -router.register(r'sharepoint/(?P[\w\W]+)/rest', - DRPSharePointSettingsRestViewSet, basename='sharepoint-settings-rest') -router.register(r'sharepoint/(?P[\w\W]+)/caml', - DRPSharePointSettingsCamlViewSet, basename='sharepoint-settings-caml') -router.register(r'sharepoint/(?P[\w\W]+)/files', - DRPSharePointSettingsFileViewSet, basename='sharepoint-settings-files') -router.register(r'sharepoint/search', - DRPSharePointSettingsSearchViewSet, basename='sharepoint-settings-search') +router.register( + r"sharepoint/(?P[\w\W]+)/rest", + DRPSharePointSettingsRestViewSet, + basename="sharepoint-settings-rest", +) +router.register( + r"sharepoint/(?P[\w\W]+)/caml", + DRPSharePointSettingsCamlViewSet, + basename="sharepoint-settings-caml", +) +router.register( + r"sharepoint/(?P[\w\W]+)/files", + DRPSharePointSettingsFileViewSet, + basename="sharepoint-settings-files", +) +router.register( + r"sharepoint/search", + DRPSharePointSettingsSearchViewSet, + basename="sharepoint-settings-search", +) urlpatterns = [ - path('metadata/static/', view=MetadataStaticAPIView.as_view(http_method_names=['get']), - name='metadata-static-list'), - path('config/', view=ConfigAPIView.as_view(http_method_names=['get']), - name='config-list'), - path(r'', include(router.urls)), + path( + "metadata/static/", + view=MetadataStaticAPIView.as_view(http_method_names=["get"]), + name="metadata-static-list", + ), + path( + "config/", + view=ConfigAPIView.as_view(http_method_names=["get"]), + name="config-list", + ), + path(r"", include(router.urls)), ] diff --git a/src/donor_reporting_portal/api/views/config.py b/src/donor_reporting_portal/api/views/config.py index 720a75e5..92e050b1 100644 --- a/src/donor_reporting_portal/api/views/config.py +++ b/src/donor_reporting_portal/api/views/config.py @@ -14,12 +14,12 @@ def get(self, request): return Response( { - 'tracker': { - 'site_tracker': settings.MATOMO_SITE_TRACKER, - 'site_id': settings.MATOMO_SITE_ID + "tracker": { + "site_tracker": settings.MATOMO_SITE_TRACKER, + "site_id": settings.MATOMO_SITE_ID, }, - 'source_id': settings.DRP_SOURCE_IDS, - 'gavi_donor_code': settings.GAVI_DONOR_CODE + "source_id": settings.DRP_SOURCE_IDS, + "gavi_donor_code": settings.GAVI_DONOR_CODE, }, - status=status.HTTP_200_OK + status=status.HTTP_200_OK, ) diff --git a/src/donor_reporting_portal/api/views/metadata.py b/src/donor_reporting_portal/api/views/metadata.py index 49171462..c7e7171b 100644 --- a/src/donor_reporting_portal/api/views/metadata.py +++ b/src/donor_reporting_portal/api/views/metadata.py @@ -35,11 +35,11 @@ class AllowedDonorMixin: model = None - permission_classes = (DonorPermission, ) + permission_classes = (DonorPermission,) def get_queryset(self): - donor_id = self.kwargs.get('donor_id', None) - secondary_donor_code = self.request.GET.get('secondary_donor_code', None) + donor_id = self.kwargs.get("donor_id", None) + secondary_donor_code = self.request.GET.get("secondary_donor_code", None) qs = self.model.objects.filter(donor_id=donor_id) if secondary_donor_code: qs = qs.filter(secondarydonor__code=secondary_donor_code) @@ -50,37 +50,38 @@ class ThemeViewSet(GenericAbstractViewSetMixin, viewsets.ReadOnlyModelViewSet): queryset = Theme.objects.all() serializer_class = ThemeSerializer filterset_class = ThemeFilter - search_fields = ('name', ) + search_fields = ("name",) class DonorViewSet(GenericAbstractViewSetMixin, viewsets.ReadOnlyModelViewSet): queryset = Donor.objects.all() serializer_class = DonorSerializer filterset_class = DonorFilter - search_fields = ('name', 'code') + search_fields = ("name", "code") def retrieve(self, *args, **kwargs): self.serializer_class = DonorSecondaryDonorSerializer return viewsets.ModelViewSet.retrieve(self, *args, **kwargs) def get_permissions(self): - if self.action in ('my_donors', 'my_admin_donors'): - return IsAuthenticated(), + if self.action in ("my_donors", "my_admin_donors"): + return (IsAuthenticated(),) return super().get_permissions() - @action(detail=False, methods=['get']) + @action(detail=False, methods=["get"]) def my_donors(self, request, *args, **kwargs): qs = self.get_queryset() - if not request.user.has_perm('roles.can_view_all_donors'): - roles = UserRole.objects.by_permissions('report_metadata.view_donor').filter(user=request.user) + if not request.user.has_perm("roles.can_view_all_donors"): + roles = UserRole.objects.by_permissions("report_metadata.view_donor").filter(user=request.user) qs = qs.filter(user_roles__in=roles) serializer = self.get_serializer(qs, many=True) return Response(serializer.data) - @action(detail=False, methods=['get']) + @action(detail=False, methods=["get"]) def my_admin_donors(self, request, *args, **kwargs): - roles = UserRole.objects.by_permissions(['report_metadata.view_donor', - 'roles.add_userrole']).filter(user=request.user) + roles = UserRole.objects.by_permissions(["report_metadata.view_donor", "roles.add_userrole"]).filter( + user=request.user + ) serializer = self.get_serializer(self.get_queryset().filter(user_roles__in=roles), many=True) return Response(serializer.data) @@ -89,25 +90,25 @@ class ExternalGrantViewSet(AllowedDonorMixin, GenericAbstractViewSetMixin, views model = ExternalGrant serializer_class = ExternalGrantSerializer filterset_class = ExternalGrantFilter - search_fields = ('code', 'donor__name') + search_fields = ("code", "donor__name") class GrantViewSet(AllowedDonorMixin, GenericAbstractViewSetMixin, viewsets.ReadOnlyModelViewSet): model = Grant serializer_class = GrantSerializer filterset_class = GrantFilter - search_fields = ('code', 'donor__name') + search_fields = ("code", "donor__name") class SecondaryDonorViewSet(GenericAbstractViewSetMixin, viewsets.ReadOnlyModelViewSet): queryset = SecondaryDonor.objects.all() serializer_class = SecondaryDonorSerializer filterset_class = SecondaryDonorFilter - search_fields = ('name', 'code') + search_fields = ("name", "code") class DRPMetadataViewSet(GenericAbstractViewSetMixin, viewsets.ReadOnlyModelViewSet): queryset = DRPMetadata.objects.all() serializer_class = DRPMetadataSerializer filterset_class = DRPMetadataFilter - search_fields = ('description', 'code') + search_fields = ("description", "code") diff --git a/src/donor_reporting_portal/api/views/sharepoint.py b/src/donor_reporting_portal/api/views/sharepoint.py index 721f686f..a3055ec1 100644 --- a/src/donor_reporting_portal/api/views/sharepoint.py +++ b/src/donor_reporting_portal/api/views/sharepoint.py @@ -68,98 +68,104 @@ class DRPSharePointUrlFileViewSet(SharePointUrlFileViewSet): class DRPSharePointSettingsFileViewSet(SharePointSettingsFileViewSet): - permission_classes = (DonorPermission, ) + permission_classes = (DonorPermission,) class DRPSharepointSearchViewSet(SharePointSearchViewSet): - prefix = 'DRP' + prefix = "DRP" serializer_class = DRPSharePointSearchSerializer def get_serializer_class(self): query_params = self.request.query_params - if query_params.get("serializer") == 'gavi': + if query_params.get("serializer") == "gavi": return GaviSharePointSearchSerializer return super().get_serializer_class() def is_public(self): """check if the source id is public or restricted to UNICEF users""" - source_id = self.request.query_params.get('source_id', None) - public = source_id in [settings.DRP_SOURCE_IDS['thematic_internal'], - settings.DRP_SOURCE_IDS['thematic_external']] + source_id = self.request.query_params.get("source_id", None) + public = source_id in [ + settings.DRP_SOURCE_IDS["thematic_internal"], + settings.DRP_SOURCE_IDS["thematic_external"], + ] if public: return True - unicef_user = self.request.user.username.endswith('@unicef.org') - return unicef_user and source_id in [settings.DRP_SOURCE_IDS['internal'], - settings.DRP_SOURCE_IDS['pool_internal']] + unicef_user = self.request.user.username.endswith("@unicef.org") + return unicef_user and source_id in [ + settings.DRP_SOURCE_IDS["internal"], + settings.DRP_SOURCE_IDS["pool_internal"], + ] def get_selected(self, selected): def to_drp(source, value): - prefix = 'CTN' if isinstance(value, (CTNSearchSharePointField, CTNSearchMultiSharePointField)) else 'DRP' + prefix = "CTN" if isinstance(value, (CTNSearchSharePointField, CTNSearchMultiSharePointField)) else "DRP" return prefix + to_camel(source) autofields = [to_drp(key, value) for key, value in self.get_serializer_class()._declared_fields.items()] - selected = selected.split(',') if selected else autofields + selected = selected.split(",") if selected else autofields return selected + ["Title", "Author", "Path"] def get_filters(self, kwargs): # we can enforce filters here - kwargs.pop('serializer', None) + kwargs.pop("serializer", None) new_kwargs = { # 'IsDocument': '1', } - drp_fields = [key for key, value in self.get_serializer_class()._declared_fields.items() - if isinstance(value, DRPSearchSharePointField)] - - ctn_fields = [key for key, value in self.get_serializer_class()._declared_fields.items() - if isinstance(value, CTNSearchSharePointField)] + drp_fields = [ + key + for key, value in self.get_serializer_class()._declared_fields.items() + if isinstance(value, DRPSearchSharePointField) + ] + + ctn_fields = [ + key + for key, value in self.get_serializer_class()._declared_fields.items() + if isinstance(value, CTNSearchSharePointField) + ] for key, value in kwargs.items(): - key_splits = key.split('__') + key_splits = key.split("__") filter_name = key_splits[0] filter_type = key_splits[-1] if len(key_splits) > 1 else None if filter_name in drp_fields: new_key = self.prefix + to_camel(filter_name) if filter_type: - new_key = f'{new_key}__{filter_type}' + new_key = f"{new_key}__{filter_type}" new_kwargs[new_key] = value elif filter_name in ctn_fields: - new_key = 'CTN' + to_camel(filter_name) + new_key = "CTN" + to_camel(filter_name) if filter_type: - new_key = f'{new_key}__{filter_type}' + new_key = f"{new_key}__{filter_type}" new_kwargs[new_key] = value else: new_kwargs[key] = value return new_kwargs - -class DRPSharePointSettingsSearchViewSet(DRPViewSet, DRPSharepointSearchViewSet, SharePointSettingsSearchViewSet): - """DRP Search Viewset for settings based""" - - @action(detail=False, methods=['get']) + @action(detail=False, methods=["get"]) def export(self, request, *args, **kwargs): - exit_condition = True - response = HttpResponse(content_type='text/csv') - filename = 'drp_export_{}.csv'.format(timezone.now().date()) - response['Content-Disposition'] = f'attachment; filename="{filename}"' + response = HttpResponse(content_type="text/csv") + filename = "drp_export_{}.csv".format(timezone.now().date()) + response["Content-Disposition"] = f'attachment; filename="{filename}"' - headers = ["CTNNumber", "CTNMOUNumber", "CTNMOUREference", "CTNSentToGAVIDate", "CTNFundsDueDate", - "CTNGAVIWBS", "CTNCountryName", "CTNVaccineType", "CTNPurchaseOrder", "CTNMaterialCode", - "CTNApprovalYear", "CTNPrepaidStatus", "CTNAllocationRound", "CTNVendor", "CTNUrgent", "Title"] + headers = self.get_serializer_class().export_headers writer = csv.writer(response) page = 1 qs = self.get_queryset(page=page) - writer.writerow([str(item['Key']).replace('CTN', "") for item in qs[0] if item['Key'] in headers]) + writer.writerow([key.replace("CTN", "") for key in qs[0].keys() if key in headers]) while exit_condition: for row in qs: - writer.writerow( - [str(item['Value']) if item['Value'] else '-' for item in row if item['Key'] in headers]) + writer.writerow([str(value) for key, value in row.items() if key in headers]) exit_condition = page * SHAREPOINT_PAGE_SIZE < self.total_rows page += 1 qs = self.get_queryset(page=page) return response +class DRPSharePointSettingsSearchViewSet(DRPViewSet, DRPSharepointSearchViewSet, SharePointSettingsSearchViewSet): + """DRP Search Viewset for settings based""" + + class DRPSharePointUrlSearchViewSet(DRPViewSet, DRPSharepointSearchViewSet, SharePointUrlSearchViewSet): """DRP Search Viewset for url based""" diff --git a/src/donor_reporting_portal/api/views/static.py b/src/donor_reporting_portal/api/views/static.py index c2fd60b4..cde01062 100644 --- a/src/donor_reporting_portal/api/views/static.py +++ b/src/donor_reporting_portal/api/views/static.py @@ -6,8 +6,8 @@ from rest_framework.views import APIView -def list_to_json(items, key='code', value='description'): - return [{key: x.lower().replace(' ', '_'), value: x} for x in items] +def list_to_json(items, key="code", value="description"): + return [{key: x.lower().replace(" ", "_"), value: x} for x in items] class MetadataStaticAPIView(APIView): @@ -19,124 +19,124 @@ def get(self, request): years = [str(year) for year in range(2000, datetime.today().year + 2)] report_years = [str(year) for year in range(2019, datetime.today().year + 2)] grant_issue_years = approval_year = [str(year) for year in range(2018, datetime.today().year + 2)] - report_type = [ - 'Quarterly', - 'Final', - 'Interim' - ] + report_type = ["Quarterly", "Final", "Interim"] donor_document = [ - 'Certified Financial Statement - EC', - 'Certified Financial Statement - US Government', - 'Certified Statement of Account', - 'Certified Statement of Account EU', - 'Certified Statement of Account JPO', - 'Donor Statement CERF', - 'Certified Financial Report - Final', - 'Certified Financial Report - Interim', - 'Donor Statement Innovation', - 'Donor Statement Joint Programme', - 'Donor Statement Joint Programme PUNO', - 'Donor Statement JPO Summary', - 'Donor Statement Trust Fund', - 'Donor Statement UN', - 'Donor Statement UNICEF Hosted Funds', - 'FFR Form (SF-425)', - 'JPO Expenditure Summary', - 'Statement of Account Thematic Funds', - 'Donor Statement by Activity', - 'Interim Statement by Nature of expense', - 'Funds Request Report', - 'Non-Standard Statement', - 'Emergency Consolidated - Final', - 'Emergency  Consolidated - Interim', - 'Thematic Emergency Global - Final', - 'Thematic Emergency Global - Interim', - 'Emergency - Two Pager', - 'Emergency - Final', - 'Emergency - Interim', - 'Human Interest / Photos', - 'Narrative - Final', - 'Narrative - Interim', - 'Narrative Consolidated - Final', - 'Narrative  Consolidated - Interim', - 'Thematic Consolidated - Final', - 'Thematic Consolidated - Interim', - 'Thematic Global - Final', - 'Thematic Global - Interim', - 'Thematic - Final', - 'Thematic - Interim', - 'Short Summary Update', - 'Agreements', - 'Agreement Amendments', - 'Correspondence', - 'Extensions', - 'Framework Agreements', - 'Framework Agreement Checklist', - 'JPOs', - 'Note for the Records', - 'Official Receipts', - 'Others', - 'Proposals', - 'Payment Request', - 'Input Report - Final', - 'Input Report - Interim', - 'Quarterly Monitoring Report', + "Certified Financial Statement - EC", + "Certified Financial Statement - US Government", + "Certified Statement of Account", + "Certified Statement of Account EU", + "Certified Statement of Account JPO", + "Donor Statement CERF", + "Certified Financial Report - Final", + "Certified Financial Report - Interim", + "Donor Statement Innovation", + "Donor Statement Joint Programme", + "Donor Statement Joint Programme PUNO", + "Donor Statement JPO Summary", + "Donor Statement Trust Fund", + "Donor Statement UN", + "Donor Statement UNICEF Hosted Funds", + "FFR Form (SF-425)", + "JPO Expenditure Summary", + "Statement of Account Thematic Funds", + "Donor Statement by Activity", + "Interim Statement by Nature of expense", + "Funds Request Report", + "Non-Standard Statement", + "Emergency Consolidated - Final", + "Emergency  Consolidated - Interim", + "Thematic Emergency Global - Final", + "Thematic Emergency Global - Interim", + "Emergency - Two Pager", + "Emergency - Final", + "Emergency - Interim", + "Human Interest / Photos", + "Narrative - Final", + "Narrative - Interim", + "Narrative Consolidated - Final", + "Narrative  Consolidated - Interim", + "Thematic Consolidated - Final", + "Thematic Consolidated - Interim", + "Thematic Global - Final", + "Thematic Global - Interim", + "Thematic - Final", + "Thematic - Interim", + "Short Summary Update", + "Agreements", + "Agreement Amendments", + "Correspondence", + "Extensions", + "Framework Agreements", + "Framework Agreement Checklist", + "JPOs", + "Note for the Records", + "Official Receipts", + "Others", + "Proposals", + "Payment Request", + "Input Report - Final", + "Input Report - Interim", + "Quarterly Monitoring Report", ] donor_reporting_category = [ - 'Donor Narrative', - 'Donor Financial Certified', - 'Grant Master Document', - 'Donor Financial Uncertified', - 'Input Report', - 'Donor Narrative Special', + "Donor Narrative", + "Donor Financial Certified", + "Grant Master Document", + "Donor Financial Uncertified", + "Input Report", + "Donor Narrative Special", ] - recertified = { - 'yes': 'Yes', - 'no': 'No' - } + recertified = {"yes": "Yes", "no": "No"} rp_status = [ - 'New', - 'Pending Review by Reporting Manager', - 'Rejected by Reporting Manager', - 'Approved by Reporting Manager', - 'Pending Approval by Comptroller', - 'Rejected by Comptroller', - 'Certified by Comptroller', + "New", + "Pending Review by Reporting Manager", + "Rejected by Reporting Manager", + "Approved by Reporting Manager", + "Pending Approval by Comptroller", + "Rejected by Comptroller", + "Certified by Comptroller", ] awards = { - 'EMG': 'Emergency', - 'IKC': 'In-Kind - Cash', - 'IKG': 'In-Kind - Goods', - 'IKS': 'In-Kind - Services', - 'JPO': 'Junior Professional Officer', - 'NTH': 'Non-Thematic', - 'PLF': 'Pooled Funding', - 'POL': 'Polio', - 'THM': 'Thematic', + "EMG": "Emergency", + "IKC": "In-Kind - Cash", + "IKG": "In-Kind - Goods", + "IKS": "In-Kind - Services", + "JPO": "Junior Professional Officer", + "NTH": "Non-Thematic", + "PLF": "Pooled Funding", + "POL": "Polio", + "THM": "Thematic", } - if not (self.request.user.is_superuser or self.request.user.email.endswith('@unicef.org')): - donor_reporting_category.remove('Input Report',) - donor_document = [item for item in donor_document if item not in [ - 'Input Report - Final', - 'Input Report - Interim', - 'Correspondence', - 'Others', - 'Note for the Record', - 'Framework Agreement Checklist' - ]] + if not (self.request.user.is_superuser or self.request.user.email.endswith("@unicef.org")): + donor_reporting_category.remove( + "Input Report", + ) + donor_document = [ + item + for item in donor_document + if item + not in [ + "Input Report - Final", + "Input Report - Interim", + "Correspondence", + "Others", + "Note for the Record", + "Framework Agreement Checklist", + ] + ] return Response( { - 'years': list_to_json(years), - 'report_years': list_to_json(report_years), - 'grant_issue_years': list_to_json(grant_issue_years), - 'report_type': list_to_json(report_type), - 'donor_document': list_to_json(donor_document), - 'donor_reporting_category': list_to_json(donor_reporting_category), - 'recertified': list_to_json(recertified), - 'rp_status': list_to_json(rp_status), - 'awards': list_to_json(awards), - 'approval_year': list_to_json(approval_year), + "years": list_to_json(years), + "report_years": list_to_json(report_years), + "grant_issue_years": list_to_json(grant_issue_years), + "report_type": list_to_json(report_type), + "donor_document": list_to_json(donor_document), + "donor_reporting_category": list_to_json(donor_reporting_category), + "recertified": list_to_json(recertified), + "rp_status": list_to_json(rp_status), + "awards": list_to_json(awards), + "approval_year": list_to_json(approval_year), }, - status=status.HTTP_200_OK + status=status.HTTP_200_OK, ) diff --git a/src/donor_reporting_portal/api/views/userrole.py b/src/donor_reporting_portal/api/views/userrole.py index db4284c0..0b98c07c 100644 --- a/src/donor_reporting_portal/api/views/userrole.py +++ b/src/donor_reporting_portal/api/views/userrole.py @@ -22,7 +22,7 @@ class GroupViewSet(GenericAbstractViewSetMixin, viewsets.ModelViewSet): queryset = Group.objects.all() serializer_class = GroupSerializer - search_fields = ('name', ) + search_fields = ("name",) filterset_class = GroupFilter @@ -30,17 +30,19 @@ class UserViewSet(GenericAbstractViewSetMixin, viewsets.ModelViewSet): queryset = User.objects.all() serializer_class = UserSerializer filterset_class = UserFilter - search_fields = ('donor__name', 'user__username', 'group__name') + search_fields = ("donor__name", "user__username", "group__name") - @action(detail=False, methods=['get']) + @action(detail=False, methods=["get"]) def my_profile(self, request, *args, **kwargs): object = self.request.user serializer = UserProfileSerializer(object) return Response(serializer.data) def get_permissions(self): - if self.action == 'my_profile': - return [IsAuthenticated(), ] + if self.action == "my_profile": + return [ + IsAuthenticated(), + ] return super().get_permissions() @@ -48,8 +50,14 @@ class UserRoleViewSet(GenericAbstractViewSetMixin, viewsets.ModelViewSet): queryset = UserRole.objects.all() serializer_class = UserRoleSerializer filterset_class = UserRoleFilter - search_fields = ('donor__name', 'secondary_donor__name', 'group__name', - 'user__username', 'user__first_name', 'user__last_name') + search_fields = ( + "donor__name", + "secondary_donor__name", + "group__name", + "user__username", + "user__first_name", + "user__last_name", + ) def perform_destroy(self, instance): user = instance.user @@ -62,4 +70,4 @@ class BusinessAreaViewSet(GenericAbstractViewSetMixin, viewsets.ModelViewSet): queryset = BusinessArea.objects.all() serializer_class = BusinessAreaSerializer filterset_class = BusinessAreaFilter - search_fields = ('code', 'name', 'long_name') + search_fields = ("code", "name", "long_name") diff --git a/src/donor_reporting_portal/apps/core/apps.py b/src/donor_reporting_portal/apps/core/apps.py index 55aac118..2b2051d0 100644 --- a/src/donor_reporting_portal/apps/core/apps.py +++ b/src/donor_reporting_portal/apps/core/apps.py @@ -2,5 +2,5 @@ class AppConfig(BaseAppConfig): - name = __name__.rpartition('.')[0] - verbose_name = 'Core' + name = __name__.rpartition(".")[0] + verbose_name = "Core" diff --git a/src/donor_reporting_portal/apps/core/backends.py b/src/donor_reporting_portal/apps/core/backends.py index bd723e69..a9410375 100644 --- a/src/donor_reporting_portal/apps/core/backends.py +++ b/src/donor_reporting_portal/apps/core/backends.py @@ -26,10 +26,10 @@ def has_perm(self, user_obj, perm, context_obj): donor_obj = context_obj[0] secondary_donor_obj = context_obj[-1] donor_perm = UserRole.objects.get_permissions_by_donor(user_obj, donor_obj) - donor_secondary_donor_perm = UserRole.objects.get_permissions_by_donor_secondary_donor(user_obj, - donor_obj, - secondary_donor_obj) + donor_secondary_donor_perm = UserRole.objects.get_permissions_by_donor_secondary_donor( + user_obj, donor_obj, secondary_donor_obj + ) perms = donor_perm | donor_secondary_donor_perm else: return set() - return perm in {f'{app_label}.{perm_name}' for app_label, perm_name in perms} + return perm in {f"{app_label}.{perm_name}" for app_label, perm_name in perms} diff --git a/src/donor_reporting_portal/apps/core/checks.py b/src/donor_reporting_portal/apps/core/checks.py index 4e988d7d..5c093c2b 100644 --- a/src/donor_reporting_portal/apps/core/checks.py +++ b/src/donor_reporting_portal/apps/core/checks.py @@ -6,18 +6,20 @@ def check_imports(package=donor_reporting_portal): for importer, modname, ispkg in pkgutil.iter_modules(package.__path__): - current_module = '{}.{}'.format(package.__name__, modname) + current_module = "{}.{}".format(package.__name__, modname) m = importlib.import_module(current_module) - if hasattr(m, '__path__'): # pragma: no cover + if hasattr(m, "__path__"): # pragma: no cover for _, sub_mod, __ in pkgutil.iter_modules(m.__path__): - sub_module = '{}.{}'.format(current_module, sub_mod) + sub_module = "{}.{}".format(current_module, sub_mod) sm = importlib.import_module(sub_module) - if hasattr(sm, '__path__'): + if hasattr(sm, "__path__"): for _, s_sub_mod, __ in pkgutil.iter_modules(sm.__path__): - s_sub_mod = '{}.{}.{}'.format(current_module, sub_mod, s_sub_mod) + s_sub_mod = "{}.{}.{}".format(current_module, sub_mod, s_sub_mod) try: importlib.import_module(s_sub_mod) except Exception as e: # pragma: no cover - raise Exception(f"""Error importing '{s_sub_mod}'. + raise Exception( + f"""Error importing '{s_sub_mod}'. {e} - """) + """ + ) diff --git a/src/donor_reporting_portal/apps/core/management/commands/db-isready.py b/src/donor_reporting_portal/apps/core/management/commands/db_isready.py similarity index 57% rename from src/donor_reporting_portal/apps/core/management/commands/db-isready.py rename to src/donor_reporting_portal/apps/core/management/commands/db_isready.py index bef73279..5eaf14fd 100644 --- a/src/donor_reporting_portal/apps/core/management/commands/db-isready.py +++ b/src/donor_reporting_portal/apps/core/management/commands/db_isready.py @@ -6,41 +6,43 @@ class Command(BaseCommand): - args = '' - help = 'Help text here....' + args = "" + help = "Help text here...." requires_migrations_checks = False - def __init__(self, *args, **kwargs): - super(Command, self).__init__(*args, **kwargs) - def add_arguments(self, parser): - super(Command, self).add_arguments(parser) + super().add_arguments(parser) parser.add_argument( - '--sleep', default=1, + "--sleep", + default=1, action="store", type=int, - help='sleep time between attempt', + help="sleep time between attempt", ) parser.add_argument( - '--wait', default=False, + "--wait", + default=False, action="store_true", - help='wait until database is available', + help="wait until database is available", ) parser.add_argument( - '--debug', default=False, + "--debug", + default=False, action="store_true", - help='debug mode. WARNING can dump passwords', + help="debug mode. WARNING can dump passwords", ) parser.add_argument( - '--timeout', default=30, + "--timeout", + default=30, type=int, - help='timeout in sec before OperationalError', + help="timeout in sec before OperationalError", ) parser.add_argument( - '--connection', default='default', - help='timeout in sec before OperationalError', + "--connection", + default="default", + help="timeout in sec before OperationalError", ) def _get_cursor(self, conn): @@ -48,7 +50,7 @@ def _get_cursor(self, conn): return conn def handle(self, *args, **options): - conn = connections[options['connection']] + conn = connections[options["connection"]] elapsed = 0 retcode = 1 try: @@ -58,15 +60,17 @@ def handle(self, *args, **options): try: conn = self._get_cursor(conn) except OperationalError as e: - if options['wait'] and elapsed < options['timeout']: - self.stdout.write("." * elapsed, ending='\r') + if options["wait"] and elapsed < options["timeout"]: + self.stdout.write("." * elapsed, ending="\r") self.stdout.flush() - time.sleep(options['sleep']) + time.sleep(options["sleep"]) elapsed += 1 else: - self.stderr.write(f"\nDatabase on {conn.settings_dict['HOST']}:{conn.settings_dict['PORT']} " - f"is not available after {elapsed} secs") - if options['debug']: + self.stderr.write( + f"\nDatabase on {conn.settings_dict['HOST']}:{conn.settings_dict['PORT']} " + f"is not available after {elapsed} secs" + ) + if options["debug"]: self.stderr.write(f"Error is: {e}") retcode = 1 break @@ -75,5 +79,5 @@ def handle(self, *args, **options): retcode = 0 break except KeyboardInterrupt: # pragma: no-cover - self.stdout.write('Interrupted') + self.stdout.write("Interrupted") sys.exit(retcode) diff --git a/src/donor_reporting_portal/apps/core/management/commands/init-setup.py b/src/donor_reporting_portal/apps/core/management/commands/init-setup.py deleted file mode 100644 index 0eeb3623..00000000 --- a/src/donor_reporting_portal/apps/core/management/commands/init-setup.py +++ /dev/null @@ -1,85 +0,0 @@ -import os - -from django.conf import settings -from django.contrib.auth import get_user_model -from django.contrib.auth.hashers import make_password -from django.core.management import call_command -from django.core.management.base import BaseCommand - - -class Command(BaseCommand): - help = "" - - def add_arguments(self, parser): - parser.add_argument( - '--all', - action='store_true', - dest='all', - default=False, - help='select all options but `demo`') - - parser.add_argument( - '--collectstatic', - action='store_true', - dest='collectstatic', - default=False, - help='') - - parser.add_argument( - '--users', - action='store_true', - dest='users', - default=False, - help='') - - parser.add_argument( - '--metadata', - action='store_true', - dest='metadata', - default=False, - help='') - - parser.add_argument( - '--migrate', - action='store_true', - dest='migrate', - default=False, - help='select all production deployment options') - - def handle(self, *args, **options): - verbosity = options['verbosity'] - migrate = options['migrate'] - _all = options['all'] - ModelUser = get_user_model() - if options['collectstatic'] or _all: - self.stdout.write("Run collectstatic") - call_command('collectstatic', verbosity=verbosity - 1, interactive=False) - - if migrate or _all: - self.stdout.write("Run migrations") - call_command('migrate', verbosity=verbosity - 1) - - if options['users'] or _all: - call_command('update_notifications', verbosity=verbosity - 1) - if settings.DEBUG: - pwd = '123' - admin = os.environ.get('USER', 'admin') - else: - pwd = os.environ.get('ADMIN_PASSWORD', ModelUser.objects.make_random_password()) - admin = os.environ.get('ADMIN_USERNAME', 'admin') - - _, created = ModelUser.objects.get_or_create(username=admin, defaults={ - "is_superuser": True, - "is_staff": True, - "password": make_password(pwd) - }) - - if created: # pragma: no cover - self.stdout.write(f"Created superuser `{admin}` with password `{pwd}`") - else: # pragma: no cover - self.stdout.write(f"Superuser `{admin}` already exists`.") - - if options['metadata'] or _all: - call_command('loaddata', 'groups.json') - call_command('loaddata', 'libraries.json') - call_command('loaddata', 'metadata.json') diff --git a/src/donor_reporting_portal/apps/core/management/commands/init_setup.py b/src/donor_reporting_portal/apps/core/management/commands/init_setup.py new file mode 100644 index 00000000..68c4f9ba --- /dev/null +++ b/src/donor_reporting_portal/apps/core/management/commands/init_setup.py @@ -0,0 +1,81 @@ +import os + +from django.conf import settings +from django.contrib.auth import get_user_model +from django.contrib.auth.hashers import make_password +from django.core.management import call_command +from django.core.management.base import BaseCommand + + +class Command(BaseCommand): + help = "" + + def add_arguments(self, parser): + parser.add_argument( + "--all", + action="store_true", + dest="all", + default=False, + help="select all options but `demo`", + ) + + parser.add_argument( + "--collectstatic", + action="store_true", + dest="collectstatic", + default=False, + help="", + ) + + parser.add_argument("--users", action="store_true", dest="users", default=False, help="") + + parser.add_argument("--metadata", action="store_true", dest="metadata", default=False, help="") + + parser.add_argument( + "--migrate", + action="store_true", + dest="migrate", + default=False, + help="select all production deployment options", + ) + + def handle(self, *args, **options): + verbosity = options["verbosity"] + migrate = options["migrate"] + _all = options["all"] + ModelUser = get_user_model() + if options["collectstatic"] or _all: + self.stdout.write("Run collectstatic") + call_command("collectstatic", verbosity=verbosity - 1, interactive=False) + + if migrate or _all: + self.stdout.write("Run migrations") + call_command("migrate", verbosity=verbosity - 1) + + if options["users"] or _all: + call_command("update_notifications", verbosity=verbosity - 1) + if settings.DEBUG: + pwd = "123" + admin = os.environ.get("USER", "admin") + else: + pwd = os.environ.get("ADMIN_PASSWORD", ModelUser.objects.make_random_password()) + admin = os.environ.get("ADMIN_USERNAME", "admin") + + _, created = ModelUser.objects.get_or_create( + username=admin, + defaults={ + "is_superuser": True, + "is_staff": True, + "password": make_password(pwd), + }, + ) + + if created: # pragma: no cover + self.stdout.write(f"Created superuser `{admin}` with password `{pwd}`") + else: # pragma: no cover + self.stdout.write(f"Superuser `{admin}` already exists`.") + + if options["metadata"] or _all: + call_command("loaddata", "groups.json") + call_command("loaddata", "libraries.json") + call_command("loaddata", "metadata.json") diff --git a/src/donor_reporting_portal/apps/core/management/commands/reset-migrations.py b/src/donor_reporting_portal/apps/core/management/commands/reset_migrations.py similarity index 60% rename from src/donor_reporting_portal/apps/core/management/commands/reset-migrations.py rename to src/donor_reporting_portal/apps/core/management/commands/reset_migrations.py index 91264b7f..bc7a3086 100644 --- a/src/donor_reporting_portal/apps/core/management/commands/reset-migrations.py +++ b/src/donor_reporting_portal/apps/core/management/commands/reset_migrations.py @@ -9,20 +9,24 @@ class Command(BaseCommand): - args = '' - help = 'Init Setup' + args = "" + help = "Init Setup" requires_migrations_checks = False def add_arguments(self, parser): - super(Command, self).add_arguments(parser) + super().add_arguments(parser) parser.add_argument( - '--noinput', action='store_false', - dest='interactive', default=True, - help='Tells Django to NOT prompt the user for input of any kind.') + "--noinput", + action="store_false", + dest="interactive", + default=True, + help="Tells Django to NOT prompt the user for input of any kind.", + ) def handle(self, *args, **options): - if options.get('interactive'): - confirm = input(""" + if options.get("interactive"): + confirm = input( + """ You have requested to fully reset your migrations. This will IRREVERSIBLY DESTROY ALL EXISTING MIGRATIONS. This command is intended to reduce the number of migrations created @@ -30,16 +34,17 @@ def handle(self, *args, **options): only BEFORE YOUR FIRST DEPLOYMENT IN PRODUCTION Are you sure you want to do this? - Type 'yes' to continue, or 'no' to cancel: """) + Type 'yes' to continue, or 'no' to cancel: """ + ) else: - confirm = 'yes' + confirm = "yes" - if confirm != 'yes': + if confirm != "yes": print("Migrations reset cancelled.") return - for filename in iglob('src/**/migrations/0*.py', recursive=True): + for filename in iglob("src/**/migrations/0*.py", recursive=True): os.unlink(filename) - call_command('makemigrations') + call_command("makemigrations") check_call("git add src/**/migrations/0*.py", shell=True) diff --git a/src/donor_reporting_portal/apps/core/templatetags/core.py b/src/donor_reporting_portal/apps/core/templatetags/core.py index 374897bd..71f82568 100644 --- a/src/donor_reporting_portal/apps/core/templatetags/core.py +++ b/src/donor_reporting_portal/apps/core/templatetags/core.py @@ -8,4 +8,4 @@ @register.simple_tag def version(): - return mark_safe('{}: v{}'.format(NAME, VERSION)) + return mark_safe("{}: v{}".format(NAME, VERSION)) diff --git a/src/donor_reporting_portal/apps/report_metadata/admin.py b/src/donor_reporting_portal/apps/report_metadata/admin.py index 1f574186..6b1f67c8 100644 --- a/src/donor_reporting_portal/apps/report_metadata/admin.py +++ b/src/donor_reporting_portal/apps/report_metadata/admin.py @@ -10,52 +10,52 @@ class GrantSyncMixin(ExtraButtonsMixin): - @button() def _sync_grants(self, request): grant_sync.delay() - messages.add_message(request, messages.INFO, 'Task for Grant sync has been scheduled') - return HttpResponseRedirect(reverse('admin:report_metadata_grant_changelist')) + messages.add_message(request, messages.INFO, "Task for Grant sync has been scheduled") + return HttpResponseRedirect(reverse("admin:report_metadata_grant_changelist")) @admin.register(Theme) class ThemeAdmin(admin.ModelAdmin): - search_fields = ('name', ) - list_display = ('name', ) + search_fields = ("name",) + list_display = ("name",) @admin.register(ExternalGrant) class ExternalGrantAdmin(GrantSyncMixin, admin.ModelAdmin): - search_fields = ('code', 'donor__code') - list_display = ('code', 'donor') + search_fields = ("code", "donor__code") + list_display = ("code", "donor") @admin.register(Donor) class DonorAdmin(GrantSyncMixin, admin.ModelAdmin): - search_fields = ('name', 'code') - list_display = ('name', 'code', 'us_gov', 'active') - list_filter = ('us_gov', 'active') + search_fields = ("name", "code") + list_display = ("name", "code", "us_gov", "active") + list_filter = ("us_gov", "active") @admin.register(Grant) class GrantAdmin(GrantSyncMixin, admin.ModelAdmin): - search_fields = ('code',) - list_display = ('code', 'donor', 'category', 'year') - list_filter = ('category', 'donor', 'year') - filter_horizontal = ( - 'business_areas', - ) + search_fields = ("code",) + list_display = ("code", "donor", "category", "year") + list_filter = ("category", "donor", "year") + filter_horizontal = ("business_areas",) # @admin.register(SecondaryDonor) class SecondaryDonorAdmin(GrantSyncMixin, admin.ModelAdmin): - search_fields = ('name', 'code') - list_display = ('name', 'code', ) - raw_id_fields = ('grants', ) + search_fields = ("name", "code") + list_display = ( + "name", + "code", + ) + raw_id_fields = ("grants",) @admin.register(DRPMetadata) class DRPMetadata(admin.ModelAdmin): - search_fields = ('description', 'code') - list_display = ('category', 'description', 'audience') - list_filter = ('category', 'audience') + search_fields = ("description", "code") + list_display = ("category", "description", "audience") + list_filter = ("category", "audience") diff --git a/src/donor_reporting_portal/apps/report_metadata/apps.py b/src/donor_reporting_portal/apps/report_metadata/apps.py index 64c3bfb1..4a985786 100644 --- a/src/donor_reporting_portal/apps/report_metadata/apps.py +++ b/src/donor_reporting_portal/apps/report_metadata/apps.py @@ -2,5 +2,5 @@ class AppConfig(BaseAppConfig): - name = __name__.rpartition('.')[0] - verbose_name = 'Report Metadata' + name = __name__.rpartition(".")[0] + verbose_name = "Report Metadata" diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0001_initial.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0001_initial.py index 80ec0dd3..828b3e07 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0001_initial.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0001_initial.py @@ -8,7 +8,6 @@ class Migration(migrations.Migration): - initial = True dependencies = [ @@ -17,61 +16,213 @@ class Migration(migrations.Migration): operations = [ migrations.CreateModel( - name='Donor', + name="Donor", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('name', models.CharField(max_length=64, verbose_name='Name')), - ('code', models.CharField(max_length=16, unique=True, verbose_name='Code')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ("name", models.CharField(max_length=64, verbose_name="Name")), + ( + "code", + models.CharField(max_length=16, unique=True, verbose_name="Code"), + ), ], options={ - 'ordering': ['name'], + "ordering": ["name"], }, ), migrations.CreateModel( - name='ExternalReferenceGrant', + name="ExternalReferenceGrant", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('code', models.CharField(max_length=64, verbose_name='Code')), - ('donor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='report_metadata.Donor', verbose_name='Donor')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ("code", models.CharField(max_length=64, verbose_name="Code")), + ( + "donor", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="report_metadata.Donor", + verbose_name="Donor", + ), + ), ], options={ - 'ordering': ['code'], + "ordering": ["code"], }, ), migrations.CreateModel( - name='Theme', + name="Theme", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('name', models.CharField(max_length=64, verbose_name='Name')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ("name", models.CharField(max_length=64, verbose_name="Name")), ], options={ - 'abstract': False, + "abstract": False, }, ), migrations.CreateModel( - name='Grant', + name="Grant", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('code', models.CharField(max_length=16, unique=True, verbose_name='Code')), - ('expiry_date', models.DateField(blank=True, null=True, verbose_name='Expiry Date')), - ('financial_close_date', models.DateField(blank=True, null=True, verbose_name='Financial Close Date')), - ('year', models.CharField(max_length=4, verbose_name='Year')), - ('category', models.CharField(choices=[('STD', 'Standard'), ('THE', 'Thematic'), ('FFR', 'FFR')], max_length=16, verbose_name='Category')), - ('business_areas', models.ManyToManyField(blank=True, to=settings.BUSINESSAREA_MODEL, verbose_name='Business Areas')), - ('donor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='report_metadata.Donor', verbose_name='Donor')), - ('external_reference', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='report_metadata.ExternalReferenceGrant', verbose_name='External Reference')), - ('theme', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='report_metadata.Theme', verbose_name='Theme')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ( + "code", + models.CharField(max_length=16, unique=True, verbose_name="Code"), + ), + ( + "expiry_date", + models.DateField(blank=True, null=True, verbose_name="Expiry Date"), + ), + ( + "financial_close_date", + models.DateField( + blank=True, null=True, verbose_name="Financial Close Date" + ), + ), + ("year", models.CharField(max_length=4, verbose_name="Year")), + ( + "category", + models.CharField( + choices=[ + ("STD", "Standard"), + ("THE", "Thematic"), + ("FFR", "FFR"), + ], + max_length=16, + verbose_name="Category", + ), + ), + ( + "business_areas", + models.ManyToManyField( + blank=True, + to=settings.BUSINESSAREA_MODEL, + verbose_name="Business Areas", + ), + ), + ( + "donor", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="report_metadata.Donor", + verbose_name="Donor", + ), + ), + ( + "external_reference", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="report_metadata.ExternalReferenceGrant", + verbose_name="External Reference", + ), + ), + ( + "theme", + models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + to="report_metadata.Theme", + verbose_name="Theme", + ), + ), ], options={ - 'ordering': ['donor'], + "ordering": ["donor"], }, ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0002_auto_20190920_0330.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0002_auto_20190920_0330.py index ac031a01..a997b1dc 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0002_auto_20190920_0330.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0002_auto_20190920_0330.py @@ -4,14 +4,13 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0001_initial'), + ("report_metadata", "0001_initial"), ] operations = [ migrations.RenameModel( - old_name='ExternalReferenceGrant', - new_name='ExternalGrant', + old_name="ExternalReferenceGrant", + new_name="ExternalGrant", ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0003_auto_20190920_0615.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0003_auto_20190920_0615.py index 4db1d4e3..4b8e9fa6 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0003_auto_20190920_0615.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0003_auto_20190920_0615.py @@ -4,15 +4,14 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0002_auto_20190920_0330'), + ("report_metadata", "0002_auto_20190920_0330"), ] operations = [ migrations.RenameField( - model_name='grant', - old_name='external_reference', - new_name='external_grant', + model_name="grant", + old_name="external_reference", + new_name="external_grant", ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0004_auto_20191011_0804.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0004_auto_20191011_0804.py index ad61558c..63190da8 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0004_auto_20191011_0804.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0004_auto_20191011_0804.py @@ -4,19 +4,20 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0003_auto_20190920_0615'), + ("report_metadata", "0003_auto_20190920_0615"), ] operations = [ migrations.RemoveField( - model_name='grant', - name='external_grant', + model_name="grant", + name="external_grant", ), migrations.AddField( - model_name='grant', - name='description', - field=models.CharField(blank=True, max_length=516, null=True, verbose_name='Description'), + model_name="grant", + name="description", + field=models.CharField( + blank=True, max_length=516, null=True, verbose_name="Description" + ), ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0005_auto_20191014_0955.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0005_auto_20191014_0955.py index 083a341d..cd9f56e8 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0005_auto_20191014_0955.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0005_auto_20191014_0955.py @@ -4,15 +4,23 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0004_auto_20191011_0804'), + ("report_metadata", "0004_auto_20191011_0804"), ] operations = [ migrations.AlterField( - model_name='grant', - name='category', - field=models.CharField(choices=[('STD', 'Standard'), ('THE', 'Thematic'), ('FFR', 'Us Gov'), ('JPO', 'JPO Summary')], max_length=16, verbose_name='Category'), + model_name="grant", + name="category", + field=models.CharField( + choices=[ + ("STD", "Standard"), + ("THE", "Thematic"), + ("FFR", "Us Gov"), + ("JPO", "JPO Summary"), + ], + max_length=16, + verbose_name="Category", + ), ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0006_donor_us_gov.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0006_donor_us_gov.py index f16460ba..03dfd0d0 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0006_donor_us_gov.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0006_donor_us_gov.py @@ -4,15 +4,14 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0005_auto_20191014_0955'), + ("report_metadata", "0005_auto_20191014_0955"), ] operations = [ migrations.AddField( - model_name='donor', - name='us_gov', - field=models.BooleanField(default=False, verbose_name='Us Gov Flag'), + model_name="donor", + name="us_gov", + field=models.BooleanField(default=False, verbose_name="Us Gov Flag"), ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0007_auto_20200205_1148.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0007_auto_20200205_1148.py index 10492402..0ef3b63e 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0007_auto_20200205_1148.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0007_auto_20200205_1148.py @@ -4,14 +4,13 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0006_donor_us_gov'), + ("report_metadata", "0006_donor_us_gov"), ] operations = [ migrations.AlterModelOptions( - name='theme', - options={'ordering': ['name']}, + name="theme", + options={"ordering": ["name"]}, ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0008_secondarydonor.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0008_secondarydonor.py index 0ca55f41..3e4b2c65 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0008_secondarydonor.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0008_secondarydonor.py @@ -6,24 +6,48 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0007_auto_20200205_1148'), + ("report_metadata", "0007_auto_20200205_1148"), ] operations = [ migrations.CreateModel( - name='SecondaryDonor', + name="SecondaryDonor", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('name', models.CharField(max_length=64, verbose_name='Name')), - ('code', models.CharField(max_length=16, unique=True, verbose_name='Code')), - ('grants', models.ManyToManyField(to='report_metadata.Grant')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ("name", models.CharField(max_length=64, verbose_name="Name")), + ( + "code", + models.CharField(max_length=16, unique=True, verbose_name="Code"), + ), + ("grants", models.ManyToManyField(to="report_metadata.Grant")), ], options={ - 'ordering': ['name'], + "ordering": ["name"], }, ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0009_donor_active.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0009_donor_active.py index eba2d2d3..dba7279d 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0009_donor_active.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0009_donor_active.py @@ -4,15 +4,14 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0008_secondarydonor'), + ("report_metadata", "0008_secondarydonor"), ] operations = [ migrations.AddField( - model_name='donor', - name='active', - field=models.BooleanField(default=True, verbose_name='Active'), + model_name="donor", + name="active", + field=models.BooleanField(default=True, verbose_name="Active"), ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0010_drpmetadata.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0010_drpmetadata.py index e7747cdf..2ac77489 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0010_drpmetadata.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0010_drpmetadata.py @@ -6,26 +6,63 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0009_donor_active'), + ("report_metadata", "0009_donor_active"), ] operations = [ migrations.CreateModel( - name='DRPMetadata', + name="DRPMetadata", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('category', models.CharField(max_length=128, verbose_name='Category')), - ('code', models.CharField(blank=True, max_length=128, null=True, verbose_name='Code')), - ('description', models.CharField(max_length=128, verbose_name='Description')), - ('audience', models.CharField(choices=[('int', 'int'), ('ext', 'ext'), ('all', 'all')], default='all', max_length=4, verbose_name='Audience')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ("category", models.CharField(max_length=128, verbose_name="Category")), + ( + "code", + models.CharField( + blank=True, max_length=128, null=True, verbose_name="Code" + ), + ), + ( + "description", + models.CharField(max_length=128, verbose_name="Description"), + ), + ( + "audience", + models.CharField( + choices=[("int", "int"), ("ext", "ext"), ("all", "all")], + default="all", + max_length=4, + verbose_name="Audience", + ), + ), ], options={ - 'verbose_name': 'Metadata', - 'verbose_name_plural': 'Metadata', + "verbose_name": "Metadata", + "verbose_name_plural": "Metadata", }, ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0011_remove_grant_business_areas.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0011_remove_grant_business_areas.py index 0904bd65..7e1c9ebf 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0011_remove_grant_business_areas.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0011_remove_grant_business_areas.py @@ -4,14 +4,13 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0010_drpmetadata'), + ("report_metadata", "0010_drpmetadata"), ] operations = [ migrations.RemoveField( - model_name='grant', - name='business_areas', + model_name="grant", + name="business_areas", ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0012_grant_business_areas.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0012_grant_business_areas.py index 4c8b328d..89fad035 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0012_grant_business_areas.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0012_grant_business_areas.py @@ -4,16 +4,19 @@ class Migration(migrations.Migration): - dependencies = [ - ('unicef_realm', '0001_initial'), - ('report_metadata', '0011_remove_grant_business_areas'), + ("unicef_realm", "0001_initial"), + ("report_metadata", "0011_remove_grant_business_areas"), ] operations = [ migrations.AddField( - model_name='grant', - name='business_areas', - field=models.ManyToManyField(blank=True, to='unicef_realm.businessarea', verbose_name='Business Areas'), + model_name="grant", + name="business_areas", + field=models.ManyToManyField( + blank=True, + to="unicef_realm.businessarea", + verbose_name="Business Areas", + ), ), ] diff --git a/src/donor_reporting_portal/apps/report_metadata/migrations/0013_auto_20220608_1003.py b/src/donor_reporting_portal/apps/report_metadata/migrations/0013_auto_20220608_1003.py index b1389299..a8bfbb7f 100644 --- a/src/donor_reporting_portal/apps/report_metadata/migrations/0013_auto_20220608_1003.py +++ b/src/donor_reporting_portal/apps/report_metadata/migrations/0013_auto_20220608_1003.py @@ -5,16 +5,15 @@ def clean_metadata(apps, schema_editor): ContentType = apps.get_model("contenttypes", "ContentType") - qs = ContentType.objects.filter(app_label='unicef_security', model__in=['region', 'businessarea']) + qs = ContentType.objects.filter( + app_label="unicef_security", model__in=["region", "businessarea"] + ) qs.delete() class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0012_grant_business_areas'), + ("report_metadata", "0012_grant_business_areas"), ] - operations = [ - migrations.RunPython(clean_metadata, migrations.RunPython.noop) - ] + operations = [migrations.RunPython(clean_metadata, migrations.RunPython.noop)] diff --git a/src/donor_reporting_portal/apps/report_metadata/models.py b/src/donor_reporting_portal/apps/report_metadata/models.py index ecac84d4..540bd35c 100644 --- a/src/donor_reporting_portal/apps/report_metadata/models.py +++ b/src/donor_reporting_portal/apps/report_metadata/models.py @@ -7,10 +7,11 @@ class Theme(TimeStampedModel): """Represents Thematic""" + name = models.CharField(verbose_name=_("Name"), max_length=64) class Meta: - ordering = ['name'] + ordering = ["name"] class Donor(TimeStampedModel): @@ -22,36 +23,38 @@ class Donor(TimeStampedModel): active = models.BooleanField(verbose_name=_("Active"), default=True) class Meta: - ordering = ['name'] + ordering = ["name"] def __str__(self): - return f'{self.name} ({self.code})' + return f"{self.name} ({self.code})" class ExternalGrant(TimeStampedModel): """Represents External Grant""" + code = models.CharField(verbose_name=_("Code"), max_length=64) donor = models.ForeignKey(Donor, verbose_name=_("Donor"), on_delete=models.CASCADE) class Meta: - ordering = ['code'] + ordering = ["code"] def __str__(self): - return f'{self.code} ({self.donor})' + return f"{self.code} ({self.donor})" class Grant(TimeStampedModel): """Represents the name of a Grant.""" - STANDARD = 'STD' - THEMATIC = 'THE' - FFR = 'FFR' - JPO = 'JPO' + + STANDARD = "STD" + THEMATIC = "THE" + FFR = "FFR" + JPO = "JPO" CATEGORIES = ( - (STANDARD, 'Standard'), - (THEMATIC, 'Thematic'), - (FFR, 'Us Gov'), - (JPO, 'JPO Summary'), + (STANDARD, "Standard"), + (THEMATIC, "Thematic"), + (FFR, "Us Gov"), + (JPO, "JPO Summary"), ) donor = models.ForeignKey(Donor, verbose_name=_("Donor"), on_delete=models.CASCADE) @@ -59,19 +62,16 @@ class Grant(TimeStampedModel): expiry_date = models.DateField(verbose_name=_("Expiry Date"), null=True, blank=True) financial_close_date = models.DateField(verbose_name=_("Financial Close Date"), null=True, blank=True) business_areas = models.ManyToManyField(BusinessArea, verbose_name=_("Business Areas"), blank=True) - year = models.CharField(max_length=4, verbose_name=_('Year')) + year = models.CharField(max_length=4, verbose_name=_("Year")) theme = models.ForeignKey(Theme, verbose_name=_("Theme"), on_delete=models.CASCADE, null=True, blank=True) - category = models.CharField(max_length=16, choices=CATEGORIES, verbose_name=_('Category')) - description = models.CharField(max_length=516, verbose_name=_('Description'), null=True, blank=True) + category = models.CharField(max_length=16, choices=CATEGORIES, verbose_name=_("Category")) + description = models.CharField(max_length=516, verbose_name=_("Description"), null=True, blank=True) class Meta: - ordering = ['donor'] + ordering = ["donor"] def __str__(self): - return "{}: {}".format( - self.donor.name, - self.code - ) + return "{}: {}".format(self.donor.name, self.code) class SecondaryDonor(TimeStampedModel): @@ -82,38 +82,38 @@ class SecondaryDonor(TimeStampedModel): grants = models.ManyToManyField(Grant) class Meta: - ordering = ['name'] + ordering = ["name"] def __str__(self): - return f'{self.name} ({self.code})' + return f"{self.name} ({self.code})" class DRPMetadata(TimeStampedModel): - INTERNAL = 'int' - EXTERNAL = 'ext' - ALL = 'all' + INTERNAL = "int" + EXTERNAL = "ext" + ALL = "all" AUDIENCE = ( - (INTERNAL, 'int'), - (EXTERNAL, 'ext'), - (ALL, 'all'), + (INTERNAL, "int"), + (EXTERNAL, "ext"), + (ALL, "all"), ) category = models.CharField(verbose_name=_("Category"), max_length=128) code = models.CharField(verbose_name=_("Code"), max_length=128, null=True, blank=True) description = models.CharField(verbose_name=_("Description"), max_length=128) - audience = models.CharField(max_length=4, choices=AUDIENCE, verbose_name=_('Audience'), default=ALL) + audience = models.CharField(max_length=4, choices=AUDIENCE, verbose_name=_("Audience"), default=ALL) class Meta: - verbose_name = 'Metadata' - verbose_name_plural = 'Metadata' + verbose_name = "Metadata" + verbose_name_plural = "Metadata" def __str__(self): - return f'{self.category} | {self.description} | {self.audience}' + return f"{self.category} | {self.description} | {self.audience}" @staticmethod def create_code(description): - return description.lower().replace(' ', '_') + return description.lower().replace(" ", "_") def save(self, *args, **kwargs): if not self.code: diff --git a/src/donor_reporting_portal/apps/report_metadata/notifications/notify_donor.py b/src/donor_reporting_portal/apps/report_metadata/notifications/notify_donor.py index da706bfb..461e6de7 100644 --- a/src/donor_reporting_portal/apps/report_metadata/notifications/notify_donor.py +++ b/src/donor_reporting_portal/apps/report_metadata/notifications/notify_donor.py @@ -4,7 +4,8 @@ defaults = { "description": "Notify Donor", "subject": "Updated reports available in UNICEF DRP", - "content": strip_text("""Dear user, + "content": strip_text( + """Dear user, The following reports have been updated in the Donor Reporting Portal (drp.unicef.org). @@ -22,7 +23,8 @@ Please do not reply. For any questions on the reports, please contact your UNICEF colleague. Regards. - """), + """ + ), "html_content": """Dear user,

The following reports have been updated in the Donor Reporting Portal (drp.unicef.org). diff --git a/src/donor_reporting_portal/apps/report_metadata/notifications/notify_gavi.py b/src/donor_reporting_portal/apps/report_metadata/notifications/notify_gavi.py index ae751ffb..c64a4bd5 100644 --- a/src/donor_reporting_portal/apps/report_metadata/notifications/notify_gavi.py +++ b/src/donor_reporting_portal/apps/report_metadata/notifications/notify_gavi.py @@ -4,7 +4,8 @@ defaults = { "description": "Notify GAVI Donor", "subject": "Updated GAVI reports available in UNICEF DRP", - "content": strip_text("""Dear user, + "content": strip_text( + """Dear user, The following CTNs have been uploaded in the UNICEF Reporting Portal: @@ -23,7 +24,8 @@ Please do not reply to this mail. For any questions on these reports, please contact your UNICEF focal point. Regards. - """), + """ + ), "html_content": """Dear user,

The following CTNs have been uploaded in the UNICEF Reporting Portal: diff --git a/src/donor_reporting_portal/apps/report_metadata/notifications/notify_urgent_gavi.py b/src/donor_reporting_portal/apps/report_metadata/notifications/notify_urgent_gavi.py index 6c1a7812..f1c78273 100644 --- a/src/donor_reporting_portal/apps/report_metadata/notifications/notify_urgent_gavi.py +++ b/src/donor_reporting_portal/apps/report_metadata/notifications/notify_urgent_gavi.py @@ -4,7 +4,8 @@ defaults = { "description": "Urgent: Notify GAVI Donor", "subject": "Urgent: Updated GAVI reports available in UNICEF DRP", - "content": strip_text("""Dear user, + "content": strip_text( + """Dear user, The following CTNs have been uploaded in the UNICEF Reporting Portal: @@ -23,7 +24,8 @@ Please do not reply to this mail. For any questions on these reports, please contact your UNICEF focal point. Regards. - """), + """ + ), "html_content": """Dear user,

The following CTNs have been uploaded in the UNICEF Reporting Portal: diff --git a/src/donor_reporting_portal/apps/report_metadata/synchronizers.py b/src/donor_reporting_portal/apps/report_metadata/synchronizers.py index f9cce825..de06e18c 100644 --- a/src/donor_reporting_portal/apps/report_metadata/synchronizers.py +++ b/src/donor_reporting_portal/apps/report_metadata/synchronizers.py @@ -9,30 +9,30 @@ logger = logging.getLogger(__name__) -def get_date(date_string, format='%d-%b-%y'): +def get_date(date_string, format="%d-%b-%y"): if date_string: return datetime.strptime(date_string, format) def get_type(record): - if record['THEMATIC']: + if record["THEMATIC"]: return Grant.THEMATIC - elif record['USGOV_FLAG']: + elif record["USGOV_FLAG"]: return Grant.FFR return Grant.STANDARD class GrantSynchronizer(VisionDataSynchronizer): - ENDPOINT = 'dsgrants' + ENDPOINT = "dsgrants" GLOBAL_CALL = True REQUIRED_KEYS = ( - 'DONOR_CODE', - 'DONOR_NAME', - 'GRANT_REF', + "DONOR_CODE", + "DONOR_NAME", + "GRANT_REF", ) def _convert_records(self, records): - return records['ROWSET']['ROW'] + return records["ROWSET"]["ROW"] def _save_records(self, records): processed = 0 @@ -54,35 +54,42 @@ def is_valid_record(record): def _item_save(record): logger.info(f'parsing {record["GRANT_REF"]}') - donor, _ = Donor.objects.update_or_create(code=record['DONOR_CODE'], defaults={ - 'name': record['DONOR_NAME'], - 'us_gov': bool(record['USGOV_FLAG']) - }) + donor, _ = Donor.objects.update_or_create( + code=record["DONOR_CODE"], + defaults={ + "name": record["DONOR_NAME"], + "us_gov": bool(record["USGOV_FLAG"]), + }, + ) grant_defaults = { - 'year': record['ISSUE_YEAR'], - 'expiry_date': get_date(record['EXPIRY_DATE']), - 'financial_close_date': get_date(record.get('FINANCIALLY_CLOSE_DATE', None)), - 'description': record['DESCRIPTION'], - 'donor': donor, - 'category': get_type(record), + "year": record["ISSUE_YEAR"], + "expiry_date": get_date(record["EXPIRY_DATE"]), + "financial_close_date": get_date(record.get("FINANCIALLY_CLOSE_DATE", None)), + "description": record["DESCRIPTION"], + "donor": donor, + "category": get_type(record), } - grant, _ = Grant.objects.update_or_create(code=record['GRANT_REF'], defaults=grant_defaults) - if record['THEMATIC']: - theme, _ = Theme.objects.get_or_create(name=record['THEMATIC']) - grant_defaults['theme'] = theme - if record['EXTERNAL_REF']: + grant, _ = Grant.objects.update_or_create(code=record["GRANT_REF"], defaults=grant_defaults) + if record["THEMATIC"]: + theme, _ = Theme.objects.get_or_create(name=record["THEMATIC"]) + grant_defaults["theme"] = theme + if record["EXTERNAL_REF"]: external_grant, _ = ExternalGrant.objects.get_or_create( - code=record['EXTERNAL_REF'], defaults={'donor': donor}) + code=record["EXTERNAL_REF"], defaults={"donor": donor} + ) - if record.get('RECIPIENT_OFFICE_CODE', None): - grant.business_areas.set(BusinessArea.objects.filter(code__in=record['RECIPIENT_OFFICE_CODE'].split('; '))) + if record.get("RECIPIENT_OFFICE_CODE", None): + grant.business_areas.set(BusinessArea.objects.filter(code__in=record["RECIPIENT_OFFICE_CODE"].split("; "))) - if record.get('SECONDARY_DONOR_CODE', None): - secondary_donors_codes = record['SECONDARY_DONOR_CODE'].split(';') - secondary_donors_names = record['SECONDARY_DONOR'].split(';') + if record.get("SECONDARY_DONOR_CODE", None): + secondary_donors_codes = record["SECONDARY_DONOR_CODE"].split(";") + secondary_donors_names = record["SECONDARY_DONOR"].split(";") assert len(secondary_donors_codes) == len(secondary_donors_names) for code, name in zip(secondary_donors_codes, secondary_donors_names): - secondary_donor, _, = SecondaryDonor.objects.get_or_create(code=code, defaults={'name': name}) + ( + secondary_donor, + _, + ) = SecondaryDonor.objects.get_or_create(code=code, defaults={"name": name}) secondary_donor.grants.add(grant) return 1 diff --git a/src/donor_reporting_portal/apps/report_metadata/tasks.py b/src/donor_reporting_portal/apps/report_metadata/tasks.py index c212401e..12b481dd 100644 --- a/src/donor_reporting_portal/apps/report_metadata/tasks.py +++ b/src/donor_reporting_portal/apps/report_metadata/tasks.py @@ -8,6 +8,6 @@ @app.task def grant_sync(): - logger.info('Grant Sync Area Sync Started') + logger.info("Grant Sync Area Sync Started") GrantSynchronizer().sync() - logger.info('Grant Sync Area Sync Ended') + logger.info("Grant Sync Area Sync Ended") diff --git a/src/donor_reporting_portal/apps/roles/admin.py b/src/donor_reporting_portal/apps/roles/admin.py index 72b0f334..2f97b81a 100644 --- a/src/donor_reporting_portal/apps/roles/admin.py +++ b/src/donor_reporting_portal/apps/roles/admin.py @@ -10,7 +10,11 @@ @admin.register(UserRole) class UserRoleAdmin(admin.ModelAdmin): - search_fields = ('user__username', 'donor__name', 'secondary_donor__name', ) - list_display = ('user', 'group', 'donor', 'secondary_donor', 'notification_period') - list_filter = ('group', 'donor', 'secondary_donor', 'notification_period') - raw_id_fields = ('user', 'group', 'donor', 'secondary_donor') + search_fields = ( + "user__username", + "donor__name", + "secondary_donor__name", + ) + list_display = ("user", "group", "donor", "secondary_donor", "notification_period") + list_filter = ("group", "donor", "secondary_donor", "notification_period") + raw_id_fields = ("user", "group", "donor", "secondary_donor") diff --git a/src/donor_reporting_portal/apps/roles/apps.py b/src/donor_reporting_portal/apps/roles/apps.py index 69eafa7a..4329ca85 100644 --- a/src/donor_reporting_portal/apps/roles/apps.py +++ b/src/donor_reporting_portal/apps/roles/apps.py @@ -2,5 +2,5 @@ class AppConfig(BaseAppConfig): - name = __name__.rpartition('.')[0] - verbose_name = 'Roles' + name = __name__.rpartition(".")[0] + verbose_name = "Roles" diff --git a/src/donor_reporting_portal/apps/roles/migrations/0001_initial.py b/src/donor_reporting_portal/apps/roles/migrations/0001_initial.py index d8137107..b06309c5 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0001_initial.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0001_initial.py @@ -8,30 +8,72 @@ class Migration(migrations.Migration): - initial = True dependencies = [ - ('report_metadata', '0001_initial'), + ("report_metadata", "0001_initial"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('auth', '0011_update_proxy_permissions'), + ("auth", "0011_update_proxy_permissions"), ] operations = [ migrations.CreateModel( - name='UserRole', + name="UserRole", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('donor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='roles', to='report_metadata.Donor')), - ('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='roles', to='auth.Group')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='roles', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ( + "donor", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="roles", + to="report_metadata.Donor", + ), + ), + ( + "group", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="roles", + to="auth.Group", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="roles", + to=settings.AUTH_USER_MODEL, + ), + ), ], options={ - 'verbose_name': 'User Role', - 'verbose_name_plural': 'User Roles', - 'unique_together': {('user', 'group', 'donor')}, + "verbose_name": "User Role", + "verbose_name_plural": "User Roles", + "unique_together": {("user", "group", "donor")}, }, ), ] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0002_auto_20190920_0339.py b/src/donor_reporting_portal/apps/roles/migrations/0002_auto_20190920_0339.py index dcded134..3154e47b 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0002_auto_20190920_0339.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0002_auto_20190920_0339.py @@ -4,14 +4,17 @@ class Migration(migrations.Migration): - dependencies = [ - ('roles', '0001_initial'), + ("roles", "0001_initial"), ] operations = [ migrations.AlterModelOptions( - name='userrole', - options={'permissions': (('is_unicef_user', 'Is UNICEF User'),), 'verbose_name': 'User Role', 'verbose_name_plural': 'User Roles'}, + name="userrole", + options={ + "permissions": (("is_unicef_user", "Is UNICEF User"),), + "verbose_name": "User Role", + "verbose_name_plural": "User Roles", + }, ), ] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0003_auto_20191007_1102.py b/src/donor_reporting_portal/apps/roles/migrations/0003_auto_20191007_1102.py index 41670cd5..a45a8745 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0003_auto_20191007_1102.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0003_auto_20191007_1102.py @@ -4,14 +4,17 @@ class Migration(migrations.Migration): - dependencies = [ - ('roles', '0002_auto_20190920_0339'), + ("roles", "0002_auto_20190920_0339"), ] operations = [ migrations.AlterModelOptions( - name='userrole', - options={'permissions': (('can_view_all_donors', 'Can views all Donors'),), 'verbose_name': 'User Role', 'verbose_name_plural': 'User Roles'}, + name="userrole", + options={ + "permissions": (("can_view_all_donors", "Can views all Donors"),), + "verbose_name": "User Role", + "verbose_name_plural": "User Roles", + }, ), ] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0004_auto_20200220_1101.py b/src/donor_reporting_portal/apps/roles/migrations/0004_auto_20200220_1101.py index ca7cc148..dc1404a5 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0004_auto_20200220_1101.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0004_auto_20200220_1101.py @@ -6,22 +6,27 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0008_secondarydonor'), - ('auth', '0011_update_proxy_permissions'), + ("report_metadata", "0008_secondarydonor"), + ("auth", "0011_update_proxy_permissions"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('roles', '0003_auto_20191007_1102'), + ("roles", "0003_auto_20191007_1102"), ] operations = [ migrations.AddField( - model_name='userrole', - name='secondary_donor', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='roles', to='report_metadata.SecondaryDonor'), + model_name="userrole", + name="secondary_donor", + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="roles", + to="report_metadata.SecondaryDonor", + ), ), migrations.AlterUniqueTogether( - name='userrole', - unique_together={('user', 'group', 'donor', 'secondary_donor')}, + name="userrole", + unique_together={("user", "group", "donor", "secondary_donor")}, ), ] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0005_auto_20200302_1609.py b/src/donor_reporting_portal/apps/roles/migrations/0005_auto_20200302_1609.py index 391f778f..c7ced13a 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0005_auto_20200302_1609.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0005_auto_20200302_1609.py @@ -5,16 +5,22 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0008_secondarydonor'), - ('roles', '0004_auto_20200220_1101'), + ("report_metadata", "0008_secondarydonor"), + ("roles", "0004_auto_20200220_1101"), ] operations = [ migrations.AlterField( - model_name='userrole', - name='secondary_donor', - field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='roles', to='report_metadata.SecondaryDonor'), + model_name="userrole", + name="secondary_donor", + field=models.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="roles", + to="report_metadata.SecondaryDonor", + ), ), ] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0006_userrole_notification_period.py b/src/donor_reporting_portal/apps/roles/migrations/0006_userrole_notification_period.py index ca565ce7..7a2fdc51 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0006_userrole_notification_period.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0006_userrole_notification_period.py @@ -4,15 +4,24 @@ class Migration(migrations.Migration): - dependencies = [ - ('roles', '0005_auto_20200302_1609'), + ("roles", "0005_auto_20200302_1609"), ] operations = [ migrations.AddField( - model_name='userrole', - name='notification_period', - field=models.CharField(choices=[('none', 'Disabled'), ('every_day', 'Every Day'), ('every_monday', 'Every Monday'), ('every_month', 'Every Month')], default='every_day', max_length=16, verbose_name='Notification Period'), + model_name="userrole", + name="notification_period", + field=models.CharField( + choices=[ + ("none", "Disabled"), + ("every_day", "Every Day"), + ("every_monday", "Every Monday"), + ("every_month", "Every Month"), + ], + default="every_day", + max_length=16, + verbose_name="Notification Period", + ), ), ] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0007_alter_userrole_notification_period.py b/src/donor_reporting_portal/apps/roles/migrations/0007_alter_userrole_notification_period.py index 663f9791..6b70c3f7 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0007_alter_userrole_notification_period.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0007_alter_userrole_notification_period.py @@ -4,15 +4,24 @@ class Migration(migrations.Migration): - dependencies = [ - ('roles', '0006_userrole_notification_period'), + ("roles", "0006_userrole_notification_period"), ] operations = [ migrations.AlterField( - model_name='userrole', - name='notification_period', - field=models.CharField(choices=[('none', 'Disabled'), ('every_day', 'Every Day'), ('every_monday', 'Every Monday'), ('every_month', 'Every Month')], default='none', max_length=16, verbose_name='Notification Period'), + model_name="userrole", + name="notification_period", + field=models.CharField( + choices=[ + ("none", "Disabled"), + ("every_day", "Every Day"), + ("every_monday", "Every Monday"), + ("every_month", "Every Month"), + ], + default="none", + max_length=16, + verbose_name="Notification Period", + ), ), ] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0008_auto_20220128_1054.py b/src/donor_reporting_portal/apps/roles/migrations/0008_auto_20220128_1054.py index f2892124..820e7a00 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0008_auto_20220128_1054.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0008_auto_20220128_1054.py @@ -2,17 +2,15 @@ from django.db import migrations + def migrate_workspace(apps, schema_editor): UserRole = apps.get_model("roles", "UserRole") - UserRole.objects.update(notification_period='none') + UserRole.objects.update(notification_period="none") class Migration(migrations.Migration): - dependencies = [ - ('roles', '0007_alter_userrole_notification_period'), + ("roles", "0007_alter_userrole_notification_period"), ] - operations = [ - migrations.RunPython(migrate_workspace, migrations.RunPython.noop) - ] + operations = [migrations.RunPython(migrate_workspace, migrations.RunPython.noop)] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0009_auto_20220511_1724.py b/src/donor_reporting_portal/apps/roles/migrations/0009_auto_20220511_1724.py index 1dd1b277..b265a6cb 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0009_auto_20220511_1724.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0009_auto_20220511_1724.py @@ -6,28 +6,39 @@ class Migration(migrations.Migration): - dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), + ("auth", "0012_alter_user_first_name_max_length"), migrations.swappable_dependency(settings.AUTH_USER_MODEL), # ('report_metadata', '0011_grant_businessareas'), - ('roles', '0008_auto_20220128_1054'), + ("roles", "0008_auto_20220128_1054"), ] operations = [ migrations.AlterField( - model_name='userrole', - name='donor', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_roles', to='report_metadata.donor'), + model_name="userrole", + name="donor", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="user_roles", + to="report_metadata.donor", + ), ), migrations.AlterField( - model_name='userrole', - name='group', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_roles', to='auth.group'), + model_name="userrole", + name="group", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="user_roles", + to="auth.group", + ), ), migrations.AlterField( - model_name='userrole', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_roles', to=settings.AUTH_USER_MODEL), + model_name="userrole", + name="user", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="user_roles", + to=settings.AUTH_USER_MODEL, + ), ), ] diff --git a/src/donor_reporting_portal/apps/roles/migrations/0010_alter_userrole_secondary_donor.py b/src/donor_reporting_portal/apps/roles/migrations/0010_alter_userrole_secondary_donor.py index 96f7e71e..6851d406 100644 --- a/src/donor_reporting_portal/apps/roles/migrations/0010_alter_userrole_secondary_donor.py +++ b/src/donor_reporting_portal/apps/roles/migrations/0010_alter_userrole_secondary_donor.py @@ -5,16 +5,22 @@ class Migration(migrations.Migration): - dependencies = [ - ('report_metadata', '0011_remove_grant_business_areas'), - ('roles', '0009_auto_20220511_1724'), + ("report_metadata", "0011_remove_grant_business_areas"), + ("roles", "0009_auto_20220511_1724"), ] operations = [ migrations.AlterField( - model_name='userrole', - name='secondary_donor', - field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_roles', to='report_metadata.secondarydonor'), + model_name="userrole", + name="secondary_donor", + field=models.ForeignKey( + blank=True, + default=None, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="user_roles", + to="report_metadata.secondarydonor", + ), ), ] diff --git a/src/donor_reporting_portal/apps/roles/models.py b/src/donor_reporting_portal/apps/roles/models.py index d5ce2181..cda7557b 100644 --- a/src/donor_reporting_portal/apps/roles/models.py +++ b/src/donor_reporting_portal/apps/roles/models.py @@ -13,76 +13,90 @@ class UserRoleManager(models.Manager): - def by_permissions(self, perms_name): if not isinstance(perms_name, (set, list)): - perms_name = perms_name, + perms_name = (perms_name,) for perm_name in perms_name: - app_label, codename = perm_name.split('.') - self = self.filter(group__permissions__codename=codename, - group__permissions__content_type__app_label=app_label) + app_label, codename = perm_name.split(".") + self = self.filter( + group__permissions__codename=codename, + group__permissions__content_type__app_label=app_label, + ) return self def get_permissions_by_donor(self, user, donor): return self.filter(user=user, donor=donor, secondary_donor=None).values_list( - 'group__permissions__content_type__app_label', - 'group__permissions__codename') + "group__permissions__content_type__app_label", + "group__permissions__codename", + ) def get_permissions_by_donor_secondary_donor(self, user, donor, secondary_donor): return self.filter(user=user, donor=donor, secondary_donor=secondary_donor).values_list( - 'group__permissions__content_type__app_label', - 'group__permissions__codename') + "group__permissions__content_type__app_label", + "group__permissions__codename", + ) class UserRole(TimeStampedModel): - - DISABLED = 'none' - EVERY_DAY = 'every_day' - EVERY_MONDAY = 'every_monday' - EVERY_MONTH = 'every_month' + DISABLED = "none" + EVERY_DAY = "every_day" + EVERY_MONDAY = "every_monday" + EVERY_MONTH = "every_month" PERIODS = ( - (DISABLED, 'Disabled'), - (EVERY_DAY, 'Every Day'), - (EVERY_MONDAY, 'Every Monday'), - (EVERY_MONTH, 'Every Month'), + (DISABLED, "Disabled"), + (EVERY_DAY, "Every Day"), + (EVERY_MONDAY, "Every Monday"), + (EVERY_MONTH, "Every Month"), + ) + user = models.ForeignKey( + settings.AUTH_USER_MODEL, + related_name="user_roles", + on_delete=models.deletion.CASCADE, + ) + group = models.ForeignKey(Group, related_name="user_roles", on_delete=models.deletion.CASCADE) + donor = models.ForeignKey(Donor, related_name="user_roles", on_delete=models.deletion.CASCADE) + secondary_donor = models.ForeignKey( + SecondaryDonor, + null=True, + blank=True, + default=None, + related_name="user_roles", + on_delete=models.deletion.CASCADE, + ) + notification_period = models.CharField( + max_length=16, + choices=PERIODS, + default=DISABLED, + verbose_name=_("Notification Period"), ) - user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='user_roles', on_delete=models.deletion.CASCADE) - group = models.ForeignKey(Group, related_name='user_roles', on_delete=models.deletion.CASCADE) - donor = models.ForeignKey(Donor, related_name='user_roles', on_delete=models.deletion.CASCADE) - secondary_donor = models.ForeignKey(SecondaryDonor, null=True, blank=True, default=None, related_name='user_roles', - on_delete=models.deletion.CASCADE) - notification_period = models.CharField(max_length=16, - choices=PERIODS, - default=DISABLED, - verbose_name=_('Notification Period')) objects = UserRoleManager() class Meta: - verbose_name = _('User Role') - verbose_name_plural = _('User Roles') - unique_together = (('user', 'group', 'donor', 'secondary_donor'),) - permissions = ( - ('can_view_all_donors', 'Can views all Donors'), - ) + verbose_name = _("User Role") + verbose_name_plural = _("User Roles") + unique_together = (("user", "group", "donor", "secondary_donor"),) + permissions = (("can_view_all_donors", "Can views all Donors"),) def __str__(self): - str = f'{self.user} - {self.group} | {self.donor}' + str = f"{self.user} - {self.group} | {self.donor}" if self.secondary_donor: - str = f'{str} | {self.secondary_donor}' + str = f"{str} | {self.secondary_donor}" return str @receiver(post_save, sender=get_user_model()) def assign_to_unicef_group(instance, created, **kwargs): if created and instance.email: - if instance.username.endswith('@unicef.org'): - unicef_group, _ = Group.objects.get_or_create(name='UNICEF User') + if instance.username.endswith("@unicef.org"): + unicef_group, _ = Group.objects.get_or_create(name="UNICEF User") instance.groups.add(unicef_group) else: - context = {'instance': instance, 'home_link': settings.HOST} + context = {"instance": instance, "home_link": settings.HOST} send_notification_with_template( - [instance.email, ], + [ + instance.email, + ], "access_grant_email", context, ) diff --git a/src/donor_reporting_portal/apps/roles/notifications/access_grant_email.py b/src/donor_reporting_portal/apps/roles/notifications/access_grant_email.py index afc581a7..aca17556 100644 --- a/src/donor_reporting_portal/apps/roles/notifications/access_grant_email.py +++ b/src/donor_reporting_portal/apps/roles/notifications/access_grant_email.py @@ -4,7 +4,8 @@ defaults = { "description": "Access to UNICEF Donor Reporting Portal", "subject": "Access to UNICEF Donor Reporting Portal", - "content": strip_text("""Dear {{ instance.first_name }}, + "content": strip_text( + """Dear {{ instance.first_name }}, You have been granted access to UNICEF Donor Reporting Portal. @@ -12,7 +13,8 @@ username is your e-mail address provided at the time of account registration. Thank you. - """), + """ + ), "html_content": """Dear {{ instance.first_name }},

You have been granted access to UNICEF Donor Reporting Portal.

diff --git a/src/donor_reporting_portal/apps/roles/tasks.py b/src/donor_reporting_portal/apps/roles/tasks.py index 67bcedf8..605866b0 100644 --- a/src/donor_reporting_portal/apps/roles/tasks.py +++ b/src/donor_reporting_portal/apps/roles/tasks.py @@ -35,11 +35,19 @@ def __init__(self, donor_code): self.donor = Donor.objects.get(code=donor_code) def get_notify_periods(self): - return [x for x in [ - (UserRole.EVERY_MONTH, today().replace(day=1) - relativedelta(months=1), today().day == 1), - (UserRole.EVERY_MONDAY, today() - timedelta(7), today().weekday() == 0), - (UserRole.EVERY_DAY, today(), True), - ] if x[2]] + return [ + x + for x in [ + ( + UserRole.EVERY_MONTH, + today().replace(day=1) - relativedelta(months=1), + today().day == 1, + ), + (UserRole.EVERY_MONDAY, today() - timedelta(7), today().weekday() == 0), + (UserRole.EVERY_DAY, today(), True), + ] + if x[2] + ] def get_filter_dict(self, modified_date): return {} @@ -49,7 +57,8 @@ def get_selected_fields(self): def notify(self): client = SharePointClient( - url=f'{config.SHAREPOINT_TENANT}/{config.SHAREPOINT_SITE_TYPE}/{config.SHAREPOINT_SITE}') + url=f"{config.SHAREPOINT_TENANT}/{config.SHAREPOINT_SITE_TYPE}/{config.SHAREPOINT_SITE}" + ) notification_periods = self.get_notify_periods() @@ -68,7 +77,7 @@ def notify(self): filters=filters, select=selected, source_id=self.source_id, - page=page + page=page, ) exit_condition = page * SHAREPOINT_PAGE_SIZE < total_rows page += 1 @@ -76,81 +85,86 @@ def notify(self): reports.extend(qs.data) if reports: - context = {'reports': reports, 'donor': self.donor.name} - recipients = list(set([str(user['user__email']) for user in users if user['user__email']])) + context = {"reports": reports, "donor": self.donor.name} + recipients = list(set([str(user["user__email"]) for user in users if user["user__email"]])) send_notification_with_template(recipients, self.template_name, context) class DonorNotifier(Notifier): - source_id = settings.DRP_SOURCE_IDS['external'] + source_id = settings.DRP_SOURCE_IDS["external"] serializer = DRPSharePointSearchSerializer - template_name = 'notify_donor' + template_name = "notify_donor" def get_filter_dict(self, modified_date): document_type_filter = [ - 'Certified Financial Statement - EC', - 'Certified Financial Statement - US Government', - 'Certified Statement of Account', - 'Certified Statement of Account EU', - 'Certified Statement of Account JPO', - 'Donor Statement CERF', - 'Certified Financial Report - Final', - 'Certified Financial Report - Interim', - 'Donor Statement Innovation', - 'Donor Statement Joint Programme', - 'Donor Statement Joint Programme PUNO', - 'Donor Statement JPO Summary', - 'Donor Statement Trust Fund', - 'Donor Statement UN', - 'Donor Statement UNICEF Hosted Funds', - 'FFR Form (SF-425)', - 'JPO Expenditure Summary', - 'Statement of Account Thematic Funds', - 'Donor Statement by Activity', - 'Interim Statement by Nature of expense', - 'Funds Request Report', - 'Non-Standard Statement', - 'Emergency Consolidated - Final', - 'Emergency Consolidated - Interim', - 'Thematic Emergency Global - Final', - 'Thematic Emergency Global - Interim', - 'Emergency - Two Pager', - 'Emergency - Final', - 'Emergency - Interim', - 'Human Interest / Photos', - 'Narrative - Final', - 'Narrative - Interim', - 'Narrative Consolidated - Final', - 'Narrative Consolidated - Interim', - 'Thematic Consolidated - Final', - 'Thematic Consolidated - Interim', - 'Thematic Global - Final', - 'Thematic Global - Interim', - 'Thematic - Final', - 'Thematic - Interim', - 'Short Summary Update', - 'Official Receipts', - 'Quarterly Monitoring Report', + "Certified Financial Statement - EC", + "Certified Financial Statement - US Government", + "Certified Statement of Account", + "Certified Statement of Account EU", + "Certified Statement of Account JPO", + "Donor Statement CERF", + "Certified Financial Report - Final", + "Certified Financial Report - Interim", + "Donor Statement Innovation", + "Donor Statement Joint Programme", + "Donor Statement Joint Programme PUNO", + "Donor Statement JPO Summary", + "Donor Statement Trust Fund", + "Donor Statement UN", + "Donor Statement UNICEF Hosted Funds", + "FFR Form (SF-425)", + "JPO Expenditure Summary", + "Statement of Account Thematic Funds", + "Donor Statement by Activity", + "Interim Statement by Nature of expense", + "Funds Request Report", + "Non-Standard Statement", + "Emergency Consolidated - Final", + "Emergency Consolidated - Interim", + "Thematic Emergency Global - Final", + "Thematic Emergency Global - Interim", + "Emergency - Two Pager", + "Emergency - Final", + "Emergency - Interim", + "Human Interest / Photos", + "Narrative - Final", + "Narrative - Interim", + "Narrative Consolidated - Final", + "Narrative Consolidated - Interim", + "Thematic Consolidated - Final", + "Thematic Consolidated - Interim", + "Thematic Global - Final", + "Thematic Global - Interim", + "Thematic - Final", + "Thematic - Interim", + "Short Summary Update", + "Official Receipts", + "Quarterly Monitoring Report", ] return { - 'DRPDonorCode': self.donor.code, - 'DRPDonorDocument': ','.join(document_type_filter), - 'DRPModified__gte': modified_date.strftime('%Y-%m-%d') + "DRPDonorCode": self.donor.code, + "DRPDonorDocument": ",".join(document_type_filter), + "DRPModified__gte": modified_date.strftime("%Y-%m-%d"), } def get_selected_fields(self): serializer_fields = DRPSharePointSearchSerializer._declared_fields.keys() - return ['DRP' + to_camel(x) for x in serializer_fields] + ["Title", "Author", "Path"] + return ["DRP" + to_camel(x) for x in serializer_fields] + [ + "Title", + "Author", + "Path", + ] def get_queryset(self, period): return UserRole.objects.filter(donor=self.donor, notification_period=period).values( - 'user__first_name', 'user__email') + "user__first_name", "user__email" + ) class GaviNotifier(Notifier): - source_id = settings.DRP_SOURCE_IDS['gavi'] + source_id = settings.DRP_SOURCE_IDS["gavi"] serializer = GaviSharePointSearchSerializer - template_name = 'notify_gavi' + template_name = "notify_gavi" def __init__(self, donor_code, group_name): self.donor = Donor.objects.get(code=donor_code) @@ -158,19 +172,19 @@ def __init__(self, donor_code, group_name): def get_queryset(self, period): return UserRole.objects.filter( - donor=self.donor, notification_period=period, group__name=self.group_name).values( - 'user__first_name', 'user__email') + donor=self.donor, notification_period=period, group__name=self.group_name + ).values("user__first_name", "user__email") def get_filter_dict(self, modified_date): return { - 'DRPModified': modified_date.strftime('%Y-%m-%d'), - 'CTNMOUReference': self.group_name, - 'CTNUrgent__not': 'Yes', + "DRPModified": modified_date.strftime("%Y-%m-%d"), + "CTNMOUReference": self.group_name, + "CTNUrgent__not": "Yes", } def get_selected_fields(self): def to_drp(source, value): - prefix = 'CTN' if isinstance(value, (CTNSearchSharePointField, CTNSearchMultiSharePointField)) else 'DRP' + prefix = "CTN" if isinstance(value, (CTNSearchSharePointField, CTNSearchMultiSharePointField)) else "DRP" return prefix + to_camel(source) selected = [to_drp(key, value) for key, value in self.serializer._declared_fields.items()] @@ -179,8 +193,7 @@ def to_drp(source, value): class GaviUrgentNotifier(GaviNotifier): - - template_name = 'notify_urgent_gavi' + template_name = "notify_urgent_gavi" def get_notify_periods(self): return [ @@ -189,16 +202,16 @@ def get_notify_periods(self): def get_filter_dict(self, modified_date): return { - 'DRPModified__gte': modified_date.strftime('%Y-%m-%dT%H:%M:%SZ'), - 'CTNMOUReference': self.group_name, - 'CTNUrgent': 'Yes', + "DRPModified__gte": modified_date.strftime("%Y-%m-%dT%H:%M:%SZ"), + "CTNMOUReference": self.group_name, + "CTNUrgent": "Yes", } @app.task def notify_donor(donor_code): """notify one donor""" - logger.info(f'Notifing {donor_code}') + logger.info(f"Notifing {donor_code}") notifier = DonorNotifier(donor_code) notifier.notify() @@ -206,23 +219,23 @@ def notify_donor(donor_code): @app.task def notify_gavi_donor(donor_code=settings.GAVI_DONOR_CODE): """notify GAVI and spawn one task per group""" - logger.info('Notifying GAVI') - for group_name in Group.objects.filter(name__startswith='MOU').values_list('name', flat=True): + logger.info("Notifying GAVI") + for group_name in Group.objects.filter(name__startswith="MOU").values_list("name", flat=True): notify_gavi_donor_ctn.delay(donor_code, group_name) @app.task def notify_gavi_donor_ctn(donor_code, group_name): """notify a GAVI group""" - logger.info(f'Notifying {donor_code}') + logger.info(f"Notifying {donor_code}") notifier = GaviNotifier(donor_code, group_name) notifier.notify() @app.task def notify_new_records(): - logger.info('Notify Start') - for donor_code in Donor.objects.filter(active=True).values_list('code', flat=True): + logger.info("Notify Start") + for donor_code in Donor.objects.filter(active=True).values_list("code", flat=True): if donor_code == settings.GAVI_DONOR_CODE: notify_gavi_donor(donor_code) else: @@ -239,6 +252,6 @@ def notify_urgent_by_group(group_name): @app.task def notify_urgent_records(): """notify GAVI urgent records and spawn one task per group""" - logger.info('Notify Urgent CTNs Start') - for group_name in Group.objects.filter(name__startswith='MOU').values_list('name', flat=True): + logger.info("Notify Urgent CTNs Start") + for group_name in Group.objects.filter(name__startswith="MOU").values_list("name", flat=True): notify_urgent_by_group.delay(group_name) diff --git a/src/donor_reporting_portal/apps/sharepoint/admin.py b/src/donor_reporting_portal/apps/sharepoint/admin.py index 435024a6..8621a049 100644 --- a/src/donor_reporting_portal/apps/sharepoint/admin.py +++ b/src/donor_reporting_portal/apps/sharepoint/admin.py @@ -5,6 +5,6 @@ @admin.register(SharePointGroup) class SharePointGroupAdmin(admin.ModelAdmin): - search_fields = ('name', ) - list_display = ('name', ) - filter_horizontal = ('libs', ) + search_fields = ("name",) + list_display = ("name",) + filter_horizontal = ("libs",) diff --git a/src/donor_reporting_portal/apps/sharepoint/apps.py b/src/donor_reporting_portal/apps/sharepoint/apps.py index 807db97a..47743ec7 100644 --- a/src/donor_reporting_portal/apps/sharepoint/apps.py +++ b/src/donor_reporting_portal/apps/sharepoint/apps.py @@ -2,5 +2,5 @@ class AppConfig(BaseAppConfig): - name = __name__.rpartition('.')[0] - verbose_name = 'SharePoint' + name = __name__.rpartition(".")[0] + verbose_name = "SharePoint" diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0001_initial.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0001_initial.py index 652c5733..7617ea7f 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0001_initial.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0001_initial.py @@ -7,46 +7,103 @@ class Migration(migrations.Migration): - initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='SharePointSite', + name="SharePointSite", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('name', models.CharField(max_length=32, unique=True, verbose_name='Name')), - ('url', models.URLField()), - ('wrapper_name', models.CharField(max_length=16, unique=True, verbose_name='Wrapper')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ( + "name", + models.CharField(max_length=32, unique=True, verbose_name="Name"), + ), + ("url", models.URLField()), + ( + "wrapper_name", + models.CharField( + max_length=16, unique=True, verbose_name="Wrapper" + ), + ), ], options={ - 'verbose_name': 'SharePoint Site', - 'verbose_name_plural': 'SharePoint Sites', - 'ordering': ['name'], + "verbose_name": "SharePoint Site", + "verbose_name_plural": "SharePoint Sites", + "ordering": ["name"], }, ), migrations.CreateModel( - name='SharePointLibrary', + name="SharePointLibrary", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('name', models.CharField(max_length=32, verbose_name='Name')), - ('active', models.BooleanField(default=True, verbose_name='Active')), - ('username', models.CharField(max_length=64, verbose_name='Username')), - ('password', models.CharField(max_length=64, verbose_name='Password')), - ('site', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='libraries', to='sharepoint.SharePointSite')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ("name", models.CharField(max_length=32, verbose_name="Name")), + ("active", models.BooleanField(default=True, verbose_name="Active")), + ("username", models.CharField(max_length=64, verbose_name="Username")), + ("password", models.CharField(max_length=64, verbose_name="Password")), + ( + "site", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="libraries", + to="sharepoint.SharePointSite", + ), + ), ], options={ - 'verbose_name': 'SharePoint Document Library', - 'verbose_name_plural': 'SharePoint Document Libraries', - 'ordering': ['name'], - 'unique_together': {('name', 'site')}, + "verbose_name": "SharePoint Document Library", + "verbose_name_plural": "SharePoint Document Libraries", + "ordering": ["name"], + "unique_together": {("name", "site")}, }, ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0002_auto_20191105_0444.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0002_auto_20191105_0444.py index 1004da92..57b29038 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0002_auto_20191105_0444.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0002_auto_20191105_0444.py @@ -4,28 +4,31 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint', '0001_initial'), + ("sharepoint", "0001_initial"), ] operations = [ migrations.RemoveField( - model_name='sharepointlibrary', - name='password', + model_name="sharepointlibrary", + name="password", ), migrations.RemoveField( - model_name='sharepointlibrary', - name='username', + model_name="sharepointlibrary", + name="username", ), migrations.AddField( - model_name='sharepointsite', - name='password', - field=models.CharField(blank=True, max_length=64, null=True, verbose_name='Password'), + model_name="sharepointsite", + name="password", + field=models.CharField( + blank=True, max_length=64, null=True, verbose_name="Password" + ), ), migrations.AddField( - model_name='sharepointsite', - name='username', - field=models.CharField(blank=True, max_length=64, null=True, verbose_name='Username'), + model_name="sharepointsite", + name="username", + field=models.CharField( + blank=True, max_length=64, null=True, verbose_name="Username" + ), ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0003_auto_20191105_1127.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0003_auto_20191105_1127.py index 347767e1..2a96b497 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0003_auto_20191105_1127.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0003_auto_20191105_1127.py @@ -4,20 +4,19 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint', '0002_auto_20191105_0444'), + ("sharepoint", "0002_auto_20191105_0444"), ] operations = [ migrations.AlterField( - model_name='sharepointlibrary', - name='name', - field=models.CharField(max_length=64, verbose_name='Name'), + model_name="sharepointlibrary", + name="name", + field=models.CharField(max_length=64, verbose_name="Name"), ), migrations.AlterField( - model_name='sharepointsite', - name='wrapper_name', - field=models.CharField(max_length=16, verbose_name='Wrapper'), + model_name="sharepointsite", + name="wrapper_name", + field=models.CharField(max_length=16, verbose_name="Wrapper"), ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0004_auto_20191105_1400.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0004_auto_20191105_1400.py index 1def0b10..9db944ec 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0004_auto_20191105_1400.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0004_auto_20191105_1400.py @@ -4,19 +4,20 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint', '0003_auto_20191105_1127'), + ("sharepoint", "0003_auto_20191105_1127"), ] operations = [ migrations.RemoveField( - model_name='sharepointsite', - name='wrapper_name', + model_name="sharepointsite", + name="wrapper_name", ), migrations.AddField( - model_name='sharepointsite', - name='site_type', - field=models.CharField(default='sites', max_length=16, verbose_name='Site Type'), + model_name="sharepointsite", + name="site_type", + field=models.CharField( + default="sites", max_length=16, verbose_name="Site Type" + ), ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0005_sharepointlibrary_require_donor_permission.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0005_sharepointlibrary_require_donor_permission.py index c86f4c76..c6b1d9bf 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0005_sharepointlibrary_require_donor_permission.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0005_sharepointlibrary_require_donor_permission.py @@ -4,15 +4,16 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint', '0004_auto_20191105_1400'), + ("sharepoint", "0004_auto_20191105_1400"), ] operations = [ migrations.AddField( - model_name='sharepointlibrary', - name='require_donor_permission', - field=models.BooleanField(default=True, verbose_name='Require Donor Permission'), + model_name="sharepointlibrary", + name="require_donor_permission", + field=models.BooleanField( + default=True, verbose_name="Require Donor Permission" + ), ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0006_auto_20200124_1045.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0006_auto_20200124_1045.py index 1fcf0db6..975eb4a9 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0006_auto_20200124_1045.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0006_auto_20200124_1045.py @@ -4,20 +4,19 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint', '0005_sharepointlibrary_require_donor_permission'), + ("sharepoint", "0005_sharepointlibrary_require_donor_permission"), ] operations = [ migrations.AlterField( - model_name='sharepointsite', - name='name', - field=models.CharField(max_length=32, verbose_name='Name'), + model_name="sharepointsite", + name="name", + field=models.CharField(max_length=32, verbose_name="Name"), ), migrations.AlterField( - model_name='sharepointsite', - name='url', + model_name="sharepointsite", + name="url", field=models.URLField(unique=True), ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0007_auto_20200129_1227.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0007_auto_20200129_1227.py index 31a93d13..721c7dc6 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0007_auto_20200129_1227.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0007_auto_20200129_1227.py @@ -7,48 +7,89 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint', '0006_auto_20200124_1045'), + ("sharepoint", "0006_auto_20200124_1045"), ] operations = [ migrations.CreateModel( - name='SharePointTenant', + name="SharePointTenant", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('url', models.URLField(unique=True)), - ('username', models.CharField(blank=True, max_length=64, null=True, verbose_name='Username')), - ('password', models.CharField(blank=True, max_length=64, null=True, verbose_name='Password')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ("url", models.URLField(unique=True)), + ( + "username", + models.CharField( + blank=True, max_length=64, null=True, verbose_name="Username" + ), + ), + ( + "password", + models.CharField( + blank=True, max_length=64, null=True, verbose_name="Password" + ), + ), ], options={ - 'verbose_name': 'SharePoint Tenant', - 'verbose_name_plural': 'SharePoint Tenants', - 'ordering': ['url'], + "verbose_name": "SharePoint Tenant", + "verbose_name_plural": "SharePoint Tenants", + "ordering": ["url"], }, ), migrations.RemoveField( - model_name='sharepointsite', - name='password', + model_name="sharepointsite", + name="password", ), migrations.RemoveField( - model_name='sharepointsite', - name='url', + model_name="sharepointsite", + name="url", ), migrations.RemoveField( - model_name='sharepointsite', - name='username', + model_name="sharepointsite", + name="username", ), migrations.AlterField( - model_name='sharepointsite', - name='site_type', - field=models.CharField(choices=[('sites', 'sites'), ('teams', 'teams')], default='sites', max_length=16, verbose_name='Site Type'), + model_name="sharepointsite", + name="site_type", + field=models.CharField( + choices=[("sites", "sites"), ("teams", "teams")], + default="sites", + max_length=16, + verbose_name="Site Type", + ), ), migrations.AddField( - model_name='sharepointsite', - name='tenant', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sites', to='sharepoint.SharePointTenant'), + model_name="sharepointsite", + name="tenant", + field=models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="sites", + to="sharepoint.SharePointTenant", + ), ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0008_auto_20200206_1518.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0008_auto_20200206_1518.py index a84ec2a1..7ae2e794 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0008_auto_20200206_1518.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0008_auto_20200206_1518.py @@ -5,15 +5,18 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint', '0007_auto_20200129_1227'), + ("sharepoint", "0007_auto_20200129_1227"), ] operations = [ migrations.AlterField( - model_name='sharepointsite', - name='tenant', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sites', to='sharepoint.SharePointTenant'), + model_name="sharepointsite", + name="tenant", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="sites", + to="sharepoint.SharePointTenant", + ), ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0009_auto_20200220_0939.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0009_auto_20200220_0939.py index 19f8bcd5..5ec49603 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0009_auto_20200220_0939.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0009_auto_20200220_0939.py @@ -4,23 +4,22 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint', '0008_auto_20200206_1518'), + ("sharepoint", "0008_auto_20200206_1518"), ] operations = [ migrations.RemoveField( - model_name='sharepointsite', - name='tenant', + model_name="sharepointsite", + name="tenant", ), migrations.DeleteModel( - name='SharePointLibrary', + name="SharePointLibrary", ), migrations.DeleteModel( - name='SharePointSite', + name="SharePointSite", ), migrations.DeleteModel( - name='SharePointTenant', + name="SharePointTenant", ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0010_sharepointgroup.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0010_sharepointgroup.py index 8419fb30..df8fed73 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0010_sharepointgroup.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0010_sharepointgroup.py @@ -6,26 +6,47 @@ class Migration(migrations.Migration): - initial = True dependencies = [ - ('sharepoint', '0009_auto_20200220_0939'), + ("sharepoint", "0009_auto_20200220_0939"), ] operations = [ migrations.CreateModel( - name='SharePointGroup', + name="SharePointGroup", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created', model_utils.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, verbose_name='created')), - ('modified', model_utils.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='modified')), - ('name', models.CharField(max_length=64, verbose_name='Name')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "created", + model_utils.fields.AutoCreatedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="created", + ), + ), + ( + "modified", + model_utils.fields.AutoLastModifiedField( + default=django.utils.timezone.now, + editable=False, + verbose_name="modified", + ), + ), + ("name", models.CharField(max_length=64, verbose_name="Name")), ], options={ - 'verbose_name': 'SharePoint Group', - 'verbose_name_plural': 'SharePoint Groups', - 'ordering': ['name'], + "verbose_name": "SharePoint Group", + "verbose_name_plural": "SharePoint Groups", + "ordering": ["name"], }, ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/migrations/0011_sharepointgroup_libs.py b/src/donor_reporting_portal/apps/sharepoint/migrations/0011_sharepointgroup_libs.py index 736f0674..27ab39ee 100644 --- a/src/donor_reporting_portal/apps/sharepoint/migrations/0011_sharepointgroup_libs.py +++ b/src/donor_reporting_portal/apps/sharepoint/migrations/0011_sharepointgroup_libs.py @@ -4,16 +4,17 @@ class Migration(migrations.Migration): - dependencies = [ - ('sharepoint_rest_api', '0001_initial'), - ('sharepoint', '0010_sharepointgroup'), + ("sharepoint_rest_api", "0001_initial"), + ("sharepoint", "0010_sharepointgroup"), ] operations = [ migrations.AddField( - model_name='sharepointgroup', - name='libs', - field=models.ManyToManyField(related_name='groups', to='sharepoint_rest_api.SharePointLibrary'), + model_name="sharepointgroup", + name="libs", + field=models.ManyToManyField( + related_name="groups", to="sharepoint_rest_api.SharePointLibrary" + ), ), ] diff --git a/src/donor_reporting_portal/apps/sharepoint/models.py b/src/donor_reporting_portal/apps/sharepoint/models.py index b99462e7..3e5e783f 100644 --- a/src/donor_reporting_portal/apps/sharepoint/models.py +++ b/src/donor_reporting_portal/apps/sharepoint/models.py @@ -7,12 +7,12 @@ class SharePointGroup(TimeStampedModel): name = models.CharField(verbose_name=_("Name"), max_length=64) - libs = models.ManyToManyField(SharePointLibrary, related_name='groups') + libs = models.ManyToManyField(SharePointLibrary, related_name="groups") class Meta: - ordering = ['name'] - verbose_name = 'SharePoint Group' - verbose_name_plural = 'SharePoint Groups' + ordering = ["name"] + verbose_name = "SharePoint Group" + verbose_name_plural = "SharePoint Groups" def __str__(self): - return f'{self.name}' + return f"{self.name}" diff --git a/src/donor_reporting_portal/config/celery.py b/src/donor_reporting_portal/config/celery.py index b19ea164..546d75ae 100644 --- a/src/donor_reporting_portal/config/celery.py +++ b/src/donor_reporting_portal/config/celery.py @@ -5,11 +5,11 @@ from celery import Celery # set the default Django settings module for the 'celery' program. -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'donor_reporting_portal.config.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "donor_reporting_portal.config.settings") -app = Celery('donor_reporting_portal') +app = Celery("donor_reporting_portal") # Using a string here means the worker will not have to # pickle the object when using Windows. -app.config_from_object('django.conf:settings', namespace='CELERY') +app.config_from_object("django.conf:settings", namespace="CELERY") app.autodiscover_tasks(lambda: settings.INSTALLED_APPS) # pragma: no cover diff --git a/src/donor_reporting_portal/config/settings.py b/src/donor_reporting_portal/config/settings.py index 31502da2..045d8d63 100644 --- a/src/donor_reporting_portal/config/settings.py +++ b/src/donor_reporting_portal/config/settings.py @@ -14,114 +14,114 @@ env = environ.Env(DEBUG=(bool, False)) environ.Env.read_env() -DEBUG = env.bool('DEBUG') +DEBUG = env.bool("DEBUG") -DATABASES = {'default': env.db(default='psql://postgres:pass@db:5432/postgres')} +DATABASES = {"default": env.db(default="psql://postgres:pass@db:5432/postgres")} INSTALLED_APPS = ( - 'donor_reporting_portal.apps.core', - 'donor_reporting_portal.apps.report_metadata', - 'donor_reporting_portal.apps.roles', - 'donor_reporting_portal.apps.sharepoint', - 'donor_reporting_portal.web', - 'sharepoint_rest_api', - 'unicef_security', - 'unicef_realm', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.postgres', - 'django.contrib.admin', - 'django.contrib.humanize', - 'django_extensions', - 'django_filters', - 'rest_framework', - 'rest_framework.authtoken', - 'django_celery_beat', - 'django_celery_results', - 'djcelery_email', - 'corsheaders', - 'social_django', - 'admin_extra_buttons', - 'adminactions', - 'rest_framework_social_oauth2', - 'unicef_vision.vision', - 'post_office', - 'unicef_notification', - 'impersonate', + "donor_reporting_portal.apps.core", + "donor_reporting_portal.apps.report_metadata", + "donor_reporting_portal.apps.roles", + "donor_reporting_portal.apps.sharepoint", + "donor_reporting_portal.web", + "sharepoint_rest_api", + "unicef_security", + "unicef_realm", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.postgres", + "django.contrib.admin", + "django.contrib.humanize", + "django_extensions", + "django_filters", + "rest_framework", + "rest_framework.authtoken", + "django_celery_beat", + "django_celery_results", + "djcelery_email", + "corsheaders", + "social_django", + "admin_extra_buttons", + "adminactions", + "rest_framework_social_oauth2", + "unicef_vision.vision", + "post_office", + "unicef_notification", + "impersonate", ) MIDDLEWARE = ( - 'unicef_djangolib.middleware.HealthCheckMiddleware', - 'django.middleware.security.SecurityMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'impersonate.middleware.ImpersonateMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'corsheaders.middleware.CorsMiddleware', - 'unicef_security.middleware.UNICEFSocialAuthExceptionMiddleware' + "unicef_djangolib.middleware.HealthCheckMiddleware", + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "impersonate.middleware.ImpersonateMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", + "corsheaders.middleware.CorsMiddleware", + "unicef_security.middleware.UNICEFSocialAuthExceptionMiddleware", ) AUTHENTICATION_BACKENDS = ( - 'unicef_security.backends.UNICEFAzureADB2COAuth2', - 'django.contrib.auth.backends.ModelBackend', - 'donor_reporting_portal.apps.core.backends.DonorRoleBackend', + "unicef_security.backends.UNICEFAzureADB2COAuth2", + "django.contrib.auth.backends.ModelBackend", + "donor_reporting_portal.apps.core.backends.DonorRoleBackend", ) # path BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) -MEDIA_ROOT = env('MEDIA_ROOT', default='/tmp/etools/media/') -STATIC_ROOT = env('STATIC_ROOT', default=os.path.join(BASE_DIR, 'static')) -MEDIA_URL = '/dm-media/' -STATIC_URL = env('STATIC_URL', default='/static/') +MEDIA_ROOT = env("MEDIA_ROOT", default="/tmp/etools/media/") +STATIC_ROOT = env("STATIC_ROOT", default=os.path.join(BASE_DIR, "static")) +MEDIA_URL = "/dm-media/" +STATIC_URL = env("STATIC_URL", default="/static/") STATICFILES_DIRS = [] STATICFILES_FINDERS = [ - 'django.contrib.staticfiles.finders.FileSystemFinder', - 'django.contrib.staticfiles.finders.AppDirectoriesFinder', + "django.contrib.staticfiles.finders.FileSystemFinder", + "django.contrib.staticfiles.finders.AppDirectoriesFinder", ] -SECRET_KEY = env('SECRET_KEY') +SECRET_KEY = env("SECRET_KEY") ALLOWED_HOSTS = ( - env('ALLOWED_HOST', default='localhost'), - '0.0.0.0', + env("ALLOWED_HOST", default="localhost"), + "0.0.0.0", ) -LOGIN_URL = '/login/' -LOGIN_REDIRECT_URL = '/' -LOGOUT_URL = '/accounts/logout' -LOGOUT_REDIRECT_URL = '/landing/' +LOGIN_URL = "/login/" +LOGIN_REDIRECT_URL = "/" +LOGOUT_URL = "/accounts/logout" +LOGOUT_REDIRECT_URL = "/landing/" # TIME_ZONE = env('TIME_ZONE') # Language code for this installation. All choices can be found here: # http://www.i18nguy.com/unicode/language-identifiers.html -LANGUAGE_CODE = 'en-us' +LANGUAGE_CODE = "en-us" ugettext = lambda s: s # noqa LANGUAGES = ( - ('es', ugettext('Spanish')), - ('fr', ugettext('French')), - ('en', ugettext('English')), - ('ar', ugettext('Arabic')), + ("es", ugettext("Spanish")), + ("fr", ugettext("French")), + ("en", ugettext("English")), + ("ar", ugettext("Arabic")), ) -DEFAULT_AUTO_FIELD = 'django.db.models.AutoField' +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" SITE_ID = 1 -INTERNAL_IPS = ['127.0.0.1', 'localhost'] +INTERNAL_IPS = ["127.0.0.1", "localhost"] USE_I18N = True USE_TZ = True CACHES = { - 'default': { - 'BACKEND': 'redis_cache.RedisCache', - 'LOCATION': env('REDIS_URL', default='redis://localhost:6379/0') + "default": { + "BACKEND": "redis_cache.RedisCache", + "LOCATION": env("REDIS_URL", default="redis://localhost:6379/0"), } } @@ -133,64 +133,61 @@ # } -ROOT_URLCONF = 'donor_reporting_portal.config.urls' -WSGI_APPLICATION = 'donor_reporting_portal.config.wsgi.application' +ROOT_URLCONF = "donor_reporting_portal.config.urls" +WSGI_APPLICATION = "donor_reporting_portal.config.wsgi.application" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [str(PACKAGE_DIR / 'templates')], - 'APP_DIRS': False, - 'OPTIONS': { - 'loaders': [ - 'django.template.loaders.app_directories.Loader', - 'unicef_notification.loaders.EmailTemplateLoader', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": [str(PACKAGE_DIR / "templates")], + "APP_DIRS": False, + "OPTIONS": { + "loaders": [ + "django.template.loaders.app_directories.Loader", + "unicef_notification.loaders.EmailTemplateLoader", ], - 'context_processors': [ - 'constance.context_processors.config', - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', - 'social_django.context_processors.backends', - 'social_django.context_processors.login_redirect', + "context_processors": [ + "constance.context_processors.config", + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", + "social_django.context_processors.backends", + "social_django.context_processors.login_redirect", ], - 'libraries': { - 'staticfiles': 'django.templatetags.static', - 'i18n': 'django.templatetags.i18n', + "libraries": { + "staticfiles": "django.templatetags.static", + "i18n": "django.templatetags.i18n", }, }, }, ] LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'handlers': { - 'console': { - 'class': 'logging.StreamHandler', - 'level': 'INFO' - }, + "version": 1, + "disable_existing_loggers": False, + "handlers": { + "console": {"class": "logging.StreamHandler", "level": "INFO"}, }, - 'root': { - 'handlers': ['console'], - 'level': 'WARNING', + "root": { + "handlers": ["console"], + "level": "WARNING", }, } -AUTH_USER_MODEL = 'unicef_security.User' +AUTH_USER_MODEL = "unicef_security.User" -HOST = env('HOST', default='http://localhost:8000') +HOST = env("HOST", default="http://localhost:8000") -CELERY_ACCEPT_CONTENT = ['pickle', 'json', 'application/text'] -CELERY_BROKER_URL = env('REDIS_URL', default='redis://localhost:6379/0') -CELERY_BROKER_VISIBILITY_VAR = env('CELERY_VISIBILITY_TIMEOUT', default=1800) # in seconds -CELERY_BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': int(CELERY_BROKER_VISIBILITY_VAR)} -CELERY_RESULT_BACKEND = 'django-db' -CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler' +CELERY_ACCEPT_CONTENT = ["pickle", "json", "application/text"] +CELERY_BROKER_URL = env("REDIS_URL", default="redis://localhost:6379/0") +CELERY_BROKER_VISIBILITY_VAR = env("CELERY_VISIBILITY_TIMEOUT", default=1800) # in seconds +CELERY_BROKER_TRANSPORT_OPTIONS = {"visibility_timeout": int(CELERY_BROKER_VISIBILITY_VAR)} +CELERY_RESULT_BACKEND = "django-db" +CELERY_BEAT_SCHEDULER = "django_celery_beat.schedulers.DatabaseScheduler" # Sensible settings for celery -CELERY_TASK_ALWAYS_EAGER = env('CELERY_TASK_ALWAYS_EAGER', default=False) +CELERY_TASK_ALWAYS_EAGER = env("CELERY_TASK_ALWAYS_EAGER", default=False) CELERY_TASK_ACKS_LATE = True CELERY_TASK_PUBLISH_RETRY = True CELERY_WORKER_DISABLE_RATE_LIMITS = False @@ -200,36 +197,34 @@ CELERY_WORKER_PREFETCH_MULTIPLIER = 1 REST_FRAMEWORK = { - 'DEFAULT_PERMISSION_CLASSES': [ - 'rest_framework.permissions.IsAuthenticated', + "DEFAULT_PERMISSION_CLASSES": [ + "rest_framework.permissions.IsAuthenticated", ], } # django-cors-headers: https://github.com/ottoyiu/django-cors-headers -CORS_ORIGIN_ALLOW_ALL = env('CORS_ORIGIN_ALLOW_ALL', default=False) +CORS_ORIGIN_ALLOW_ALL = env("CORS_ORIGIN_ALLOW_ALL", default=False) JWT_AUTH = { - 'JWT_VERIFY': False, # this requires private key - 'JWT_VERIFY_EXPIRATION': True, - 'JWT_LEEWAY': 60, - 'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=30000), - 'JWT_AUDIENCE': None, - 'JWT_ISSUER': None, - 'JWT_ALLOW_REFRESH': False, - 'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7), - 'JWT_AUTH_HEADER_PREFIX': 'JWT', - 'JWT_SECRET_KEY': SECRET_KEY, - 'JWT_DECODE_HANDLER': 'rest_framework_jwt.utils.jwt_decode_handler', - + "JWT_VERIFY": False, # this requires private key + "JWT_VERIFY_EXPIRATION": True, + "JWT_LEEWAY": 60, + "JWT_EXPIRATION_DELTA": datetime.timedelta(seconds=30000), + "JWT_AUDIENCE": None, + "JWT_ISSUER": None, + "JWT_ALLOW_REFRESH": False, + "JWT_REFRESH_EXPIRATION_DELTA": datetime.timedelta(days=7), + "JWT_AUTH_HEADER_PREFIX": "JWT", + "JWT_SECRET_KEY": SECRET_KEY, + "JWT_DECODE_HANDLER": "rest_framework_jwt.utils.jwt_decode_handler", # Keys will be set in core.apps.Config.ready() - 'JWT_PUBLIC_KEY': '?', + "JWT_PUBLIC_KEY": "?", # 'JWT_PRIVATE_KEY': wallet.get_private(), # 'JWT_PRIVATE_KEY': None, - 'JWT_ALGORITHM': 'RS256', - + "JWT_ALGORITHM": "RS256", } -SENTRY_DSN = env('SENTRY_DSN', default=None) # noqa: F405 +SENTRY_DSN = env("SENTRY_DSN", default=None) # noqa: F405 if SENTRY_DSN: # pragma: no cover sentry_sdk.init( @@ -240,93 +235,84 @@ ) if DEBUG: # pragma: no cover - - INSTALLED_APPS += ( # noqa - 'debug_toolbar', - ) - MIDDLEWARE += ( # noqa - 'debug_toolbar.middleware.DebugToolbarMiddleware', - ) + INSTALLED_APPS += ("debug_toolbar",) # noqa + MIDDLEWARE += ("debug_toolbar.middleware.DebugToolbarMiddleware",) # noqa DEBUG_TOOLBAR_CONFIG = { - 'SHOW_TEMPLATE_CONTEXT': True, + "SHOW_TEMPLATE_CONTEXT": True, } -INSIGHT_URL = env.str('INSIGHT_URL', 'http://invalid_vision_url') -INSIGHT_LOGGER_MODEL = 'vision.VisionLog' +INSIGHT_URL = env.str("INSIGHT_URL", "http://invalid_vision_url") +INSIGHT_LOGGER_MODEL = "vision.VisionLog" -INSIGHT_SUB_KEY = env.str('INSIGHT_SUB_KEY', 'invalid_vision_password') +INSIGHT_SUB_KEY = env.str("INSIGHT_SUB_KEY", "invalid_vision_password") -BUSINESSAREA_MODEL = 'unicef_security.BusinessArea' -REALM_TARGET_MODEL = 'unicef_realm.BusinessArea' +BUSINESSAREA_MODEL = "unicef_security.BusinessArea" +REALM_TARGET_MODEL = "unicef_realm.BusinessArea" -SHELL_PLUS_PRE_IMPORTS = ( - ('donor_reporting_portal.config', 'celery'), -) +SHELL_PLUS_PRE_IMPORTS = (("donor_reporting_portal.config", "celery"),) POST_OFFICE = { - 'DEFAULT_PRIORITY': 'now', - 'BACKENDS': { - 'default': 'djcelery_email.backends.CeleryEmailBackend' - } + "DEFAULT_PRIORITY": "now", + "BACKENDS": {"default": "djcelery_email.backends.CeleryEmailBackend"}, } -DEFAULT_FROM_EMAIL = 'donor_reporting_portal@unicef.org' -EMAIL_BACKEND = 'unicef_notification.backends.EmailBackend' -EMAIL_HOST = env('EMAIL_HOST', default='') -EMAIL_HOST_USER = env('EMAIL_HOST_USER', default='') -EMAIL_HOST_PASSWORD = env('EMAIL_HOST_PASSWORD', default='') -EMAIL_PORT = env('EMAIL_PORT', default=25) -EMAIL_USE_TLS = env('EMAIL_USE_TLS', default=False) -EMAIL_USE_SSL = env('EMAIL_USE_SSL', default=False) - -KEY = SOCIAL_AUTH_KEY = env('AZURE_B2C_CLIENT_ID', default=None) -SOCIAL_AUTH_SECRET = env('AZURE_B2C_CLIENT_SECRET', default=None) -SOCIAL_AUTH_TENANT_NAME = env('TENANT_NAME', default='unicefpartners') -SOCIAL_AUTH_TENANT_ID = f'{SOCIAL_AUTH_TENANT_NAME}.onmicrosoft.com' -SOCIAL_AUTH_TENANT_B2C_URL = f'{SOCIAL_AUTH_TENANT_NAME}.b2clogin.com' - -SOCIAL_AUTH_URL_NAMESPACE = 'social' +DEFAULT_FROM_EMAIL = "donor_reporting_portal@unicef.org" +EMAIL_BACKEND = "unicef_notification.backends.EmailBackend" +EMAIL_HOST = env("EMAIL_HOST", default="") +EMAIL_HOST_USER = env("EMAIL_HOST_USER", default="") +EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD", default="") +EMAIL_PORT = env("EMAIL_PORT", default=25) +EMAIL_USE_TLS = env("EMAIL_USE_TLS", default=False) +EMAIL_USE_SSL = env("EMAIL_USE_SSL", default=False) + +KEY = SOCIAL_AUTH_KEY = env("AZURE_B2C_CLIENT_ID", default=None) +SOCIAL_AUTH_SECRET = env("AZURE_B2C_CLIENT_SECRET", default=None) +SOCIAL_AUTH_TENANT_NAME = env("TENANT_NAME", default="unicefpartners") +SOCIAL_AUTH_TENANT_ID = f"{SOCIAL_AUTH_TENANT_NAME}.onmicrosoft.com" +SOCIAL_AUTH_TENANT_B2C_URL = f"{SOCIAL_AUTH_TENANT_NAME}.b2clogin.com" + +SOCIAL_AUTH_URL_NAMESPACE = "social" SOCIAL_AUTH_SANITIZE_REDIRECTS = False SOCIAL_AUTH_JSONFIELD_ENABLED = True -SOCIAL_AUTH_POLICY = env('AZURE_B2C_POLICY_NAME', default='B2C_1A_UNICEF_SOCIAL_signup_signin') -SOCIAL_PASSWORD_RESET_POLICY = env('AZURE_B2C_PASS_RESET_POLICY', default='B2C_1_PasswordResetPolicy') -SOCIAL_AUTH_USER_MODEL = 'unicef_security.User' +SOCIAL_AUTH_POLICY = env("AZURE_B2C_POLICY_NAME", default="B2C_1A_UNICEF_SOCIAL_signup_signin") +SOCIAL_PASSWORD_RESET_POLICY = env("AZURE_B2C_PASS_RESET_POLICY", default="B2C_1_PasswordResetPolicy") +SOCIAL_AUTH_USER_MODEL = "unicef_security.User" SOCIAL_AUTH_PIPELINE = ( - 'unicef_security.pipeline.social_details', - 'social_core.pipeline.social_auth.social_uid', - 'social_core.pipeline.social_auth.auth_allowed', - 'social_core.pipeline.social_auth.social_user', - 'social_core.pipeline.user.get_username', - 'unicef_security.pipeline.get_username', - 'social_core.pipeline.social_auth.associate_by_email', - 'unicef_security.pipeline.create_unicef_user', - 'social_core.pipeline.social_auth.associate_user', - 'social_core.pipeline.social_auth.load_extra_data', - 'social_core.pipeline.user.user_details', + "unicef_security.pipeline.social_details", + "social_core.pipeline.social_auth.social_uid", + "social_core.pipeline.social_auth.auth_allowed", + "social_core.pipeline.social_auth.social_user", + "social_core.pipeline.user.get_username", + "unicef_security.pipeline.get_username", + "social_core.pipeline.social_auth.associate_by_email", + "unicef_security.pipeline.create_unicef_user", + "social_core.pipeline.social_auth.associate_user", + "social_core.pipeline.social_auth.load_extra_data", + "social_core.pipeline.user.user_details", ) -USER_FIELDS = ['username', 'email', 'first_name', 'last_name'] +USER_FIELDS = ["username", "email", "first_name", "last_name"] -MATOMO_SITE_TRACKER = env('MATOMO_SITE_TRACKER', default='https://unisitetracker.unicef.io/') -MATOMO_SITE_ID = env('MATOMO_SITE_ID', default=None) +MATOMO_SITE_TRACKER = env("MATOMO_SITE_TRACKER", default="https://unisitetracker.unicef.io/") +MATOMO_SITE_ID = env("MATOMO_SITE_ID", default=None) IMPERSONATE = { - 'PAGINATE_COUNT': 50, - 'REQUIRE_SUPERUSER': True, - 'CUSTOM_USER_QUERYSET': 'donor_reporting_portal.libs.impersonate.queryset' + "PAGINATE_COUNT": 50, + "REQUIRE_SUPERUSER": True, + "CUSTOM_USER_QUERYSET": "donor_reporting_portal.libs.impersonate.queryset", } DRP_SOURCE_IDS = { - 'internal': env('DRP_SOURCE_ID_INTERNAL', default=None), - 'external': env('DRP_SOURCE_ID_EXTERNAL', default=None), - 'pool_internal': env('DRP_SOURCE_ID_POOL_INTERNAL', default=None), - 'pool_external': env('DRP_SOURCE_ID_POOL_EXTERNAL', default=None), - 'thematic_internal': env('DRP_SOURCE_ID_THEMATIC_INTERNAL', default=None), - 'thematic_external': env('DRP_SOURCE_ID_THEMATIC_EXTERNAL', default=None), - 'gavi': env('DRP_SOURCE_ID_GAVI', default=None), + "internal": env("DRP_SOURCE_ID_INTERNAL", default=None), + "external": env("DRP_SOURCE_ID_EXTERNAL", default=None), + "pool_internal": env("DRP_SOURCE_ID_POOL_INTERNAL", default=None), + "pool_external": env("DRP_SOURCE_ID_POOL_EXTERNAL", default=None), + "thematic_internal": env("DRP_SOURCE_ID_THEMATIC_INTERNAL", default=None), + "thematic_external": env("DRP_SOURCE_ID_THEMATIC_EXTERNAL", default=None), + "gavi": env("DRP_SOURCE_ID_GAVI", default=None), } -GAVI_DONOR_CODE = 'I49928' +GAVI_DONOR_CODE = "I49928" diff --git a/src/donor_reporting_portal/config/urls.py b/src/donor_reporting_portal/config/urls.py index efa05b83..385140b3 100644 --- a/src/donor_reporting_portal/config/urls.py +++ b/src/donor_reporting_portal/config/urls.py @@ -6,21 +6,21 @@ from rest_framework_simplejwt.views import token_obtain_pair urlpatterns = [ - path(r'admin/', admin.site.urls), - path(r'api-token-auth/', token_obtain_pair), - path(r'api-auth/', include('rest_framework.urls', namespace='rest_framework')), - path(r'security/', include('unicef_security.urls')), - path(r'social/', include('social_django.urls', namespace='social')), - path(r'api/', include('donor_reporting_portal.api.urls', namespace='api')), - path(r'api/', include('sharepoint_rest_api.urls', namespace='sharepoint')), - path(r'accounts/', include('django.contrib.auth.urls')), - path(r'manage/adminactions/', include('adminactions.urls')), - path(r'manage/impersonate/', include('impersonate.urls')), + path(r"admin/", admin.site.urls), + path(r"api-token-auth/", token_obtain_pair), + path(r"api-auth/", include("rest_framework.urls", namespace="rest_framework")), + path(r"security/", include("unicef_security.urls")), + path(r"social/", include("social_django.urls", namespace="social")), + path(r"api/", include("donor_reporting_portal.api.urls", namespace="api")), + path(r"api/", include("sharepoint_rest_api.urls", namespace="sharepoint")), + path(r"accounts/", include("django.contrib.auth.urls")), + path(r"manage/adminactions/", include("adminactions.urls")), + path(r"manage/impersonate/", include("impersonate.urls")), ] if settings.DEBUG: # pragma: no cover import debug_toolbar urlpatterns += [ - path(r'__debug__/', include(debug_toolbar.urls)), + path(r"__debug__/", include(debug_toolbar.urls)), ] diff --git a/src/donor_reporting_portal/libs/impersonate.py b/src/donor_reporting_portal/libs/impersonate.py index 7bd8c3d9..28a297fb 100644 --- a/src/donor_reporting_portal/libs/impersonate.py +++ b/src/donor_reporting_portal/libs/impersonate.py @@ -2,4 +2,4 @@ def queryset(request): - return User.objects.exclude(id=request.user.id).exclude(is_superuser=True).order_by('username') + return User.objects.exclude(id=request.user.id).exclude(is_superuser=True).order_by("username") diff --git a/tests/api/_api_checker/test_config/test_api_metadata_static/_api_metadata_static_/get/dc937b59892604f5a86ac96936cd7ff09e25f18ae6b758e8014a24c7fa039e91.response.json b/tests/api/_api_checker/test_config/test_api_metadata_static/_api_metadata_static_/get/dc937b59892604f5a86ac96936cd7ff09e25f18ae6b758e8014a24c7fa039e91.response.json index 16c0e3f3..1e3744ca 100644 --- a/tests/api/_api_checker/test_config/test_api_metadata_static/_api_metadata_static_/get/dc937b59892604f5a86ac96936cd7ff09e25f18ae6b758e8014a24c7fa039e91.response.json +++ b/tests/api/_api_checker/test_config/test_api_metadata_static/_api_metadata_static_/get/dc937b59892604f5a86ac96936cd7ff09e25f18ae6b758e8014a24c7fa039e91.response.json @@ -5,7 +5,7 @@ "Vary": "Accept, Origin, Cookie", "Allow": "GET", "X-Frame-Options": "DENY", - "Content-Length": "7525", + "Content-Length": "7673", "X-Content-Type-Options": "nosniff", "Referrer-Policy": "same-origin", "Cross-Origin-Opener-Policy": "same-origin" @@ -107,6 +107,10 @@ { "code": "2023", "description": "2023" + }, + { + "code": "2024", + "description": "2024" } ], "report_years": [ @@ -129,6 +133,10 @@ { "code": "2023", "description": "2023" + }, + { + "code": "2024", + "description": "2024" } ], "grant_issue_years": [ @@ -155,6 +163,10 @@ { "code": "2023", "description": "2023" + }, + { + "code": "2024", + "description": "2024" } ], "report_type": [ @@ -525,6 +537,10 @@ { "code": "2023", "description": "2023" + }, + { + "code": "2024", + "description": "2024" } ] }, diff --git a/tests/api/test_config.py b/tests/api/test_config.py index 1a11bd14..8cab207e 100644 --- a/tests/api/test_config.py +++ b/tests/api/test_config.py @@ -9,10 +9,10 @@ @pytest.mark.django_db @contract(LastModifiedRecorder) def test_api_metadata_static(request, django_app): - return reverse('api:metadata-static-list') + return reverse("api:metadata-static-list") @pytest.mark.django_db @contract(LastModifiedRecorder) def test_api_config(request, django_app): - return reverse('api:config-list') + return reverse("api:config-list") diff --git a/tests/api/test_metadata.py b/tests/api/test_metadata.py index c1209785..d259fe8f 100644 --- a/tests/api/test_metadata.py +++ b/tests/api/test_metadata.py @@ -35,40 +35,46 @@ def external_grant(request, db): @frozenfixture() -def grant(request, db,): +def grant( + request, + db, +): return GrantFactory() @frozenfixture() -def metadata(request, db,): +def metadata( + request, + db, +): return DRPMetadataFactory() @contract(recorder_class=LastModifiedRecorder) def test_api_theme_list(request, django_app, logged_user, theme): - return reverse('api:theme-list') + return reverse("api:theme-list") @contract(recorder_class=LastModifiedRecorder) def test_api_donor_list(request, django_app, logged_user, donor): - return reverse('api:donor-list') + return reverse("api:donor-list") @contract(recorder_class=LastModifiedRecorder) def test_api_my_donor_list_unicef_user(request, django_app, logged_user, donor): - with user_grant_permissions(logged_user, permissions=['roles.can_view_all_donors']): - return reverse('api:donor-my-donors') + with user_grant_permissions(logged_user, permissions=["roles.can_view_all_donors"]): + return reverse("api:donor-my-donors") @contract(recorder_class=LastModifiedRecorder) def test_api_my_donor_list_donor(request, django_app, logged_user, donor): - with user_grant_role_permission(logged_user, donor, permissions=['report_metadata.view_donor']): - return reverse('api:donor-my-donors') + with user_grant_role_permission(logged_user, donor, permissions=["report_metadata.view_donor"]): + return reverse("api:donor-my-donors") @contract(recorder_class=ExpectedErrorRecorder) def test_api_my_donor_list_fail(request, django_app, logged_user, donor): - return reverse('api:donor-my-donors') + return reverse("api:donor-my-donors") # @contract(recorder_class=LastModifiedRecorder) @@ -81,17 +87,17 @@ def test_api_my_donor_list_fail(request, django_app, logged_user, donor): @contract(recorder_class=ExpectedErrorRecorder) def test_api_my_admin_donor_list_donor_fail(request, django_app, logged_user, donor): - return reverse('api:donor-my-admin-donors') + return reverse("api:donor-my-admin-donors") def test_api_external_grant_list(request, django_app, logged_user, external_grant): - return reverse('api:external_grant-list', kwargs={'donor_id': external_grant.donor.pk}) + return reverse("api:external_grant-list", kwargs={"donor_id": external_grant.donor.pk}) def test_api_grant_list(request, django_app, logged_user, grant): - return reverse('api:grant-list', kwargs={'donor_id': grant.donor.pk}) + return reverse("api:grant-list", kwargs={"donor_id": grant.donor.pk}) @contract(recorder_class=LastModifiedRecorder) def test_metadata_list(request, django_app, logged_user, metadata): - return reverse('api:drpmetadata-list') + return reverse("api:drpmetadata-list") diff --git a/tests/api/test_security.py b/tests/api/test_security.py index 7866e851..94b82555 100644 --- a/tests/api/test_security.py +++ b/tests/api/test_security.py @@ -24,20 +24,20 @@ def business_area(request, db): @contract(recorder_class=LastModifiedRecorder) def test_api_user_list(request, django_app, user): - return reverse('api:user-list') + return reverse("api:user-list") @contract(recorder_class=LastModifiedRecorder) def test_api_user_profile(request, django_app, logged_user, userrole): - return reverse('api:user-my-profile') + return reverse("api:user-my-profile") @contract(recorder_class=LastModifiedRecorder) def test_api_userrole_list(request, django_app, logged_user, userrole): - return reverse('api:userrole-list') + return reverse("api:userrole-list") @pytest.mark.django_db @contract(LastModifiedRecorder) def test_api_business_area_list(request, django_app, business_area): - return reverse('api:businessarea-list') + return reverse("api:businessarea-list") diff --git a/tests/api/test_sharepoint.py b/tests/api/test_sharepoint.py index a74c3c00..ad884f45 100644 --- a/tests/api/test_sharepoint.py +++ b/tests/api/test_sharepoint.py @@ -19,62 +19,61 @@ @frozenfixture() def donor(request, db): - return DonorFactory( - name='European Commission / ECHO', - code='I49912' - ) + return DonorFactory(name="European Commission / ECHO", code="I49912") @frozenfixture() def tenant(request, db): - return SharePointTenantFactory( - url='https://unitst.sharepoint.com/', - username=None, - password=None - ) + return SharePointTenantFactory(url="https://unitst.sharepoint.com/", username=None, password=None) @frozenfixture() def site(tenant, request, db): return SharePointSiteFactory( tenant=tenant, - name='GLB-DRP', - site_type='sites', + name="GLB-DRP", + site_type="sites", ) @frozenfixture() def library(site, request, db): - return SharePointLibraryFactory( - site=site, - name='2020 Certified Reports' - ) + return SharePointLibraryFactory(site=site, name="2020 Certified Reports") @frozenfixture() def group(library, request, db): - return SharePointGroupFactory.create( - name='Donors Reports', - libs=(library,) - ) + return SharePointGroupFactory.create(name="Donors Reports", libs=(library,)) -@VCR.use_cassette(str(Path(__file__).parent / 'vcr_cassettes/list.yml')) +@VCR.use_cassette(str(Path(__file__).parent / "vcr_cassettes/list.yml")) def test_api(api_checker_datadir, logged_user, library, donor): # noqa - url = reverse('api:sharepoint-url-list', - kwargs={'tenant': library.site.tenant.name, 'site': library.site.name, 'folder': library.name}) - data = {'donor_code': donor.code} - with user_grant_role_permission(logged_user, donor, permissions=['report_metadata.view_donor']): + url = reverse( + "api:sharepoint-url-list", + kwargs={ + "tenant": library.site.tenant.name, + "site": library.site.name, + "folder": library.name, + }, + ) + data = {"donor_code": donor.code} + with user_grant_role_permission(logged_user, donor, permissions=["report_metadata.view_donor"]): recorder = Recorder(api_checker_datadir, as_user=logged_user) recorder.assertGET(url, data=data) -@VCR.use_cassette(str(Path(__file__).parent / 'vcr_cassettes/caml-list.yml')) +@VCR.use_cassette(str(Path(__file__).parent / "vcr_cassettes/caml-list.yml")) def test_api_caml(api_checker_datadir, logged_user, library, donor): # noqa - url = reverse('api:sharepoint-url-caml-list', - kwargs={'tenant': library.site.tenant.name, 'site': library.site.name, 'folder': library.name}) - data = {'donor_code': donor.code} - with user_grant_role_permission(logged_user, donor, permissions=['report_metadata.view_donor']): + url = reverse( + "api:sharepoint-url-caml-list", + kwargs={ + "tenant": library.site.tenant.name, + "site": library.site.name, + "folder": library.name, + }, + ) + data = {"donor_code": donor.code} + with user_grant_role_permission(logged_user, donor, permissions=["report_metadata.view_donor"]): recorder = Recorder(api_checker_datadir, as_user=logged_user) recorder.assertGET(url, data=data) @@ -91,4 +90,4 @@ def test_api_caml(api_checker_datadir, logged_user, library, donor): # noqa @contract(recorder_class=LastModifiedRecorder) def test_api_group_list(group, request, django_app, logged_user, theme): - return reverse('api:sharepoint-group-list') + return reverse("api:sharepoint-group-list") diff --git a/tests/api_checker.py b/tests/api_checker.py index 0533ce2b..9809029b 100644 --- a/tests/api_checker.py +++ b/tests/api_checker.py @@ -18,17 +18,19 @@ def deco(func): @wraps(func) def _inner(*args, **kwargs): - if is_fixture and 'request' not in kwargs: - raise ValueError('frozenfixture must have `request` argument') - request = kwargs.get('request', None) - parts = [os.path.dirname(func.__code__.co_filename), - BASE_DATADIR, - func.__module__, - func.__name__] + if is_fixture and "request" not in kwargs: + raise ValueError("frozenfixture must have `request` argument") + request = kwargs.get("request", None) + parts = [ + os.path.dirname(func.__code__.co_filename), + BASE_DATADIR, + func.__module__, + func.__name__, + ] seed = os.path.join(*parts) destination = fixture_name(seed, request) - if not os.path.exists(destination) or os.environ.get('API_CHECKER_RESET'): + if not os.path.exists(destination) or os.environ.get("API_CHECKER_RESET"): mktree(os.path.dirname(destination)) data = func(*args, **kwargs) dump_fixtures({func.__name__: data}, destination) @@ -47,7 +49,6 @@ def get_user(): class LastModifiedRecorder(Recorder): - @property def client(self): user = get_user() @@ -56,12 +57,12 @@ def client(self): return client def assert_modified(self, response: Response, stored: Response, path: str): - value = response['modified'] - assert datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f%z') + value = response["modified"] + assert datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f%z") def assert_created(self, response: Response, stored: Response, path: str): - value = response['created'] - assert datetime.datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%f%z') + value = response["created"] + assert datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f%z") class ExpectedErrorRecorder(Recorder): diff --git a/tests/apps/test_backends.py b/tests/apps/test_backends.py index 2460cabd..42329770 100644 --- a/tests/apps/test_backends.py +++ b/tests/apps/test_backends.py @@ -6,22 +6,22 @@ @pytest.mark.django_db -@override_settings(AUTHENTICATION_BACKENDS=('donor_reporting_portal.apps.core.backends.DonorRoleBackend',)) +@override_settings(AUTHENTICATION_BACKENDS=("donor_reporting_portal.apps.core.backends.DonorRoleBackend",)) def test_donor_role_superuser(admin_user, donor): - assert admin_user.has_perm('any', donor) + assert admin_user.has_perm("any", donor) @pytest.mark.django_db -@override_settings(AUTHENTICATION_BACKENDS=('donor_reporting_portal.apps.core.backends.DonorRoleBackend',)) +@override_settings(AUTHENTICATION_BACKENDS=("donor_reporting_portal.apps.core.backends.DonorRoleBackend",)) def test_donor_role_inactive(userrole): - with user_grant_role_permission(userrole.user, userrole.donor, permissions=['roles.can_view_all_donors']): + with user_grant_role_permission(userrole.user, userrole.donor, permissions=["roles.can_view_all_donors"]): userrole.user.is_active = False userrole.user.save() - assert not userrole.user.has_perm('roles.can_view_all_donors', userrole.donor) + assert not userrole.user.has_perm("roles.can_view_all_donors", userrole.donor) @pytest.mark.django_db -@override_settings(AUTHENTICATION_BACKENDS=('donor_reporting_portal.apps.core.backends.DonorRoleBackend',)) +@override_settings(AUTHENTICATION_BACKENDS=("donor_reporting_portal.apps.core.backends.DonorRoleBackend",)) def test_donor_role_ok(userrole): - with user_grant_role_permission(userrole.user, userrole.donor, permissions=['roles.can_view_all_donors']): - assert userrole.user.has_perm('roles.can_view_all_donors', userrole.donor) + with user_grant_role_permission(userrole.user, userrole.donor, permissions=["roles.can_view_all_donors"]): + assert userrole.user.has_perm("roles.can_view_all_donors", userrole.donor) diff --git a/tests/apps/test_commands.py b/tests/apps/test_commands.py index 94ed4653..d0e8ab40 100644 --- a/tests/apps/test_commands.py +++ b/tests/apps/test_commands.py @@ -12,37 +12,46 @@ @pytest.fixture() def autocreate_users(): - os.environ['AUTOCREATE_USERS'] = "user1,pwd|user2,pwd" + os.environ["AUTOCREATE_USERS"] = "user1,pwd|user2,pwd" yield - del os.environ['AUTOCREATE_USERS'] + del os.environ["AUTOCREATE_USERS"] @pytest.fixture() def invalidate_cache(): - os.environ['INVALIDATE_CACHE'] = "1" + os.environ["INVALIDATE_CACHE"] = "1" yield - del os.environ['INVALIDATE_CACHE'] + del os.environ["INVALIDATE_CACHE"] @pytest.mark.django_db def test_db_is_ready(db, monkeypatch): monkeypatch.setattr("sys.exit", lambda v: v) - call_command("db-isready", stdout=StringIO(), stderr=StringIO()) + call_command("db_isready", stdout=StringIO(), stderr=StringIO()) @pytest.mark.django_db def test_db_is_ready_error(db, monkeypatch): monkeypatch.setattr("sys.exit", lambda v: v) - with mock.patch('donor_reporting_portal.apps.core.management.commands.db-isready.Command._get_cursor', - side_effect=OperationalError()): - call_command("db-isready", wait=True, timeout=1, - stdout=StringIO(), stderr=StringIO()) + with mock.patch( + "donor_reporting_portal.apps.core.management.commands.db_isready.Command._get_cursor", + side_effect=OperationalError(), + ): + call_command("db_isready", wait=True, timeout=1, stdout=StringIO(), stderr=StringIO()) @pytest.mark.django_db def test_db_is_ready_debug(db, monkeypatch): monkeypatch.setattr("sys.exit", lambda v: v) - with mock.patch('donor_reporting_portal.apps.core.management.commands.db-isready.Command._get_cursor', - side_effect=OperationalError()): - call_command("db-isready", wait=True, timeout=1, debug=True, - stdout=StringIO(), stderr=StringIO()) + with mock.patch( + "donor_reporting_portal.apps.core.management.commands.db_isready.Command._get_cursor", + side_effect=OperationalError(), + ): + call_command( + "db_isready", + wait=True, + timeout=1, + debug=True, + stdout=StringIO(), + stderr=StringIO(), + ) diff --git a/tests/apps/test_metadata.py b/tests/apps/test_metadata.py index 078ea89d..ecec4e1a 100644 --- a/tests/apps/test_metadata.py +++ b/tests/apps/test_metadata.py @@ -5,34 +5,34 @@ def test_admin_theme(django_app, admin_user, theme): assert str(theme) is not None - url = reverse('admin:report_metadata_theme_changelist') + url = reverse("admin:report_metadata_theme_changelist") response = django_app.get(url, user=admin_user) assert response def test_admin_donor(django_app, admin_user, donor): assert str(donor) is not None - url = reverse('admin:report_metadata_donor_changelist') + url = reverse("admin:report_metadata_donor_changelist") response = django_app.get(url, user=admin_user) assert response def test_admin_externalgrant(django_app, admin_user, external_grant): assert str(external_grant) is not None - url = reverse('admin:report_metadata_externalgrant_changelist') + url = reverse("admin:report_metadata_externalgrant_changelist") response = django_app.get(url, user=admin_user) assert response def test_admin_grant(django_app, admin_user, grant): assert str(grant) is not None - url = reverse('admin:report_metadata_grant_changelist') + url = reverse("admin:report_metadata_grant_changelist") response = django_app.get(url, user=admin_user) assert response def test_grant_sync_url(django_app, admin_user): - with mock.patch('donor_reporting_portal.apps.report_metadata.admin.grant_sync'): - url = '/admin/report_metadata/externalgrant/_sync_grants/' + with mock.patch("donor_reporting_portal.apps.report_metadata.admin.grant_sync"): + url = "/admin/report_metadata/externalgrant/_sync_grants/" response = django_app.get(url, user=admin_user) assert response diff --git a/tests/apps/test_roles.py b/tests/apps/test_roles.py index 9550e46b..0f23515d 100644 --- a/tests/apps/test_roles.py +++ b/tests/apps/test_roles.py @@ -9,9 +9,10 @@ def test_admin_userrole(django_app, admin_user, userrole, donor, group, secondary_donor): assert str(userrole) is not None userrole_secondary_donor = UserRoleFactory( - user=admin_user, donor=donor, group=group, secondary_donor=secondary_donor) + user=admin_user, donor=donor, group=group, secondary_donor=secondary_donor + ) assert str(userrole_secondary_donor) is not None - url = reverse('admin:roles_userrole_changelist') + url = reverse("admin:roles_userrole_changelist") response = django_app.get(url, user=admin_user) assert response @@ -31,9 +32,9 @@ def test_manager_by_donor_secondary_donor(logged_user, donor, group, secondary_d def test_manager_by_permissions(logged_user, donor, secondary_donor): ContentType.objects.first() - content_type = ContentType.objects.get(model='donor', app_label='report_metadata') - perm = Permission.objects.get(content_type=content_type, codename='view_donor') - group = GroupFactory(permissions=(perm, )) + content_type = ContentType.objects.get(model="donor", app_label="report_metadata") + perm = Permission.objects.get(content_type=content_type, codename="view_donor") + group = GroupFactory(permissions=(perm,)) UserRoleFactory(user=logged_user, donor=donor, group=group, secondary_donor=secondary_donor) - assert UserRole.objects.by_permissions('report_metadata.view_donor').count() == 1 - assert UserRole.objects.by_permissions(['report_metadata.view_donor', 'roles.add_userrole']).count() == 0 + assert UserRole.objects.by_permissions("report_metadata.view_donor").count() == 1 + assert UserRole.objects.by_permissions(["report_metadata.view_donor", "roles.add_userrole"]).count() == 0 diff --git a/tests/apps/test_security.py b/tests/apps/test_security.py index a80d1110..9a8210c8 100644 --- a/tests/apps/test_security.py +++ b/tests/apps/test_security.py @@ -3,6 +3,6 @@ def test_admin_userrole(django_app, admin_user, userrole): assert str(userrole) is not None - url = reverse('admin:roles_userrole_changelist') + url = reverse("admin:roles_userrole_changelist") response = django_app.get(url, user=admin_user) assert response diff --git a/tests/apps/test_sharepoint.py b/tests/apps/test_sharepoint.py index db940f00..2bcf0bb5 100644 --- a/tests/apps/test_sharepoint.py +++ b/tests/apps/test_sharepoint.py @@ -3,6 +3,6 @@ def test_admin_sharepoint_group(django_app, admin_user, sharepoint_group): assert str(sharepoint_group) is not None - url = reverse('admin:sharepoint_sharepointgroup_changelist') + url = reverse("admin:sharepoint_sharepointgroup_changelist") response = django_app.get(url, user=admin_user) assert response diff --git a/tests/apps/test_signals.py b/tests/apps/test_signals.py index 51281c6e..769064f5 100644 --- a/tests/apps/test_signals.py +++ b/tests/apps/test_signals.py @@ -7,14 +7,14 @@ @pytest.mark.django_db def test_assign_to_unicef_group_ok(): - GroupFactory(name='UNICEF User') - user = get_user_model().objects.create(username='user@unicef.org', email='user@unicef.org') + GroupFactory(name="UNICEF User") + user = get_user_model().objects.create(username="user@unicef.org", email="user@unicef.org") assert user.groups.count() == 1 - assert user.groups.first().name == 'UNICEF User' + assert user.groups.first().name == "UNICEF User" @pytest.mark.django_db def test_assign_to_unicef_group_ko(): - GroupFactory(name='UNICEF User') - user = get_user_model().objects.create(username='user@wfp.org', email='user@wfp.org') + GroupFactory(name="UNICEF User") + user = get_user_model().objects.create(username="user@wfp.org", email="user@wfp.org") assert user.groups.count() == 0 diff --git a/tests/apps/test_synchronizers.py b/tests/apps/test_synchronizers.py index 054562bc..037c4f81 100644 --- a/tests/apps/test_synchronizers.py +++ b/tests/apps/test_synchronizers.py @@ -8,7 +8,7 @@ @pytest.mark.django_db -@VCR.use_cassette(str(Path(__file__).parent / 'vcr_cassettes/test_grant_sync.yml')) +@VCR.use_cassette(str(Path(__file__).parent / "vcr_cassettes/test_grant_sync.yml")) def test_grant_sync(): assert Donor.objects.count() == 0 assert Grant.objects.count() == 0 diff --git a/tests/apps/test_tasks.py b/tests/apps/test_tasks.py index ffec72f4..a4644063 100644 --- a/tests/apps/test_tasks.py +++ b/tests/apps/test_tasks.py @@ -4,5 +4,5 @@ def test_grant_sync_url(django_app, admin_user): - with mock.patch('donor_reporting_portal.apps.report_metadata.tasks.GrantSynchronizer'): + with mock.patch("donor_reporting_portal.apps.report_metadata.tasks.GrantSynchronizer"): grant_sync() diff --git a/tests/apps/test_wsgi.py b/tests/apps/test_wsgi.py index 3aa47340..96cdb56f 100644 --- a/tests/apps/test_wsgi.py +++ b/tests/apps/test_wsgi.py @@ -1,3 +1,4 @@ def test_wsgi(): from donor_reporting_portal.config.wsgi import application + assert application diff --git a/tests/conftest.py b/tests/conftest.py index 786a4f57..4c96c1d8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -22,14 +22,14 @@ def pytest_configure(config): # enable this to remove deprecations - os.environ['CELERY_TASK_ALWAYS_EAGER'] = "1" - os.environ['STATIC_ROOT'] = tempfile.gettempdir() + os.environ["CELERY_TASK_ALWAYS_EAGER"] = "1" + os.environ["STATIC_ROOT"] = tempfile.gettempdir() -@pytest.fixture(scope='session') +@pytest.fixture(scope="session") def django_db_setup(django_db_setup, django_db_blocker): with django_db_blocker.unblock(): - call_command('loaddata', 'notifications.json') + call_command("loaddata", "notifications.json") @pytest.fixture() diff --git a/tests/factories/metadata.py b/tests/factories/metadata.py index f9d5a436..8d528d09 100644 --- a/tests/factories/metadata.py +++ b/tests/factories/metadata.py @@ -15,7 +15,7 @@ class ThemeFactory(factory.django.DjangoModelFactory): class Meta: model = Theme - django_get_or_create = ('name',) + django_get_or_create = ("name",) class DonorFactory(factory.django.DjangoModelFactory): @@ -23,7 +23,7 @@ class DonorFactory(factory.django.DjangoModelFactory): class Meta: model = Donor - django_get_or_create = ('code',) + django_get_or_create = ("code",) class ExternalGrantFactory(factory.django.DjangoModelFactory): @@ -32,7 +32,7 @@ class ExternalGrantFactory(factory.django.DjangoModelFactory): class Meta: model = ExternalGrant - django_get_or_create = ('code',) + django_get_or_create = ("code",) class GrantFactory(factory.django.DjangoModelFactory): @@ -41,7 +41,7 @@ class GrantFactory(factory.django.DjangoModelFactory): class Meta: model = Grant - django_get_or_create = ('code',) + django_get_or_create = ("code",) class SecondaryDonorFactory(factory.django.DjangoModelFactory): @@ -49,7 +49,7 @@ class SecondaryDonorFactory(factory.django.DjangoModelFactory): class Meta: model = SecondaryDonor - django_get_or_create = ('code',) + django_get_or_create = ("code",) class DRPMetadataFactory(factory.django.DjangoModelFactory): diff --git a/tests/factories/roles.py b/tests/factories/roles.py index fed5add7..a2d889f8 100644 --- a/tests/factories/roles.py +++ b/tests/factories/roles.py @@ -24,22 +24,22 @@ def permissions(self, create, extracted, **kwargs): class Meta: model = Group - django_get_or_create = ('name',) + django_get_or_create = ("name",) @factory.django.mute_signals(signals.post_save) class UserFactory(factory.django.DjangoModelFactory): class Meta: model = unicef_security.models.User - django_get_or_create = ('username',) + django_get_or_create = ("username",) username = factory.Sequence(lambda n: "user%03d" % n) - last_name = factory.Faker('last_name') - first_name = factory.Faker('first_name') + last_name = factory.Faker("last_name") + first_name = factory.Faker("first_name") email = factory.Sequence(lambda n: "m%03d@mailinator.com" % n) - password = 'password' + password = "password" is_superuser = False is_active = True @@ -47,9 +47,9 @@ class Meta: def _prepare(cls, create, **kwargs): from ..perms import user_grant_permissions - permissions = kwargs.pop('permissions', []) + permissions = kwargs.pop("permissions", []) - password = kwargs.pop('password') + password = kwargs.pop("password") user = super()._prepare(cls, create, **kwargs) if password: user.set_password(password) @@ -64,7 +64,7 @@ class AdminFactory(UserFactory): class AnonUserFactory(UserFactory): - username = 'anonymous' + username = "anonymous" class RegionFactory(factory.django.DjangoModelFactory): @@ -73,7 +73,7 @@ class RegionFactory(factory.django.DjangoModelFactory): class Meta: model = Region - django_get_or_create = ('name',) + django_get_or_create = ("name",) class BusinessAreaFactory(factory.django.DjangoModelFactory): @@ -82,7 +82,7 @@ class BusinessAreaFactory(factory.django.DjangoModelFactory): class Meta: model = BusinessArea - django_get_or_create = ('code',) + django_get_or_create = ("code",) class UserRoleFactory(factory.django.DjangoModelFactory): diff --git a/tests/factories/sharepoint.py b/tests/factories/sharepoint.py index 9e6b3a0c..6c457291 100644 --- a/tests/factories/sharepoint.py +++ b/tests/factories/sharepoint.py @@ -5,10 +5,9 @@ class SharePointTenantFactory(factory.django.DjangoModelFactory): - class Meta: model = SharePointTenant - django_get_or_create = ('url',) + django_get_or_create = ("url",) class SharePointSiteFactory(factory.django.DjangoModelFactory): @@ -16,7 +15,7 @@ class SharePointSiteFactory(factory.django.DjangoModelFactory): class Meta: model = SharePointSite - django_get_or_create = ('name',) + django_get_or_create = ("name",) class SharePointLibraryFactory(factory.django.DjangoModelFactory): @@ -24,7 +23,7 @@ class SharePointLibraryFactory(factory.django.DjangoModelFactory): class Meta: model = SharePointLibrary - django_get_or_create = ('name',) + django_get_or_create = ("name",) class SharePointGroupFactory(factory.django.DjangoModelFactory): @@ -41,4 +40,4 @@ def libs(self, create, extracted, **kwargs): class Meta: model = SharePointGroup - django_get_or_create = ('name',) + django_get_or_create = ("name",) diff --git a/tests/perms.py b/tests/perms.py index 82ac29df..d7f47fbf 100644 --- a/tests/perms.py +++ b/tests/perms.py @@ -12,9 +12,9 @@ from .factories import GroupFactory -whitespace = ' \t\n\r\v\f' -lowercase = 'abcdefghijklmnopqrstuvwxyz' -uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +whitespace = " \t\n\r\v\f" +lowercase = "abcdefghijklmnopqrstuvwxyz" +uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" letters = lowercase + uppercase ascii_lowercase = lowercase ascii_uppercase = uppercase @@ -24,7 +24,7 @@ def text(length, choices=ascii_letters): - """ returns a random (fixed length) string + """returns a random (fixed length) string :param length: string length :param choices: string containing all the chars can be used to build the string @@ -32,7 +32,7 @@ def text(length, choices=ascii_letters): .. seealso:: :py:func:`rtext` """ - return ''.join(choice(choices) for x in range(length)) + return "".join(choice(choices) for x in range(length)) def get_group(name=None, permissions=None): @@ -40,21 +40,27 @@ def get_group(name=None, permissions=None): permission_names = permissions or [] for permission_name in permission_names: try: - app_label, codename = permission_name.split('.') + app_label, codename = permission_name.split(".") except ValueError: raise ValueError("Invalid permission name `{0}`".format(permission_name)) try: permission = Permission.objects.get(content_type__app_label=app_label, codename=codename) except Permission.DoesNotExist: - raise Permission.DoesNotExist('Permission `{0}` does not exists', permission_name) + raise Permission.DoesNotExist("Permission `{0}` does not exists", permission_name) group.permissions.add(permission) return group class user_grant_permissions(ContextDecorator): # noqa - caches = ['_group_perm_cache', '_user_perm_cache', '_dsspermissionchecker', - '_officepermissionchecker', '_perm_cache', '_dss_acl_cache'] + caches = [ + "_group_perm_cache", + "_user_perm_cache", + "_dsspermissionchecker", + "_officepermissionchecker", + "_perm_cache", + "_dss_acl_cache", + ] def __init__(self, user, permissions=None): self.user = user @@ -95,17 +101,17 @@ def __init__(self, user, donor, permissions): self.permissions = permissions def __enter__(self): - if hasattr(self.user, '_group_perm_cache'): + if hasattr(self.user, "_group_perm_cache"): del self.user._group_perm_cache - if hasattr(self.user, '_perm_cache'): + if hasattr(self.user, "_perm_cache"): del self.user._perm_cache or_queries = [] if self.permissions: self.group, _ = Group.objects.get_or_create(name="context_group") for permission in self.permissions: - app, perm = permission.split('.') - or_queries.append(Q(**{'codename': perm, 'content_type__app_label': app})) + app, perm = permission.split(".") + or_queries.append(Q(**{"codename": perm, "content_type__app_label": app})) self.group.permissions.set(Permission.objects.filter(reduce(operator.or_, or_queries))) self.group.save() self.user_role, _ = UserRole.objects.get_or_create(user=self.user, group=self.group, donor=self.donor) diff --git a/tests/vcrpy.py b/tests/vcrpy.py index 6b68877c..f44b0d79 100644 --- a/tests/vcrpy.py +++ b/tests/vcrpy.py @@ -1,8 +1,10 @@ import vcr -VCR = vcr.VCR(serializer='yaml', - record_mode='once', - match_on=['uri', 'method'], - filter_headers=['authorization', 'token'], - filter_post_data_parameters=['client_id', 'client_secret', 'password'], - decode_compressed_response=True) +VCR = vcr.VCR( + serializer="yaml", + record_mode="once", + match_on=["uri", "method"], + filter_headers=["authorization", "token"], + filter_post_data_parameters=["client_id", "client_secret", "password"], + decode_compressed_response=True, +) diff --git a/tox.ini b/tox.ini index 559ef080..752c99f8 100644 --- a/tox.ini +++ b/tox.ini @@ -21,12 +21,12 @@ markers = slow: marks tests as slow (deselect with '-m "not slow"') [tox] -envlist = d{40} +envlist = d{42} envtmpdir={toxinidir}/build/{envname}/tmp envlogdir={toxinidir}/build/{envname}/log [testenv] -basepython=python3.9 +basepython=python3.11 passenv = PYTHONDONTWRITEBYTECODE USER @@ -43,11 +43,11 @@ setenv = extras = test deps = - d40: django==4.0.* + d41: django==4.1.* -whitelist_externals = +allowlist_externals = pipenv - /bin/mkdir + mkdir commands = mkdir -p {toxinidir}/~build/flake {toxinidir}/build/results @@ -56,6 +56,7 @@ commands = ; python -W ignore manage.py makemigrations --dry-run --check flake8 src/ tests/ --format=html --htmldir=~build/flake isort src/ tests/ --check-only + black --check . pytest tests \ -q \ --create-db \ From 35f673200c66be5e7d9d2f15532b55c5cc9f1f91 Mon Sep 17 00:00:00 2001 From: Domenico DiNicola Date: Fri, 31 Mar 2023 03:02:41 -0600 Subject: [PATCH 3/6] new lock --- Pipfile.lock | 228 +++++++++++++++++++++++++-------------------------- 1 file changed, 114 insertions(+), 114 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 6788b409..0d4ae123 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -254,28 +254,28 @@ }, "cryptography": { "hashes": [ - "sha256:14da8c26755ffa5c7863ffa5e8b87cb9596a21b6c34852cb19e0f48c226c64fb", - "sha256:168ded448fb5d82dfa911156ab8b13b1716de65bd50ff977f4657643f998fa05", - "sha256:22e63fb48e2615cfab5a9c4bb457d35e7ae03ea8593996bfbe257e78244d12d0", - "sha256:23c42c59c2b5b9ddc6a85b5c46b8fabc4d63a1714f4dbea4bf20d25690bf2365", - "sha256:34f502619964210939bb7ee7cd5df53178534eb08d3526f941695a8f7aa0efe4", - "sha256:43089be365c0ca4235c6e4e781f3bc125bc1fff576c9dd22cdfb585309b9bb9d", - "sha256:6b36e2864e04c82634879c7e7aad48824b1847fdb06b64cd410d2ec5e51d1b31", - "sha256:7162ae4530958114ca2eee30a56eca46527def33493f622f059dc2e825fd0913", - "sha256:71cb346b9dd1537102e7466a2d629385b01847f8d96cd7405f0e717d91cebc8e", - "sha256:722cfddae79684166840be2cbbae154f44a455519e644b60bf274a50ccb834db", - "sha256:754dc5ab648113dc54197f242db43234a04e4d61193fb5d3ebb42bd569dca571", - "sha256:7cc9fc3ffcb766c313ed0515d77d0deabb4f36bdcff3a9f115c43e5ec611b82a", - "sha256:b05c9f25a1ea42e427085230815bbdebe15a53bb6163c4c06022e5630645046b", - "sha256:e5855a80c77565fe2464e88e0095764e25d8ddb2d24df2b1d31773e80be94435", - "sha256:e917a07094217edeefe8f6ea960b45d7aab650b982e4209da078332cc9d3ac3a", - "sha256:f2c4134d29cdce0735c16abf48fa8435f001a7b0031e68dd9a9ee1c80a29374a", - "sha256:f421f6777592eb199ca8abac7c20b9ecef27c50ad63546e6c614b29771b46d0d", - "sha256:fafa997b9e6818db333ded4b379f5b7679b48bd88ac878428cea2a1aa6e79fd8", - "sha256:fba36ec552794a06a07ac8bdc5ad83a587f6959d98547f373d401975d55c7c9e" + "sha256:0a4e3406cfed6b1f6d6e87ed243363652b2586b2d917b0609ca4f97072994405", + "sha256:1e0af458515d5e4028aad75f3bb3fe7a31e46ad920648cd59b64d3da842e4356", + "sha256:2803f2f8b1e95f614419926c7e6f55d828afc614ca5ed61543877ae668cc3472", + "sha256:28d63d75bf7ae4045b10de5413fb1d6338616e79015999ad9cf6fc538f772d41", + "sha256:32057d3d0ab7d4453778367ca43e99ddb711770477c4f072a51b3ca69602780a", + "sha256:3a4805a4ca729d65570a1b7cac84eac1e431085d40387b7d3bbaa47e39890b88", + "sha256:63dac2d25c47f12a7b8aa60e528bfb3c51c5a6c5a9f7c86987909c6c79765554", + "sha256:650883cc064297ef3676b1db1b7b1df6081794c4ada96fa457253c4cc40f97db", + "sha256:6f2bbd72f717ce33100e6467572abaedc61f1acb87b8d546001328d7f466b778", + "sha256:7c872413353c70e0263a9368c4993710070e70ab3e5318d85510cc91cce77e7c", + "sha256:918cb89086c7d98b1b86b9fdb70c712e5a9325ba6f7d7cfb509e784e0cfc6917", + "sha256:9618a87212cb5200500e304e43691111570e1f10ec3f35569fdfcd17e28fd797", + "sha256:a805a7bce4a77d51696410005b3e85ae2839bad9aa38894afc0aa99d8e0c3160", + "sha256:cc3a621076d824d75ab1e1e530e66e7e8564e357dd723f2533225d40fe35c60c", + "sha256:cd033d74067d8928ef00a6b1327c8ea0452523967ca4463666eeba65ca350d4c", + "sha256:cf91e428c51ef692b82ce786583e214f58392399cf65c341bc7301d096fa3ba2", + "sha256:d36bbeb99704aabefdca5aee4eba04455d7a27ceabd16f3b3ba9bdcc31da86c4", + "sha256:d8aa3609d337ad85e4eb9bb0f8bcf6e4409bfb86e706efa9a027912169e89122", + "sha256:f5d7b79fa56bc29580faafc2ff736ce05ba31feaa9d4735048b0de7d9ceb2b94" ], "markers": "python_version >= '3.6'", - "version": "==40.0.0" + "version": "==40.0.1" }, "defusedxml": { "hashes": [ @@ -295,11 +295,11 @@ }, "dj-database-url": { "hashes": [ - "sha256:5c2993b91801c0f78a8b19e642b497b90831124cbade0c265900d4c1037b4730", - "sha256:b23b15046cb38180e0c95207bcc90fe5e9dbde8eef16065907dd85cf4ca7036c" + "sha256:80a115bd7675c9fe14a900b2f8b5c8b1822b5a279b333bf9b2804de681656c7c", + "sha256:87be5f7c4c83d9b3d8ce94b834f96cea14b3986f3629aac097afdd9318d7b098" ], "index": "pypi", - "version": "==1.2.0" + "version": "==1.3.0" }, "dj-static": { "hashes": [ @@ -417,11 +417,11 @@ }, "django-filter": { "hashes": [ - "sha256:ed429e34760127e3520a67f415bec4c905d4649fbe45d0d6da37e6ff5e0287eb", - "sha256:ed473b76e84f7e83b2511bb2050c3efb36d135207d0128dfe3ae4b36e3594ba5" + "sha256:dee5dcf2cea4d7f767e271b6d01f767fce7500676d5e5dc58dac8154000b87df", + "sha256:e3c52ad83c32fb5882125105efb5fea2a1d6a85e7dc64b04ef52edbf14451b6c" ], "index": "pypi", - "version": "==22.1" + "version": "==23.1" }, "django-fsm": { "hashes": [ @@ -576,24 +576,24 @@ }, "newrelic": { "hashes": [ - "sha256:15d3088d9ab4d708e7b3826e651c2402f2cb9c72689e47a0badc8281ab20bfe9", - "sha256:2249a25b1ce967267604cb0ce3268256fb25da481312f3c7b04df90245708131", - "sha256:2fc9807a1e3277e1dbddb7cd84e00b1f70faea602f0bbe53109e0e68b0c20e3c", - "sha256:432a6fa9c0051154f4110f4203831f464c8ba5bc842e709639391175d4ba50e6", - "sha256:4f48e481ebb7d873fd16a7fe0df30383c834e75daa6b0b514e147b8d683d922d", - "sha256:69a7ed5788fb6347e96f7df18a641ea242d5dac7ccb76bbaa869851cade335c4", - "sha256:6fc4169f66e80f4b497d16be3759feaf5be08ec389b8f42b8b62ce632de9eb3f", - "sha256:95484f2ca36952831b47e3b054e808317a0a12597ca9ef5166789a425545de44", - "sha256:b5c53a5922c92d742eff37da87c113a18762cd06e310bfc430df02603298def9", - "sha256:d02acde140c6d4f549f36a2bda64025a18efc5b6457c8fa505146c7bcaaac23b", - "sha256:d39f6f3ffc458337e22ef4d4e7bacf5b0b2712feb7668538299d029bc87f9b7a", - "sha256:d7b510f3889fe57330bb85de78abcac2d0711b49e9da74fcd1b936a57b139238", - "sha256:eb3a27fd7b9d51941fb20c452aa3b3b2dd52fe652cda2d5d269dcc14f64ade6e", - "sha256:ec8d38d9f7c30c464cddd594cb390cf66a2b573d08e09ac231d3d349a26e0f96", - "sha256:f79a599b53894870dfdfcd88fa7ca7e81cac77f4a253ca0c08c58f400bb0a5ab" - ], - "index": "pypi", - "version": "==8.7.1" + "sha256:1bc307d06e2033637e7b484af22f540ca041fb23a54b311bcd5968ca1a64e4ef", + "sha256:435ac9e3791f78e05c9da8107a6ef49c13e62ac302696858fa2411198fe201ff", + "sha256:6662ec79493f23f9d0995a015177c87508bea4c541f7c9f17a61b503b82e1367", + "sha256:67902b3c53fa497dba887068166261d114ac2347c8a4908d735d7594cca163dc", + "sha256:6b4db0e7544232d4e6e835a02ee28637970576f8dce82ffcaa3d675246e822d5", + "sha256:796ed5ff44b04b41e051dc0112e5016e53a37e39e95023c45ff7ecd34c254a7d", + "sha256:84d1f71284efa5f1cae696161e0c3cb65eaa2f53116fe5e7c5a62be7d15d9536", + "sha256:9355f209ba8d82fd0f9d78d7cc1d9bef0ae4677b3cfed7b7aaec521adbe87559", + "sha256:9c0d5153b7363d5cb5cac7f8d1a4e03669b074afee2dda201851a67c7bed1e32", + "sha256:bcd3219e1e816a0fdb51ac993cac6744e6a835c13ee72e21d86bcbc2d16628ce", + "sha256:c4a0556c6ece49132ab1c32bfe398047a8311f9a8b6862b482495d132fcb0ad4", + "sha256:caccdf201735df80b470ddf772f60a154f2c07c0c1b2b3f6e999d55e79ce601e", + "sha256:d21af16cee1e0caf4c73c4c1b2d7ba9f33fe6a870d93135dc8b23ac592f49b38", + "sha256:da8f2dc31e182768fe314d8ceb6f42acd09956708846f8ae71f07f044a3aa05e", + "sha256:ef9c178329f8c04f0574908c1f04ff1f18b9eba55b869744583fee3eac48e571" + ], + "index": "pypi", + "version": "==8.8.0" }, "oauthlib": { "hashes": [ @@ -734,10 +734,10 @@ }, "pytz": { "hashes": [ - "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0", - "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a" + "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", + "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb" ], - "version": "==2022.7.1" + "version": "==2023.3" }, "redis": { "hashes": [ @@ -765,19 +765,19 @@ }, "sentry-sdk": { "hashes": [ - "sha256:3c4e898f7a3edf5a2042cd0dcab6ee124e2112189228c272c08ad15d3850c201", - "sha256:ad40860325c94d1a656da70fba5a7c4dbb2f6809d3cc2d00f74ca0b608330f14" + "sha256:714203a9adcac4a4a35e348dc9d3e294ad0200a66cdca26c068967d728f34fcb", + "sha256:d07b9569a151033b462f7a7113ada94cc41ecf49daa83d35f5f852a0b9cf3b44" ], "index": "pypi", - "version": "==1.17.0" + "version": "==1.18.0" }, "setuptools": { "hashes": [ - "sha256:2ee892cd5f29f3373097f5a814697e397cf3ce313616df0af11231e2ad118077", - "sha256:b78aaa36f6b90a074c1fa651168723acbf45d14cb1196b6f02c0fd07f17623b2" + "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a", + "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078" ], "markers": "python_version >= '3.7'", - "version": "==67.6.0" + "version": "==67.6.1" }, "sharepoint-rest-api": { "hashes": [ @@ -797,22 +797,22 @@ }, "social-auth-app-django": { "hashes": [ - "sha256:e4e9eb2c8c1258f443d4f1c04cb6693c0303e8ee2fa0981ba1b371546195a939", - "sha256:fdf1dc6bcb8b457001d88d2279f637bc9955f1aedf750c627784bb5104601b1c" + "sha256:0347ca4cd23ea9d15a665da9d22950552fb66b95600e6c2ebae38ca883b3a4ed", + "sha256:4a5dae406f3874b4003708ff120c02cb1a4c8eeead56cd163646347309fcd0f8" ], "index": "pypi", - "version": "==5.1.0" + "version": "==5.2.0" }, "social-auth-core": { "extras": [ "azuread" ], "hashes": [ - "sha256:359f6be5bb2d4caef6500eb6e1b40821a40dde9add8d339d539b1adbba2c9bf7", - "sha256:89536f218fa1a769caeaa56ef90f965ea50a81b9a7e3e5a2c5a61b832df11bde" + "sha256:29f5ea3174162797ccb9b849f7a38a9490bfb920304ecd9b7f63c6c3a5ceb7a3", + "sha256:cff78e0707ed0f6bdd3beec6ce713591875492b98272ea6298cc173912e3234b" ], "index": "pypi", - "version": "==4.4.0" + "version": "==4.4.1" }, "sqlparse": { "hashes": [ @@ -845,11 +845,11 @@ }, "tzdata": { "hashes": [ - "sha256:905ae9e6744dd9ef5ce94d2aaa2dd00282fee38b670b2133407f23c388f110a1", - "sha256:c3b51b235b07f9f1889089c2264bcbeaaba260a63f89bea09e350ea4205eb95f" + "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a", + "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda" ], "markers": "python_version >= '2'", - "version": "==2023.2" + "version": "==2023.3" }, "unicef-djangolib": { "hashes": [ @@ -1096,34 +1096,34 @@ }, "black": { "hashes": [ - "sha256:0052dba51dec07ed029ed61b18183942043e00008ec65d5028814afaab9a22fd", - "sha256:0680d4380db3719ebcfb2613f34e86c8e6d15ffeabcf8ec59355c5e7b85bb555", - "sha256:121ca7f10b4a01fd99951234abdbd97728e1240be89fde18480ffac16503d481", - "sha256:162e37d49e93bd6eb6f1afc3e17a3d23a823042530c37c3c42eeeaf026f38468", - "sha256:2a951cc83ab535d248c89f300eccbd625e80ab880fbcfb5ac8afb5f01a258ac9", - "sha256:2bf649fda611c8550ca9d7592b69f0637218c2369b7744694c5e4902873b2f3a", - "sha256:382998821f58e5c8238d3166c492139573325287820963d2f7de4d518bd76958", - "sha256:49f7b39e30f326a34b5c9a4213213a6b221d7ae9d58ec70df1c4a307cf2a1580", - "sha256:57c18c5165c1dbe291d5306e53fb3988122890e57bd9b3dcb75f967f13411a26", - "sha256:7a0f701d314cfa0896b9001df70a530eb2472babb76086344e688829efd97d32", - "sha256:8178318cb74f98bc571eef19068f6ab5613b3e59d4f47771582f04e175570ed8", - "sha256:8b70eb40a78dfac24842458476135f9b99ab952dd3f2dab738c1881a9b38b753", - "sha256:9880d7d419bb7e709b37e28deb5e68a49227713b623c72b2b931028ea65f619b", - "sha256:9afd3f493666a0cd8f8df9a0200c6359ac53940cbde049dcb1a7eb6ee2dd7074", - "sha256:a29650759a6a0944e7cca036674655c2f0f63806ddecc45ed40b7b8aa314b651", - "sha256:a436e7881d33acaf2536c46a454bb964a50eff59b21b51c6ccf5a40601fbef24", - "sha256:a59db0a2094d2259c554676403fa2fac3473ccf1354c1c63eccf7ae65aac8ab6", - "sha256:a8471939da5e824b891b25751955be52ee7f8a30a916d570a5ba8e0f2eb2ecad", - "sha256:b0bd97bea8903f5a2ba7219257a44e3f1f9d00073d6cc1add68f0beec69692ac", - "sha256:b6a92a41ee34b883b359998f0c8e6eb8e99803aa8bf3123bf2b2e6fec505a221", - "sha256:bb460c8561c8c1bec7824ecbc3ce085eb50005883a6203dcfb0122e95797ee06", - "sha256:bfffba28dc52a58f04492181392ee380e95262af14ee01d4bc7bb1b1c6ca8d27", - "sha256:c1c476bc7b7d021321e7d93dc2cbd78ce103b84d5a4cf97ed535fbc0d6660648", - "sha256:c91dfc2c2a4e50df0026f88d2215e166616e0c80e86004d0003ece0488db2739", - "sha256:e6663f91b6feca5d06f2ccd49a10f254f9298cc1f7f49c46e498a0771b507104" - ], - "index": "pypi", - "version": "==23.1.0" + "sha256:064101748afa12ad2291c2b91c960be28b817c0c7eaa35bec09cc63aa56493c5", + "sha256:0945e13506be58bf7db93ee5853243eb368ace1c08a24c65ce108986eac65915", + "sha256:11c410f71b876f961d1de77b9699ad19f939094c3a677323f43d7a29855fe326", + "sha256:1c7b8d606e728a41ea1ccbd7264677e494e87cf630e399262ced92d4a8dac940", + "sha256:1d06691f1eb8de91cd1b322f21e3bfc9efe0c7ca1f0e1eb1db44ea367dff656b", + "sha256:3238f2aacf827d18d26db07524e44741233ae09a584273aa059066d644ca7b30", + "sha256:32daa9783106c28815d05b724238e30718f34155653d4d6e125dc7daec8e260c", + "sha256:35d1381d7a22cc5b2be2f72c7dfdae4072a3336060635718cc7e1ede24221d6c", + "sha256:3a150542a204124ed00683f0db1f5cf1c2aaaa9cc3495b7a3b5976fb136090ab", + "sha256:48f9d345675bb7fbc3dd85821b12487e1b9a75242028adad0333ce36ed2a6d27", + "sha256:50cb33cac881766a5cd9913e10ff75b1e8eb71babf4c7104f2e9c52da1fb7de2", + "sha256:562bd3a70495facf56814293149e51aa1be9931567474993c7942ff7d3533961", + "sha256:67de8d0c209eb5b330cce2469503de11bca4085880d62f1628bd9972cc3366b9", + "sha256:6b39abdfb402002b8a7d030ccc85cf5afff64ee90fa4c5aebc531e3ad0175ddb", + "sha256:6f3c333ea1dd6771b2d3777482429864f8e258899f6ff05826c3a4fcc5ce3f70", + "sha256:714290490c18fb0126baa0fca0a54ee795f7502b44177e1ce7624ba1c00f2331", + "sha256:7c3eb7cea23904399866c55826b31c1f55bbcd3890ce22ff70466b907b6775c2", + "sha256:92c543f6854c28a3c7f39f4d9b7694f9a6eb9d3c5e2ece488c327b6e7ea9b266", + "sha256:a6f6886c9869d4daae2d1715ce34a19bbc4b95006d20ed785ca00fa03cba312d", + "sha256:a8a968125d0a6a404842fa1bf0b349a568634f856aa08ffaff40ae0dfa52e7c6", + "sha256:c7ab5790333c448903c4b721b59c0d80b11fe5e9803d8703e84dcb8da56fec1b", + "sha256:e114420bf26b90d4b9daa597351337762b63039752bdf72bf361364c1aa05925", + "sha256:e198cf27888ad6f4ff331ca1c48ffc038848ea9f031a3b40ba36aced7e22f2c8", + "sha256:ec751418022185b0c1bb7d7736e6933d40bbb14c14a0abcf9123d1b159f98dd4", + "sha256:f0bd2f4a58d6666500542b26354978218a9babcdc972722f4bf90779524515f3" + ], + "index": "pypi", + "version": "==23.3.0" }, "cachetools": { "hashes": [ @@ -1397,11 +1397,11 @@ }, "filelock": { "hashes": [ - "sha256:6d332dc5c896f18ba93a21d987155e97c434a96d3fe4042ca70d0b3b46e3b470", - "sha256:9fc1734dbddcdcd4aaa02c160dd94db5272b92dfa859b44ec8df28e160b751f0" + "sha256:892be14aa8efc01673b5ed6589dbccb95f9a8596f0507e232626155495c18105", + "sha256:bde48477b15fde2c7e5a0713cbe72721cb5a5ad32ee0b8f419907960b9d75536" ], "markers": "python_version >= '3.7'", - "version": "==3.10.4" + "version": "==3.10.7" }, "flake8": { "hashes": [ @@ -1461,11 +1461,11 @@ }, "ipython": { "hashes": [ - "sha256:5b54478e459155a326bf5f42ee4f29df76258c0279c36f21d71ddb560f88b156", - "sha256:735cede4099dbc903ee540307b9171fbfef4aa75cfcacc5a273b2cda2f02be04" + "sha256:1c183bf61b148b00bcebfa5d9b39312733ae97f6dad90d7e9b4d86c8647f498c", + "sha256:a950236df04ad75b5bc7f816f9af3d74dc118fd42f2ff7e80e8e60ca1f182e2d" ], "index": "pypi", - "version": "==8.11.0" + "version": "==8.12.0" }, "isort": { "hashes": [ @@ -1716,11 +1716,11 @@ }, "platformdirs": { "hashes": [ - "sha256:024996549ee88ec1a9aa99ff7f8fc819bb59e2c3477b410d90a16d32d6e707aa", - "sha256:e5986afb596e4bb5bde29a79ac9061aa955b94fca2399b7aaac4090860920dd8" + "sha256:d5b638ca397f25f979350ff789db335903d7ea010ab28903f57b27e1b16c2b08", + "sha256:ebe11c0d7a805086e99506aa331612429a72ca7cd52a1f0d277dc4adc20cb10e" ], "markers": "python_version >= '3.7'", - "version": "==3.1.1" + "version": "==3.2.0" }, "pluggy": { "hashes": [ @@ -1732,11 +1732,11 @@ }, "pre-commit": { "hashes": [ - "sha256:818f0d998059934d0f81bb3667e3ccdc32da6ed7ccaac33e43dc231561ddaaa9", - "sha256:f712d3688102e13c8e66b7d7dbd8934a6dda157e58635d89f7d6fecdca39ce8a" + "sha256:a06a7fcce7f420047a71213c175714216498b49ebc81fe106f7716ca265f5bb6", + "sha256:b5aee7d75dbba21ee161ba641b01e7ae10c5b91967ebf7b2ab0dfae12d07e1f1" ], "index": "pypi", - "version": "==3.2.0" + "version": "==3.2.1" }, "prompt-toolkit": { "hashes": [ @@ -1878,10 +1878,10 @@ }, "pytz": { "hashes": [ - "sha256:01a0681c4b9684a28304615eba55d1ab31ae00bf68ec157ec3708a8182dbbcd0", - "sha256:78f4f37d8198e0627c5f1143240bb0206b8691d8d7ac6d78fee88b78733f8c4a" + "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588", + "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb" ], - "version": "==2022.7.1" + "version": "==2023.3" }, "pyyaml": { "hashes": [ @@ -1947,11 +1947,11 @@ }, "setuptools": { "hashes": [ - "sha256:2ee892cd5f29f3373097f5a814697e397cf3ce313616df0af11231e2ad118077", - "sha256:b78aaa36f6b90a074c1fa651168723acbf45d14cb1196b6f02c0fd07f17623b2" + "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a", + "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078" ], "markers": "python_version >= '3.7'", - "version": "==67.6.0" + "version": "==67.6.1" }, "six": { "hashes": [ @@ -2064,11 +2064,11 @@ }, "tox": { "hashes": [ - "sha256:52c92a96e2c3fd47c5301e9c26f5a871466133d5376958c1ed95ef4ff4629cbe", - "sha256:da10ca1d809b99fae80b706b9dc9656b1daf505a395ac427d130a8a85502d08f" + "sha256:12fe562b8992ea63b1e92556b7e28600cd1b70c9e01ce08984f60ce2d32c243c", + "sha256:524640254de8b0f03facbdc6b7c18a35700592e3ada0ede42f509b3504b745ff" ], "index": "pypi", - "version": "==4.4.7" + "version": "==4.4.8" }, "traitlets": { "hashes": [ @@ -2080,10 +2080,10 @@ }, "types-pyyaml": { "hashes": [ - "sha256:19304869a89d49af00be681e7b267414df213f4eb89634c4495fa62e8f942b9f", - "sha256:5314a4b2580999b2ea06b2e5f9a7763d860d6e09cdf21c0e9561daa9cbd60178" + "sha256:5aed5aa66bd2d2e158f75dda22b059570ede988559f030cf294871d3b647e3e8", + "sha256:c51b1bd6d99ddf0aa2884a7a328810ebf70a4262c292195d3f4f9a0005f9eeb6" ], - "version": "==6.0.12.8" + "version": "==6.0.12.9" }, "urllib3": { "hashes": [ From 0478a7c64e5d0ee4c5e1fb6978dca2b1fc05a2d4 Mon Sep 17 00:00:00 2001 From: Domenico DiNicola Date: Fri, 31 Mar 2023 07:34:12 -0600 Subject: [PATCH 4/6] revert alpine version --- docker/Dockerfile.base | 2 +- docker/Dockerfile.flat | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base index 10766734..549a6e6a 100644 --- a/docker/Dockerfile.base +++ b/docker/Dockerfile.base @@ -1,4 +1,4 @@ -FROM python:3.11.2-alpine3.17 +FROM python:3.11.2-alpine3.16 ARG PIPENV_ARGS diff --git a/docker/Dockerfile.flat b/docker/Dockerfile.flat index bf68c38c..7931aec6 100644 --- a/docker/Dockerfile.flat +++ b/docker/Dockerfile.flat @@ -1,4 +1,4 @@ -FROM python:3.11.2-alpine3.17 +FROM python:3.11.2-alpine3.16 ARG BUILD_DATE ARG PIPENV_ARGS From 33ebbb2d7dfe2a35504490b3d3f3eda03736731a Mon Sep 17 00:00:00 2001 From: Domenico DiNicola Date: Tue, 4 Apr 2023 11:28:14 +0200 Subject: [PATCH 5/6] dj4.2 --- Pipfile.lock | 169 ++++++++++++++++++++++++--------------------------- 1 file changed, 80 insertions(+), 89 deletions(-) diff --git a/Pipfile.lock b/Pipfile.lock index 0d4ae123..1d3800d4 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -310,11 +310,11 @@ }, "django": { "hashes": [ - "sha256:44f714b81c5f190d9d2ddad01a532fe502fa01c4cb8faf1d081f4264ed15dcd8", - "sha256:f2f431e75adc40039ace496ad3b9f17227022e8b11566f4b363da44c7e44761e" + "sha256:ad33ed68db9398f5dfb33282704925bce044bef4261cd4fb59e4e7f9ae505a78", + "sha256:c36e2ab12824e2ac36afa8b2515a70c53c7742f0d6eaefa7311ec379558db997" ], "index": "pypi", - "version": "==4.1.7" + "version": "==4.2" }, "django-admin-extra-buttons": { "hashes": [ @@ -393,11 +393,11 @@ }, "django-debug-toolbar": { "hashes": [ - "sha256:24ef1a7d44d25e60d7951e378454c6509bf536dce7e7d9d36e7c387db499bc27", - "sha256:879f8a4672d41621c06a4d322dcffa630fc4df056cada6e417ed01db0e5e0478" + "sha256:89619f6e0ea1057dca47bfc429ed99b237ef70074dabc065a7faa5f00e1459cf", + "sha256:bad339d68520652ddc1580c76f136fcbc3e020fd5ed96510a89a02ec81bb3fb1" ], "index": "pypi", - "version": "==3.8.1" + "version": "==4.0.0" }, "django-environ": { "hashes": [ @@ -620,80 +620,71 @@ }, "psycopg2-binary": { "hashes": [ - "sha256:00475004e5ed3e3bf5e056d66e5dcdf41a0dc62efcd57997acd9135c40a08a50", - "sha256:01ad49d68dd8c5362e4bfb4158f2896dc6e0c02e87b8a3770fc003459f1a4425", - "sha256:024030b13bdcbd53d8a93891a2cf07719715724fc9fee40243f3bd78b4264b8f", - "sha256:02551647542f2bf89073d129c73c05a25c372fc0a49aa50e0de65c3c143d8bd0", - "sha256:043a9fd45a03858ff72364b4b75090679bd875ee44df9c0613dc862ca6b98460", - "sha256:05b3d479425e047c848b9782cd7aac9c6727ce23181eb9647baf64ffdfc3da41", - "sha256:0775d6252ccb22b15da3b5d7adbbf8cfe284916b14b6dc0ff503a23edb01ee85", - "sha256:1764546ffeaed4f9428707be61d68972eb5ede81239b46a45843e0071104d0dd", - "sha256:1e491e6489a6cb1d079df8eaa15957c277fdedb102b6a68cfbf40c4994412fd0", - "sha256:212757ffcecb3e1a5338d4e6761bf9c04f750e7d027117e74aa3cd8a75bb6fbd", - "sha256:215d6bf7e66732a514f47614f828d8c0aaac9a648c46a831955cb103473c7147", - "sha256:25382c7d174c679ce6927c16b6fbb68b10e56ee44b1acb40671e02d29f2fce7c", - "sha256:2abccab84d057723d2ca8f99ff7b619285d40da6814d50366f61f0fc385c3903", - "sha256:2d964eb24c8b021623df1c93c626671420c6efadbdb8655cb2bd5e0c6fa422ba", - "sha256:2ec46ed947801652c9643e0b1dc334cfb2781232e375ba97312c2fc256597632", - "sha256:2ef892cabdccefe577088a79580301f09f2a713eb239f4f9f62b2b29cafb0577", - "sha256:33e632d0885b95a8b97165899006c40e9ecdc634a529dca7b991eb7de4ece41c", - "sha256:3520d7af1ebc838cc6084a3281145d5cd5bdd43fdef139e6db5af01b92596cb7", - "sha256:3d790f84201c3698d1bfb404c917f36e40531577a6dda02e45ba29b64d539867", - "sha256:3fc33295cfccad697a97a76dec3f1e94ad848b7b163c3228c1636977966b51e2", - "sha256:422e3d43b47ac20141bc84b3d342eead8d8099a62881a501e97d15f6addabfe9", - "sha256:426c2ae999135d64e6a18849a7d1ad0e1bd007277e4a8f4752eaa40a96b550ff", - "sha256:46512486be6fbceef51d7660dec017394ba3e170299d1dc30928cbedebbf103a", - "sha256:46850a640df62ae940e34a163f72e26aca1f88e2da79148e1862faaac985c302", - "sha256:484405b883630f3e74ed32041a87456c5e0e63a8e3429aa93e8714c366d62bd1", - "sha256:4e7904d1920c0c89105c0517dc7e3f5c20fb4e56ba9cdef13048db76947f1d79", - "sha256:56b2957a145f816726b109ee3d4e6822c23f919a7d91af5a94593723ed667835", - "sha256:5c6527c8efa5226a9e787507652dd5ba97b62d29b53c371a85cd13f957fe4d42", - "sha256:5cbc554ba47ecca8cd3396ddaca85e1ecfe3e48dd57dc5e415e59551affe568e", - "sha256:5d28ecdf191db558d0c07d0f16524ee9d67896edf2b7990eea800abeb23ebd61", - "sha256:5fc447058d083b8c6ac076fc26b446d44f0145308465d745fba93a28c14c9e32", - "sha256:63e318dbe52709ed10d516a356f22a635e07a2e34c68145484ed96a19b0c4c68", - "sha256:68d81a2fe184030aa0c5c11e518292e15d342a667184d91e30644c9d533e53e1", - "sha256:6e63814ec71db9bdb42905c925639f319c80e7909fb76c3b84edc79dadef8d60", - "sha256:6f8a9bcab7b6db2e3dbf65b214dfc795b4c6b3bb3af922901b6a67f7cb47d5f8", - "sha256:70831e03bd53702c941da1a1ad36c17d825a24fbb26857b40913d58df82ec18b", - "sha256:74eddec4537ab1f701a1647214734bc52cee2794df748f6ae5908e00771f180a", - "sha256:7b3751857da3e224f5629400736a7b11e940b5da5f95fa631d86219a1beaafec", - "sha256:7cf1d44e710ca3a9ce952bda2855830fe9f9017ed6259e01fcd71ea6287565f5", - "sha256:7d07f552d1e412f4b4e64ce386d4c777a41da3b33f7098b6219012ba534fb2c2", - "sha256:7d88db096fa19d94f433420eaaf9f3c45382da2dd014b93e4bf3215639047c16", - "sha256:7ee3095d02d6f38bd7d9a5358fcc9ea78fcdb7176921528dd709cc63f40184f5", - "sha256:902844f9c4fb19b17dfa84d9e2ca053d4a4ba265723d62ea5c9c26b38e0aa1e6", - "sha256:937880290775033a743f4836aa253087b85e62784b63fd099ee725d567a48aa1", - "sha256:95076399ec3b27a8f7fa1cc9a83417b1c920d55cf7a97f718a94efbb96c7f503", - "sha256:9c38d3869238e9d3409239bc05bc27d6b7c99c2a460ea337d2814b35fb4fea1b", - "sha256:9e32cedc389bcb76d9f24ea8a012b3cb8385ee362ea437e1d012ffaed106c17d", - "sha256:9ffdc51001136b699f9563b1c74cc1f8c07f66ef7219beb6417a4c8aaa896c28", - "sha256:a0adef094c49f242122bb145c3c8af442070dc0e4312db17e49058c1702606d4", - "sha256:a36a0e791805aa136e9cbd0ffa040d09adec8610453ee8a753f23481a0057af5", - "sha256:a7e518a0911c50f60313cb9e74a169a65b5d293770db4770ebf004245f24b5c5", - "sha256:af0516e1711995cb08dc19bbd05bec7dbdebf4185f68870595156718d237df3e", - "sha256:b8104f709590fff72af801e916817560dbe1698028cd0afe5a52d75ceb1fce5f", - "sha256:b911dfb727e247340d36ae20c4b9259e4a64013ab9888ccb3cbba69b77fd9636", - "sha256:b9a794cef1d9c1772b94a72eec6da144c18e18041d294a9ab47669bc77a80c1d", - "sha256:b9c33d4aef08dfecbd1736ceab8b7b3c4358bf10a0121483e5cd60d3d308cc64", - "sha256:b9d38a4656e4e715d637abdf7296e98d6267df0cc0a8e9a016f8ba07e4aa3eeb", - "sha256:bcda1c84a1c533c528356da5490d464a139b6e84eb77cc0b432e38c5c6dd7882", - "sha256:bef7e3f9dc6f0c13afdd671008534be5744e0e682fb851584c8c3a025ec09720", - "sha256:c15ba5982c177bc4b23a7940c7e4394197e2d6a424a2d282e7c236b66da6d896", - "sha256:c5254cbd4f4855e11cebf678c1a848a3042d455a22a4ce61349c36aafd4c2267", - "sha256:c5682a45df7d9642eff590abc73157c887a68f016df0a8ad722dcc0f888f56d7", - "sha256:c5e65c6ac0ae4bf5bef1667029f81010b6017795dcb817ba5c7b8a8d61fab76f", - "sha256:d4c7b3a31502184e856df1f7bbb2c3735a05a8ce0ade34c5277e1577738a5c91", - "sha256:d892bfa1d023c3781a3cab8dd5af76b626c483484d782e8bd047c180db590e4c", - "sha256:dbc332beaf8492b5731229a881807cd7b91b50dbbbaf7fe2faf46942eda64a24", - "sha256:dc85b3777068ed30aff8242be2813038a929f2084f69e43ef869daddae50f6ee", - "sha256:e59137cdb970249ae60be2a49774c6dfb015bd0403f05af1fe61862e9626642d", - "sha256:e67b3c26e9b6d37b370c83aa790bbc121775c57bfb096c2e77eacca25fd0233b", - "sha256:e72c91bda9880f097c8aa3601a2c0de6c708763ba8128006151f496ca9065935", - "sha256:f95b8aca2703d6a30249f83f4fe6a9abf2e627aa892a5caaab2267d56be7ab69" - ], - "index": "pypi", - "version": "==2.9.5" + "sha256:02c0f3757a4300cf379eb49f543fb7ac527fb00144d39246ee40e1df684ab514", + "sha256:02c6e3cf3439e213e4ee930308dc122d6fb4d4bea9aef4a12535fbd605d1a2fe", + "sha256:0645376d399bfd64da57148694d78e1f431b1e1ee1054872a5713125681cf1be", + "sha256:0892ef645c2fabb0c75ec32d79f4252542d0caec1d5d949630e7d242ca4681a3", + "sha256:0d236c2825fa656a2d98bbb0e52370a2e852e5a0ec45fc4f402977313329174d", + "sha256:0e0f754d27fddcfd74006455b6e04e6705d6c31a612ec69ddc040a5468e44b4e", + "sha256:15e2ee79e7cf29582ef770de7dab3d286431b01c3bb598f8e05e09601b890081", + "sha256:1876843d8e31c89c399e31b97d4b9725a3575bb9c2af92038464231ec40f9edb", + "sha256:1f64dcfb8f6e0c014c7f55e51c9759f024f70ea572fbdef123f85318c297947c", + "sha256:2ab652e729ff4ad76d400df2624d223d6e265ef81bb8aa17fbd63607878ecbee", + "sha256:30637a20623e2a2eacc420059be11527f4458ef54352d870b8181a4c3020ae6b", + "sha256:34b9ccdf210cbbb1303c7c4db2905fa0319391bd5904d32689e6dd5c963d2ea8", + "sha256:38601cbbfe600362c43714482f43b7c110b20cb0f8172422c616b09b85a750c5", + "sha256:441cc2f8869a4f0f4bb408475e5ae0ee1f3b55b33f350406150277f7f35384fc", + "sha256:498807b927ca2510baea1b05cc91d7da4718a0f53cb766c154c417a39f1820a0", + "sha256:4ac30da8b4f57187dbf449294d23b808f8f53cad6b1fc3623fa8a6c11d176dd0", + "sha256:4c727b597c6444a16e9119386b59388f8a424223302d0c06c676ec8b4bc1f963", + "sha256:4d67fbdaf177da06374473ef6f7ed8cc0a9dc640b01abfe9e8a2ccb1b1402c1f", + "sha256:4dfb4be774c4436a4526d0c554af0cc2e02082c38303852a36f6456ece7b3503", + "sha256:4ea29fc3ad9d91162c52b578f211ff1c931d8a38e1f58e684c45aa470adf19e2", + "sha256:51537e3d299be0db9137b321dfb6a5022caaab275775680e0c3d281feefaca6b", + "sha256:61b047a0537bbc3afae10f134dc6393823882eb263088c271331602b672e52e9", + "sha256:6460c7a99fc939b849431f1e73e013d54aa54293f30f1109019c56a0b2b2ec2f", + "sha256:65bee1e49fa6f9cf327ce0e01c4c10f39165ee76d35c846ade7cb0ec6683e303", + "sha256:65c07febd1936d63bfde78948b76cd4c2a411572a44ac50719ead41947d0f26b", + "sha256:71f14375d6f73b62800530b581aed3ada394039877818b2d5f7fc77e3bb6894d", + "sha256:7a40c00dbe17c0af5bdd55aafd6ff6679f94a9be9513a4c7e071baf3d7d22a70", + "sha256:7e13a5a2c01151f1208d5207e42f33ba86d561b7a89fca67c700b9486a06d0e2", + "sha256:7f0438fa20fb6c7e202863e0d5ab02c246d35efb1d164e052f2f3bfe2b152bd0", + "sha256:8122cfc7cae0da9a3077216528b8bb3629c43b25053284cc868744bfe71eb141", + "sha256:8338a271cb71d8da40b023a35d9c1e919eba6cbd8fa20a54b748a332c355d896", + "sha256:84d2222e61f313c4848ff05353653bf5f5cf6ce34df540e4274516880d9c3763", + "sha256:8a6979cf527e2603d349a91060f428bcb135aea2be3201dff794813256c274f1", + "sha256:8a76e027f87753f9bd1ab5f7c9cb8c7628d1077ef927f5e2446477153a602f2c", + "sha256:964b4dfb7c1c1965ac4c1978b0f755cc4bd698e8aa2b7667c575fb5f04ebe06b", + "sha256:9972aad21f965599ed0106f65334230ce826e5ae69fda7cbd688d24fa922415e", + "sha256:a8c28fd40a4226b4a84bdf2d2b5b37d2c7bd49486b5adcc200e8c7ec991dfa7e", + "sha256:ae102a98c547ee2288637af07393dd33f440c25e5cd79556b04e3fca13325e5f", + "sha256:af335bac6b666cc6aea16f11d486c3b794029d9df029967f9938a4bed59b6a19", + "sha256:afe64e9b8ea66866a771996f6ff14447e8082ea26e675a295ad3bdbffdd72afb", + "sha256:b4b24f75d16a89cc6b4cdff0eb6a910a966ecd476d1e73f7ce5985ff1328e9a6", + "sha256:b6c8288bb8a84b47e07013bb4850f50538aa913d487579e1921724631d02ea1b", + "sha256:b83456c2d4979e08ff56180a76429263ea254c3f6552cd14ada95cff1dec9bb8", + "sha256:bfb13af3c5dd3a9588000910178de17010ebcccd37b4f9794b00595e3a8ddad3", + "sha256:c3dba7dab16709a33a847e5cd756767271697041fbe3fe97c215b1fc1f5c9848", + "sha256:c48d8f2db17f27d41fb0e2ecd703ea41984ee19362cbce52c097963b3a1b4365", + "sha256:c7e62ab8b332147a7593a385d4f368874d5fe4ad4e341770d4983442d89603e3", + "sha256:c83a74b68270028dc8ee74d38ecfaf9c90eed23c8959fca95bd703d25b82c88e", + "sha256:cacbdc5839bdff804dfebc058fe25684cae322987f7a38b0168bc1b2df703fb1", + "sha256:cf4499e0a83b7b7edcb8dabecbd8501d0d3a5ef66457200f77bde3d210d5debb", + "sha256:cfec476887aa231b8548ece2e06d28edc87c1397ebd83922299af2e051cf2827", + "sha256:d26e0342183c762de3276cca7a530d574d4e25121ca7d6e4a98e4f05cb8e4df7", + "sha256:d4e6036decf4b72d6425d5b29bbd3e8f0ff1059cda7ac7b96d6ac5ed34ffbacd", + "sha256:d57c3fd55d9058645d26ae37d76e61156a27722097229d32a9e73ed54819982a", + "sha256:dfa74c903a3c1f0d9b1c7e7b53ed2d929a4910e272add6700c38f365a6002820", + "sha256:e3ed340d2b858d6e6fb5083f87c09996506af483227735de6964a6100b4e6a54", + "sha256:e78e6e2a00c223e164c417628572a90093c031ed724492c763721c2e0bc2a8df", + "sha256:e9182eb20f41417ea1dd8e8f7888c4d7c6e805f8a7c98c1081778a3da2bee3e4", + "sha256:e99e34c82309dd78959ba3c1590975b5d3c862d6f279f843d47d26ff89d7d7e1", + "sha256:f6a88f384335bb27812293fdb11ac6aee2ca3f51d3c7820fe03de0a304ab6249", + "sha256:f81e65376e52f03422e1fb475c9514185669943798ed019ac50410fb4c4df232", + "sha256:ffe9dc0a884a8848075e576c1de0290d85a533a9f6e9c4e564f19adf8f6e54a7" + ], + "index": "pypi", + "version": "==2.9.6" }, "pycparser": { "hashes": [ @@ -1328,11 +1319,11 @@ }, "django": { "hashes": [ - "sha256:44f714b81c5f190d9d2ddad01a532fe502fa01c4cb8faf1d081f4264ed15dcd8", - "sha256:f2f431e75adc40039ace496ad3b9f17227022e8b11566f4b363da44c7e44761e" + "sha256:ad33ed68db9398f5dfb33282704925bce044bef4261cd4fb59e4e7f9ae505a78", + "sha256:c36e2ab12824e2ac36afa8b2515a70c53c7742f0d6eaefa7311ec379558db997" ], "index": "pypi", - "version": "==4.1.7" + "version": "==4.2" }, "django-webtest": { "hashes": [ @@ -1382,11 +1373,11 @@ }, "faker": { "hashes": [ - "sha256:4c98c42984db54be2246d40e6407cd983db7b1511a70eaff64c3f383a51bace6", - "sha256:9bd71833146b844d848791b79720c7806108130c9603c7074123b3f77b4e97a1" + "sha256:a000bba893ea502cea66d06acf14e01655a2289e4904de80faf9dbe880fa1a39", + "sha256:f3299679a6b23409cfe69774bbd1148324a05bd38bda041da6c302e618d7d4a0" ], "markers": "python_version >= '3.7'", - "version": "==18.3.1" + "version": "==18.3.2" }, "fancycompleter": { "hashes": [ @@ -1732,11 +1723,11 @@ }, "pre-commit": { "hashes": [ - "sha256:a06a7fcce7f420047a71213c175714216498b49ebc81fe106f7716ca265f5bb6", - "sha256:b5aee7d75dbba21ee161ba641b01e7ae10c5b91967ebf7b2ab0dfae12d07e1f1" + "sha256:0b4210aea813fe81144e87c5a291f09ea66f199f367fa1df41b55e1d26e1e2b4", + "sha256:5b808fcbda4afbccf6d6633a56663fed35b6c2bc08096fd3d47ce197ac351d9d" ], "index": "pypi", - "version": "==3.2.1" + "version": "==3.2.2" }, "prompt-toolkit": { "hashes": [ From 28d189972b534f8887196bd37e30549652276426 Mon Sep 17 00:00:00 2001 From: Domenico DiNicola Date: Tue, 4 Apr 2023 11:50:56 +0200 Subject: [PATCH 6/6] version update --- src/donor_reporting_portal/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/donor_reporting_portal/__init__.py b/src/donor_reporting_portal/__init__.py index f44b2f68..68c4449e 100644 --- a/src/donor_reporting_portal/__init__.py +++ b/src/donor_reporting_portal/__init__.py @@ -1,2 +1,2 @@ NAME = "donor-reporting-portal" -VERSION = __version__ = "2.0.3" +VERSION = __version__ = "2.1"