diff --git a/Pipfile b/Pipfile index 125c27f8..3be25b83 100644 --- a/Pipfile +++ b/Pipfile @@ -14,21 +14,20 @@ django-silk = "*" black = "*" [packages] -factory-boy = "==2.11.0" -wagtail_factories = "==2.0.0" -django = "==3.2.16" -whitenoise = "~=5.3" +factory-boy = "~=3.3" +wagtail_factories = "~=4.0" +django = "~=4.2" +whitenoise = "~=6.6" psycopg2-binary = "==2.9.3" -gunicorn = "==19.10.0" -python-dotenv = "==0.13.0" -dj-database-url = "==0.4.1" -raven = "==6.9.0" +gunicorn = "~=21.2.0" +python-dotenv = "~=1.0.0" +dj-database-url = "~=2.1.0" django-extensions = "*" -graphene-django = "==2.15.0" -django-filter = "~=21.1" -djangorestframework = "~=3.8" +graphene-django = "*" +django-filter = "*" +djangorestframework = "*" pillow = "==9.1.0" -wagtail = "~=4.2" +wagtail = "==5.0.5" django-cors-headers = "~=3.0" django-storages = "*" boto3 = "*" @@ -36,8 +35,7 @@ django-compressor = "*" django-libsass = "*" bleach = "*" newrelic = "*" -sentry-sdk = "==1.38.0" -python-http-client = "==3.2.1" +sentry-sdk = "~=1.38.0" ipython = "*" requests = "*" unittest-xml-reporting = "*" diff --git a/Pipfile.lock b/Pipfile.lock index f72c97c8..3ac0c3f9 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "206150258b8979912bf9986f82049bdb1530666d5e9f7997e1c4acbe56c7eaf2" + "sha256": "26df7fc2ce976c8437910e196f69cd281d39b7cd5551c9fbf7a298d14d3cf531" }, "pipfile-spec": 6, "requires": { @@ -18,10 +18,10 @@ "default": { "aniso8601": { "hashes": [ - "sha256:513d2b6637b7853806ae79ffaca6f3e8754bdd547048f5ccc1420aec4b714f1e", - "sha256:d10a4bf949f619f719b227ef5386e31f49a2b6d453004b21f02661ccc8670c7b" + "sha256:1d2b7ef82963909e93c4f24ce48d4de9e66009a21bf1c1e1c85bdd0812fe412f", + "sha256:72e3117667eedf66951bb2d93f4296a56b94b078a8a95905a052611fb3f1b973" ], - "version": "==7.0.0" + "version": "==9.0.1" }, "anyascii": { "hashes": [ @@ -36,7 +36,7 @@ "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e", "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.7.2" }, "asttokens": { @@ -104,19 +104,19 @@ }, "boto3": { "hashes": [ - "sha256:b8c818125489fc0371ef28d806d36d8f1dcb71734fcb0d96b3201563e3e86f22", - "sha256:d02a084b25aa8d46ef917b128e90877efab1ba45f9d1ba3a11f336930378e350" + "sha256:9486f66f9a89f66d64d25cb4baa55aad323a1734ef9815b7a2c4c0787a3fc1fb", + "sha256:baa6ea61527bcc82365a4ef365aa8f34126483ff8533d01274f3cdb340c22d73" ], "index": "pypi", - "version": "==1.33.8" + "version": "==1.33.9" }, "botocore": { "hashes": [ - "sha256:90236e6e69d7e80875d7f9d39383630706edbc1298026698c6c70d9b6a65576e", - "sha256:e6970bf89cbe2624399aeffce52c253917d8e5a1c671de4054557603ab56c922" + "sha256:07ff4eea62f546da540310887000c81fca802c788eb374fef06eda28009dcafd", + "sha256:1b90be11dd9a9a25290c995a6b713e76b9e2bf7bf86ba9036e0d28f2ceb2edfc" ], - "markers": "python_full_version >= '3.7.0'", - "version": "==1.33.8" + "markers": "python_version >= '3.7'", + "version": "==1.33.9" }, "certifi": { "hashes": [ @@ -277,7 +277,7 @@ "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.3.2" }, "click": { @@ -285,7 +285,7 @@ "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==8.1.7" }, "coverage": { @@ -375,7 +375,7 @@ "sha256:e3114da6d7f95d2dee7d3f4eec16dacff819740bbab931aff8648cb13c5ff5e7", "sha256:f983596065a18a2183e7f79ab3fd4c475205b839e02cbc0efbbf9666c4b3083d" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==41.0.7" }, "decorator": { @@ -386,27 +386,36 @@ "markers": "python_version >= '3.5'", "version": "==5.1.1" }, + "defusedxml": { + "hashes": [ + "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", + "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.7.1" + }, "dj-database-url": { "hashes": [ - "sha256:7f4c78d2a090df8dfaf56d5d3ff7bbee17360436e4879558317e2314424864cd" + "sha256:04bc34b248d4c21aaa13e4ab419ae6575ef5f10f3df735ce7da97722caa356e0", + "sha256:f2042cefe1086e539c9da39fad5ad7f61173bf79665e69bf7e4de55fa88b135f" ], "index": "pypi", - "version": "==0.4.1" + "version": "==2.1.0" }, "django": { "hashes": [ - "sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121", - "sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d" + "sha256:6cb5dcea9e3d12c47834d32156b8841f533a4493c688e2718cafd51aa430ba6d", + "sha256:d69d5e36cc5d9f4eb4872be36c622878afcdce94062716cf3e25bcedcb168b62" ], "index": "pypi", - "version": "==3.2.16" + "version": "==4.2.8" }, "django-appconf": { "hashes": [ "sha256:c3ae442fba1ff7ec830412c5184b17169a7a1e71cf0864a4c3f93cf4c98a1993", "sha256:cfe87ea827c4ee04b9a70fab90b86d704cb02f2981f89da8423cb0fabf88efbf" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==1.0.6" }, "django-compressor": { @@ -435,11 +444,11 @@ }, "django-filter": { "hashes": [ - "sha256:632a251fa8f1aadb4b8cceff932bb52fe2f826dd7dfe7f3eac40e5c463d6836e", - "sha256:f4a6737a30104c98d2e2a5fb93043f36dd7978e0c7ddc92f5998e85433ea5063" + "sha256:ed429e34760127e3520a67f415bec4c905d4649fbe45d0d6da37e6ff5e0287eb", + "sha256:ed473b76e84f7e83b2511bb2050c3efb36d135207d0128dfe3ae4b36e3594ba5" ], "index": "pypi", - "version": "==21.1" + "version": "==22.1" }, "django-libsass": { "hashes": [ @@ -462,7 +471,7 @@ "sha256:4340bb20c4477fffb13b4cc5cccf9f1b1010b64f79956c291c72d2ad2ed243f8", "sha256:d341a961a27cc77fde8cc42141c6ab55cc1f0cb886963cc2d6967b9674fa47d6" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.1" }, "django-silk": { @@ -544,7 +553,7 @@ "sha256:88256416ae766bc9e8895c76a87928c0012183da3cc4fc18016e6f050e025f41", "sha256:cc59bc4423742fd71ad227122eb0dd44db51efb3dc4095b45ac9a08c770096af" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==2.0.2" }, "executing": { @@ -557,11 +566,11 @@ }, "factory-boy": { "hashes": [ - "sha256:3763ecabafb341df75b82f3a80c40747adef32d0288282c0c2db7a13e53c6944", - "sha256:d0f7209473312c99dfcf154069a1c559d83cfcae0979af43cf8779c9a9f645b3" + "sha256:a2cdbdb63228177aa4f1c52f4b6d83fab2b8623bf602c7dedd7eb83c0f69c04c", + "sha256:bc76d97d1a65bbd9842a6d722882098eb549ec8ee1081f9fb2e8ff29f0c300f1" ], "index": "pypi", - "version": "==2.11.0" + "version": "==3.3.0" }, "faker": { "hashes": [ @@ -571,6 +580,13 @@ "markers": "python_version >= '3.8'", "version": "==20.1.0" }, + "filetype": { + "hashes": [ + "sha256:66b56cd6474bf41d8c54660347d37afcc3f7d1970648de365c102ef77548aadb", + "sha256:7ce71b6880181241cf7ac8697a2f1eb6a8bd9b429f7ad6d27b8db9ba5f1c2d25" + ], + "version": "==1.2.0" + }, "gprof2dot": { "hashes": [ "sha256:45b4d298bd36608fccf9511c3fd88a773f7a1abc04d6cd39445b11ba43133ec5", @@ -581,40 +597,42 @@ }, "graphene": { "hashes": [ - "sha256:3d446eb1237c551052bc31155cf1a3a607053e4f58c9172b83a1b597beaa0868", - "sha256:b9f2850e064eebfee9a3ef4a1f8aa0742848d97652173ab44c82cc8a62b9ed93" + "sha256:529bf40c2a698954217d3713c6041d69d3f719ad0080857d7ee31327112446b0", + "sha256:bb3810be33b54cb3e6969506671eb72319e8d7ba0d5ca9c8066472f75bf35a38" ], - "version": "==2.1.9" + "version": "==3.3" }, "graphene-django": { "hashes": [ - "sha256:02671d195f0c09c8649acff2a8f4ad4f297d0f7d98ea6e6cdf034b81bab92880", - "sha256:b78c9b05bc899016b9cc5bf13faa1f37fe1faa8c5407552c6ddd1a28f46fc31a" + "sha256:2e42742fae21fa50e514f3acae26a9bc6cb5e51c179a97b3db5390ff258ca816", + "sha256:abe42f820b9731d94bebff6d73088d0dc2ffb8c8863a6d7bf3d378412d866a3b" ], "index": "pypi", - "version": "==2.15.0" + "version": "==3.1.5" }, "graphql-core": { "hashes": [ - "sha256:44c9bac4514e5e30c5a595fac8e3c76c1975cae14db215e8174c7fe995825bad", - "sha256:aac46a9ac524c9855910c14c48fc5d60474def7f99fd10245e76608eba7af746" + "sha256:06d2aad0ac723e35b1cb47885d3e5c45e956a53bc1b209a9fc5369007fe46676", + "sha256:5766780452bd5ec8ba133f8bf287dc92713e3868ddd83aee4faab9fc3e303dc3" ], - "version": "==2.3.2" + "markers": "python_version >= '3.6' and python_version < '4'", + "version": "==3.2.3" }, "graphql-relay": { "hashes": [ - "sha256:870b6b5304123a38a0b215a79eace021acce5a466bf40cd39fa18cb8528afabb", - "sha256:ac514cb86db9a43014d7e73511d521137ac12cf0101b2eaa5f0a3da2e10d913d" + "sha256:1ff1c51298356e481a0be009ccdff249832ce53f30559c1338f22a0e0d17250c", + "sha256:c9b22bd28b170ba1fe674c74384a8ff30a76c8e26f88ac3aa1584dd3179953e5" ], - "version": "==2.0.1" + "markers": "python_version >= '3.6' and python_version < '4'", + "version": "==3.2.0" }, "gunicorn": { "hashes": [ - "sha256:c3930fe8de6778ab5ea716cab432ae6335fa9f03b3f2c3e02529214c476f4bcb", - "sha256:f9de24e358b841567063629cd0a656b26792a41e23a24d0dcb40224fc3940081" + "sha256:3213aa5e8c24949e792bcacfc176fef362e7aac80b76c56f6b5122bf350722f0", + "sha256:88ec8bff1d634f98e61b9f65bc4bf3cd918a90806c6f5c48bc5603849ec81033" ], "index": "pypi", - "version": "==19.10.0" + "version": "==21.2.0" }, "html5lib": { "hashes": [ @@ -637,7 +655,7 @@ "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==2.0.0" }, "ipython": { @@ -661,7 +679,7 @@ "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==1.0.1" }, "l18n": { @@ -862,7 +880,7 @@ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==23.2" }, "parso": { @@ -878,7 +896,7 @@ "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.11.2" }, "pexpect": { @@ -960,7 +978,7 @@ "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0", "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.0.41" }, "psycopg2-binary": { @@ -1062,7 +1080,7 @@ "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==2.17.2" }, "pytest": { @@ -1070,7 +1088,7 @@ "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac", "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==7.4.3" }, "pytest-cov": { @@ -1107,20 +1125,11 @@ }, "python-dotenv": { "hashes": [ - "sha256:25c0ff1a3e12f4bde8d592cc254ab075cfe734fc5dd989036716fd17ee7e5ec7", - "sha256:3b9909bc96b0edc6b01586e1eed05e71174ef4e04c71da5786370cebea53ad74" + "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba", + "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a" ], "index": "pypi", - "version": "==0.13.0" - }, - "python-http-client": { - "hashes": [ - "sha256:01f58f1871612fdce6a4545df7c867a6d1457695652a7ca48d5c22e5bf57628d", - "sha256:c2776054245db376ea26c859b80e9280b1a470b96ed998d60d35951f89bbbe79", - "sha256:e455ae0dfd5819ac483f7fecf08ab8693048d9dc47a0a6fe0d4aebf86d9d1d17" - ], - "index": "pypi", - "version": "==3.2.1" + "version": "==1.0.0" }, "pytz": { "hashes": [ @@ -1129,14 +1138,6 @@ ], "version": "==2023.3.post1" }, - "raven": { - "hashes": [ - "sha256:3fd787d19ebb49919268f06f19310e8112d619ef364f7989246fc8753d469888", - "sha256:95f44f3ea2c1b176d5450df4becdb96c15bf2632888f9ab193e9dd22300ce46a" - ], - "index": "pypi", - "version": "==6.9.0" - }, "rcssmin": { "hashes": [ "sha256:271e3d2f8614a6d4637ed8fff3d90007f03e2a654cd9444f37d888797662ba72", @@ -1201,18 +1202,12 @@ ], "version": "==1.2.1" }, - "rx": { - "hashes": [ - "sha256:ca71b65d0fc0603a3b5cfaa9e33f5ba81e4aae10a58491133595088d7734b2da" - ], - "version": "==1.6.3" - }, "s3transfer": { "hashes": [ "sha256:368ac6876a9e9ed91f6bc86581e319be08188dc60d50e0d56308ed5765446283", "sha256:c9e56cbe88b28d8e197cf841f1f0c130f246595e77ae5b5a05b69fe7cb83de76" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.8.2" }, "sentry-sdk": { @@ -1223,14 +1218,6 @@ "index": "pypi", "version": "==1.38.0" }, - "singledispatch": { - "hashes": [ - "sha256:6061bd291204beaeac90cdbc342b68d213b7a6efb44ae6c5e6422a78be351c8a", - "sha256:f3430b886d5b4213d07d715096a75da5e4a8105284c497b9aee6d6d48bfe90cb" - ], - "markers": "python_version >= '3.8'", - "version": "==4.1.0" - }, "six": { "hashes": [ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", @@ -1325,11 +1312,11 @@ }, "wagtail": { "hashes": [ - "sha256:4bf146194e1725cd4305bf1998f507d46f587e207d609bc2ec73a6c5cce04410", - "sha256:93e8d39a14a44099ca620e46613a3a2319b1d10c622dc7f0ff8658807b18190c" + "sha256:cbdef3e08d87a949cb2a63afb73c112e8921bb91608711fa1a9608f5591a77e2", + "sha256:ec59a23013ef8cbc260d95ed73977010985edf5f8cb6097fdd740db6854babee" ], "index": "pypi", - "version": "==4.2.4" + "version": "==5.0.5" }, "wagtail-autocomplete": { "hashes": [ @@ -1341,11 +1328,11 @@ }, "wagtail-factories": { "hashes": [ - "sha256:2198e791854ef3883812f532a4d1b364aae1c68abc58a48b8ecec8c61e4a151f", - "sha256:416196b88dcdb2d2787926692d7eef7fa0664556900eb6166537026b085d9fbf" + "sha256:067e3e1a30721a90eaa1514c8214aae7a171490bbedf026eeaa904a2ed9abcd0", + "sha256:6abd435518fdf0cdd3d9920acb2abbd9005936d6fecfdf6fdde3e404834d4b0c" ], "index": "pypi", - "version": "==2.0.0" + "version": "==4.1.0" }, "wcwidth": { "hashes": [ @@ -1363,19 +1350,20 @@ }, "whitenoise": { "hashes": [ - "sha256:d234b871b52271ae7ed6d9da47ffe857c76568f11dd30e28e18c5869dbd11e12", - "sha256:d963ef25639d1417e8a247be36e6aedd8c7c6f0a08adcb5a89146980a96b577c" + "sha256:8998f7370973447fac1e8ef6e8ded2c5209a7b1f67c1012866dbcd09681c3251", + "sha256:b1f9db9bf67dc183484d760b99f4080185633136a273a03f6436034a41064146" ], "index": "pypi", - "version": "==5.3.0" + "version": "==6.6.0" }, "willow": { + "extras": [], "hashes": [ - "sha256:0df8ff528531e00b48d40bf72ed81beac1dc82f2d42e5bbed4aff0218bef8c0d", - "sha256:fc4042696d090e75aef922fa1ed26d483c764f005b36cf523cf7c34e69d5dd7a" + "sha256:143cefd30d3bb816cdff857c454da24991dda35a0315ea795101675e0b14262f", + "sha256:f4b17a16c6315864604dadb6cdf2987d0b685e295cca74c6da28b94167a3126e" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.4.1" + "markers": "python_version >= '3.8'", + "version": "==1.6.3" } }, "develop": { @@ -1384,7 +1372,7 @@ "sha256:89b2ef2247e3b562a16eef663bc0e2e703ec6468e2fa8a5cd61cd449786d4f6e", "sha256:9e0ce3aa93a819ba5b45120216b23878cf6e8525eb3848653452b4192b92afed" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.7.2" }, "asttokens": { @@ -1404,11 +1392,11 @@ }, "awscli": { "hashes": [ - "sha256:d589961a525f08caf4e3df3a85030768e5afdc89089cb720b78626fa812ad574", - "sha256:f8a6c7066b8a375b76200146f375b40121dfb2df5464fc76a9f7ad44fa3a6dbe" + "sha256:448d5fdf00dac64f8c19a0ea8342aec3c33eba36551b49e7d1d563e75572e103", + "sha256:f10ef081eb55eb354573239d12994b9c9c1454e271a5c09bb0bce26ffcbc2eca" ], "index": "pypi", - "version": "==1.31.8" + "version": "==1.31.9" }, "black": { "hashes": [ @@ -1436,18 +1424,18 @@ }, "botocore": { "hashes": [ - "sha256:90236e6e69d7e80875d7f9d39383630706edbc1298026698c6c70d9b6a65576e", - "sha256:e6970bf89cbe2624399aeffce52c253917d8e5a1c671de4054557603ab56c922" + "sha256:07ff4eea62f546da540310887000c81fca802c788eb374fef06eda28009dcafd", + "sha256:1b90be11dd9a9a25290c995a6b713e76b9e2bf7bf86ba9036e0d28f2ceb2edfc" ], - "markers": "python_full_version >= '3.7.0'", - "version": "==1.33.8" + "markers": "python_version >= '3.7'", + "version": "==1.33.9" }, "click": { "hashes": [ "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==8.1.7" }, "colorama": { @@ -1529,11 +1517,11 @@ }, "django": { "hashes": [ - "sha256:18ba8efa36b69cfcd4b670d0fa187c6fe7506596f0ababe580e16909bcdec121", - "sha256:3adc285124244724a394fa9b9839cc8cd116faf7d159554c43ecdaa8cdf0b94d" + "sha256:6cb5dcea9e3d12c47834d32156b8841f533a4493c688e2718cafd51aa430ba6d", + "sha256:d69d5e36cc5d9f4eb4872be36c622878afcdce94062716cf3e25bcedcb168b62" ], "index": "pypi", - "version": "==3.2.16" + "version": "==4.2.8" }, "django-silk": { "hashes": [ @@ -1596,7 +1584,7 @@ "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==1.0.1" }, "matplotlib-inline": { @@ -1620,7 +1608,7 @@ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==23.2" }, "parso": { @@ -1636,7 +1624,7 @@ "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20", "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.11.2" }, "pexpect": { @@ -1660,7 +1648,7 @@ "sha256:941367d97fc815548822aa26c2a269fdc4eb21e9ec05fc5d447cf09bad5d75f0", "sha256:f36fe301fafb7470e86aaf90f036eef600a3210be4decf461a5b1ca8403d3cb2" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==3.0.41" }, "ptyprocess": { @@ -1698,7 +1686,7 @@ "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c", "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==2.17.2" }, "python-dateutil": { @@ -1778,7 +1766,7 @@ "sha256:368ac6876a9e9ed91f6bc86581e319be08188dc60d50e0d56308ed5765446283", "sha256:c9e56cbe88b28d8e197cf841f1f0c130f246595e77ae5b5a05b69fe7cb83de76" ], - "markers": "python_full_version >= '3.7.0'", + "markers": "python_version >= '3.7'", "version": "==0.8.2" }, "six": { diff --git a/server/books/factories.py b/server/books/factories.py index a1d1cf84..230dd662 100644 --- a/server/books/factories.py +++ b/server/books/factories.py @@ -28,7 +28,16 @@ from books.blocks import ( SurveyBlock, VideoBlock, ) -from books.models import Book, Chapter, ContentBlock, Module, TextBlock, Topic, ModuleLevel, ModuleCategory +from books.models import ( + Book, + Chapter, + ContentBlock, + Module, + TextBlock, + Topic, + ModuleLevel, + ModuleCategory, +) from core.factories import ( BasePageFactory, DummyImageFactory, @@ -109,7 +118,7 @@ class TextBlockFactory(wagtail_factories.StructBlockFactory): model = TextBlock -class InstrumentCategoryFactory(factory.DjangoModelFactory): +class InstrumentCategoryFactory(factory.django.DjangoModelFactory): class Meta: model = InstrumentCategory django_get_or_create = ("name",) @@ -121,7 +130,7 @@ class InstrumentCategoryFactory(factory.DjangoModelFactory): background = factory.Iterator(["FF0000", "FFFFFF", "000000"]) -class InstrumentTypeFactory(factory.DjangoModelFactory): +class InstrumentTypeFactory(factory.django.DjangoModelFactory): class Meta: model = InstrumentType @@ -201,16 +210,19 @@ class VideoBlockFactory(wagtail_factories.StructBlockFactory): class Meta: model = VideoBlock -class ModuleLevelFactory(factory.DjangoModelFactory): + +class ModuleLevelFactory(factory.django.DjangoModelFactory): class Meta: model = ModuleLevel - name = '1. Lehrjahr' + + name = "1. Lehrjahr" -class ModuleTypeFactory(factory.DjangoModelFactory): +class ModuleTypeFactory(factory.django.DjangoModelFactory): class Meta: model = ModuleCategory - name = 'Lernfeld 1' + + name = "Lernfeld 1" block_types = [ @@ -238,15 +250,17 @@ class ContentBlockFactory(BasePageFactory): contents = wagtail_factories.StreamFieldFactory( { - "text_block": TextBlockFactory, - "basic_knowledge": BasicKnowledgeBlockFactory, - "assignment": AssignmentBlockFactory, - "image_block": wagtail_factories.ImageChooserBlockFactory, - "image_url_block": ImageUrlBlockFactory, - "link_block": LinkBlockFactory, - "video_block": VideoBlockFactory, - "solution": TextBlockFactory, - "survey": SurveyBlockFactory, + "text_block": factory.SubFactory(TextBlockFactory), + "basic_knowledge": factory.SubFactory(BasicKnowledgeBlockFactory), + "assignment": factory.SubFactory(AssignmentBlockFactory), + "image_block": factory.SubFactory( + wagtail_factories.ImageChooserBlockFactory + ), + "image_url_block": factory.SubFactory(ImageUrlBlockFactory), + "link_block": factory.SubFactory(LinkBlockFactory), + "video_block": factory.SubFactory(VideoBlockFactory), + "solution": factory.SubFactory(TextBlockFactory), + "survey": factory.SubFactory(SurveyBlockFactory), } ) diff --git a/server/core/factories.py b/server/core/factories.py index 9290c1ba..0c57904c 100644 --- a/server/core/factories.py +++ b/server/core/factories.py @@ -27,7 +27,7 @@ class BasePageFactory(wagtail_factories.PageFactory): title = factory.LazyAttribute(fake_title) -class DummyDocumentFactory(factory.DjangoModelFactory): +class DummyDocumentFactory(factory.django.DjangoModelFactory): class Meta: model = get_document_model() @@ -37,7 +37,7 @@ class DummyDocumentFactory(factory.DjangoModelFactory): ) -class DummyImageFactory(factory.DjangoModelFactory): +class DummyImageFactory(factory.django.DjangoModelFactory): class Meta: model = get_image_model() diff --git a/server/notes/factories.py b/server/notes/factories.py index 05b47329..13c956b7 100644 --- a/server/notes/factories.py +++ b/server/notes/factories.py @@ -3,10 +3,10 @@ import factory from notes.models import ChapterBookmark, ModuleBookmark -class ChapterBookmarkFactory(factory.DjangoModelFactory): +class ChapterBookmarkFactory(factory.django.DjangoModelFactory): class Meta: model = ChapterBookmark -class ModuleBookmarkFactory(factory.DjangoModelFactory): +class ModuleBookmarkFactory(factory.django.DjangoModelFactory): class Meta: model = ModuleBookmark diff --git a/server/oauth/tests/test_coupon.py b/server/oauth/tests/test_coupon.py index 7134bc58..e88c6c8e 100644 --- a/server/oauth/tests/test_coupon.py +++ b/server/oauth/tests/test_coupon.py @@ -1,4 +1,4 @@ -from unittest.mock import patch +from unittest.mock import MagicMock, patch from authlib.integrations.base_client import BaseApp from django.contrib.sessions.middleware import SessionMiddleware @@ -57,6 +57,7 @@ INVALID_LICENSE = { class CouponTests(TestCase): def setUp(self): + get_response = MagicMock() self.user = UserFactory( username="aschi@iterativ.ch", email="aschi@iterativ.ch", hep_id=3 ) @@ -66,7 +67,7 @@ class CouponTests(TestCase): # adding session request = RequestFactory().post("/") - middleware = SessionMiddleware() + middleware = SessionMiddleware(get_response) middleware.process_request(request) request.user = self.user request.session.save() @@ -165,8 +166,9 @@ class CouponTests(TestCase): BaseApp, "put", return_value=MockResponse(200, data=["201", "Invalid Coupon"]) ) def test_unauthenticated_user_cannot_redeem(self, response_mock): + get_response = MagicMock() request = RequestFactory().post("/") - middleware = SessionMiddleware() + middleware = SessionMiddleware(get_response) middleware.process_request(request) request.session.save() client = Client(schema=schema, context_value=request) diff --git a/server/oauth/tests/test_login.py b/server/oauth/tests/test_login.py index 4715fbdd..480e54b3 100644 --- a/server/oauth/tests/test_login.py +++ b/server/oauth/tests/test_login.py @@ -1,6 +1,6 @@ import time from datetime import timedelta -from unittest.mock import patch +from unittest.mock import MagicMock, patch import requests from authlib.integrations.django_client import DjangoOAuth2App @@ -11,9 +11,18 @@ from django.utils import timezone from core.factories import UserFactory from oauth.hep_client import HepClient -from oauth.user_signup_login_handler import EMAIL_NOT_VERIFIED, NO_VALID_LICENSE, UNKNOWN_ERROR +from oauth.user_signup_login_handler import ( + EMAIL_NOT_VERIFIED, + NO_VALID_LICENSE, + UNKNOWN_ERROR, +) from oauth.views import authorize, OAUTH_REDIRECT -from users.tests.mock_hep_data_factory import MockResponse, ME_DATA, VALID_STUDENT_ORDERS, VALID_TEACHERS_ORDERS +from users.tests.mock_hep_data_factory import ( + MockResponse, + ME_DATA, + VALID_STUDENT_ORDERS, + VALID_TEACHERS_ORDERS, +) from users.factories import LicenseFactory from users.models import Role, User, SchoolClass, License, UserData @@ -21,65 +30,69 @@ IN_A_HOUR = timezone.now() + timedelta(hours=1) IN_A_HOUR_UNIX = time.mktime(IN_A_HOUR.timetuple()) TOKEN = { - 'token_type': 'hep', - 'access_token': '123456', - 'refresh_token': 'abcdqwer', - 'expires_at': IN_A_HOUR_UNIX, + "token_type": "hep", + "access_token": "123456", + "refresh_token": "abcdqwer", + "expires_at": IN_A_HOUR_UNIX, } NEW_ME_DATA = ME_DATA.copy() -NEW_ME_DATA['email'] = 'stiller@has.ch' -NEW_ME_DATA['id'] = 99 +NEW_ME_DATA["email"] = "stiller@has.ch" +NEW_ME_DATA["id"] = 99 class LoginTests(TestCase): def setUp(self): - self.user = UserFactory(username=ME_DATA['id'], email=ME_DATA['id']) + self.user = UserFactory(username=ME_DATA["id"], email=ME_DATA["id"]) Role.objects.create_default_roles() self.teacher_role = Role.objects.get_default_teacher_role() self.factory = RequestFactory() def _login(self, url): + get_response = MagicMock() request = self.factory.get(url) - middleware = SessionMiddleware() + middleware = SessionMiddleware(get_response) middleware.process_request(request) request.session.save() request.user = AnonymousUser() return authorize(request) - @patch.object(DjangoOAuth2App, 'authorize_access_token', return_value=TOKEN) - @patch.object(HepClient, 'user_details', return_value=ME_DATA) + @patch.object(DjangoOAuth2App, "authorize_access_token", return_value=TOKEN) + @patch.object(HepClient, "user_details", return_value=ME_DATA) def test_user_data_is_synced_on_login(self, user_mock, authorize_mock): + old_mail = "aschi@iterativ.ch" - old_mail = 'aschi@iterativ.ch' - - self.user.hep_id = ME_DATA['id'] + self.user.hep_id = ME_DATA["id"] self.user.email = old_mail self.user.username = old_mail self.user.save() now = timezone.now() expiry_date = now + timedelta(365) - LicenseFactory(expire_date=expiry_date, licensee=self.user, for_role=self.teacher_role).save() + LicenseFactory( + expire_date=expiry_date, licensee=self.user, for_role=self.teacher_role + ).save() - response = self._login('/api/oauth/authorize?code=1234') + response = self._login("/api/oauth/authorize?code=1234") user = User.objects.get(hep_id=self.user.hep_id) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, f'/{OAUTH_REDIRECT}?state=success') - self.assertEqual(user.username, ME_DATA['email']) - self.assertEqual(user.email, ME_DATA['email']) + self.assertEqual(response.url, f"/{OAUTH_REDIRECT}?state=success") + self.assertEqual(user.username, ME_DATA["email"]) + self.assertEqual(user.email, ME_DATA["email"]) self.assertTrue(self.user.is_authenticated) - @patch.object(HepClient, 'fetch_eorders', return_value=VALID_TEACHERS_ORDERS) - @patch.object(DjangoOAuth2App, 'authorize_access_token', return_value=TOKEN) - @patch.object(HepClient, 'user_details', return_value=ME_DATA) - def test_teacher_can_login_with_valid_license(self, user_mock, authorize_mock, orders_mock): - response = self._login('/api/oauth/authorize?code=1234') + @patch.object(HepClient, "fetch_eorders", return_value=VALID_TEACHERS_ORDERS) + @patch.object(DjangoOAuth2App, "authorize_access_token", return_value=TOKEN) + @patch.object(HepClient, "user_details", return_value=ME_DATA) + def test_teacher_can_login_with_valid_license( + self, user_mock, authorize_mock, orders_mock + ): + response = self._login("/api/oauth/authorize?code=1234") - user = User.objects.get(email=ME_DATA['email']) + user = User.objects.get(email=ME_DATA["email"]) user_role_key = user.user_roles.get(user=user).role.key self.assertEqual(user_role_key, Role.objects.TEACHER_KEY) @@ -91,22 +104,25 @@ class LoginTests(TestCase): self.assertIsNotNone(school_class) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, f'/{OAUTH_REDIRECT}?state=success') + self.assertEqual(response.url, f"/{OAUTH_REDIRECT}?state=success") self.assertTrue(self.user.is_authenticated) try: UserData.objects.get(user=user) - self.fail('LoginTests.test_teacher_can_login_with_valid_license: Userdata should not exist') + self.fail( + "LoginTests.test_teacher_can_login_with_valid_license: Userdata should not exist" + ) except: pass - @patch.object(HepClient, 'fetch_eorders', return_value=VALID_STUDENT_ORDERS) - @patch.object(DjangoOAuth2App, 'authorize_access_token', return_value=TOKEN) - @patch.object(HepClient, 'user_details', return_value=ME_DATA) - def test_student_can_login_with_valid_license(self, user_mock, authorize_mock, orders_mock): - - response = self._login('/api/oauth/authorize?code=1234') - user = User.objects.get(email=ME_DATA['email']) + @patch.object(HepClient, "fetch_eorders", return_value=VALID_STUDENT_ORDERS) + @patch.object(DjangoOAuth2App, "authorize_access_token", return_value=TOKEN) + @patch.object(HepClient, "user_details", return_value=ME_DATA) + def test_student_can_login_with_valid_license( + self, user_mock, authorize_mock, orders_mock + ): + response = self._login("/api/oauth/authorize?code=1234") + user = User.objects.get(email=ME_DATA["email"]) user_role_key = user.user_roles.get(user=user).role.key self.assertEqual(user_role_key, Role.objects.STUDENT_KEY) @@ -115,60 +131,70 @@ class LoginTests(TestCase): self.assertEqual(license.for_role.key, Role.objects.STUDENT_KEY) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, f'/{OAUTH_REDIRECT}?state=success') + self.assertEqual(response.url, f"/{OAUTH_REDIRECT}?state=success") self.assertTrue(self.user.is_authenticated) - @patch.object(HepClient, 'is_email_verified', return_value=False) - @patch.object(DjangoOAuth2App, 'authorize_access_token', return_value=TOKEN) - @patch.object(HepClient, 'user_details', return_value=ME_DATA) - def test_user_with_unconfirmed_email_cannot_login(self, user_mock, authorize_mock, verified_mock): - response = self._login('/api/oauth/authorize?code=1234') + @patch.object(HepClient, "is_email_verified", return_value=False) + @patch.object(DjangoOAuth2App, "authorize_access_token", return_value=TOKEN) + @patch.object(HepClient, "user_details", return_value=ME_DATA) + def test_user_with_unconfirmed_email_cannot_login( + self, user_mock, authorize_mock, verified_mock + ): + response = self._login("/api/oauth/authorize?code=1234") - User.objects.get(email=ME_DATA['email']) + User.objects.get(email=ME_DATA["email"]) self.assertEqual(302, response.status_code) - self.assertEqual(f'/{OAUTH_REDIRECT}?state={EMAIL_NOT_VERIFIED}', response.url) + self.assertEqual(f"/{OAUTH_REDIRECT}?state={EMAIL_NOT_VERIFIED}", response.url) - @patch.object(HepClient, 'fetch_eorders', return_value=[]) - @patch.object(DjangoOAuth2App, 'authorize_access_token', return_value=TOKEN) - @patch.object(HepClient, 'user_details', return_value=ME_DATA) + @patch.object(HepClient, "fetch_eorders", return_value=[]) + @patch.object(DjangoOAuth2App, "authorize_access_token", return_value=TOKEN) + @patch.object(HepClient, "user_details", return_value=ME_DATA) def test_user_can_login_without_license(self, me_mock, product_mock, verified_mock): - response = self._login('/api/oauth/authorize?code=1234') + response = self._login("/api/oauth/authorize?code=1234") self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, f'/{OAUTH_REDIRECT}?state={NO_VALID_LICENSE}') + self.assertEqual(response.url, f"/{OAUTH_REDIRECT}?state={NO_VALID_LICENSE}") self.assertTrue(self.user.is_authenticated) - @patch.object(HepClient, 'fetch_eorders', return_value=[]) - @patch.object(DjangoOAuth2App, 'authorize_access_token', return_value=TOKEN) - @patch.object(HepClient, 'user_details', return_value=ME_DATA) - def test_user_can_login_local_license_invalid(self, me_mock, product_mock, verified_mock): + @patch.object(HepClient, "fetch_eorders", return_value=[]) + @patch.object(DjangoOAuth2App, "authorize_access_token", return_value=TOKEN) + @patch.object(HepClient, "user_details", return_value=ME_DATA) + def test_user_can_login_local_license_invalid( + self, me_mock, product_mock, verified_mock + ): now = timezone.now() expiry_date = now - timedelta(1) - LicenseFactory(expire_date=expiry_date, licensee=self.user, for_role=self.teacher_role).save() + LicenseFactory( + expire_date=expiry_date, licensee=self.user, for_role=self.teacher_role + ).save() - response = self._login('/api/oauth/authorize?code=1234') + response = self._login("/api/oauth/authorize?code=1234") self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, f'/{OAUTH_REDIRECT}?state={NO_VALID_LICENSE}') + self.assertEqual(response.url, f"/{OAUTH_REDIRECT}?state={NO_VALID_LICENSE}") self.assertTrue(self.user.is_authenticated) - @patch.object(requests, 'get', return_value=MockResponse(500)) + @patch.object(requests, "get", return_value=MockResponse(500)) def test_user_gets_notified_if_server_error(self, post_mock): - response = self._login('/api/oauth/authorize?code=1234') + response = self._login("/api/oauth/authorize?code=1234") self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, f'/{OAUTH_REDIRECT}?state={UNKNOWN_ERROR}') + self.assertEqual(response.url, f"/{OAUTH_REDIRECT}?state={UNKNOWN_ERROR}") - @patch.object(HepClient, 'fetch_eorders', return_value=VALID_TEACHERS_ORDERS) - @patch.object(DjangoOAuth2App, 'authorize_access_token', return_value=TOKEN) - @patch.object(HepClient, 'user_details', return_value=NEW_ME_DATA) - def new_user_is_created_in_system_after_login_with_valid_license(self, user_mock, authorize_mock, orders_mock): - response = self._login('/api/oauth/authorize?code=1234') + @patch.object(HepClient, "fetch_eorders", return_value=VALID_TEACHERS_ORDERS) + @patch.object(DjangoOAuth2App, "authorize_access_token", return_value=TOKEN) + @patch.object(HepClient, "user_details", return_value=NEW_ME_DATA) + def new_user_is_created_in_system_after_login_with_valid_license( + self, user_mock, authorize_mock, orders_mock + ): + response = self._login("/api/oauth/authorize?code=1234") try: - user = User.objects.get(email=NEW_ME_DATA['email']) + user = User.objects.get(email=NEW_ME_DATA["email"]) except: - self.fail('LoginTests.new_user_is_created_in_system_after_login: User was not created') + self.fail( + "LoginTests.new_user_is_created_in_system_after_login: User was not created" + ) user_role_key = user.user_roles.get(user=user).role.key self.assertEqual(user_role_key, Role.objects.TEACHER_KEY) @@ -180,25 +206,31 @@ class LoginTests(TestCase): self.assertIsNotNone(school_class) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, f'/{OAUTH_REDIRECT}?state=success') + self.assertEqual(response.url, f"/{OAUTH_REDIRECT}?state=success") self.assertTrue(self.user.is_authenticated) try: UserData.objects.get(user=user) - self.fail('LoginTests.test_teacher_can_login_with_valid_license: Userdata should not exist') + self.fail( + "LoginTests.test_teacher_can_login_with_valid_license: Userdata should not exist" + ) except: pass - @patch.object(HepClient, 'fetch_eorders', return_value=[]) - @patch.object(DjangoOAuth2App, 'authorize_access_token', return_value=TOKEN) - @patch.object(HepClient, 'user_details', return_value=NEW_ME_DATA) - def new_user_is_created_in_system_after_login(self, user_mock, authorize_mock, orders_mock): - response = self._login('/api/oauth/authorize?code=1234') + @patch.object(HepClient, "fetch_eorders", return_value=[]) + @patch.object(DjangoOAuth2App, "authorize_access_token", return_value=TOKEN) + @patch.object(HepClient, "user_details", return_value=NEW_ME_DATA) + def new_user_is_created_in_system_after_login( + self, user_mock, authorize_mock, orders_mock + ): + response = self._login("/api/oauth/authorize?code=1234") try: - user = User.objects.get(email=NEW_ME_DATA['email']) + user = User.objects.get(email=NEW_ME_DATA["email"]) except: - self.fail('LoginTests.new_user_is_created_in_system_after_login: User was not created') + self.fail( + "LoginTests.new_user_is_created_in_system_after_login: User was not created" + ) user_role_key = user.user_roles.get(user=user).role.key self.assertEqual(user_role_key, Role.objects.TEACHER_KEY) @@ -210,12 +242,14 @@ class LoginTests(TestCase): self.assertIsNotNone(school_class) self.assertEqual(response.status_code, 302) - self.assertEqual(response.url, f'/{OAUTH_REDIRECT}?state={NO_VALID_LICENSE}') + self.assertEqual(response.url, f"/{OAUTH_REDIRECT}?state={NO_VALID_LICENSE}") self.assertTrue(self.user.is_authenticated) try: UserData.objects.get(user=user) - self.fail('LoginTests.test_teacher_can_login_with_valid_license: Userdata should not exist') + self.fail( + "LoginTests.test_teacher_can_login_with_valid_license: Userdata should not exist" + ) except: pass diff --git a/server/rooms/factories.py b/server/rooms/factories.py index c96027f1..39b620da 100644 --- a/server/rooms/factories.py +++ b/server/rooms/factories.py @@ -16,45 +16,67 @@ class RoomFactory(factory.django.DjangoModelFactory): class Meta: model = Room - title = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(4, 8))) + title = factory.LazyAttribute( + lambda x: fake.sentence(nb_words=random.randint(4, 8)) + ) school_class = factory.Iterator(SchoolClass.objects.all()) - appearance = factory.LazyAttribute(lambda x: random.choice(['red', 'green', 'brown'])) + appearance = factory.LazyAttribute( + lambda x: random.choice(["red", "green", "brown"]) + ) -block_types = ['text_block', 'image_block'] +block_types = ["text_block", "image_block"] class RoomEntryFactory(factory.django.DjangoModelFactory): class Meta: model = RoomEntry - title = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(8, 12))) - description = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(20, 30))) + title = factory.LazyAttribute( + lambda x: fake.sentence(nb_words=random.randint(8, 12)) + ) + description = factory.LazyAttribute( + lambda x: fake.sentence(nb_words=random.randint(20, 30)) + ) author = factory.Iterator(get_user_model().objects.all()) room = factory.SubFactory(RoomFactory) - contents = wagtail_factories.StreamFieldFactory({ - 'text_block': TextBlockFactory, - 'image_url_block': ImageUrlBlockFactory, - 'link_block': LinkBlockFactory - }) + contents = wagtail_factories.StreamFieldFactory( + { + "text_block": factory.SubFactory(TextBlockFactory), + "image_url_block": factory.SubFactory(ImageUrlBlockFactory), + "link_block": factory.SubFactory(LinkBlockFactory), + } + ) @classmethod def stream_field_magic(cls, kwargs, stream_field_name): if stream_field_name in kwargs: for idx, resource in enumerate(kwargs[stream_field_name]): - value = resource['value'] + value = resource["value"] for jdx, field in enumerate(value): - block_type = resource['type'] + block_type = resource["type"] - if block_type == 'text_block': - kwargs['{}__{}__{}__{}'.format(stream_field_name, idx, block_type, field)] = RichText(value[field]) + if block_type == "text_block": + kwargs[ + "{}__{}__{}__{}".format( + stream_field_name, idx, block_type, field + ) + ] = RichText(value[field]) - if block_type == 'image_url_block': - kwargs['{}__{}__{}__{}'.format(stream_field_name, idx, block_type, field)] = value[field] + if block_type == "image_url_block": + kwargs[ + "{}__{}__{}__{}".format( + stream_field_name, idx, block_type, field + ) + ] = value[field] - if block_type == 'link_block': - kwargs['{}__{}__{}__{}'.format(stream_field_name, idx, block_type, field)] = value[field] + if block_type == "link_block": + kwargs[ + "{}__{}__{}__{}".format( + stream_field_name, idx, block_type, field + ) + ] = value[field] # elif block_type == 'image_block': # kwargs['{}__{}__{}__{}'.format(stream_field_name, idx, block_type, 'image__title')] = fake_paragraph() @@ -67,15 +89,19 @@ class RoomEntryFactory(factory.django.DjangoModelFactory): else: for i in range(0, random.randint(3, 7)): block_type = random.choice(block_types) - if block_type == 'text_block': - kwargs['{}__{}__{}__{}'.format(stream_field_name, i, 'text_block', 'text')] = RichText(fake_paragraph()) + if block_type == "text_block": + kwargs[ + "{}__{}__{}__{}".format( + stream_field_name, i, "text_block", "text" + ) + ] = RichText(fake_paragraph()) # elif block_type == 'image_block': # kwargs['{}__{}__{}__{}'.format(stream_field_name, i, 'image_block', 'image__title')] = fake_paragraph() @classmethod def create(cls, **kwargs): - cls.stream_field_magic(kwargs, 'contents') + cls.stream_field_magic(kwargs, "contents") return cls._generate(CREATE_STRATEGY, kwargs) @@ -83,12 +109,14 @@ class ModuleRoomSlugFactory(factory.django.DjangoModelFactory): class Meta: model = ModuleRoomSlug - slug = factory.Sequence(lambda n: u'slug-{:d}'.format(n)) - title = factory.Sequence(lambda n: u'Title {:d}'.format(n)) + slug = factory.Sequence(lambda n: "slug-{:d}".format(n)) + title = factory.Sequence(lambda n: "Title {:d}".format(n)) class CommentFactory(factory.django.DjangoModelFactory): class Meta: model = Comment - text = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(10, 30))) + text = factory.LazyAttribute( + lambda x: fake.sentence(nb_words=random.randint(10, 30)) + ) diff --git a/server/rooms/tests/test_room_entry_mutations.py b/server/rooms/tests/test_room_entry_mutations.py index fcfe2420..aaf128b5 100644 --- a/server/rooms/tests/test_room_entry_mutations.py +++ b/server/rooms/tests/test_room_entry_mutations.py @@ -38,66 +38,66 @@ mutation AddRoomEntry($input: AddRoomEntryInput!){ class RoomEntryMutationsTestCase(SkillboxTestCase): def setUp(self): - self.user = UserFactory(username='aschi') - self.another_user = UserFactory(username='pesche') - self.yet_another_user = UserFactory(username='hansueli') + self.user = UserFactory(username="aschi") + self.another_user = UserFactory(username="pesche") + self.yet_another_user = UserFactory(username="hansueli") s = SchoolClassFactory(users=[self.user, self.another_user]) s2 = SchoolClassFactory(users=[self.yet_another_user]) - self.room_entry = RoomEntryFactory(author=self.user, room=RoomFactory(school_class=s)) + # self.room_entry = RoomEntryFactory(author=self.user, room=RoomFactory(school_class=s)) + self.room_entry = RoomEntryFactory(author=self.user, room__school_class=s) self.room = self.room_entry.room self.first_school_class = s - request = RequestFactory().get('/') + request = RequestFactory().get("/") request.user = self.user self.client = Client(schema=schema, context_value=request) def test_delete_room_entry(self): self.assertEqual(RoomEntry.objects.count(), 1) - mutation = ''' + mutation = """ mutation DeleteRoomEntry($input: DeleteRoomEntryInput!) { deleteRoomEntry(input: $input) { success errors } } - ''' + """ - result = self.client.execute(mutation, variables={ - 'input': { - 'slug': self.room_entry.slug - } - }) - self.assertIsNone(result.get('errors')) + result = self.client.execute( + mutation, variables={"input": {"slug": self.room_entry.slug}} + ) + self.assertIsNone(result.get("errors")) self.assertEqual(RoomEntry.objects.count(), 0) def test_delete_room_not_owner(self): self.assertEqual(RoomEntry.objects.count(), 1) - mutation = ''' + mutation = """ mutation DeleteRoomEntry($input: DeleteRoomEntryInput!) { deleteRoomEntry(input: $input) { success errors } } - ''' + """ - request = RequestFactory().get('/') + request = RequestFactory().get("/") request.user = self.another_user client = Client(schema=schema, context_value=request) - result = client.execute(mutation, variables={ - 'input': { - 'id': to_global_id('RoomEntryNode', self.room_entry.pk) - } - }) + result = client.execute( + mutation, + variables={ + "input": {"id": to_global_id("RoomEntryNode", self.room_entry.pk)} + }, + ) - self.assertIsNotNone(result.get('errors')) + self.assertIsNotNone(result.get("errors")) self.assertEqual(RoomEntry.objects.count(), 1) def test_update_room_entry_not_owner_but_same_class(self): self.assertEqual(RoomEntry.objects.count(), 1) - mutation = ''' + mutation = """ mutation UpdateRoomEntry($input: UpdateRoomEntryInput!){ updateRoomEntry(input: $input) { roomEntry { @@ -109,30 +109,33 @@ class RoomEntryMutationsTestCase(SkillboxTestCase): errors } } - ''' + """ - request = RequestFactory().get('/') + request = RequestFactory().get("/") request.user = self.another_user client = Client(schema=schema, context_value=request) - new_title = 'new title, Alte!' + new_title = "new title, Alte!" - result = client.execute(mutation, variables={ - 'input': { - 'roomEntry': { - 'id': to_global_id('RoomEntryNode', self.room_entry.pk), - 'title': new_title + result = client.execute( + mutation, + variables={ + "input": { + "roomEntry": { + "id": to_global_id("RoomEntryNode", self.room_entry.pk), + "title": new_title, + } } - } - }) + }, + ) entry = RoomEntry.objects.get(pk=self.room_entry.pk) - self.assertIsNotNone(result.get('errors')) + self.assertIsNotNone(result.get("errors")) self.assertEqual(entry.title, self.room_entry.title) def test_update_room_entry_not_owner_from_other_class(self): self.assertEqual(RoomEntry.objects.count(), 1) - mutation = ''' + mutation = """ mutation UpdateRoomEntry($input: UpdateRoomEntryInput!){ updateRoomEntry(input: $input) { roomEntry { @@ -144,25 +147,28 @@ class RoomEntryMutationsTestCase(SkillboxTestCase): errors } } - ''' + """ - request = RequestFactory().get('/') + request = RequestFactory().get("/") request.user = self.yet_another_user client = Client(schema=schema, context_value=request) - new_title = 'new title, Alte!' + new_title = "new title, Alte!" - result = client.execute(mutation, variables={ - 'input': { - 'roomEntry': { - 'id': to_global_id('RoomEntryNode', self.room_entry.pk), - 'title': new_title + result = client.execute( + mutation, + variables={ + "input": { + "roomEntry": { + "id": to_global_id("RoomEntryNode", self.room_entry.pk), + "title": new_title, + } } - } - }) + }, + ) entry = RoomEntry.objects.get(pk=self.room_entry.pk) - self.assertIsNotNone(result.get('errors')) + self.assertIsNotNone(result.get("errors")) self.assertEqual(entry.title, self.room_entry.title) def test_add_room_entry_not_owner_from_other_class(self): @@ -171,39 +177,32 @@ class RoomEntryMutationsTestCase(SkillboxTestCase): # title = graphene.String(required=True) # contents = graphene.List(ContentElementInput) # room = graphene.ID(required=True) - room_entry = { - 'title': 'Bad Actor!', - 'roomSlug': self.room.slug - } + room_entry = {"title": "Bad Actor!", "roomSlug": self.room.slug} - result = self.get_client(self.yet_another_user).execute(ADD_ROOM_ENTRY_MUTATION, variables={ - 'input': { - 'roomEntry': room_entry - } - }) + result = self.get_client(self.yet_another_user).execute( + ADD_ROOM_ENTRY_MUTATION, variables={"input": {"roomEntry": room_entry}} + ) self.assertIsNotNone(result.errors) - self.assertTrue('message' in result.errors[0]) - self.assertEqual(result.errors[0]['message'], 'You are in the wrong class') + self.assertTrue("message" in result.errors[0]) + self.assertEqual(result.errors[0]["message"], "You are in the wrong class") def test_add_room_entry(self): self.assertEqual(RoomEntry.objects.count(), 1) text_block = {"type": "text_block", "value": {"text": "
some text
"}} subtitle_block = {"type": "subtitle", "value": {"text": "A subtitle"}} room_entry = { - 'title': 'A room entry', - 'roomSlug': self.room.slug, - 'contents': [text_block, subtitle_block] + "title": "A room entry", + "roomSlug": self.room.slug, + "contents": [text_block, subtitle_block], } - result = self.get_client(self.user).execute(ADD_ROOM_ENTRY_MUTATION, variables={ - 'input': { - 'roomEntry': room_entry - } - }) + result = self.get_client(self.user).execute( + ADD_ROOM_ENTRY_MUTATION, variables={"input": {"roomEntry": room_entry}} + ) self.assertIsNone(result.errors) - room_entry_data = result.data.get('addRoomEntry').get('roomEntry') - contents = room_entry_data.get('contents') + room_entry_data = result.data.get("addRoomEntry").get("roomEntry") + contents = room_entry_data.get("contents") self.assertEqual(len(contents), 2) text, subtitle = contents - self.assertEqual(text.get('type'), 'text_block') - self.assertEqual(subtitle.get('type'), 'subtitle') + self.assertEqual(text.get("type"), "text_block") + self.assertEqual(subtitle.get("type"), "subtitle") self.assertEqual(RoomEntry.objects.count(), 2) diff --git a/server/statistics/urls.py b/server/statistics/urls.py index 0f575b83..bb461369 100644 --- a/server/statistics/urls.py +++ b/server/statistics/urls.py @@ -1,4 +1,3 @@ -from django.conf.urls import url from django.urls import re_path from statistics.views import StatisticsView diff --git a/server/users/tests/test_local_login.py b/server/users/tests/test_local_login.py index a5e2089a..0024a871 100644 --- a/server/users/tests/test_local_login.py +++ b/server/users/tests/test_local_login.py @@ -7,6 +7,7 @@ # # Created on 2019-10-02 # @author: chrigu