From 7c02f356568fc548ec1b8e6dde995f70211bf608 Mon Sep 17 00:00:00 2001 From: Oliver Stolpe Date: Tue, 10 Sep 2024 16:20:08 +0200 Subject: [PATCH] feat: upgrade to sodar core v1 (#1973) --- .github/workflows/main.yml | 2 +- backend/Makefile | 11 +- backend/Pipfile | 15 +- backend/Pipfile.lock | 841 ++++-------------- backend/beaconsite/tests/test_permissions.py | 8 +- .../beaconsite/tests/test_permissions_ajax.py | 6 +- .../beaconsite/tests/test_permissions_api.py | 6 +- backend/beaconsite/tests/test_views_ajax.py | 4 +- backend/beaconsite/urls.py | 60 +- backend/cases/tests/test_permissions.py | 4 +- backend/cases/tests/test_permissions_ajax.py | 26 +- backend/cases/tests/test_permissions_api.py | 24 +- backend/cases/tests/test_views.py | 4 +- backend/cases/tests/test_views_ajax.py | 24 +- backend/cases/urls.py | 114 +-- .../tests/test_permissions_api.py | 6 +- backend/cases_import/models/executors.py | 2 +- .../tests/test_models_executor.py | 2 +- .../tests/test_permissions_api.py | 4 +- .../cases_qc/tests/test_permissions_api.py | 6 +- backend/cases_qc/tests/test_views_api.py | 2 +- .../migrations/0008_alter_cohort_user.py | 28 + .../cohorts/tests/test_permissions_ajax.py | 8 +- backend/cohorts/tests/test_permissions_api.py | 8 +- backend/cohorts/tests/test_views_ui.py | 4 +- backend/cohorts/urls.py | 58 +- backend/config/settings/base.py | 109 +-- backend/config/urls.py | 136 ++- ...ntquerygestaltmatcherscores_id_and_more.py | 27 + backend/genepanels/forms.py | 7 +- backend/genepanels/tests/test_models.py | 6 +- backend/genepanels/tests/test_permissions.py | 4 +- backend/genepanels/urls.py | 62 +- .../0012_alter_importcasebgjob_bg_job.py | 25 + backend/importer/urls.py | 67 +- backend/seqmeta/tests/test_models.py | 2 +- backend/seqmeta/tests/test_permissions.py | 4 +- backend/seqmeta/urls.py | 30 +- backend/seqvars/tests/test_permissions_api.py | 34 +- ...buildbackgroundsvsetjob_bg_job_and_more.py | 59 ++ .../tests/test_permissions_ajax_presets.py | 4 +- .../tests/test_permissions_ajax_queries.py | 14 +- backend/svs/urls.py | 98 +- backend/varannos/tests/helpers.py | 6 +- backend/varannos/tests/test_models.py | 2 +- backend/varannos/tests/test_permissions.py | 4 +- .../varannos/tests/test_permissions_api.py | 4 +- backend/varannos/urls.py | 26 +- backend/varfish/templates/users/login.html | 111 +-- .../users/management/commands/initdev.py | 2 +- backend/varfish/users/urls.py | 10 +- backend/varfish/vueapp/urls.py | 6 +- ...piredexportedfilesbgjob_bg_job_and_more.py | 141 +++ .../migrations/0110_drop_variant_summary.py | 103 +++ .../migrations/0111_create_variant_summary.py | 80 ++ backend/variants/models/maintenance.py | 77 ++ backend/variants/tests/helpers.py | 8 +- backend/variants/tests/test_file_export.py | 4 +- .../variants/tests/test_permissions_ajax.py | 12 +- .../tests/test_permissions_ajax_annos.py | 4 +- .../tests/test_permissions_ajax_presets.py | 58 +- .../variants/tests/test_permissions_api.py | 14 +- backend/variants/tests/test_ui.py | 2 +- .../variants/tests/test_views_ajax_presets.py | 303 +++---- backend/variants/urls/__init__.py | 340 +++---- backend/variants/urls/annos.py | 6 +- backend/variants/urls/presets.py | 118 +-- frontend/ext/reev-frontend-lib | 2 +- .../SvFilterForm/GenesRegionsPane.vue | 4 +- .../StrucvarFilterLegacy.vue | 10 +- .../varfish/components/FilterForm/DevPane.vue | 6 +- .../components/FilterForm/ClinvarPane.vue | 2 +- .../components/FilterForm/EffectPane.vue | 2 +- .../components/FilterForm/FlagsPane.vue | 2 +- .../components/FilterForm/FrequencyPane.vue | 2 +- .../FilterForm/GenesRegionsPane.vue | 8 +- .../components/FilterForm/QualityPane.vue | 2 +- .../components/QueryPresets/SetEditor.vue | 6 +- .../components/QueryPresets/SetProperties.vue | 4 +- 79 files changed, 1618 insertions(+), 1838 deletions(-) create mode 100644 backend/cohorts/migrations/0008_alter_cohort_user.py create mode 100644 backend/ext_gestaltmatcher/migrations/0003_alter_smallvariantquerygestaltmatcherscores_id_and_more.py create mode 100644 backend/importer/migrations/0012_alter_importcasebgjob_bg_job.py create mode 100644 backend/svs/migrations/0029_alter_buildbackgroundsvsetjob_bg_job_and_more.py create mode 100644 backend/variants/migrations/0109_alter_clearexpiredexportedfilesbgjob_bg_job_and_more.py create mode 100644 backend/variants/migrations/0110_drop_variant_summary.py create mode 100644 backend/variants/migrations/0111_create_variant_summary.py diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8d7c49d29..42fb410fe 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -14,7 +14,7 @@ jobs: - 6379:6379 postgres: - image: postgres:14 + image: postgres:16 env: POSTGRES_DB: varfish_web POSTGRES_USER: varfish_web diff --git a/backend/Makefile b/backend/Makefile index 87aae96bb..4194bc31f 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -109,13 +109,16 @@ ci: \ docs: pipenv run $(MAKE) -C ../docs clean html -.PHONY: _migrate -_migrate: +.PHONY: _makemigrations +_makemigrations: pipenv run $(MANAGE) makemigrations - pipenv run $(MANAGE) migrate + +.PHONY: makemigrations +makemigrations: _makemigrations format .PHONY: migrate -migrate: _migrate format +migrate: + pipenv run $(MANAGE) migrate .PHONY: shell shell: diff --git a/backend/Pipfile b/backend/Pipfile index a5d780c52..5d6050df4 100644 --- a/backend/Pipfile +++ b/backend/Pipfile @@ -7,7 +7,7 @@ name = "pypi" aldjemy = "~=2.2" altamisa = "~=0.2.5" attrs = "~=24.2" -beautifulsoup4 = "~=4.9" +beautifulsoup4 = "~=4.12.3" cattrs = "*" django = "*" # whatever django-sodar-core enforces django-clone = "*" @@ -15,12 +15,13 @@ django-cryptographic-fields-bihealth = "~=0.6.0" django-debug-toolbar = "*" django-extensions = "~=3.2" django-postgres-copy = "~=2.3.5" # there are issues above 2.3 -django-plugins-bihealth = "~=0.4.0" -django-sodar-core = "~=0.13.4" +django-plugins-bihealth = "~=0.5.2" +django-sodar-core = "~=1.0.2" django-su = "~=1.0.0" djangorestframework-httpsignature = "~=1.0" +djangorestframework = "~=3.15" djproxy = "~=2.3" -drf-keyed-list-bihealth = "~=0.1.1" +drf-keyed-list-bihealth = "~=0.2.1" httpsig = "~=1.3" interval-binning = "~=1.0" intervaltree = "~=3.1" @@ -51,10 +52,10 @@ wrapt = "~=1.16" xlsxwriter = "~=3.2" django-pydantic-field = "*" pydantic = "*" +typing-extensions="*" universal-pathlib = "*" s3fs = "*" toml = "*" -black = "*" rich = "*" drf-writable-nested = "*" django-modelcluster = "*" @@ -96,7 +97,7 @@ django-types = "*" [ldap-packages] # Dependencies for enabling LDAP support. You will need the system library # named `libldap` (or similar). -django-auth-ldap = "~=4.1" +django-auth-ldap = "~=4.6" python-ldap = "~=3.4" # Packages needed in production. @@ -109,4 +110,4 @@ django-storages = "*" django_redis = "*" [requires] -python_version = "3.10" +python_version = "3.11" diff --git a/backend/Pipfile.lock b/backend/Pipfile.lock index 12146d752..acab96764 100644 --- a/backend/Pipfile.lock +++ b/backend/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "39da2c3fd1d58d12ca7f6720a6df350bdcfaaa0f09cf696c5a991591ae1cc291" + "sha256": "b97a5098866eac8b68ddaa148238dc47c367563bfc681ddfc30b6605a12b8192" }, "pipfile-spec": 6, "requires": { - "python_version": "3.10" + "python_version": "3.11" }, "sources": [ { @@ -159,7 +159,6 @@ "sha256:a739e2924bf7940daee3a17ccec99fd7175363a160d6e8c3329e61d6534a165e" ], "index": "pypi", - "markers": "python_full_version >= '3.6.1' and python_version < '4.0'", "version": "==2.6" }, "altamisa": { @@ -250,7 +249,6 @@ "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==24.2.0" }, "awesome-slugify": { @@ -273,44 +271,15 @@ "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed" ], "index": "pypi", - "markers": "python_full_version >= '3.6.0'", "version": "==4.12.3" }, "billiard": { "hashes": [ - "sha256:299de5a8da28a783d51b197d496bef4f1595dd023a93a4f59dde1886ae905547", - "sha256:87103ea78fa6ab4d5c751c4909bcff74617d985de7fa8b672cf8618afd5a875b" + "sha256:12b641b0c539073fc8d3f5b8b7be998956665c4233c7c1fcd66a7e677c4fb36f", + "sha256:40b59a4ac8806ba2c2369ea98d876bc6108b051c227baffd928c644d15d8f3cb" ], - "version": "==3.6.4.0" - }, - "black": { - "hashes": [ - "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6", - "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e", - "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f", - "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018", - "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e", - "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd", - "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4", - "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed", - "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2", - "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42", - "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af", - "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb", - "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368", - "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb", - "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af", - "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed", - "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47", - "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2", - "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a", - "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c", - "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920", - "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==24.8.0" + "markers": "python_version >= '3.7'", + "version": "==4.2.1" }, "botocore": { "hashes": [ @@ -326,16 +295,15 @@ "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==24.1.2" }, "celery": { "hashes": [ - "sha256:138420c020cd58d6707e6257b6beda91fd39af7afde5d36c6334d175302c0e14", - "sha256:fafbd82934d30f8a004f81e8f7a062e31413a23d444be8ee3326553915958c6d" + "sha256:870cc71d737c0200c397290d730344cc991d13a057534353d124c9380267aab9", + "sha256:9da4ea0118d232ce97dff5ed4974587fb1c0ff5c10042eb15278487cdd27d1af" ], - "markers": "python_version >= '3.7'", - "version": "==5.2.7" + "markers": "python_version >= '3.8'", + "version": "==5.3.6" }, "certifi": { "hashes": [ @@ -550,7 +518,6 @@ "sha256:b3064769e3cf62bd19d12523d391496bce96ce2c057df2b49e53f922ef1369fb" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==0.18.2" }, "conditional": { @@ -563,11 +530,11 @@ }, "crispy-bootstrap4": { "hashes": [ - "sha256:5241ab1dc2188c95560aa786439bcbedec7416e6b0f5a52dded82380810367ec", - "sha256:f18386c4d96180c1bb1212487d6e8f5a3dd1a9bb58d3032183973d4d130b55f9" + "sha256:208673bf6a25892a656971af7a00e18ba2f7f06cd4a0d667923bd6134e64d276", + "sha256:46cf98777a28621d240bf71eb36d4a26ff86e9e19be1cfd822645f4043d18c31" ], - "markers": "python_version >= '3.7'", - "version": "==2022.1" + "markers": "python_version >= '3.8'", + "version": "==2024.1" }, "cryptography": { "hashes": [ @@ -604,26 +571,25 @@ }, "defusedxml": { "hashes": [ - "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", - "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" + "sha256:138c7d540a78775182206c7c97fe65b246a2f40b29471e1a2f1b0da76e7a3942", + "sha256:1c812964311154c3bf4aaf3bc1443b31ee13530b7f255eaaa062c0553c76103d" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.7.1" + "markers": "python_version >= '3.6'", + "version": "==0.8.0rc2" }, "django": { "hashes": [ - "sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777", - "sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38" + "sha256:1ddc333a16fc139fd253035a1606bb24261951bbc3a6ca256717fa06cc41a898", + "sha256:6f1616c2786c408ce86ab7e10f792b8f15742f7b7b7460243929cb371e7f1dad" ], "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.2.25" + "version": "==4.2.16" }, "django-autocomplete-light": { "hashes": [ - "sha256:0f6da75c1c7186698b867a467a8cdb359f0513fdd8e09288a0c2fb018ae3d94e" + "sha256:212576a17e3308ef7ca77e280b86684167916d2091d4b73640f38845d9516328" ], - "version": "==3.9.4" + "version": "==3.11.0" }, "django-clone": { "hashes": [ @@ -631,16 +597,15 @@ "sha256:ea2e5a770d01c62ecf66d0dd6e8df284e26321245b8abcc6d82d8740765b42d5" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==5.3.3" }, "django-crispy-forms": { "hashes": [ - "sha256:90193b068bf948d9c68449bc8260afed1a8e2afe11ee0bac8c4ebfaeb175b322", - "sha256:d1d4e585929058a9ab3b797666ea5b69320b9ba7937f9d146d32173246a6fd13" + "sha256:4d7ec431933ad4d4b5c5a6de4a584d24613c347db9ac168723c9aaf63af4bb96", + "sha256:d592044771412ae1bd539cc377203aa61d4eebe77fcbc07fbc8f12d3746d4f6b" ], - "markers": "python_version >= '3.7'", - "version": "==2.0" + "markers": "python_version >= '3.8'", + "version": "==2.1" }, "django-cryptographic-fields-bihealth": { "hashes": [ @@ -651,18 +616,18 @@ }, "django-db-file-storage": { "hashes": [ - "sha256:5d5da694b78ab202accab4508b958e0e37b3d146310e76f6f6125e1bdeaaad14" + "sha256:3feac1e060b550c3c03c35e95d2111d9f100bc247863ace691a78b107f1fc3d5", + "sha256:f0c4540ed6b772e8b3141eae3222acde4c29ab771477a5c999013a3980856c7f" ], - "version": "==0.5.5" + "version": "==0.5.6.1" }, "django-debug-toolbar": { "hashes": [ - "sha256:0b0dddee5ea29b9cb678593bc0d7a6d76b21d7799cb68e091a2148341a80f3c4", - "sha256:e09b7dcb8417b743234dfc57c95a7c1d1d87a88844abd13b4c5387f807b31bf6" + "sha256:36e421cb908c2f0675e07f9f41e3d1d8618dc386392ec82d23bcfcd5d29c7044", + "sha256:3beb671c9ec44ffb817fad2780667f172bd1c067dbcabad6268ce39a81335f45" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==4.3.0" + "version": "==4.4.6" }, "django-dirtyfields": { "hashes": [ @@ -681,11 +646,11 @@ }, "django-environ": { "hashes": [ - "sha256:510f8c9c1d0a38b0815f91504270c29440a0cf44fab07f55942fa8d31bbb9be6", - "sha256:b3559a91439c9d774a9e0c1ced872364772c612cdf6dc919506a2b13f7a77225" + "sha256:0ff95ab4344bfeff693836aa978e6840abef2e2f1145adff7735892711590c05", + "sha256:f32a87aa0899894c27d4e1776fa6b477e8164ed7f6b3e410a62a6d72caaf64be" ], - "markers": "python_version >= '3.5' and python_version < '4'", - "version": "==0.10.0" + "markers": "python_version >= '3.6' and python_version < '4'", + "version": "==0.11.2" }, "django-extensions": { "hashes": [ @@ -693,16 +658,14 @@ "sha256:9600b7562f79a92cbf1fde6403c04fee314608fefbb595502e34383ae8203401" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==3.2.3" }, "django-iconify": { "hashes": [ - "sha256:f17960f1336af39c3a50ee719203b3fe33ce61fa7300c0627a7a315615ec325c", - "sha256:f624e16f242c6afadb06f0ee97610c9eefb27016649b05a8a51551c8990f71e0" + "sha256:ced9314f011b318ccf56dd5145ca54bb3ec2a7dde3880571552236a31ebbcd97" ], "markers": "python_version >= '3.7' and python_version < '4.0'", - "version": "==0.1.1" + "version": "==0.3" }, "django-markupfield": { "hashes": [ @@ -713,11 +676,11 @@ }, "django-model-utils": { "hashes": [ - "sha256:2e2e4f13e4f14613134a9777db7ad4265f59a1d8f1384107bcaa3028fe3c87c1", - "sha256:8c0b0177bab909a8635b602d960daa67e80607aa5469217857271a60726d7a4b" + "sha256:7b73179480e4d4a737d0188e7c49da03776bbadedad569a534c4e9f1afc004d4", + "sha256:d57143e8b7345fd4719c5a95d07d7a50f7d11134da6a729aa6b73fb9674bec9d" ], - "markers": "python_version >= '3.7'", - "version": "==4.3.1" + "markers": "python_version >= '3.8'", + "version": "==4.4.0" }, "django-modelcluster": { "hashes": [ @@ -725,7 +688,6 @@ "sha256:a8783d6565a0663f41cd6003ea361c3a5711e8a2a326160f1ec1eceb3e973d4f" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==6.3" }, "django-pagedown": { @@ -737,10 +699,10 @@ }, "django-plugins-bihealth": { "hashes": [ - "sha256:5f3d3922f3825348d6d4a7fceb6c6a705c527edcae396ef32ab181d8dbe69536" + "sha256:6f1d85b4225ce8b6ec3195fa158ad120b5aeea61cf1ab744f1512b3809ef6a33" ], "index": "pypi", - "version": "==0.4.0" + "version": "==0.5.2" }, "django-postgres-copy": { "hashes": [ @@ -756,7 +718,6 @@ "sha256:c9824962d300dacd7009b76a64ef9ede81858cc769edbeb25a2c81d338c6f9b8" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==0.3.10" }, "django-rest-knox": { @@ -767,20 +728,12 @@ "markers": "python_version >= '3.6'", "version": "==4.2.0" }, - "django-saml2-auth-ai": { - "hashes": [ - "sha256:5301846103429ba996f9c105474ea531928acebec24132a2516d06fcc6e6852a", - "sha256:6dca13d6d3633b7fb1b818fb3c54a62a71959697d6a2a94cdf3e009ae2704738" - ], - "version": "==2.1.6" - }, "django-sodar-core": { "hashes": [ - "sha256:55b6c73c4c0384d33c2a8cb2fae369475baa551aee924af20f05a07027201762" + "sha256:1efbce524671eae8645ab5516129b7d1a6d45cb76b196539f08ab887c143471b" ], "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==0.13.4" + "version": "==1.0.2" }, "django-su": { "hashes": [ @@ -791,11 +744,11 @@ }, "djangorestframework": { "hashes": [ - "sha256:579a333e6256b09489cbe0a067e66abe55c6595d8926be6b99423786334350c8", - "sha256:eb63f58c9f218e1a7d064d17a70751f528ed4e1d35547fdade9aaf4cd103fd08" + "sha256:2b8871b062ba1aefc2de01f773875441a961fefbf79f5eed1e32b2f096944b20", + "sha256:36fe88cd2d6c6bec23dca9804bab2ba5517a8bb9d8f47ebc68981b56840107ad" ], - "markers": "python_version >= '3.6'", - "version": "==3.14.0" + "index": "pypi", + "version": "==3.15.2" }, "djangorestframework-httpsignature": { "hashes": [ @@ -814,18 +767,18 @@ }, "docutils": { "hashes": [ - "sha256:23010f129180089fbcd3bc08cfefccb3b890b0050e1ca00c867036e9d161b98c", - "sha256:679987caf361a7539d76e584cbeddc311e3aee937877c87346f31debc63e9d06" + "sha256:96f387a2c5562db4476f09f13bbab2192e764cac08ebbf3a34a95d9b1e4a59d6", + "sha256:f08a4e276c3a1583a86dce3e34aba3fe04d02bba2dd51ed16106244e8a923e3b" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.18.1" + "markers": "python_version >= '3.7'", + "version": "==0.20.1" }, "drf-keyed-list-bihealth": { "hashes": [ - "sha256:e28d0111bfad9adae60a1ace79d50c28b9cf10f5bad950ac487014c7a16c9457" + "sha256:c43f456b0190853a185ff7d5288306d3735d4cca1acc9b00a5ff1a04c7d85e6f" ], "index": "pypi", - "version": "==0.1.1" + "version": "==0.2.1" }, "drf-spectacular": { "extras": [ @@ -835,7 +788,7 @@ "sha256:a199492f2163c4101055075ebdbb037d59c6e0030692fc83a1a8c0fc65929981", "sha256:b1c04bf8b2fbbeaf6f59414b4ea448c8787aba4d32f76055c3b13335cf7ec37b" ], - "markers": "python_version >= '3.7'", + "index": "pypi", "version": "==0.27.2" }, "drf-spectacular-sidecar": { @@ -850,17 +803,8 @@ "sha256:154c0381e8a3a477e0fd539d5e1caf8ff4c1097a9c0c0fe741d4858b11b0455b" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==0.7.0" }, - "elementpath": { - "hashes": [ - "sha256:a16438bcc6b2b3069dde204c1e105322378a108b28faea3055d1b294443babea", - "sha256:affdc8de95af1a4c10d1d2ed79c6fa56b59c26c7fce64b73497569e9dea46998" - ], - "markers": "python_version >= '3.8'", - "version": "==4.5.0" - }, "exceptiongroup": { "hashes": [ "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", @@ -875,7 +819,6 @@ "sha256:e0593931bd7be9a9ea984b5d8c302ef1cec19392585d1e90d444199271d0a94d" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==30.1.0" }, "frozenlist": { @@ -1155,7 +1098,6 @@ "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==4.23.0" }, "jsonschema-specifications": { @@ -1323,16 +1265,15 @@ "sha256:fb66442c2546446944437df74379e9cf9e9db353e61301d1a0e26482f43f0dd8" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==5.3.0" }, "markdown": { "hashes": [ - "sha256:08fb8465cffd03d10b9dd34a5c3fea908e20391a2a90b88d66362cb05beed186", - "sha256:3b809086bb6efad416156e00a0da66fe47618a5d6918dd688f53f40c8e4cfeff" + "sha256:d43323865d89fc0cb9b20c75fc8ad313af307cc087e84b657d9eec768eddeadd", + "sha256:e1ac7b3dc550ee80e602e71c1d168002f062e49f1b11e26a36264dafd4df2ef8" ], - "markers": "python_version >= '3.7'", - "version": "==3.4.1" + "markers": "python_version >= '3.8'", + "version": "==3.5.2" }, "markdown-it-py": { "hashes": [ @@ -1418,10 +1359,11 @@ }, "mistune": { "hashes": [ - "sha256:0246113cb2492db875c6be56974a7c893333bf26cd92891c85f63151cee09d34", - "sha256:bad7f5d431886fcbaf5f758118ecff70d31f75231b34024a1341120340a65ce8" + "sha256:71481854c30fdbc938963d3605b72501f5c10a9320ecd412c121c163a1c7d205", + "sha256:fc7f93ded930c92394ef2cb6f04a8aabab4117a91449e72dcc8dfa646a508be8" ], - "version": "==2.0.5" + "markers": "python_version >= '3.7'", + "version": "==3.0.2" }, "multidict": { "hashes": [ @@ -1521,14 +1463,6 @@ "markers": "python_version >= '3.8'", "version": "==6.1.0" }, - "mypy-extensions": { - "hashes": [ - "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", - "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" - ], - "markers": "python_version >= '3.5'", - "version": "==1.0.0" - }, "numpy": { "hashes": [ "sha256:05b2d4e667895cc55e3ff2b56077e4c8a5604361fc21a042845ea3ad67465aa8", @@ -1586,9 +1520,16 @@ "sha256:fc44e3c68ff00fd991b59092a54350e6e4911152682b4782f68070985aa9e648" ], "index": "pypi", - "markers": "python_version >= '3.10'", "version": "==2.1.2" }, + "oauthlib": { + "hashes": [ + "sha256:8139f29aac13e25d502680e9e19963e83f16838d48a0d71c287fe40e7067fbca", + "sha256:9859c40929662bec5d64f34d01c99e093149682a3f38915dc0655d5a633dd918" + ], + "markers": "python_version >= '3.6'", + "version": "==3.2.2" + }, "packaging": { "hashes": [ "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", @@ -1643,24 +1584,14 @@ "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319" ], "index": "pypi", - "markers": "python_version >= '3.9'", "version": "==2.2.3" }, - "pathspec": { - "hashes": [ - "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", - "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" - ], - "markers": "python_version >= '3.8'", - "version": "==0.12.1" - }, "phenopackets": { "hashes": [ "sha256:6f3935d1875fb97e44584ffa4374d2078497f95c7331dc4a04ca6945ab110e45", "sha256:a262a28dbf9851d2ad2e98bea1ccac4d00bebb9613f868020d2cb5f8a06adb9e" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==2.0.2.post4" }, "pillow": { @@ -1749,21 +1680,12 @@ "markers": "python_version >= '3.8'", "version": "==10.4.0" }, - "platformdirs": { - "hashes": [ - "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", - "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb" - ], - "markers": "python_version >= '3.8'", - "version": "==4.3.6" - }, "prettytable": { "hashes": [ "sha256:7e23ca1e68bbfd06ba8de98bf553bf3493264c96d5e8a615c0471025deeba722", "sha256:aa17083feb6c71da11a68b2c213b04675c4af4ce9c541762632ca3f2cb3546dd" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==3.11.0" }, "prompt-toolkit": { @@ -1800,7 +1722,6 @@ "sha256:f4c42102bc82a51108e449cbb32b19b180022941c727bac0cfd50170341f16ee" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==3.20.3" }, "psutil": { @@ -1824,7 +1745,6 @@ "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==6.0.0" }, "psycopg2": { @@ -1976,7 +1896,6 @@ "sha256:f048cec7b26778210e28a0459867920654d48e5e62db0958433636cde4254f12" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==2.9.2" }, "pydantic-core": { @@ -2082,13 +2001,13 @@ "markers": "python_version >= '3.8'", "version": "==2.18.0" }, - "pyopenssl": { + "pyjwt": { "hashes": [ - "sha256:4247f0dbe3748d560dcbb2ff3ea01af0f9a1a001ef5f7c4c647956ed8cbf0e95", - "sha256:967d5719b12b243588573f39b0c677637145c7a1ffedcd495a487e58177fbb8d" + "sha256:3b02fb0f44517787776cf48f2ae25d8e14f300e6d7545a4315cee571a415e850", + "sha256:7e1e5b56cc735432a7369cbfa0efe50fa113ebecdc04ae6922deba8b84582d0c" ], - "markers": "python_version >= '3.7'", - "version": "==24.2.1" + "markers": "python_version >= '3.8'", + "version": "==2.9.0" }, "pysam": { "hashes": [ @@ -2121,24 +2040,14 @@ "sha256:faa5298291b54f185c7b8f84510224918bddc64bbdcb2e8426ff43e83452310f" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==0.22.1" }, - "pysaml2": { - "hashes": [ - "sha256:bc6627cc344476a83c757f440a73fda1369f13b6fda1b4e16bca63ffbabb5318", - "sha256:f36871d4e5ee857c6b85532e942550d2cf90ea4ee943d75eb681044bbc4f54f7" - ], - "markers": "python_version >= '3.9' and python_version < '4.0'", - "version": "==7.5.0" - }, "python-dateutil": { "hashes": [ "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.9.0.post0" }, "python-dotenv": { @@ -2147,9 +2056,15 @@ "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==1.0.1" }, + "python3-openid": { + "hashes": [ + "sha256:33fbf6928f401e0b790151ed2b5290b02545e8775f982485205a066f874aaeaf", + "sha256:6626f771e0417486701e0b4daff762e7212e820ca5b29fcc0d05f6f8736dfa6b" + ], + "version": "==3.2.0" + }, "pytz": { "hashes": [ "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", @@ -2214,7 +2129,6 @@ "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==6.0.2" }, "redis": { @@ -2223,7 +2137,6 @@ "sha256:f8ea06b7482a668c6475ae202ed8d9bcaa409f6e87fb77ed1043d912afd62e24" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==5.1.1" }, "referencing": { @@ -2340,7 +2253,6 @@ "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==2.32.3" }, "requests-http-signature": { @@ -2351,13 +2263,20 @@ "index": "pypi", "version": "==0.2.0" }, + "requests-oauthlib": { + "hashes": [ + "sha256:7dd8a5c40426b779b0868c404bdef9768deccf22749cde15852df527e6269b36", + "sha256:b3dffaebd884d8cd778494369603a9e7b58d29111bf6b41bdc2dcd87203af4e9" + ], + "markers": "python_version >= '3.4'", + "version": "==2.0.0" + }, "rich": { "hashes": [ "sha256:51a2c62057461aaf7152b4d611168f93a9fc73068f8ded2790f29fe2b5366d0c", "sha256:8c82a3d3f8dcfe9e734771313e606b39d8247bb6b826e196f4914b333b743cf1" ], "index": "pypi", - "markers": "python_full_version >= '3.8.0'", "version": "==13.9.2" }, "rpds-py": { @@ -2482,7 +2401,6 @@ "sha256:6493705abb50374d6b7994f9616d27adbdd8a219c8635100bdc286382efd91f5" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==2024.9.0" }, "sentry-sdk": { @@ -2491,16 +2409,15 @@ "sha256:a599e7d3400787d6f43327b973e55a087b931ba2c592a7a7afa691f8eb5e75e2" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==2.15.0" }, "setuptools": { "hashes": [ - "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a", - "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078" + "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4", + "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0" ], - "markers": "python_version >= '3.7'", - "version": "==67.6.1" + "markers": "python_version >= '3.8'", + "version": "==70.0.0" }, "simplejson": { "hashes": [ @@ -2616,7 +2533,6 @@ "sha256:ff7bc1bbdaa3e487c9469128bf39408e91f5573901cb852e03af378d3582c52d" ], "index": "pypi", - "markers": "python_version >= '2.5' and python_version not in '3.0, 3.1, 3.2'", "version": "==3.19.3" }, "six": { @@ -2642,6 +2558,22 @@ ], "version": "==2.2.0" }, + "social-auth-app-django": { + "hashes": [ + "sha256:0c041a31707921aef9a930f143183c65d8c7b364381364a50f3f7c6fcc9d62f6", + "sha256:c8832c6cf13da6ad76f5613bcda2647d89ae7cfbc5217fadd13477a3406feaa8" + ], + "markers": "python_version >= '3.8'", + "version": "==5.4.2" + }, + "social-auth-core": { + "hashes": [ + "sha256:33cf970a623c442376f9d4a86fb187579e4438649daa5b5be993d05e74d7b2db", + "sha256:d3dbeb0999ffd0e68aa4bd73f2ac698a18133fd11b3fc890e1366f18c8889fac" + ], + "markers": "python_version >= '3.8'", + "version": "==4.5.4" + }, "sortedcontainers": { "hashes": [ "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", @@ -2659,11 +2591,11 @@ }, "sphinx": { "hashes": [ - "sha256:6d56a34697bb749ffa0152feafc4b19836c755d90a7c59b72bc7dfd371b9cc6b", - "sha256:97787ff1fa3256a3eef9eda523a63dbf299f7b47e053cfcf684a1c2a8380c912" + "sha256:1e09160a40b956dc623c910118fa636da93bd3ca0b9876a7b3df90f07d691560", + "sha256:9a5160e1ea90688d5963ba09a2dcd8bdd526620edbb65c328728f1b2228d5ab5" ], - "markers": "python_version >= '3.8'", - "version": "==6.2.1" + "markers": "python_version >= '3.9'", + "version": "==7.2.6" }, "sphinx-jsonschema": { "hashes": [ @@ -2674,11 +2606,11 @@ }, "sphinx-rtd-theme": { "hashes": [ - "sha256:01c5c5a72e2d025bd23d1f06c59a4831b06e6ce6c01fdd5ebfe9986c0a880fc7", - "sha256:6a7e7d8af34eb8fc57d52a09c6b6b9c46ff44aea5951bc831eeb9245378f3689" + "sha256:bd5d7b80622406762073a04ef8fadc5f9151261563d47027de09910ce03afe6b", + "sha256:ec93d0856dc280cf3aee9a4c9807c60e027c7f7b461b77aeffed682e68f0e586" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.2.2" + "markers": "python_version >= '3.6'", + "version": "==2.0.0" }, "sphinxcontrib-applehelp": { "hashes": [ @@ -2784,7 +2716,6 @@ "sha256:fc9ffd9a38e21fad3e8c5a88926d57f94a32546e937e0be46142b2702003eba7" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", "version": "==1.4.54" }, "sqlparse": { @@ -2793,7 +2724,6 @@ "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==0.5.1" }, "tabulate": { @@ -2810,24 +2740,14 @@ "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" ], "index": "pypi", - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", "version": "==0.10.2" }, - "tomli": { - "hashes": [ - "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38", - "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed" - ], - "markers": "python_version < '3.11'", - "version": "==2.0.2" - }, "tqdm": { "hashes": [ "sha256:90279a3770753eafc9194a0364852159802111925aa30eb3f9d85b0e805ac7cd", "sha256:e1020aef2e5096702d8a025ac7d16b1577279c9d63f8375b63083e9a5f0fcbad" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==4.66.5" }, "typing-extensions": { @@ -2835,7 +2755,7 @@ "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" ], - "markers": "python_version >= '3.8'", + "index": "pypi", "version": "==4.12.2" }, "tzdata": { @@ -2859,7 +2779,6 @@ "sha256:ea5d4fb8178c2ab469cf4fa46d0ceb16ccb378da46dbbc28a8b9c1eebdccc655" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==0.2.5" }, "uritemplate": { @@ -2887,11 +2806,11 @@ }, "versioneer": { "hashes": [ - "sha256:11ffc09427ac99db4ce61bdc85785dae819618d0de28153adfce3085956125a8", - "sha256:7175ca8e7bb4dd0e3c9779dd2745e5b4a6036304af3f5e50bd896f10196586d6" + "sha256:0f1a137bb5d6811e96a79bb0486798aeae9b9c6efc24b389659cebb0ee396cb9", + "sha256:5ab283b9857211d61b53318b7c792cf68e798e765ee17c27ade9f6c924235731" ], "markers": "python_version >= '3.7'", - "version": "==0.28" + "version": "==0.29" }, "vine": { "hashes": [ @@ -2910,11 +2829,11 @@ }, "wheel": { "hashes": [ - "sha256:cd1196f3faee2b31968d626e1731c94f99cbdb67cf5a46e4f5656cbee7738873", - "sha256:d236b20e7cb522daf2390fa84c55eea81c5c30190f90f29ae2ca1ad8355bf247" + "sha256:177f9c9b0d45c47873b619f5b650346d632cdc35fb5e4d25058e09c9e581433d", + "sha256:c45be39f7882c9d34243236f2d63cbd58039e360f85d0913425fbd7ceea617a8" ], "markers": "python_version >= '3.7'", - "version": "==0.40.0" + "version": "==0.42.0" }, "wrapt": { "hashes": [ @@ -2990,7 +2909,6 @@ "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==1.16.0" }, "xlsxwriter": { @@ -2999,17 +2917,8 @@ "sha256:ecfd5405b3e0e228219bcaf24c2ca0915e012ca9464a14048021d21a995d490e" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==3.2.0" }, - "xmlschema": { - "hashes": [ - "sha256:4f7497de6c8b6dc2c28ad7b9ed6e21d186f4afe248a5bea4f54eedab4da44083", - "sha256:ec2b2a15c8896c1fcd14dcee34ca30032b99456c3c43ce793fdb9dca2fb4b869" - ], - "markers": "python_version >= '3.7'", - "version": "==2.5.1" - }, "xmltodict": { "hashes": [ "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56", @@ -3131,37 +3040,35 @@ "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==24.2.0" }, "black": { "hashes": [ - "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6", - "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e", - "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f", - "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018", - "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e", - "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd", - "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4", - "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed", - "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2", - "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42", - "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af", - "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb", - "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368", - "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb", - "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af", - "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed", - "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47", - "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2", - "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a", - "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c", - "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920", - "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==24.8.0" + "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474", + "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1", + "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0", + "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8", + "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96", + "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1", + "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04", + "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021", + "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94", + "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d", + "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c", + "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7", + "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c", + "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc", + "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7", + "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d", + "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c", + "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741", + "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce", + "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb", + "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063", + "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e" + ], + "index": "pypi", + "version": "==24.4.2" }, "certifi": { "hashes": [ @@ -3362,7 +3269,6 @@ "sha256:7b2a0a2bcef94f295e3cf28dcc55ca40b71c77d1c2446b538e85f0f7bc21aa69" ], "index": "pypi", - "markers": "python_version < '3.13' and python_version >= '3.8'", "version": "==4.0.1" }, "decorator": { @@ -3387,7 +3293,6 @@ "sha256:96e4e16fabd3e0339a4b46e02a0a88c92c19800de38d00446571ea036614d332" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==2.2.4" }, "django-types": { @@ -3396,7 +3301,6 @@ "sha256:b3f529de17f6374d41ca67232aa01330c531bbbaa3ac4097896f31ac33c96c30" ], "index": "pypi", - "markers": "python_version >= '3.7' and python_version < '4.0'", "version": "==0.19.1" }, "docopt": { @@ -3435,7 +3339,6 @@ "sha256:8317aa5289cdfc45f9cae570feb07a6177316c82e34d14df3c2e1f22f26abef0" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==3.3.1" }, "faker": { @@ -3444,7 +3347,6 @@ "sha256:e0593931bd7be9a9ea984b5d8c302ef1cec19392585d1e90d444199271d0a94d" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==30.1.0" }, "fastdiff": { @@ -3460,7 +3362,6 @@ "sha256:597477df7860daa5aa0fdd84bf5208a043ab96b8e96ab708770ae0364dd03213" ], "index": "pypi", - "markers": "python_full_version >= '3.8.1'", "version": "==7.1.1" }, "flake8-import-order": { @@ -3476,7 +3377,6 @@ "sha256:6249fe53545205af5e76837644dc80b4c10037e73a0e5db87ff562d75fb5bd4a" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==1.2.3" }, "freezegun": { @@ -3485,7 +3385,6 @@ "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==1.5.1" }, "future": { @@ -3518,7 +3417,6 @@ "sha256:e3ac6018ef05126d442af680aad863006ec19d02290561ac88b8b1c0b0cfc726" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==0.13.13" }, "ipython": { @@ -3535,7 +3433,6 @@ "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6" ], "index": "pypi", - "markers": "python_full_version >= '3.8.0'", "version": "==5.13.2" }, "jedi": { @@ -3544,7 +3441,6 @@ "sha256:e983c654fe5c02867aef4cdfce5a2fbb4a50adc0af145f70504238f18ef5e7e0" ], "index": "pypi", - "markers": "python_version >= '3.6'", "version": "==0.19.1" }, "jsonmatch": { @@ -3650,7 +3546,6 @@ "sha256:24f3b0aecb06656e983f58e07c732a90577b9d7af3e1066fc2b663bbf0370248" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==3.3.0" }, "openpyxl": { @@ -3659,7 +3554,6 @@ "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==3.1.5" }, "outcome": { @@ -3684,7 +3578,6 @@ "sha256:7fc905272cefa4f364c1a3429cbbe9c0f98b793988efb5bf90aac80f08db09b1" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==0.9.0" }, "parso": { @@ -3753,7 +3646,6 @@ "sha256:f4c42102bc82a51108e449cbb32b19b180022941c727bac0cfd50170341f16ee" ], "index": "pypi", - "markers": "python_version >= '3.7'", "version": "==3.20.3" }, "protolint-bin": { @@ -3821,7 +3713,6 @@ "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==2.9.0.post0" }, "requests": { @@ -3830,7 +3721,6 @@ "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==2.32.3" }, "requests-mock": { @@ -3839,7 +3729,6 @@ "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401" ], "index": "pypi", - "markers": "python_version >= '3.5'", "version": "==1.12.1" }, "selenium": { @@ -3848,16 +3737,15 @@ "sha256:95d08d3b82fb353f3c474895154516604c7f0e6a9a565ae6498ef36c9bac6921" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==4.25.0" }, "setuptools": { "hashes": [ - "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a", - "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078" + "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4", + "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0" ], - "markers": "python_version >= '3.7'", - "version": "==67.6.1" + "markers": "python_version >= '3.8'", + "version": "==70.0.0" }, "six": { "hashes": [ @@ -3903,7 +3791,6 @@ "sha256:93622790a0a29e04f0346458face1e144dc4d32f493714c6c3dff82a4adb77e6" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==3.0.0" }, "termcolor": { @@ -3952,7 +3839,6 @@ "sha256:d181af8a256e5a91ce8d5adb53496e880efd9144c7d54483e3653332b60296f0" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==5.28.0.20240924" }, "types-psycopg2": { @@ -3968,7 +3854,7 @@ "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" ], - "markers": "python_version >= '3.8'", + "index": "pypi", "version": "==4.12.2" }, "uritemplate": { @@ -4059,7 +3945,6 @@ "sha256:f01f4a3565a387080dc49bdd1fefe4ecc77f894991b88ef927edbfa45eb10818" ], "index": "pypi", - "markers": "python_version >= '3.9'", "version": "==5.0.3" }, "wcwidth": { @@ -4083,7 +3968,6 @@ "sha256:34f2371506b250df4d4f84bfe7b0921e4762525762bbd936614909fe25cd7306" ], "index": "pypi", - "markers": "python_version >= '3.8'", "version": "==3.0.4" }, "wsproto": { @@ -4094,412 +3978,5 @@ "markers": "python_full_version >= '3.7.0'", "version": "==1.2.0" } - }, - "ldap-packages": { - "asgiref": { - "hashes": [ - "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", - "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590" - ], - "markers": "python_version >= '3.8'", - "version": "==3.8.1" - }, - "django": { - "hashes": [ - "sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777", - "sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.2.25" - }, - "django-auth-ldap": { - "hashes": [ - "sha256:4b4b944f3c28bce362f33fb6e8db68429ed8fd8f12f0c0c4b1a4344a7ef225ce", - "sha256:604250938ddc9fda619f247c7a59b0b2f06e53a7d3f46a156f28aa30dd71a738" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==4.8.0" - }, - "pyasn1": { - "hashes": [ - "sha256:0d632f46f2ba09143da3a8afe9e33fb6f92fa2320ab7e886e2d0f7672af84629", - "sha256:6f580d2bdd84365380830acf45550f2511469f673cb4a5ae3857a3170128b034" - ], - "markers": "python_version >= '3.8'", - "version": "==0.6.1" - }, - "pyasn1-modules": { - "hashes": [ - "sha256:49bfa96b45a292b711e986f222502c1c9a5e1f4e568fc30e2574a6c7d07838fd", - "sha256:c28e2dbf9c06ad61c71a075c7e0f9fd0f1b0bb2d2ad4377f240d33ac2ab60a7c" - ], - "markers": "python_version >= '3.8'", - "version": "==0.4.1" - }, - "python-ldap": { - "hashes": [ - "sha256:7edb0accec4e037797705f3a05cbf36a9fde50d08c8f67f2aef99a2628fab828" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.4.4" - }, - "sqlparse": { - "hashes": [ - "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4", - "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==0.5.1" - }, - "typing-extensions": { - "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" - ], - "markers": "python_version >= '3.8'", - "version": "==4.12.2" - } - }, - "prod-packages": { - "asgiref": { - "hashes": [ - "sha256:3e1e3ecc849832fe52ccf2cb6686b7a55f82bb1d6aee72a58826471390335e47", - "sha256:c343bd80a0bec947a9860adb4c432ffa7db769836c64238fc34bdc3fec84d590" - ], - "markers": "python_version >= '3.8'", - "version": "==3.8.1" - }, - "async-timeout": { - "hashes": [ - "sha256:4640d96be84d82d02ed59ea2b7105a0f7b33abe8703703cd0ab0bf87c427522f", - "sha256:7405140ff1230c310e51dc27b3145b9092d659ce68ff733fb0cefe3ee42be028" - ], - "markers": "python_full_version < '3.11.3'", - "version": "==4.0.3" - }, - "boto3": { - "hashes": [ - "sha256:291e7b97a34967ed93297e6171f1bebb8529e64633dd48426760e3fdef1cdea8", - "sha256:57e6ee8504e7929bc094bb2afc879943906064179a1e88c23b4812e2c6f61532" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==1.35.34" - }, - "botocore": { - "hashes": [ - "sha256:25b17a9ccba6ad32bb5bf7ba4f52656aa03c1cb29f6b4e438050ee4ad1967a3b", - "sha256:cab9ec4e0367b9f33f0bc02c5a29f587b0119ecffd6d125bacee085dcbc8817d" - ], - "markers": "python_version >= '3.8'", - "version": "==1.35.23" - }, - "django": { - "hashes": [ - "sha256:7ca38a78654aee72378594d63e51636c04b8e28574f5505dff630895b5472777", - "sha256:a52ea7fcf280b16f7b739cec38fa6d3f8953a5456986944c3ca97e79882b4e38" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==3.2.25" - }, - "django-redis": { - "hashes": [ - "sha256:6a02abaa34b0fea8bf9b707d2c363ab6adc7409950b2db93602e6cb292818c42", - "sha256:ebc88df7da810732e2af9987f7f426c96204bf89319df4c6da6ca9a2942edd5b" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==5.4.0" - }, - "django-storages": { - "hashes": [ - "sha256:69aca94d26e6714d14ad63f33d13619e697508ee33ede184e462ed766dc2a73f", - "sha256:d61930acb4a25e3aebebc6addaf946a3b1df31c803a6bf1af2f31c9047febaa3" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==1.14.4" - }, - "gevent": { - "hashes": [ - "sha256:03aa5879acd6b7076f6a2a307410fb1e0d288b84b03cdfd8c74db8b4bc882fc5", - "sha256:117e5837bc74a1673605fb53f8bfe22feb6e5afa411f524c835b2ddf768db0de", - "sha256:141a2b24ad14f7b9576965c0c84927fc85f824a9bb19f6ec1e61e845d87c9cd8", - "sha256:14532a67f7cb29fb055a0e9b39f16b88ed22c66b96641df8c04bdc38c26b9ea5", - "sha256:1dffb395e500613e0452b9503153f8f7ba587c67dd4a85fc7cd7aa7430cb02cc", - "sha256:2955eea9c44c842c626feebf4459c42ce168685aa99594e049d03bedf53c2800", - "sha256:2ae3a25ecce0a5b0cd0808ab716bfca180230112bb4bc89b46ae0061d62d4afe", - "sha256:2e9ac06f225b696cdedbb22f9e805e2dd87bf82e8fa5e17756f94e88a9d37cf7", - "sha256:368a277bd9278ddb0fde308e6a43f544222d76ed0c4166e0d9f6b036586819d9", - "sha256:3adfb96637f44010be8abd1b5e73b5070f851b817a0b182e601202f20fa06533", - "sha256:3d5325ccfadfd3dcf72ff88a92fb8fc0b56cacc7225f0f4b6dcf186c1a6eeabc", - "sha256:432fc76f680acf7cf188c2ee0f5d3ab73b63c1f03114c7cd8a34cebbe5aa2056", - "sha256:44098038d5e2749b0784aabb27f1fcbb3f43edebedf64d0af0d26955611be8d6", - "sha256:5a1df555431f5cd5cc189a6ee3544d24f8c52f2529134685f1e878c4972ab026", - "sha256:6c47ae7d1174617b3509f5d884935e788f325eb8f1a7efc95d295c68d83cce40", - "sha256:6f947a9abc1a129858391b3d9334c45041c08a0f23d14333d5b844b6e5c17a07", - "sha256:782a771424fe74bc7e75c228a1da671578c2ba4ddb2ca09b8f959abdf787331e", - "sha256:7899a38d0ae7e817e99adb217f586d0a4620e315e4de577444ebeeed2c5729be", - "sha256:7b00f8c9065de3ad226f7979154a7b27f3b9151c8055c162332369262fc025d8", - "sha256:8f4b8e777d39013595a7740b4463e61b1cfe5f462f1b609b28fbc1e4c4ff01e5", - "sha256:90cbac1ec05b305a1b90ede61ef73126afdeb5a804ae04480d6da12c56378df1", - "sha256:918cdf8751b24986f915d743225ad6b702f83e1106e08a63b736e3a4c6ead789", - "sha256:9202f22ef811053077d01f43cc02b4aaf4472792f9fd0f5081b0b05c926cca19", - "sha256:94138682e68ec197db42ad7442d3cf9b328069c3ad8e4e5022e6b5cd3e7ffae5", - "sha256:968581d1717bbcf170758580f5f97a2925854943c45a19be4d47299507db2eb7", - "sha256:9d8d0642c63d453179058abc4143e30718b19a85cbf58c2744c9a63f06a1d388", - "sha256:a7ceb59986456ce851160867ce4929edaffbd2f069ae25717150199f8e1548b8", - "sha256:b9913c45d1be52d7a5db0c63977eebb51f68a2d5e6fd922d1d9b5e5fd758cc98", - "sha256:bde283313daf0b34a8d1bab30325f5cb0f4e11b5869dbe5bc61f8fe09a8f66f3", - "sha256:bf5b9c72b884c6f0c4ed26ef204ee1f768b9437330422492c319470954bc4cc7", - "sha256:ca80b121bbec76d7794fcb45e65a7eca660a76cc1a104ed439cdbd7df5f0b060", - "sha256:cdf66977a976d6a3cfb006afdf825d1482f84f7b81179db33941f2fc9673bb1d", - "sha256:d4faf846ed132fd7ebfbbf4fde588a62d21faa0faa06e6f468b7faa6f436b661", - "sha256:d7f87c2c02e03d99b95cfa6f7a776409083a9e4d468912e18c7680437b29222c", - "sha256:dd23df885318391856415e20acfd51a985cba6919f0be78ed89f5db9ff3a31cb", - "sha256:f5de3c676e57177b38857f6e3cdfbe8f38d1cd754b63200c0615eaa31f514b4f", - "sha256:f5e8e8d60e18d5f7fd49983f0c4696deeddaf6e608fbab33397671e2fcc6cc91", - "sha256:f7cac622e11b4253ac4536a654fe221249065d9a69feb6cdcd4d9af3503602e0", - "sha256:f8a04cf0c5b7139bc6368b461257d4a757ea2fe89b3773e494d235b7dd51119f", - "sha256:f8bb35ce57a63c9a6896c71a285818a3922d8ca05d150fd1fe49a7f57287b836", - "sha256:fbfdce91239fe306772faab57597186710d5699213f4df099d1612da7320d682" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==24.2.1" - }, - "greenlet": { - "hashes": [ - "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", - "sha256:03a088b9de532cbfe2ba2034b2b85e82df37874681e8c470d6fb2f8c04d7e4b7", - "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", - "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", - "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", - "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", - "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", - "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9", - "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", - "sha256:1d3755bcb2e02de341c55b4fca7a745a24a9e7212ac953f6b3a48d117d7257aa", - "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942", - "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", - "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441", - "sha256:3319aa75e0e0639bc15ff54ca327e8dc7a6fe404003496e3c6925cd3142e0e22", - "sha256:346bed03fe47414091be4ad44786d1bd8bef0c3fcad6ed3dee074a032ab408a9", - "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", - "sha256:37b9de5a96111fc15418819ab4c4432e4f3c2ede61e660b1e33971eba26ef9ba", - "sha256:396979749bd95f018296af156201d6211240e7a23090f50a8d5d18c370084dc3", - "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", - "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", - "sha256:47da355d8687fd65240c364c90a31569a133b7b60de111c255ef5b606f2ae291", - "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", - "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", - "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", - "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", - "sha256:54558ea205654b50c438029505def3834e80f0869a70fb15b871c29b4575ddef", - "sha256:5e06afd14cbaf9e00899fae69b24a32f2196c19de08fcb9f4779dd4f004e5e7c", - "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", - "sha256:63e4844797b975b9af3a3fb8f7866ff08775f5426925e1e0bbcfe7932059a12c", - "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", - "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", - "sha256:6ef9ea3f137e5711f0dbe5f9263e8c009b7069d8a1acea822bd5e9dae0ae49c8", - "sha256:7017b2be767b9d43cc31416aba48aab0d2309ee31b4dbf10a1d38fb7972bdf9d", - "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01", - "sha256:73aaad12ac0ff500f62cebed98d8789198ea0e6f233421059fa68a5aa7220145", - "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", - "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", - "sha256:7939aa3ca7d2a1593596e7ac6d59391ff30281ef280d8632fa03d81f7c5f955e", - "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", - "sha256:85f3ff71e2e60bd4b4932a043fbbe0f499e263c628390b285cb599154a3b03b1", - "sha256:8b8b36671f10ba80e159378df9c4f15c14098c4fd73a36b9ad715f057272fbef", - "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", - "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", - "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", - "sha256:94ebba31df2aa506d7b14866fed00ac141a867e63143fe5bca82a8e503b36437", - "sha256:95ffcf719966dd7c453f908e208e14cde192e09fde6c7186c8f1896ef778d8cd", - "sha256:98884ecf2ffb7d7fe6bd517e8eb99d31ff7855a840fa6d0d63cd07c037f6a981", - "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36", - "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", - "sha256:a0dfc6c143b519113354e780a50381508139b07d2177cb6ad6a08278ec655798", - "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", - "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", - "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0", - "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", - "sha256:b8da394b34370874b4572676f36acabac172602abf054cbc4ac910219f3340af", - "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", - "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", - "sha256:ca9d0ff5ad43e785350894d97e13633a66e2b50000e8a183a50a88d834752d42", - "sha256:d0028e725ee18175c6e422797c407874da24381ce0690d6b9396c204c7f7276e", - "sha256:d21e10da6ec19b457b82636209cbe2331ff4306b54d06fa04b7c138ba18c8a81", - "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", - "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", - "sha256:db32b5348615a04b82240cc67983cb315309e88d444a288934ee6ceaebcad6cc", - "sha256:dcc62f31eae24de7f8dce72134c8651c58000d3b1868e01392baea7c32c247de", - "sha256:dfc59d69fc48664bc693842bd57acfdd490acafda1ab52c7836e3fc75c90a111", - "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", - "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", - "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", - "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", - "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", - "sha256:f1d4aeb8891338e60d1ab6127af1fe45def5259def8094b9c7e34690c8858803", - "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", - "sha256:f6ff3b14f2df4c41660a7dec01045a045653998784bf8cfcb5a525bdffffbc8f" - ], - "markers": "python_version >= '3' and (platform_machine == 'aarch64' or (platform_machine == 'ppc64le' or (platform_machine == 'x86_64' or (platform_machine == 'amd64' or (platform_machine == 'AMD64' or (platform_machine == 'win32' or platform_machine == 'WIN32'))))))", - "version": "==3.1.1" - }, - "gunicorn": { - "hashes": [ - "sha256:ec400d38950de4dfd418cff8328b2c8faed0edb0d517d3394e457c317908ca4d", - "sha256:f014447a0101dc57e294f6c18ca6b40227a4c90e9bdb586042628030cba004ec" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==23.0.0" - }, - "jmespath": { - "hashes": [ - "sha256:02e2e4cc71b5bcab88332eebf907519190dd9e6e82107fa7f83b1003a6252980", - "sha256:90261b206d6defd58fdd5e85f478bf633a2901798906be2ad389150c5c60edbe" - ], - "markers": "python_version >= '3.7'", - "version": "==1.0.1" - }, - "packaging": { - "hashes": [ - "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5", - "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7" - ], - "markers": "python_version >= '3.7'", - "version": "==23.2" - }, - "python-dateutil": { - "hashes": [ - "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", - "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==2.9.0.post0" - }, - "redis": { - "hashes": [ - "sha256:f6c997521fedbae53387307c5d0bf784d9acc28d9f1d058abeac566ec4dbed72", - "sha256:f8ea06b7482a668c6475ae202ed8d9bcaa409f6e87fb77ed1043d912afd62e24" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==5.1.1" - }, - "s3transfer": { - "hashes": [ - "sha256:0711534e9356d3cc692fdde846b4a1e4b0cb6519971860796e6bc4c7aea00ef6", - "sha256:eca1c20de70a39daee580aef4986996620f365c4e0fda6a86100231d62f1bf69" - ], - "markers": "python_version >= '3.8'", - "version": "==0.10.2" - }, - "setuptools": { - "hashes": [ - "sha256:257de92a9d50a60b8e22abfcbb771571fde0dbf3ec234463212027a4eeecbe9a", - "sha256:e728ca814a823bf7bf60162daf9db95b93d532948c4c0bea762ce62f60189078" - ], - "markers": "python_version >= '3.7'", - "version": "==67.6.1" - }, - "six": { - "hashes": [ - "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", - "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==1.16.0" - }, - "sqlparse": { - "hashes": [ - "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4", - "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==0.5.1" - }, - "typing-extensions": { - "hashes": [ - "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", - "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8" - ], - "markers": "python_version >= '3.8'", - "version": "==4.12.2" - }, - "urllib3": { - "hashes": [ - "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", - "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9" - ], - "markers": "python_version >= '3.8'", - "version": "==2.2.3" - }, - "whitenoise": { - "hashes": [ - "sha256:58c7a6cd811e275a6c91af22e96e87da0b1109e9a53bb7464116ef4c963bf636", - "sha256:a1ae85e01fdc9815d12fa33f17765bc132ed2c54fa76daf9e39e879dd93566f6" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==6.7.0" - }, - "zope.event": { - "hashes": [ - "sha256:2832e95014f4db26c47a13fdaef84cef2f4df37e66b59d8f1f4a8f319a632c26", - "sha256:bac440d8d9891b4068e2b5a2c5e2c9765a9df762944bda6955f96bb9b91e67cd" - ], - "markers": "python_version >= '3.7'", - "version": "==5.0" - }, - "zope.interface": { - "hashes": [ - "sha256:01e6e58078ad2799130c14a1d34ec89044ada0e1495329d72ee0407b9ae5100d", - "sha256:064ade95cb54c840647205987c7b557f75d2b2f7d1a84bfab4cf81822ef6e7d1", - "sha256:11fa1382c3efb34abf16becff8cb214b0b2e3144057c90611621f2d186b7e1b7", - "sha256:1bee1b722077d08721005e8da493ef3adf0b7908e0cd85cc7dc836ac117d6f32", - "sha256:1eeeb92cb7d95c45e726e3c1afe7707919370addae7ed14f614e22217a536958", - "sha256:21a207c6b2c58def5011768140861a73f5240f4f39800625072ba84e76c9da0b", - "sha256:2545d6d7aac425d528cd9bf0d9e55fcd47ab7fd15f41a64b1c4bf4c6b24946dc", - "sha256:2c4316a30e216f51acbd9fb318aa5af2e362b716596d82cbb92f9101c8f8d2e7", - "sha256:35062d93bc49bd9b191331c897a96155ffdad10744ab812485b6bad5b588d7e4", - "sha256:382d31d1e68877061daaa6499468e9eb38eb7625d4369b1615ac08d3860fe896", - "sha256:3aa8fcbb0d3c2be1bfd013a0f0acd636f6ed570c287743ae2bbd467ee967154d", - "sha256:3d4b91821305c8d8f6e6207639abcbdaf186db682e521af7855d0bea3047c8ca", - "sha256:3de1d553ce72868b77a7e9d598c9bff6d3816ad2b4cc81c04f9d8914603814f3", - "sha256:3fcdc76d0cde1c09c37b7c6b0f8beba2d857d8417b055d4f47df9c34ec518bdd", - "sha256:5112c530fa8aa2108a3196b9c2f078f5738c1c37cfc716970edc0df0414acda8", - "sha256:53d678bb1c3b784edbfb0adeebfeea6bf479f54da082854406a8f295d36f8386", - "sha256:6195c3c03fef9f87c0dbee0b3b6451df6e056322463cf35bca9a088e564a3c58", - "sha256:6d04b11ea47c9c369d66340dbe51e9031df2a0de97d68f442305ed7625ad6493", - "sha256:6dd647fcd765030638577fe6984284e0ebba1a1008244c8a38824be096e37fe3", - "sha256:799ef7a444aebbad5a145c3b34bff012b54453cddbde3332d47ca07225792ea4", - "sha256:7d92920416f31786bc1b2f34cc4fc4263a35a407425319572cbf96b51e835cd3", - "sha256:7e0c151a6c204f3830237c59ee4770cc346868a7a1af6925e5e38650141a7f05", - "sha256:84f8794bd59ca7d09d8fce43ae1b571be22f52748169d01a13d3ece8394d8b5b", - "sha256:95e5913ec718010dc0e7c215d79a9683b4990e7026828eedfda5268e74e73e11", - "sha256:9b9369671a20b8d039b8e5a1a33abd12e089e319a3383b4cc0bf5c67bd05fe7b", - "sha256:ab985c566a99cc5f73bc2741d93f1ed24a2cc9da3890144d37b9582965aff996", - "sha256:af94e429f9d57b36e71ef4e6865182090648aada0cb2d397ae2b3f7fc478493a", - "sha256:c96b3e6b0d4f6ddfec4e947130ec30bd2c7b19db6aa633777e46c8eecf1d6afd", - "sha256:cd2690d4b08ec9eaf47a85914fe513062b20da78d10d6d789a792c0b20307fb1", - "sha256:d3b7ce6d46fb0e60897d62d1ff370790ce50a57d40a651db91a3dde74f73b738", - "sha256:d976fa7b5faf5396eb18ce6c132c98e05504b52b60784e3401f4ef0b2e66709b", - "sha256:db6237e8fa91ea4f34d7e2d16d74741187e9105a63bbb5686c61fea04cdbacca", - "sha256:ecd32f30f40bfd8511b17666895831a51b532e93fc106bfa97f366589d3e4e0e", - "sha256:f418c88f09c3ba159b95a9d1cfcdbe58f208443abb1f3109f4b9b12fd60b187c" - ], - "markers": "python_version >= '3.8'", - "version": "==7.0.3" - } } } diff --git a/backend/beaconsite/tests/test_permissions.py b/backend/beaconsite/tests/test_permissions.py index a834747dc..493aa1733 100644 --- a/backend/beaconsite/tests/test_permissions.py +++ b/backend/beaconsite/tests/test_permissions.py @@ -1,5 +1,5 @@ from django.urls import reverse -from projectroles.tests.test_permissions import TestProjectPermissionBase +from projectroles.tests.test_permissions import ProjectPermissionTestBase from beaconsite.tests.factories import ConsortiumFactory, SiteFactory @@ -24,14 +24,14 @@ def setUp(self): ] -class TestIndexView(UsersMixin, TestProjectPermissionBase): +class TestIndexView(UsersMixin, ProjectPermissionTestBase): def test_index(self): url = reverse("beaconsite:index") self.assert_response(url, self.good_users, 200) self.assert_response(url, self.bad_users, 302) -class TestConsortiumViews(UsersMixin, TestProjectPermissionBase): +class TestConsortiumViews(UsersMixin, ProjectPermissionTestBase): def test_list(self): url = reverse("beaconsite:consortium-list") self.assert_response(url, self.good_users, 200) @@ -59,7 +59,7 @@ def test_delete(self): self.assert_response(url, self.bad_users, 302) -class TestSiteViews(UsersMixin, TestProjectPermissionBase): +class TestSiteViews(UsersMixin, ProjectPermissionTestBase): def test_list(self): url = reverse("beaconsite:site-list") self.assert_response(url, self.good_users, 200) diff --git a/backend/beaconsite/tests/test_permissions_ajax.py b/backend/beaconsite/tests/test_permissions_ajax.py index 37641008e..97ea70c7d 100644 --- a/backend/beaconsite/tests/test_permissions_ajax.py +++ b/backend/beaconsite/tests/test_permissions_ajax.py @@ -1,6 +1,6 @@ import cattr from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase import requests_mock from ..models import Site @@ -8,7 +8,7 @@ from .factories import SiteFactory -class TestOrganisationAjaxViews(TestProjectAPIPermissionBase): +class TestOrganisationAjaxViews(ProjectAPIPermissionTestBase): @requests_mock.Mocker() def test_get(self, r_mock): _local_site = SiteFactory(role=Site.LOCAL) # noqa: F841 @@ -57,7 +57,7 @@ def test_get(self, r_mock): self.assert_response(url, bad_users, 302, method="GET") # redirect to login -class TestBeaconQueryAjaxView(TestProjectAPIPermissionBase): +class TestBeaconQueryAjaxView(ProjectAPIPermissionTestBase): @requests_mock.Mocker() def test_get(self, r_mock): _local_site = SiteFactory(role=Site.LOCAL) # noqa: F841 diff --git a/backend/beaconsite/tests/test_permissions_api.py b/backend/beaconsite/tests/test_permissions_api.py index e47925497..4a4aef1f0 100644 --- a/backend/beaconsite/tests/test_permissions_api.py +++ b/backend/beaconsite/tests/test_permissions_api.py @@ -7,7 +7,7 @@ from django.shortcuts import reverse from django.utils import timezone import httpsig -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.tests.factories import SmallVariantFactory @@ -42,7 +42,7 @@ def get_accept_header(self, media_type, version): return {_header_canonical(k): v for k, v in signed_headers_dict.items()} -class TestBeaconInfoApiView(AcceptHeaderMixin, TestProjectAPIPermissionBase): +class TestBeaconInfoApiView(AcceptHeaderMixin, ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.consortium = ConsortiumWithLocalAndRemoteSiteFactory() @@ -110,7 +110,7 @@ def _get_date(): self.get_date = old_get_date -class TestBeaconQueryApiView(AcceptHeaderMixin, TestProjectAPIPermissionBase): +class TestBeaconQueryApiView(AcceptHeaderMixin, ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.consortium = ConsortiumWithLocalAndRemoteSiteFactory() diff --git a/backend/beaconsite/tests/test_views_ajax.py b/backend/beaconsite/tests/test_views_ajax.py index 6d7260c4d..a33fd1fa2 100644 --- a/backend/beaconsite/tests/test_views_ajax.py +++ b/backend/beaconsite/tests/test_views_ajax.py @@ -2,14 +2,14 @@ from django.urls import reverse import jsonmatch -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase import requests_mock RE_UUID4 = re.compile(r"^[0-9a-f-]+$") RE_DATETIME = re.compile(r"^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ$") -class TestBeaconInfoAjaxView(TestProjectAPIPermissionBase): +class TestBeaconInfoAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the AJAX views dealing with Organisation.""" def setUp(self): diff --git a/backend/beaconsite/urls.py b/backend/beaconsite/urls.py index 1d6e97844..262482825 100644 --- a/backend/beaconsite/urls.py +++ b/backend/beaconsite/urls.py @@ -1,87 +1,87 @@ """URL configuration for the ``beaconsite`` app. """ -from django.conf.urls import url +from django.urls import path from . import views, views_ajax, views_api app_name = "beaconsite" ui_urlpatterns = [ - url( - regex=r"^$", + path( + route="", view=views.IndexView.as_view(), name="index", ), - url( - regex=r"^consortium$", + path( + route="consortium/", view=views.ConsortiumListView.as_view(), name="consortium-list", ), - url( - regex=r"^consortium/(?P[0-9a-f-]+)$", + path( + route="consortium//", view=views.ConsortiumDetailView.as_view(), name="consortium-detail", ), - url( - regex=r"^consortium/create/$", + path( + route="consortium/create/", view=views.ConsortiumCreateView.as_view(), name="consortium-create", ), - url( - regex=r"^consortium/update/(?P[0-9a-f-]+)$", + path( + route="consortium/update//", view=views.ConsortiumUpdateView.as_view(), name="consortium-update", ), - url( - regex=r"^consortium/delete/(?P[0-9a-f-]+)$", + path( + route="consortium/delete//", view=views.ConsortiumDeleteView.as_view(), name="consortium-delete", ), - url( - regex=r"^site$", + path( + route="site/", view=views.SiteListView.as_view(), name="site-list", ), - url( - regex=r"^site/(?P[0-9a-f-]+)$", + path( + route="site//", view=views.SiteDetailView.as_view(), name="site-detail", ), - url( - regex=r"^site/create/$", + path( + route="site/create/", view=views.SiteCreateView.as_view(), name="site-create", ), - url( - regex=r"^site/update/(?P[0-9a-f-]+)$", + path( + route="site/update//", view=views.SiteUpdateView.as_view(), name="site-update", ), - url( - regex=r"^site/delete/(?P[0-9a-f-]+)$", + path( + route="site/delete//", view=views.SiteDeleteView.as_view(), name="site-delete", ), ] ajax_urlpatterns = [ - url( - regex=r"^ajax/beacon/info/(?P[0-9a-f-]+)$", + path( + route="ajax/beacon/info//", view=views_ajax.BeaconInfoAjaxView.as_view(), name="ajax-beacon-info", ), - url( - regex=r"^ajax/beacon/query/(?P[0-9a-f-]+)$", + path( + route="ajax/beacon/query//", view=views_ajax.BeaconQueryAjaxView.as_view(), name="ajax-beacon-query", ), ] beacon_api_urlpatterns = [ - url(regex=r"^endpoint/?$", view=views_api.BeaconInfoApiView.as_view(), name="beacon-api-info"), - url( - regex=r"^endpoint/query/?$", + path(route="endpoint", view=views_api.BeaconInfoApiView.as_view(), name="beacon-api-info"), + path( + route="endpoint/query/", view=views_api.BeaconQueryApiView.as_view(), name="beacon-api-query", ), diff --git a/backend/cases/tests/test_permissions.py b/backend/cases/tests/test_permissions.py index c76fd71b0..764e44d4d 100644 --- a/backend/cases/tests/test_permissions.py +++ b/backend/cases/tests/test_permissions.py @@ -1,8 +1,8 @@ from django.urls import reverse -from projectroles.tests.test_permissions import TestProjectPermissionBase +from projectroles.tests.test_permissions import ProjectPermissionTestBase -class TestCasesViews(TestProjectPermissionBase): +class TestCasesViews(ProjectPermissionTestBase): """Permission tests for the ``cases`` views""" def test_entrypoint(self): diff --git a/backend/cases/tests/test_permissions_ajax.py b/backend/cases/tests/test_permissions_ajax.py index 98f00c915..19a79e9dd 100644 --- a/backend/cases/tests/test_permissions_ajax.py +++ b/backend/cases/tests/test_permissions_ajax.py @@ -1,13 +1,13 @@ import json from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.models import Case, CaseComments, CasePhenotypeTerms from variants.tests.factories import CaseCommentsFactory, CaseFactory, CasePhenotypeTermsFactory -class TestCaseAjaxView(TestProjectAPIPermissionBase): +class TestCaseAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``Case``.""" def setUp(self): @@ -94,7 +94,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestCasePhenotypeTermsCreateListAjaxView(TestProjectAPIPermissionBase): +class TestCasePhenotypeTermsCreateListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the create/list API views dealing with ``CasePhenotypeTerms``.""" def setUp(self): @@ -149,7 +149,7 @@ def cleanup(): ) -class TestAnnotationReleaseInfoListAjaxView(TestProjectAPIPermissionBase): +class TestAnnotationReleaseInfoListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the list AJAX views dealing with ``AnnotationReleaseInfo``.""" def setUp(self): @@ -175,7 +175,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSvAnnotationReleaseInfoListAjaxView(TestProjectAPIPermissionBase): +class TestSvAnnotationReleaseInfoListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the list AJAX views dealing with ``SvAnnotationReleaseInfo``.""" def setUp(self): @@ -201,7 +201,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestCasePhenotypeTermsRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestCasePhenotypeTermsRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the retrieve/update/destroy AJAX views dealing with ``CasePhenotypeTerms``.""" def setUp(self): @@ -285,7 +285,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestCaseCommentCreateListAjaxView(TestProjectAPIPermissionBase): +class TestCaseCommentCreateListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the create/list API views dealing with ``CaseComment``.""" def setUp(self): @@ -333,7 +333,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestCaseCommentRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestCaseCommentRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the retrieve/update/destroy AJAX views dealing with ``CaseComment``.""" def setUp(self): @@ -413,7 +413,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestCaseGeneAnnotationListAjaxView(TestProjectAPIPermissionBase): +class TestCaseGeneAnnotationListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``CaseGeneAnnotation``.""" def setUp(self): @@ -439,7 +439,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestProjectUserPermissionsAjaxView(TestProjectAPIPermissionBase): +class TestProjectUserPermissionsAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the API views returning permissions.""" def setUp(self): @@ -462,7 +462,7 @@ def test_list(self): self.assert_response(url, good_users, 200, method="GET") -class TestCaseAlignmentStatsListAjaxView(TestProjectAPIPermissionBase): +class TestCaseAlignmentStatsListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``CaseAlignmentStats``.""" def setUp(self): @@ -488,7 +488,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSampleVariantStatisticsListAjaxView(TestProjectAPIPermissionBase): +class TestSampleVariantStatisticsListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``SampleVariantStatistics``.""" def setUp(self): @@ -514,7 +514,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestPedigreeRelatednessListAjaxView(TestProjectAPIPermissionBase): +class TestPedigreeRelatednessListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``PedigreeRelatedness``.""" def setUp(self): diff --git a/backend/cases/tests/test_permissions_api.py b/backend/cases/tests/test_permissions_api.py index d2f93c8ea..036381772 100644 --- a/backend/cases/tests/test_permissions_api.py +++ b/backend/cases/tests/test_permissions_api.py @@ -1,13 +1,13 @@ import json from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.models import Case, CaseComments, CasePhenotypeTerms from variants.tests.factories import CaseCommentsFactory, CaseFactory, CasePhenotypeTermsFactory -class TestCaseApiView(TestProjectAPIPermissionBase): +class TestCaseApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``Case``.""" def setUp(self): @@ -102,7 +102,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestCasePhenotypeTermsCreateListAjaxView(TestProjectAPIPermissionBase): +class TestCasePhenotypeTermsCreateListAjaxView(ProjectAPIPermissionTestBase): """Permission tests for the create/list API views dealing with ``CasePhenotypeTerms``.""" def setUp(self): @@ -153,7 +153,7 @@ def cleanup(): ) -class TestCasePhenotypeTermsRetrieveUpdateDestroyApiView(TestProjectAPIPermissionBase): +class TestCasePhenotypeTermsRetrieveUpdateDestroyApiView(ProjectAPIPermissionTestBase): """Permission tests for the retrieve/update/destroy AJAX views dealing with ``CasePhenotypeTerms``.""" def setUp(self): @@ -235,7 +235,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestAnnotationReleaseInfoListApiView(TestProjectAPIPermissionBase): +class TestAnnotationReleaseInfoListApiView(ProjectAPIPermissionTestBase): """Permission tests for the list API views dealing with ``AnnotationReleaseInfo``.""" def setUp(self): @@ -261,7 +261,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSvAnnotationReleaseInfoListApiView(TestProjectAPIPermissionBase): +class TestSvAnnotationReleaseInfoListApiView(ProjectAPIPermissionTestBase): """Permission tests for the list API views dealing with ``SvAnnotationReleaseInfo``.""" def setUp(self): @@ -287,7 +287,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestCaseCommentCreateListApiView(TestProjectAPIPermissionBase): +class TestCaseCommentCreateListApiView(ProjectAPIPermissionTestBase): """Permission tests for the create/list API views dealing with ``CaseComment``.""" def setUp(self): @@ -337,7 +337,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestCaseCommentRetrieveUpdateDestroyApiView(TestProjectAPIPermissionBase): +class TestCaseCommentRetrieveUpdateDestroyApiView(ProjectAPIPermissionTestBase): """Permission tests for the retrieve/update/destroy API views dealing with ``CaseComment``.""" def setUp(self): @@ -419,7 +419,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestCaseGeneAnnotationListApiView(TestProjectAPIPermissionBase): +class TestCaseGeneAnnotationListApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``CaseGeneAnnotation``.""" def setUp(self): @@ -445,7 +445,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestCaseAlignmentStatsListApiView(TestProjectAPIPermissionBase): +class TestCaseAlignmentStatsListApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``CaseAlignmentStats``.""" def setUp(self): @@ -471,7 +471,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSampleVariantStatisticsListApiView(TestProjectAPIPermissionBase): +class TestSampleVariantStatisticsListApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``SampleVariantStatistics``.""" def setUp(self): @@ -497,7 +497,7 @@ def test_list(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestPedigreeRelatednessListApiView(TestProjectAPIPermissionBase): +class TestPedigreeRelatednessListApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``PedigreeRelatedness``.""" def setUp(self): diff --git a/backend/cases/tests/test_views.py b/backend/cases/tests/test_views.py index 7edcc9203..17095b385 100644 --- a/backend/cases/tests/test_views.py +++ b/backend/cases/tests/test_views.py @@ -1,8 +1,8 @@ from django.urls import reverse -from projectroles.tests.test_permissions import TestProjectPermissionBase +from projectroles.tests.test_permissions import ProjectPermissionTestBase -class TestCasesViews(TestProjectPermissionBase): +class TestCasesViews(ProjectPermissionTestBase): """Tests for the ``cases`` views""" def test_entrypoint(self): diff --git a/backend/cases/tests/test_views_ajax.py b/backend/cases/tests/test_views_ajax.py index 838376c83..3e7965c1c 100644 --- a/backend/cases/tests/test_views_ajax.py +++ b/backend/cases/tests/test_views_ajax.py @@ -5,7 +5,7 @@ from django.conf import settings from django.urls import reverse import jsonmatch -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from cases.tests.factories import ( BAM_STATS_SAMPLE, @@ -38,7 +38,7 @@ TIMEF = settings.REST_FRAMEWORK["DATETIME_FORMAT"] -class TestCaseListAjaxView(TestProjectAPIPermissionBase): +class TestCaseListAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -147,7 +147,7 @@ def test_get_querylimit(self): self.assertEqual(response.status_code, 200) -class TestCaseRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestCaseRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -225,7 +225,7 @@ def test_destroy_case_no_roles(self): self._test_destroy_case_base(self.user_no_roles, allowed=False) -class TestCasePhenotypeTermsListCreateAjaxView(TestProjectAPIPermissionBase): +class TestCasePhenotypeTermsListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -290,7 +290,7 @@ def test_post(self): self.assertEqual(CasePhenotypeTerms.objects.count(), 1) -class TestCasePhenotypeTermsRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestCasePhenotypeTermsRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -360,7 +360,7 @@ def test_delete(self): self.assertEqual(CasePhenotypeTerms.objects.count(), 0) -class TestCaseCommentListCreateAjaxView(TestProjectAPIPermissionBase): +class TestCaseCommentListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.casecomment = CaseCommentsFactory(case__project=self.project) @@ -414,7 +414,7 @@ def test_post(self): self.assertEqual(CaseComments.objects.count(), 2) -class TestCaseCommentRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestCaseCommentRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.casecomment = CaseCommentsFactory( @@ -485,7 +485,7 @@ def test_delete(self): self.assertEqual(CaseComments.objects.count(), 0) -class TestCaseGeneAnnotationListAjaxView(TestProjectAPIPermissionBase): +class TestCaseGeneAnnotationListAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case_gene_annotation = CaseGeneAnnotationEntryFactory(case__project=self.project) @@ -513,7 +513,7 @@ def test_get(self): expected0.assert_matches(res_json[0]) -class TestProjectUserPermissionsAjaxView(TestProjectAPIPermissionBase): +class TestProjectUserPermissionsAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -596,7 +596,7 @@ def test_get_with_other_users(self): self.assertEqual(response.data, expected_perms, f"user={user}") -class TestCaseAlignmentStatsListApiView(TestProjectAPIPermissionBase): +class TestCaseAlignmentStatsListApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.casealignmentstats = CaseAlignmentStatsFactory(case__project=self.project) @@ -624,7 +624,7 @@ def test_get(self): ) -class TestSampleVariantStatisticsListApiView(TestProjectAPIPermissionBase): +class TestSampleVariantStatisticsListApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case, variant_set, _ = CaseWithVariantSetFactory.get("small", project=self.project) @@ -664,7 +664,7 @@ def test_get(self): ) -class TestPedigreeRelatednessListApiView(TestProjectAPIPermissionBase): +class TestPedigreeRelatednessListApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.pedigreerelatedness = PedigreeRelatednessFactory( diff --git a/backend/cases/urls.py b/backend/cases/urls.py index 2e2ee005f..728034379 100644 --- a/backend/cases/urls.py +++ b/backend/cases/urls.py @@ -1,152 +1,152 @@ -from django.conf.urls import url +from django.urls import path from cases import views, views_ajax, views_api app_name = "cases" ui_urlpatterns = [ - url( - regex=r"^vueapp/(?P[0-9a-f-]+)/?$", + path( + route="vueapp//", view=views.EntrypointView.as_view(), name="entrypoint", ), ] ajax_urlpatterns = [ - url( - regex=r"^ajax/case/list/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case/list//", view=views_ajax.CaseListAjaxView.as_view(), name="ajax-case-list", ), - url( - regex=r"^ajax/case/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case/retrieve-update-destroy//", view=views_ajax.CaseRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-case-retrieveupdatedestroy", ), - url( - regex=r"^ajax/case-comment/list-create/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-comment/list-create//", view=views_ajax.CaseCommentListCreateAjaxView.as_view(), name="ajax-casecomment-listcreate", ), - url( - regex=r"^ajax/case-comment/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-comment/retrieve-update-destroy//", view=views_ajax.CaseCommentRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-casecomment-retrieveupdatedestroy", ), - url( - regex=r"^ajax/case-phenotype-terms/list-create/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-phenotype-terms/list-create//", view=views_ajax.CasePhenotypeTermsListCreateAjaxView.as_view(), name="ajax-casephenotypeterms-listcreate", ), - url( - regex=r"^ajax/case-phenotype-terms/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-phenotype-terms/retrieve-update-destroy//", view=views_ajax.CasePhenotypeTermsRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-casephenotypeterms-retrieveupdatedestroy", ), - url( - regex=r"^ajax/annotation-release-info/list/(?P[0-9a-f-]+)/?$", + path( + route="ajax/annotation-release-info/list//", view=views_ajax.AnnotationReleaseInfoAjaxView.as_view(), name="ajax-annotationreleaseinfo-list", ), - url( - regex=r"^ajax/sv-annotation-release-info/list/(?P[0-9a-f-]+)/?$", + path( + route="ajax/sv-annotation-release-info/list//", view=views_ajax.SvAnnotationReleaseInfoAjaxView.as_view(), name="ajax-svannotationreleaseinfo-list", ), - url( - regex=r"^ajax/case-gene-annotation/list/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-gene-annotation/list//", view=views_ajax.CaseGeneAnnotationListAjaxView.as_view(), name="ajax-casegeneannotation-list", ), - url( - regex=r"ajax/user-permissions/(?P[0-9a-f-]+)/?$", + path( + route="ajax/user-permissions//", view=views_ajax.ProjectUserPermissionsAjaxView.as_view(), name="ajax-userpermissions", ), - url( - regex=r"^ajax/case-alignment-stats/list/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-alignment-stats/list//", view=views_ajax.CaseAlignmentStatsListAjaxView.as_view(), name="ajax-casealignmentstats-list", ), - url( - regex=r"^ajax/case-variant-stats/list/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-variant-stats/list//", view=views_ajax.SampleVariantStatisticsListAjaxView.as_view(), name="ajax-casevariantstats-list", ), - url( - regex=r"^ajax/case-relatedness/list/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-relatedness/list//", view=views_ajax.PedigreeRelatednessListAjaxView.as_view(), name="ajax-caserelatedness-list", ), ] api_urlpatterns = [ - url( - regex=r"^api/case/count/(?P[0-9a-f-]+)/?$", + path( + route="api/case/count//", view=views_api.CaseCountApiView.as_view(), name="api-case-count", ), - url( - regex=r"^api/case/list/(?P[0-9a-f-]+)/?$", + path( + route="api/case/list//", view=views_api.CaseListApiView.as_view(), name="api-case-list", ), - url( - regex=r"^api/case/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + route="api/case/retrieve-update-destroy//", view=views_api.CaseRetrieveUpdateDestroyApiView.as_view(), name="api-case-retrieveupdatedestroy", ), - url( - regex=r"^api/case-comment/list-create/(?P[0-9a-f-]+)/?$", + path( + route="api/case-comment/list-create//", view=views_api.CaseCommentListCreateApiView.as_view(), name="api-casecomment-listcreate", ), - url( - regex=r"^ajax/case-comment/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + route="ajax/case-comment/retrieve-update-destroy//", view=views_api.CaseCommentRetrieveUpdateDestroyApiView.as_view(), name="api-casecomment-retrieveupdatedestroy", ), - url( - regex=r"^api/case-phenotype-terms/list-create/(?P[0-9a-f-]+)/?$", + path( + route="api/case-phenotype-terms/list-create//", view=views_api.CasePhenotypeTermsListCreateApiView.as_view(), name="api-casephenotypeterms-listcreate", ), - url( - regex=r"^api/case-phenotype-terms/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + route="api/case-phenotype-terms/retrieve-update-destroy//", view=views_api.CasePhenotypeTermsRetrieveUpdateDestroyApiView.as_view(), name="api-casephenotypeterms-retrieveupdatedestroy", ), - url( - regex=r"^api/annotation-release-info/list/(?P[0-9a-f-]+)/?$", + path( + route="api/annotation-release-info/list//", view=views_api.AnnotationReleaseInfoApiView.as_view(), name="api-annotationreleaseinfo-list", ), - url( - regex=r"^api/sv-annotation-release-info/list/(?P[0-9a-f-]+)/?$", + path( + route="api/sv-annotation-release-info/list//", view=views_api.SvAnnotationReleaseInfoApiView.as_view(), name="api-svannotationreleaseinfo-list", ), - url( - regex=r"^api/case-gene-annotation/list/(?P[0-9a-f-]+)/?$", + path( + route="api/case-gene-annotation/list//", view=views_ajax.CaseGeneAnnotationListAjaxView.as_view(), name="api-casegeneannotation-list", ), - url( - regex=r"^api/case-alignment-stats/list/(?P[0-9a-f-]+)/?$", + path( + route="api/case-alignment-stats/list//", view=views_ajax.CaseAlignmentStatsListAjaxView.as_view(), name="api-casealignmentstats-list", ), - url( - regex=r"^api/case-variant-stats/list/(?P[0-9a-f-]+)/?$", + path( + route="api/case-variant-stats/list//", view=views_ajax.SampleVariantStatisticsListAjaxView.as_view(), name="api-casevariantstats-list", ), - url( - regex=r"^api/case-relatedness/list/(?P[0-9a-f-]+)/?$", + path( + route="api/case-relatedness/list//", view=views_ajax.PedigreeRelatednessListAjaxView.as_view(), name="api-caserelatedness-list", ), - url( - regex=r"^api/user-and-global-settings/?$", + path( + route="api/user-and-global-settings/", view=views_api.UserAndGlobalSettingsView.as_view(), name="api-userandglobalsettings", ), diff --git a/backend/cases_analysis/tests/test_permissions_api.py b/backend/cases_analysis/tests/test_permissions_api.py index 4d7a10ffc..8ba4119e8 100644 --- a/backend/cases_analysis/tests/test_permissions_api.py +++ b/backend/cases_analysis/tests/test_permissions_api.py @@ -1,11 +1,11 @@ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from cases_analysis.tests.factories import CaseAnalysisFactory, CaseAnalysisSessionFactory from variants.tests.factories import CaseFactory -class TestCaseAnalysisViewSet(TestProjectAPIPermissionBase): +class TestCaseAnalysisViewSet(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``Case``.""" def setUp(self): @@ -52,7 +52,7 @@ def test_retrieve(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestCasenalysisSessionViewSet(TestProjectAPIPermissionBase): +class TestCasenalysisSessionViewSet(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``Case``.""" def setUp(self): diff --git a/backend/cases_import/models/executors.py b/backend/cases_import/models/executors.py index f539cfc3d..512f8cd7b 100644 --- a/backend/cases_import/models/executors.py +++ b/backend/cases_import/models/executors.py @@ -136,7 +136,7 @@ def __init__(self, project: Project): def _build_fs_options(self, project: Project) -> FileSystemOptions: """Build `FileSystemOptions` from project settings.""" app_settings = AppSettingAPI() - kwargs = {"app_name": "cases_import", "project": project} + kwargs = {"plugin_name": "cases_import", "project": project} path = app_settings.get(setting_name="import_data_path", **kwargs) or None if not path: diff --git a/backend/cases_import/tests/test_models_executor.py b/backend/cases_import/tests/test_models_executor.py index 51eb40ad9..1abac3c63 100644 --- a/backend/cases_import/tests/test_models_executor.py +++ b/backend/cases_import/tests/test_models_executor.py @@ -51,7 +51,7 @@ def _setUpExecutor(self, action, fac_kwargs=None): app_settings = AppSettingAPI() app_settings.set( - app_name="cases_import", + plugin_name="cases_import", setting_name="import_data_protocol", value="file", project=self.project, diff --git a/backend/cases_import/tests/test_permissions_api.py b/backend/cases_import/tests/test_permissions_api.py index ea3243383..690688f55 100644 --- a/backend/cases_import/tests/test_permissions_api.py +++ b/backend/cases_import/tests/test_permissions_api.py @@ -5,7 +5,7 @@ """ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from cases_import.models.base import CaseImportAction from cases_import.proto import family_payload_with_updated_case_name @@ -13,7 +13,7 @@ from variants.tests.factories import CaseFactory -class CaseImportActionApiPermissionTest(TestProjectAPIPermissionBase): +class CaseImportActionApiPermissionTest(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.maxDiff = None diff --git a/backend/cases_qc/tests/test_permissions_api.py b/backend/cases_qc/tests/test_permissions_api.py index f615d3e32..9dbebe2c0 100644 --- a/backend/cases_qc/tests/test_permissions_api.py +++ b/backend/cases_qc/tests/test_permissions_api.py @@ -1,10 +1,10 @@ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from cases_qc.tests.factories import CaseQcFactory -class TestCaseQcRetrieveApiView(TestProjectAPIPermissionBase): +class TestCaseQcRetrieveApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``CaseQc``.""" def setUp(self): @@ -32,7 +32,7 @@ def test_retrieve(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestVarfishStatsRetrieveApiView(TestProjectAPIPermissionBase): +class TestVarfishStatsRetrieveApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``VarfishStats``.""" def setUp(self): diff --git a/backend/cases_qc/tests/test_views_api.py b/backend/cases_qc/tests/test_views_api.py index ada8e82e4..87eccfc84 100644 --- a/backend/cases_qc/tests/test_views_api.py +++ b/backend/cases_qc/tests/test_views_api.py @@ -91,7 +91,7 @@ def _setUpExecutor(self, fac_kwargs: typing.Dict[str, str]): app_settings = AppSettingAPI() app_settings.set( - app_name="cases_import", + plugin_name="cases_import", setting_name="import_data_protocol", value="file", project=self.project, diff --git a/backend/cohorts/migrations/0008_alter_cohort_user.py b/backend/cohorts/migrations/0008_alter_cohort_user.py new file mode 100644 index 000000000..93b4c0557 --- /dev/null +++ b/backend/cohorts/migrations/0008_alter_cohort_user.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.16 on 2024-10-07 12:53 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("cohorts", "0007_alter_cohort_cases"), + ] + + operations = [ + migrations.AlterField( + model_name="cohort", + name="user", + field=models.ForeignKey( + blank=True, + help_text="User who created the cohorts", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(app_label)s_%(class)s_related", + to=settings.AUTH_USER_MODEL, + ), + ), + ] diff --git a/backend/cohorts/tests/test_permissions_ajax.py b/backend/cohorts/tests/test_permissions_ajax.py index 4a081c9ad..d33e69408 100644 --- a/backend/cohorts/tests/test_permissions_ajax.py +++ b/backend/cohorts/tests/test_permissions_ajax.py @@ -1,12 +1,12 @@ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from cohorts.models import CohortCase from cohorts.tests.factories import CohortCaseFactory, CohortFactory from variants.tests.factories import CaseFactory -class TestCohortApiView(TestProjectAPIPermissionBase): +class TestCohortApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``Case``.""" def setUp(self): @@ -98,7 +98,7 @@ def restore_cohort(): self.assert_response(url, bad_users, 403, method="DELETE") -class TestAccessibleProjectsCasesApiView(TestProjectAPIPermissionBase): +class TestAccessibleProjectsCasesApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views listing accessible projects included cases.""" def setUp(self): @@ -123,7 +123,7 @@ def test_list(self): self.assert_response(url, bad_users, 403, method="GET") -class TestCohortCaseApiView(TestProjectAPIPermissionBase): +class TestCohortCaseApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``CohortCase``.""" def setUp(self): diff --git a/backend/cohorts/tests/test_permissions_api.py b/backend/cohorts/tests/test_permissions_api.py index d46c1b9ac..df6ef13bc 100644 --- a/backend/cohorts/tests/test_permissions_api.py +++ b/backend/cohorts/tests/test_permissions_api.py @@ -1,12 +1,12 @@ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from cohorts.models import CohortCase from cohorts.tests.factories import CohortCaseFactory, CohortFactory from variants.tests.factories import CaseFactory -class TestCohortApiView(TestProjectAPIPermissionBase): +class TestCohortApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``Case``.""" def setUp(self): @@ -105,7 +105,7 @@ def restore_cohort(): self.assert_response_api(url, bad_users_403, 403, method="DELETE") -class TestAccessibleProjectsCasesApiView(TestProjectAPIPermissionBase): +class TestAccessibleProjectsCasesApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views listing accessible projects included cases.""" def setUp(self): @@ -134,7 +134,7 @@ def test_list(self): self.assert_response_api(url, bad_users_403, 403, method="GET") -class TestCohortCaseApiView(TestProjectAPIPermissionBase): +class TestCohortCaseApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``CohortCase``.""" def setUp(self): diff --git a/backend/cohorts/tests/test_views_ui.py b/backend/cohorts/tests/test_views_ui.py index 8a149a459..ebf9864b8 100644 --- a/backend/cohorts/tests/test_views_ui.py +++ b/backend/cohorts/tests/test_views_ui.py @@ -1,8 +1,8 @@ -# from variants.tests.test_ui import TestUIBase +# from variants.tests.test_ui import UITestBase # # # TODO -# class TestEntrypointView(TestUIBase): +# class TestEntrypointView(UITestBase): # """Tests for cohorts entrypoint view.""" # # view = "cohorts:entrypoint" diff --git a/backend/cohorts/urls.py b/backend/cohorts/urls.py index c6ea11f69..00b9d85d9 100644 --- a/backend/cohorts/urls.py +++ b/backend/cohorts/urls.py @@ -1,85 +1,85 @@ """URL configuration for the ``importer`` app. """ -from django.conf.urls import url +from django.urls import path from . import views, views_ajax, views_api app_name = "cohorts" ui_urlpatterns = [ - url( - regex=r"^vueapp/(?P[0-9a-f-]+)/?$", + path( + "vueapp//", view=views.EntrypointView.as_view(), name="entrypoint", ), ] ajax_urlpatterns = [ - url( - regex=r"^ajax/cohort/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/cohort/list-create//", view=views_ajax.CohortListCreateAjaxView.as_view(), name="ajax-cohort-list-create", ), - url( - regex=r"^ajax/cohort/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/cohort/retrieve-update-destroy//", view=views_ajax.CohortRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-cohort-retrieve-update-destroy", ), - url( - regex=r"^ajax/cohortcase/create/(?P[0-9a-f-]+)/?$", + path( + "ajax/cohortcase/create//", view=views_ajax.CohortCaseCreateAjaxView.as_view(), name="ajax-cohortcase-create", ), - url( - regex=r"^ajax/cohortcase/list/(?P[0-9a-f-]+)/?$", + path( + "ajax/cohortcase/list//", view=views_ajax.CohortCaseListAjaxView.as_view(), name="ajax-cohortcase-list", ), - url( - regex=r"^ajax/cohortcase/destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/cohortcase/destroy//", view=views_ajax.CohortCaseDestroyAjaxView.as_view(), name="ajax-cohortcase-destroy", ), - url( - regex=r"^ajax/accessible-projects-cases/list/(?P[0-9a-f-]+)/?$", + path( + "ajax/accessible-projects-cases/list//", view=views_ajax.AccessibleProjectsCasesAjaxView.as_view(), name="ajax-accessible-projects-cases-list", ), - url( - regex=r"ajax/user-permissions/(?P[0-9a-f-]+)/?$", + path( + "ajax/user-permissions//", view=views_ajax.ProjectUserPermissionsAjaxView.as_view(), name="ajax-userpermissions", ), ] api_urlpatterns = [ - url( - regex=r"^api/cohort/list-create/(?P[0-9a-f-]+)/?$", + path( + "api/cohort/list-create//", view=views_api.CohortListCreateApiView.as_view(), name="api-cohort-list-create", ), - url( - regex=r"^api/cohort/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "api/cohort/retrieve-update-destroy//", view=views_api.CohortRetrieveUpdateDestroyApiView.as_view(), name="api-cohort-retrieve-update-destroy", ), - url( - regex=r"^api/cohortcase/create/(?P[0-9a-f-]+)/?$", + path( + "api/cohortcase/create//", view=views_api.CohortCaseCreateApiView.as_view(), name="api-cohortcase-create", ), - url( - regex=r"^api/cohortcase/list/(?P[0-9a-f-]+)/?$", + path( + "api/cohortcase/list//", view=views_api.CohortCaseListApiView.as_view(), name="api-cohortcase-list", ), - url( - regex=r"^api/cohortcase/destroy/(?P[0-9a-f-]+)/?$", + path( + "api/cohortcase/destroy//", view=views_api.CohortCaseDestroyApiView.as_view(), name="api-cohortcase-destroy", ), - url( - regex=r"^api/accessible-projects-cases/list/(?P[0-9a-f-]+)/?$", + path( + "api/accessible-projects-cases/list//", view=views_api.AccessibleProjectsCasesApiView.as_view(), name="api-accessible-projects-cases-list", ), diff --git a/backend/config/settings/base.py b/backend/config/settings/base.py index ea570342e..6a632fbe0 100644 --- a/backend/config/settings/base.py +++ b/backend/config/settings/base.py @@ -77,11 +77,12 @@ "markupfield", "rest_framework", "knox", + "social_django", # For OIDC authentication "aldjemy", "adminalerts", + "projectroles.apps.ProjectrolesConfig", "appalerts.apps.AppalertsConfig", "userprofile.apps.UserprofileConfig", - "projectroles.apps.ProjectrolesConfig", "timeline.apps.TimelineConfig", "siteinfo.apps.SiteinfoConfig", "docs", # For the online user documentation/manual @@ -89,7 +90,6 @@ "dal_select2", "cryptographic_fields", "rest_framework_httpsignature", - "django_saml2_auth", "dj_iconify.apps.DjIconifyConfig", "drf_spectacular", "drf_spectacular_sidecar", @@ -435,7 +435,7 @@ # Location of root django.contrib.admin URL, use {% url 'admin:index' %} -ADMIN_URL = r"^admin/" +ADMIN_URL = "admin/" # Celery # ------------------------------------------------------------------------------ @@ -861,85 +861,36 @@ def set_logging(level): DJANGO_SU_CUSTOM_LOGIN_ACTION = None -# SAML configuration +# OpenID Connect (OIDC) configuration # ------------------------------------------------------------------------------ +ENABLE_OIDC = env.bool("ENABLE_OIDC", False) -ENABLE_SAML = env.bool("ENABLE_SAML", False) -SAML2_AUTH = { - # Required setting - # - # Pysaml2 Saml client settings, cf. - # https://pysaml2.readthedocs.io/en/latest/howto/config.html - "SAML_CLIENT_SETTINGS": { - # The optional entity ID string to be passed in the 'Issuer' - # element of authn request, if required by the IDP. - "entityid": env.str("SAML_CLIENT_ENTITY_ID", "SODARcore"), - "entitybaseurl": env.str("SAML_CLIENT_ENTITY_URL", "https://localhost:8000"), - "metadata": { - "local": [ - env.str( - "SAML_CLIENT_METADATA_FILE", "metadata.xml" - ), # The auto(dynamic) metadata configuration URL of SAML2 - ], - }, - "service": { - "sp": { - "idp": env.str( - "SAML_CLIENT_IDP", - "https://sso.hpc.bihealth.org/auth/realms/cubi", - ), - # Keycloak expects client signature - "authn_requests_signed": "true", - # Enforce POST binding which is required by keycloak - "binding": "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", - }, - }, - "key_file": env.str("SAML_CLIENT_KEY_FILE", "key.pem"), - "cert_file": env.str("SAML_CLIENT_CERT_FILE", "cert.pem"), - "xmlsec_binary": env.str("SAML_CLIENT_XMLSEC1", "/usr/bin/xmlsec1"), - "encryption_keypairs": [ - { - "key_file": env.str("SAML_CLIENT_KEY_FILE", "key.pem"), - "cert_file": env.str("SAML_CLIENT_CERT_FILE", "cert.pem"), - } - ], - }, - # Custom target redirect URL after the user get logged in. Default to - # /admin if not set. This setting will be overwritten if you have parameter - # ?next= specificed in the login URL. - "DEFAULT_NEXT_URL": "/", - # Optional settings - "NEW_USER_PROFILE": { - "USER_GROUPS": env.list("SAML_NEW_USER_GROUPS", default=[]), - "ACTIVE_STATUS": env.bool("SAML_NEW_USER_ACTIVE_STATUS", True), - "STAFF_STATUS": env.bool("SAML_NEW_USER_STAFF_STATUS", True), - "SUPERUSER_STATUS": env.bool("SAML_NEW_USER_SUPERUSER_STATUS", False), - }, - "ATTRIBUTES_MAP": env.dict( - "SAML_ATTRIBUTES_MAP", - default={ - "email": "urn:oid:1.2.840.113549.1.9.1", - "username": "username", - "first_name": "urn:oid:2.5.4.42", - "last_name": "urn:oid:2.5.4.4", - }, - ), - # Optional SAML Trigger - # Very unlikely to be needed in configuration, since it requires - # changes to the codebase - # 'TRIGGER': { - # 'FIND_USER': 'path.to.your.find.user.hook.method', - # 'NEW_USER': 'path.to.your.new.user.hook.method', - # 'CREATE_USER': 'path.to.your.create.user.hook.method', - # 'BEFORE_LOGIN': 'path.to.your.login.hook.method', - # }, -} - -# 'ASSERTION_URL': 'https://your.url.here', # Custom URL to validate incoming SAML requests against -assertion_url = env.str("SAML_ASSERTION_URL", None) -if assertion_url is not None: - SAML2_AUTH = {**SAML2_AUTH, **{"ASSERTION_URL": assertion_url}} +if ENABLE_OIDC: + AUTHENTICATION_BACKENDS = tuple( + itertools.chain( + ("social_core.backends.open_id_connect.OpenIdConnectAuth",), + AUTHENTICATION_BACKENDS, + ) + ) + TEMPLATES[0]["OPTIONS"]["context_processors"] += [ + "social_django.context_processors.backends", + "social_django.context_processors.login_redirect", + ] + SOCIAL_AUTH_JSONFIELD_ENABLED = True + SOCIAL_AUTH_JSONFIELD_CUSTOM = "django.db.models.JSONField" + SOCIAL_AUTH_USER_MODEL = AUTH_USER_MODEL + SOCIAL_AUTH_ADMIN_USER_SEARCH_FIELDS = [ + "username", + "name", + "first_name", + "last_name", + "email", + ] + SOCIAL_AUTH_OIDC_OIDC_ENDPOINT = env.str("SOCIAL_AUTH_OIDC_OIDC_ENDPOINT", None) + SOCIAL_AUTH_OIDC_KEY = env.str("SOCIAL_AUTH_OIDC_KEY", "CHANGEME") + SOCIAL_AUTH_OIDC_SECRET = env.str("SOCIAL_AUTH_OIDC_SECRET", "CHANGEME") + SOCIAL_AUTH_OIDC_USERNAME_KEY = env.str("SOCIAL_AUTH_OIDC_USERNAME_KEY", "username") # STORAGE CONFIGURATION diff --git a/backend/config/urls.py b/backend/config/urls.py index 52638824c..ffa0768d7 100644 --- a/backend/config/urls.py +++ b/backend/config/urls.py @@ -1,16 +1,15 @@ from django.conf import settings -from django.conf.urls import include, url +from django.conf.urls import include from django.conf.urls.static import static from django.contrib import admin from django.contrib.auth import views as auth_views from django.contrib.staticfiles import finders from django.http import HttpResponse from django.shortcuts import render -from django.urls import path +from django.urls import path, re_path from django.views import View from django.views import defaults as default_views from django.views.generic import TemplateView -import django_saml2_auth.views from djproxy.views import HttpProxy from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView from projectroles.views import HomeView as ProjectRolesHomeView @@ -24,74 +23,51 @@ def handler500(request, *args, **argv): return HttpResponse(status=500) -# URL Patterns for SAML / Logins -# ------------------------------------------------------------------------------ - -urlpatterns = [ - # These are the SAML2 related URLs. You can change "^saml2_auth/" regex to - # any path you want, like "^sso_auth/", "^sso_login/", etc. (required) - url(r"^saml2_auth/", include("django_saml2_auth.urls")), - # The following line will replace the default user login with SAML2 (optional) - # If you want to specific the after-login-redirect-URL, use parameter "?next=/the/path/you/want" - # with this view. - url(r"^sso/login/$", django_saml2_auth.views.signin), - # The following line will replace the admin login with SAML2 (optional) - # If you want to specific the after-login-redirect-URL, use parameter "?next=/the/path/you/want" - # with this view. - url(r"^sso/admin/login/$", django_saml2_auth.views.signin), - # The following line will replace the default user logout with the signout page (optional) - url(r"^sso/logout/$", django_saml2_auth.views.signout), - # The following line will replace the default admin user logout with the signout page (optional) - url(r"^sso/admin/logout/$", django_saml2_auth.views.signout), -] - # URL Patterns for SODAR Core # ------------------------------------------------------------------------------ -urlpatterns += [url(r"^$", ProjectRolesHomeView.as_view(), name="home")] +urlpatterns = [path("", ProjectRolesHomeView.as_view(), name="home")] HomeView = ProjectRolesHomeView # URL Patterns for VarFish # ------------------------------------------------------------------------------ urlpatterns += [ - url(r"^icons/", include("dj_iconify.urls")), - # url(r'^$', TemplateView.as_view(template_name='pages/home.html'), name='home'), - url(r"^variants/", include("variants.urls")), - url(r"^importer/", include("importer.urls")), - url(r"^svs/", include("svs.urls")), - url(r"^bgjobs/", include("bgjobs.urls")), - url(r"^about/$", TemplateView.as_view(template_name="pages/about.html"), name="about"), + path("icons/", include("dj_iconify.urls")), + path("variants/", include("variants.urls")), + path("importer/", include("importer.urls")), + path("svs/", include("svs.urls")), + path("bgjobs/", include("bgjobs.urls")), + path("about/", TemplateView.as_view(template_name="pages/about.html"), name="about"), # Django Admin, use {% url 'admin:index' %} - url(settings.ADMIN_URL, admin.site.urls), + path(settings.ADMIN_URL, admin.site.urls), # User management - # url(r'^users/', include('varfish.users.urls', namespace='users')), # Your stuff: custom urls includes go here - url(r"api/auth/", include("knox.urls")), - url(r"^login/$", auth_views.LoginView.as_view(template_name="users/login.html"), name="login"), - url(r"^logout/$", auth_views.logout_then_login, name="logout"), + path("api/auth/", include("knox.urls")), + path("login/", auth_views.LoginView.as_view(template_name="users/login.html"), name="login"), + path("logout/", auth_views.logout_then_login, name="logout"), # SODAR-core - url(r"^project/", include("projectroles.urls")), - url(r"^timeline/", include("timeline.urls")), - url(r"^admin_alerts/", include("adminalerts.urls")), - url(r"^app_alerts/", include("appalerts.urls")), - url(r"^siteinfo/", include("siteinfo.urls")), - url(r"^userprofile/", include("userprofile.urls")), - url(r"^tokens/", include("tokens.urls")), # will go to SODAR-core + path("project/", include("projectroles.urls")), + path("timeline/", include("timeline.urls")), + path("admin_alerts/", include("adminalerts.urls")), + path("app_alerts/", include("appalerts.urls")), + path("siteinfo/", include("siteinfo.urls")), + path("userprofile/", include("userprofile.urls")), + path("tokens/", include("tokens.urls")), # will go to SODAR-core # The rendered Sphinx-based manual. - url(r"^manual/", include("docs.urls")), - url(r"^su/", include("django_su.urls")), - url(r"^cohorts/", include("cohorts.urls")), - url(r"^beaconsite/", include("beaconsite.urls")), - url(r"^genepanels/", include("genepanels.urls")), - url(r"^vueapp/", include("varfish.vueapp.urls")), - url(r"^cases/", include("cases.urls")), - url(r"^varannos/", include("varannos.urls")), - url(r"^seqmeta/", include("seqmeta.urls")), - url(r"^cases-import/", include("cases_import.urls")), - url(r"^cases-qc/", include("cases_qc.urls")), - url(r"^cases-analysis/", include("cases_analysis.urls")), - url(r"^seqvars/", include("seqvars.urls")), + path("manual/", include("docs.urls")), + path("su/", include("django_su.urls")), + path("cohorts/", include("cohorts.urls")), + path("beaconsite/", include("beaconsite.urls")), + path("genepanels/", include("genepanels.urls")), + path("vueapp/", include("varfish.vueapp.urls")), + path("cases/", include("cases.urls")), + path("varannos/", include("varannos.urls")), + path("seqmeta/", include("seqmeta.urls")), + path("cases-import/", include("cases_import.urls")), + path("cases-qc/", include("cases_qc.urls")), + path("cases-analysis/", include("cases_analysis.urls")), + path("seqvars/", include("seqvars.urls")), ] # URL Patterns for DRF Spectacular @@ -115,53 +91,53 @@ def handler500(request, *args, **argv): urlpatterns += [ # Augment url patterns with proxy for genomics england panelapp. - url( - r"^proxy/panelapp/(?P.*)$", + re_path( + r"proxy/panelapp/(?P.*)$", HttpProxy.as_view( base_url="https://panelapp.genomicsengland.co.uk/api/", ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], ), ), # Augment url patterns with proxy for variantvalidator.org. - url( - r"^proxy/variantvalidator/(?P.*)$", + re_path( + r"proxy/variantvalidator/(?P.*)$", HttpProxy.as_view( base_url="https://rest.variantvalidator.org/VariantValidator/variantvalidator/", ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], ), ), # Augment URL patterns with proxy for local services. - url( - r"^proxy/varfish/annonars/(?P.*)$", + re_path( + r"proxy/varfish/annonars/(?P.*)$", HttpProxy.as_view( base_url=settings.VARFISH_BACKEND_URL_ANNONARS, ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], ), ), - url( - r"^proxy/varfish/mehari/(?P.*)$", + re_path( + r"proxy/varfish/mehari/(?P.*)$", HttpProxy.as_view( base_url=settings.VARFISH_BACKEND_URL_MEHARI, ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], ), ), - url( - r"^proxy/varfish/nginx/(?P.*)$", + re_path( + r"proxy/varfish/nginx/(?P.*)$", HttpProxy.as_view( base_url=settings.VARFISH_BACKEND_URL_NGINX, ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], ), ), # Augment url patterns with proxy for PubTator3 - url( - r"^proxy/remote/pubtator3-api/(?P.*)$", + re_path( + r"proxy/remote/pubtator3-api/(?P.*)$", HttpProxy.as_view( base_url="https://www.ncbi.nlm.nih.gov/research/pubtator3-api/", ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], ), ), - url( - r"^proxy/varfish/viguno/(?P.*)$", + re_path( + r"proxy/varfish/viguno/(?P.*)$", HttpProxy.as_view( base_url=settings.VARFISH_BACKEND_URL_VIGUNO, ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], @@ -189,8 +165,8 @@ def get(self, *args, **kwargs): return HttpResponse(content, content_type="text/html") urlpatterns += [ - url( - r"^-.*", + path( + "-.*", ServeStringView.as_view(), name="vueapp-entrypoint", ) @@ -203,20 +179,20 @@ def get(self, *args, **kwargs): # This allows the error pages to be debugged during development, just visit # these url in browser to see how these error pages look like. urlpatterns += [ - url(r"^400/$", default_views.bad_request, kwargs={"exception": Exception("Bad Request!")}), - url( - r"^403/$", + path("400/", default_views.bad_request, kwargs={"exception": Exception("Bad Request!")}), + path( + "403/", default_views.permission_denied, kwargs={"exception": Exception("Permission Denied")}, ), - url( - r"^404/$", + path( + "404/", default_views.page_not_found, kwargs={"exception": Exception("Page not Found")}, ), - url(r"^500/$", default_views.server_error), + path("500/", default_views.server_error), ] if "debug_toolbar" in settings.INSTALLED_APPS: import debug_toolbar - urlpatterns = [url(r"^__debug__/", include(debug_toolbar.urls))] + urlpatterns + urlpatterns = [path("__debug__/", include(debug_toolbar.urls))] + urlpatterns diff --git a/backend/ext_gestaltmatcher/migrations/0003_alter_smallvariantquerygestaltmatcherscores_id_and_more.py b/backend/ext_gestaltmatcher/migrations/0003_alter_smallvariantquerygestaltmatcherscores_id_and_more.py new file mode 100644 index 000000000..ec69866ae --- /dev/null +++ b/backend/ext_gestaltmatcher/migrations/0003_alter_smallvariantquerygestaltmatcherscores_id_and_more.py @@ -0,0 +1,27 @@ +# Generated by Django 4.2.16 on 2024-10-07 12:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("ext_gestaltmatcher", "0002_smallvariantquerypediascores"), + ] + + operations = [ + migrations.AlterField( + model_name="smallvariantquerygestaltmatcherscores", + name="id", + field=models.BigAutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + migrations.AlterField( + model_name="smallvariantquerypediascores", + name="id", + field=models.BigAutoField( + auto_created=True, primary_key=True, serialize=False, verbose_name="ID" + ), + ), + ] diff --git a/backend/genepanels/forms.py b/backend/genepanels/forms.py index 436638c50..491435849 100644 --- a/backend/genepanels/forms.py +++ b/backend/genepanels/forms.py @@ -24,8 +24,11 @@ def __init__(self, *args, **kwargs): self.fields["genes"] = self._build_genes_field() def _build_genes_field(self): - rows = [entry.symbol for entry in self.instance.genepanelentry_set.all()] - initial_value = "\n".join(rows) + if self.instance.pk: + rows = [entry.symbol for entry in self.instance.genepanelentry_set.all()] + initial_value = "\n".join(rows) + else: + initial_value = "" return forms.CharField( label="Genes", widget=forms.Textarea, diff --git a/backend/genepanels/tests/test_models.py b/backend/genepanels/tests/test_models.py index 2380cf354..4d18a3725 100644 --- a/backend/genepanels/tests/test_models.py +++ b/backend/genepanels/tests/test_models.py @@ -24,7 +24,9 @@ def test_create(self): def test_get_absolute_url(self): category = GenePanelCategoryFactory() - self.assertEqual(category.get_absolute_url(), f"/genepanels/category/{category.sodar_uuid}") + self.assertEqual( + category.get_absolute_url(), f"/genepanels/category/{category.sodar_uuid}/" + ) def test_str(self): category = GenePanelCategoryFactory() @@ -46,7 +48,7 @@ def test_create(self): def test_get_absolute_url(self): panel = GenePanelFactory() - self.assertEqual(panel.get_absolute_url(), f"/genepanels/panel/{panel.sodar_uuid}") + self.assertEqual(panel.get_absolute_url(), f"/genepanels/panel/{panel.sodar_uuid}/") def test_get_hgnc_list(self): panel = GenePanelFactory() diff --git a/backend/genepanels/tests/test_permissions.py b/backend/genepanels/tests/test_permissions.py index e7550ea59..9703bae70 100644 --- a/backend/genepanels/tests/test_permissions.py +++ b/backend/genepanels/tests/test_permissions.py @@ -1,5 +1,5 @@ from django.urls import reverse -from projectroles.tests.test_permissions import TestProjectPermissionBase +from projectroles.tests.test_permissions import ProjectPermissionTestBase from genepanels.models import GenePanelState from genepanels.tests.factories import GenePanelFactory @@ -26,7 +26,7 @@ def setUp(self): ] -class TestGenepanelsView(UsersMixin, TestProjectPermissionBase): +class TestGenepanelsView(UsersMixin, ProjectPermissionTestBase): def test_index(self): url = reverse("genepanels:index") self.assert_response(url, self.users_edit + self.users_view, 200) diff --git a/backend/genepanels/urls.py b/backend/genepanels/urls.py index 34fd62f7d..25f2789f5 100644 --- a/backend/genepanels/urls.py +++ b/backend/genepanels/urls.py @@ -1,88 +1,88 @@ """URL configuration for the ``genepanels`` app. """ -from django.conf.urls import url +from django.urls import path from genepanels import views, views_api app_name = "genepanels" ui_urlpatterns = [ - url( - regex=r"^$", + path( + "", view=views.IndexView.as_view(), name="index", ), - url( - regex=r"^category/$", + path( + "category/", view=views.GenePanelCategoryListView.as_view(), name="category-list", ), - url( - regex=r"^category/create/$", + path( + "category/create/", view=views.GenePanelCategoryCreateView.as_view(), name="category-create", ), - url( - regex=r"^category/update/(?P[0-9a-f-]+)$", + path( + "category/update//", view=views.GenePanelCategoryUpdateView.as_view(), name="category-update", ), - url( - regex=r"^category/(?P[0-9a-f-]+)$", + path( + "category//", view=views.GenePanelCategoryDetailView.as_view(), name="category-detail", ), - url( - regex=r"^category/delete/(?P[0-9a-f-]+)$", + path( + "category/delete//", view=views.GenePanelCategoryDeleteView.as_view(), name="category-delete", ), - url( - regex=r"^panel/create/$", + path( + "panel/create/", view=views.GenePanelCreateView.as_view(), name="genepanel-create", ), - url( - regex=r"^panel/update/(?P[0-9a-f-]+)$", + path( + "panel/update//", view=views.GenePanelUpdateView.as_view(), name="genepanel-update", ), - url( - regex=r"^panel/(?P[0-9a-f-]+)$", + path( + "panel//", view=views.GenePanelDetailView.as_view(), name="genepanel-detail", ), - url( - regex=r"^panel/delete/(?P[0-9a-f-]+)$", + path( + "panel/delete//", view=views.GenePanelDeleteView.as_view(), name="genepanel-delete", ), - url( - regex=r"^panel/copy-as-draft/(?P[0-9a-f-]+)$", + path( + "panel/copy-as-draft//", view=views.GenePanelCopyAsDraftView.as_view(), name="genepanel-copy-as-draft", ), - url( - regex=r"^panel/release/(?P[0-9a-f-]+)$", + path( + "panel/release//", view=views.GenePanelReleaseView.as_view(), name="genepanel-release", ), - url( - regex=r"^panel/retire/(?P[0-9a-f-]+)$", + path( + "panel/retire//", view=views.GenePanelRetireView.as_view(), name="genepanel-retire", ), ] api_patterns = [ - url( - regex=r"^api/genepanel-category/list/$", + path( + "api/genepanel-category/list/", view=views_api.GenePanelCategoryListApiView.as_view(), name="genepanel-category-list", ), - url( - regex=r"^api/lookup-genepanel/$", + path( + "api/lookup-genepanel/", view=views_api.LookupGenePanelApiView.as_view(), name="lookup-genepanel", ), diff --git a/backend/importer/migrations/0012_alter_importcasebgjob_bg_job.py b/backend/importer/migrations/0012_alter_importcasebgjob_bg_job.py new file mode 100644 index 000000000..4d3db4033 --- /dev/null +++ b/backend/importer/migrations/0012_alter_importcasebgjob_bg_job.py @@ -0,0 +1,25 @@ +# Generated by Django 4.2.16 on 2024-10-07 12:53 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ("bgjobs", "0001_squashed_0006_auto_20200526_1657"), + ("importer", "0011_casegeneannotationfile"), + ] + + operations = [ + migrations.AlterField( + model_name="importcasebgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + ] diff --git a/backend/importer/urls.py b/backend/importer/urls.py index 2bdc4a395..ba6d08d1a 100644 --- a/backend/importer/urls.py +++ b/backend/importer/urls.py @@ -1,92 +1,89 @@ """URL configuration for the ``importer`` app. """ -from django.conf.urls import url +from django.urls import path from . import views, views_api app_name = "importer" ui_urlpatterns = [ - url(regex=r"^import-info$", view=views.ImportInfoView.as_view(), name="import-info"), - url( - regex=r"^(?P[0-9a-f-]+)/import/(?P[0-9a-f-]+)/$", + path("import-info/", view=views.ImportInfoView.as_view(), name="import-info"), + path( + "/import//", view=views.ImportCaseBgJobDetailView.as_view(), name="import-case-job-detail", ), ] api_urlpatterns = [ - url( - regex=r"^api/case-import-info/(?P[0-9a-f-]+)/$", + path( + "api/case-import-info//", view=views_api.CaseImportInfoListCreateView.as_view(), name="api-case-import-info-list-create", ), - url( - regex=r"^api/case-import-info/(?P[0-9a-f-]+)/(?P[0-9a-f-]+)/$", + path( + "api/case-import-info///", view=views_api.CaseImportInfoRetrieveUpdateDestroyView.as_view(), name="api-case-import-info-retrieve-update-destroy", ), - url( - regex=r"^api/variant-set-import-info/(?P[0-9a-f-]+)/$", + path( + "api/variant-set-import-info//", view=views_api.VariantSetImportInfoListCreateView.as_view(), name="api-variant-set-import-info-list-create", ), - url( - regex=r"^api/variant-set-import-info/(?P[0-9a-f-]+)/(?P[0-9a-f-]+)/$", + path( + "api/variant-set-import-info///", view=views_api.VariantSetImportInfoRetrieveUpdateDestroyView.as_view(), name="api-variant-set-import-info-retrieve-update-destroy", ), - url( - regex=r"^api/bam-qc-file/(?P[0-9a-f-]+)/$", + path( + "api/bam-qc-file//", view=views_api.BamQcFileListCreateView.as_view(), name="api-bam-qc-file-list-create", ), - url( - regex=r"^api/bam-qc-file/(?P[0-9a-f-]+)/(?P[0-9a-f-]+)/$", + path( + "api/bam-qc-file///", view=views_api.BamQcFileRetrieveDestroyView.as_view(), name="api-bam-qc-file-retrieve-destroy", ), - url( - regex=r"^api/case-gene-annotation-file/(?P[0-9a-f-]+)/$", + path( + "api/case-gene-annotation-file//", view=views_api.CaseGeneAnnotationFileListCreateView.as_view(), name="api-case-gene-annotation-file-list-create", ), - url( - regex=( - r"^api/case-gene-annotation-file/(?P[0-9a-f-]+)/" - r"(?P[0-9a-f-]+)/$" - ), + path( + "api/case-gene-annotation-file///", view=views_api.CaseGeneAnnotationFileRetrieveDestroyView.as_view(), name="api-case-gene-annotation-file-retrieve-destroy", ), - url( - regex=r"^api/genotype-file/(?P[0-9a-f-]+)/$", + path( + "api/genotype-file//", view=views_api.GenotypeFileListCreateView.as_view(), name="api-genotype-file-list-create", ), - url( - regex=r"^api/genotype-file/(?P[0-9a-f-]+)/(?P[0-9a-f-]+)/$", + path( + "api/genotype-file///", view=views_api.GenotypeFileRetrieveDestroyView.as_view(), name="api-genotype-file-retrieve-destroy", ), - url( - regex=r"^api/effects-file/(?P[0-9a-f-]+)/$", + path( + "api/effects-file//", view=views_api.EffectsFileListCreateView.as_view(), name="api-effects-file-list-create", ), - url( - regex=r"^api/effects-file/(?P[0-9a-f-]+)/(?P[0-9a-f-]+)/$", + path( + "api/effects-file///", view=views_api.EffectsFileRetrieveDestroyView.as_view(), name="api-effects-file-retrieve-destroy", ), - url( - regex=r"^api/database-info-file/(?P[0-9a-f-]+)/$", + path( + "api/database-info-file//", view=views_api.DatabaseInfoFileListCreateView.as_view(), name="api-db-info-file-list-create", ), - url( - regex=r"^api/database-info-file/(?P[0-9a-f-]+)/(?P[0-9a-f-]+)/$", + path( + "api/database-info-file///", view=views_api.DatabaseInfoFileRetrieveDestroyView.as_view(), name="api-db-info-file-retrieve-destroy", ), diff --git a/backend/seqmeta/tests/test_models.py b/backend/seqmeta/tests/test_models.py index 96acef346..22492066e 100644 --- a/backend/seqmeta/tests/test_models.py +++ b/backend/seqmeta/tests/test_models.py @@ -12,7 +12,7 @@ def test_create(self): def test_get_absolute_url(self): kit = EnrichmentKitFactory() - self.assertEqual(kit.get_absolute_url(), f"/seqmeta/enrichmentkit/{kit.sodar_uuid}") + self.assertEqual(kit.get_absolute_url(), f"/seqmeta/enrichmentkit/{kit.sodar_uuid}/") def test_str(self): kit = EnrichmentKitFactory() diff --git a/backend/seqmeta/tests/test_permissions.py b/backend/seqmeta/tests/test_permissions.py index 4d996a957..648396038 100644 --- a/backend/seqmeta/tests/test_permissions.py +++ b/backend/seqmeta/tests/test_permissions.py @@ -1,5 +1,5 @@ from django.urls import reverse -from projectroles.tests.test_permissions import TestProjectPermissionBase +from projectroles.tests.test_permissions import ProjectPermissionTestBase from seqmeta.tests.factories import EnrichmentKitFactory @@ -23,7 +23,7 @@ def setUp(self): ] -class TestSeqmetaView(UsersMixin, TestProjectPermissionBase): +class TestSeqmetaView(UsersMixin, ProjectPermissionTestBase): def test_index(self): url = reverse("seqmeta:index") self.assert_response(url, self.users_edit + self.users_view, 200) diff --git a/backend/seqmeta/urls.py b/backend/seqmeta/urls.py index f3a9a54e3..7fd9afc4c 100644 --- a/backend/seqmeta/urls.py +++ b/backend/seqmeta/urls.py @@ -1,22 +1,22 @@ -from django.conf.urls import url +from django.urls import path from seqmeta import views, views_api app_name = "seqmeta" ui_urlpatterns = [ - url( - regex=r"^$", + path( + "", view=views.IndexView.as_view(), name="index", ), - url( - regex=r"^enrichmentkit/?$", + path( + "enrichmentkit/", view=views.EnrichmentKitListView.as_view(), name="enrichmentkit-list", ), - url( - regex=r"^enrichmentkit/(?P[0-9a-f-]+)/?$", + path( + "enrichmentkit//", view=views.EnrichmentKitDetailView.as_view(), name="enrichmentkit-detail", ), @@ -25,23 +25,23 @@ ajax_urlpatterns = [] api_urlpatterns = [ - url( - regex=r"^api/enrichmentkit/list-create/?$", + path( + "api/enrichmentkit/list-create/", view=views_api.EnrichmentKitListCreateApiView.as_view(), name="api-enrichmentkit-listcreate", ), - url( - regex=r"^api/enrichmentkit/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "api/enrichmentkit/retrieve-update-destroy//", view=views_api.EnrichmentKitRetrieveUpdateDestroyApiView.as_view(), name="api-enrichmentkit-retrieveupdatedestroy", ), - url( - regex=r"^api/targetbedfile/list-create/(?P[0-9a-f-]+)/?$", + path( + "api/targetbedfile/list-create//", view=views_api.TargetBedFileListCreateApiView.as_view(), name="api-targetbedfile-listcreate", ), - url( - regex=r"^api/targetbedfile/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "api/targetbedfile/retrieve-update-destroy//", view=views_api.TargetBedFileRetrieveUpdateDestroyApiView.as_view(), name="api-targetbedfile-retrieveupdatedestroy", ), diff --git a/backend/seqvars/tests/test_permissions_api.py b/backend/seqvars/tests/test_permissions_api.py index aaddc645b..a50afce9c 100644 --- a/backend/seqvars/tests/test_permissions_api.py +++ b/backend/seqvars/tests/test_permissions_api.py @@ -1,5 +1,5 @@ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from cases_analysis.tests.factories import CaseAnalysisFactory, CaseAnalysisSessionFactory from seqvars.factory_defaults import create_seqvarspresetsset_short_read_exome_legacy @@ -59,7 +59,7 @@ from variants.tests.factories import CaseFactory -class TestQueryPresetsSetViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsSetViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -202,7 +202,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsVersionSetViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsVersionSetViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -353,7 +353,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsFrequencyViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsFrequencyViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -507,7 +507,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsQualityViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsQualityViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -659,7 +659,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsConsequenceViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsConsequenceViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -813,7 +813,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsLocusViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsLocusViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -963,7 +963,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsPhenotypePrioViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsPhenotypePrioViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -1117,7 +1117,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsVariantPrioViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsVariantPrioViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -1271,7 +1271,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsColumnsViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsColumnsViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -1423,7 +1423,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryPresetsClinvarViewSet(TestProjectAPIPermissionBase): +class TestQueryPresetsClinvarViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -1575,7 +1575,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestPredefinedQueryViewSet(TestProjectAPIPermissionBase): +class TestPredefinedQueryViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -1725,7 +1725,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQuerySettingsViewSet(TestProjectAPIPermissionBase): +class TestQuerySettingsViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -1923,7 +1923,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestQueryViewSet(TestProjectAPIPermissionBase): +class TestQueryViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -2192,7 +2192,7 @@ def cleanup(): ) -class TestQueryExecutionViewSet(TestProjectAPIPermissionBase): +class TestQueryExecutionViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -2246,7 +2246,7 @@ def test_retrieve(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestResultSetViewSet(TestProjectAPIPermissionBase): +class TestResultSetViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() @@ -2301,7 +2301,7 @@ def test_retrieve(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestResultRowViewSet(TestProjectAPIPermissionBase): +class TestResultRowViewSet(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() diff --git a/backend/svs/migrations/0029_alter_buildbackgroundsvsetjob_bg_job_and_more.py b/backend/svs/migrations/0029_alter_buildbackgroundsvsetjob_bg_job_and_more.py new file mode 100644 index 000000000..f1668d2ac --- /dev/null +++ b/backend/svs/migrations/0029_alter_buildbackgroundsvsetjob_bg_job_and_more.py @@ -0,0 +1,59 @@ +# Generated by Django 4.2.16 on 2024-10-07 12:53 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("bgjobs", "0001_squashed_0006_auto_20200526_1657"), + ("svs", "0028_auto_20240807_0850"), + ] + + operations = [ + migrations.AlterField( + model_name="buildbackgroundsvsetjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="cleanupbackgroundsvsetjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="importstructuralvariantbgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="svquery", + name="user", + field=models.ForeignKey( + blank=True, + help_text="User who created the query", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(app_label)s_%(class)s_related", + to=settings.AUTH_USER_MODEL, + ), + ), + ] diff --git a/backend/svs/tests/test_permissions_ajax_presets.py b/backend/svs/tests/test_permissions_ajax_presets.py index f4521447f..de64b4c3a 100644 --- a/backend/svs/tests/test_permissions_ajax_presets.py +++ b/backend/svs/tests/test_permissions_ajax_presets.py @@ -1,12 +1,12 @@ """Permission tests for the views in ``svs.views.ajax.presets``.""" from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.tests.factories import CaseFactory -class TestSvQuerySettingsShortcutAjaxView(TestProjectAPIPermissionBase): +class TestSvQuerySettingsShortcutAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) diff --git a/backend/svs/tests/test_permissions_ajax_queries.py b/backend/svs/tests/test_permissions_ajax_queries.py index 0f3b22ef2..0faffd64e 100644 --- a/backend/svs/tests/test_permissions_ajax_queries.py +++ b/backend/svs/tests/test_permissions_ajax_queries.py @@ -1,14 +1,14 @@ """Permission tests for the views in ``svs.views.ajax.queries``.""" from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from svs.models import SvQuery from svs.tests.factories import SvQueryFactory, SvQueryResultRowFactory, SvQueryResultSetFactory from variants.tests.factories import CaseFactory -class TestSvQueryListCreateAjaxView(TestProjectAPIPermissionBase): +class TestSvQueryListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -45,7 +45,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestSvQueryRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestSvQueryRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -108,7 +108,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestSvQueryResultSetListAjaxView(TestProjectAPIPermissionBase): +class TestSvQueryResultSetListAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -131,7 +131,7 @@ def test_get(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSvQueryResultSetRetrieveAjaxView(TestProjectAPIPermissionBase): +class TestSvQueryResultSetRetrieveAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -157,7 +157,7 @@ def test_get(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSvQueryResultRowListAjaxView(TestProjectAPIPermissionBase): +class TestSvQueryResultRowListAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -183,7 +183,7 @@ def test_get(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSvQueryResultRowRetrieveView(TestProjectAPIPermissionBase): +class TestSvQueryResultRowRetrieveView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) diff --git a/backend/svs/urls.py b/backend/svs/urls.py index 8924958cb..ce964caf6 100644 --- a/backend/svs/urls.py +++ b/backend/svs/urls.py @@ -1,5 +1,5 @@ from django.conf import settings -from django.conf.urls import url +from django.urls import path, re_path from djproxy.views import HttpProxy from svs import views @@ -8,136 +8,136 @@ urlpatterns_ui = [ # Views related to background SV jobs. - url( - regex=r"^(?P[0-9a-f-]+)/import/(?P[0-9a-f-]+)/?$", + path( + "/import//", view=views.ImportStructuralVariantsJobDetailView.as_view(), name="import-job-detail", ), - url( - regex=r"^build-bg-sv/(?P[0-9a-f-]+)/?$", + path( + "build-bg-sv//", view=views.BuildBackgroundSvSetJobDetailView.as_view(), name="build-bg-sv-set-job-detail", ), - url( - regex=r"^cleanup-bg-sv/(?P[0-9a-f-]+)/?$", + path( + "cleanup-bg-sv//", view=views.CleanupBackgroundSvSetJobDetailView.as_view(), name="cleanup-bg-sv-set-job-detail", ), ] urlpatterns_ajax = [ - url( - regex=r"^ajax/fetch-variants/(?P[0-9a-f-]+)/?$", + path( + "ajax/fetch-variants//", view=views.SvFetchVariantsAjaxView.as_view(), name="ajax-variants-fetch", ), - url( - regex=r"^ajax/query-case/quick-presets/?$", + path( + "ajax/query-case/quick-presets", view=views.SvQuickPresetsAjaxView.as_view(), name="ajax-quick-presets", ), - url( - regex=r"^ajax/query-case/category-presets/(?P[a-zA-Z0-9\._-]+)/?$", + path( + "ajax/query-case/category-presets//", view=views.SvCategoryPresetsApiView.as_view(), name="ajax-category-presets", ), - url( - regex=r"^ajax/query-case/inheritance-presets/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/inheritance-presets//", view=views.SvInheritancePresetsApiView.as_view(), name="ajax-inheritance-presets", ), # URLs for ``svs.queries.presets`` - url( - regex=r"^ajax/query-case/query-settings-shortcut/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/query-settings-shortcut//", view=views.SvQuerySettingsShortcutAjaxView.as_view(), name="ajax-svquerysettings-shortcut", ), # URLs for ``svs.queries.results`` - url( - regex=r"^ajax/sv-query/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/sv-query/list-create//", view=views.SvQueryListCreateAjaxView.as_view(), name="ajax-svquery-listcreate", ), - url( - regex=r"^ajax/sv-query/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/sv-query/retrieve-update-destroy//", view=views.SvQueryRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-svquery-retrieveupdatedestroy", ), - url( - regex=r"^sv-query-result-set/list/(?P[0-9a-f-]+)/?$", + path( + "sv-query-result-set/list//", view=views.SvQueryResultSetListAjaxView.as_view(), name="ajax-svqueryresultset-list", ), - url( - regex=r"^sv-query-result-set/retrieve/(?P[0-9a-f-]+)/?$", + path( + "sv-query-result-set/retrieve//", view=views.SvQueryResultSetRetrieveAjaxView.as_view(), name="ajax-svqueryresultset-retrieve", ), - url( - regex=r"^sv-query-result-row/list/(?P[0-9a-f-]+)/?$", + path( + "sv-query-result-row/list//", view=views.SvQueryResultRowListAjaxView.as_view(), name="ajax-svqueryresultrow-list", ), - url( - regex=r"^sv-query-result-row/retrieve/(?P[0-9a-f-]+)/?$", + path( + "sv-query-result-row/retrieve//", view=views.SvQueryResultRowRetrieveAjaxView.as_view(), name="ajax-svqueryresultrow-retrieve", ), # URLs user annotations (flags, comments) - url( - regex=r"^ajax/structural-variant-flags/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-flags/list-create//", view=views.StructuralVariantFlagsListCreateAjaxView.as_view(), name="ajax-structuralvariantflags-listcreate", ), - url( - regex=r"^ajax/structural-variant-flags/list-project/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-flags/list-project//", view=views.StructuralVariantFlagsListProjectAjaxView.as_view(), name="ajax-structuralvariantflags-listproject", ), - url( - regex=r"^ajax/structural-variant-flags/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-flags/retrieve-update-destroy//", view=views.StructuralVariantFlagsRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-structuralvariantflags-retrieveupdatedestroy", ), - url( - regex=r"^ajax/structural-variant-comment/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-comment/list-create//", view=views.StructuralVariantCommentListCreateAjaxView.as_view(), name="ajax-structuralvariantcomment-listcreate", ), - url( - regex=r"^ajax/structural-variant-comment/list-project/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-comment/list-project//", view=views.StructuralVariantCommentListProjectAjaxView.as_view(), name="ajax-structuralvariantcomment-listproject", ), - url( - regex=r"^ajax/structural-variant-comment/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-comment/retrieve-update-destroy//", view=views.StructuralVariantCommentRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-structuralvariantcomment-retrieveupdatedestroy", ), - url( - regex=r"^ajax/structural-variant-acmg-rating/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-acmg-rating/list-create//", view=views.StructuralVariantAcmgRatingListCreateAjaxView.as_view(), name="ajax-structuralvariantacmgrating-listcreate", ), - url( - regex=r"^ajax/structural-variant-acmg-rating/list-project/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-acmg-rating/list-project//", view=views.StructuralVariantAcmgRatingListProjectAjaxView.as_view(), name="ajax-structuralvariantacmgrating-listproject", ), - url( - regex=r"^ajax/structural-variant-acmg-rating/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/structural-variant-acmg-rating/retrieve-update-destroy//", view=views.StructuralVariantAcmgRatingRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-structuralvariantacmgrating-retrieveupdatedestroy", ), # Augment url patterns with proxy to worker. - url( + re_path( r"^worker/(?P.*)$", HttpProxy.as_view( base_url=f"{settings.WORKER_REST_BASE_URL}/public/svs/", ignored_request_headers=HttpProxy.ignored_upstream_headers + ["cookie"], ), ), - url( + re_path( r"^tracks/(?P.*)$", HttpProxy.as_view( base_url=f"{settings.WORKER_REST_BASE_URL}/public/tracks/", diff --git a/backend/varannos/tests/helpers.py b/backend/varannos/tests/helpers.py index cb40d4c23..69d67b68a 100644 --- a/backend/varannos/tests/helpers.py +++ b/backend/varannos/tests/helpers.py @@ -1,6 +1,6 @@ from django.conf import settings from django.test import RequestFactory -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from test_plus import TestCase from variants.tests.factories import ProjectFactory @@ -11,7 +11,7 @@ VARFISH_INVALID_VERSION = "0.0.0" -class TestViewsBase(TestCase): +class ViewTestBase(TestCase): def setUp(self): super().setUp() self.superuser = self.make_user("superuser") @@ -28,7 +28,7 @@ def setUp(self): self.request_factory = RequestFactory() -class ApiViewTestBase(ViewTestBaseMixin, TestProjectAPIPermissionBase): +class ApiViewTestBase(ViewTestBaseMixin, ProjectAPIPermissionTestBase): """Base class for API view testing (and file export)""" media_type = settings.SODAR_API_MEDIA_TYPE diff --git a/backend/varannos/tests/test_models.py b/backend/varannos/tests/test_models.py index bea8b47b9..4567fe96b 100644 --- a/backend/varannos/tests/test_models.py +++ b/backend/varannos/tests/test_models.py @@ -17,7 +17,7 @@ def test_create(self): def test_get_absolute_url(self): obj = VarAnnoSetFactory() - self.assertEqual(obj.get_absolute_url(), f"/varannos/varannoset/details/{obj.sodar_uuid}") + self.assertEqual(obj.get_absolute_url(), f"/varannos/varannoset/details/{obj.sodar_uuid}/") def test_days_since_modification(self): with freeze_time((datetime.now() - timedelta(days=10)).strftime("%Y-%m-%d")): diff --git a/backend/varannos/tests/test_permissions.py b/backend/varannos/tests/test_permissions.py index fcc0d3dc9..6316f1a02 100644 --- a/backend/varannos/tests/test_permissions.py +++ b/backend/varannos/tests/test_permissions.py @@ -1,10 +1,10 @@ from django.urls import reverse -from projectroles.tests.test_permissions import TestProjectPermissionBase +from projectroles.tests.test_permissions import ProjectPermissionTestBase from varannos.tests.factories import VarAnnoSetFactory -class TestVarAnnoSetViews(TestProjectPermissionBase): +class TestVarAnnoSetViews(ProjectPermissionTestBase): """Permission tests for the ``VarAnnoSet`` views""" def setUp(self): diff --git a/backend/varannos/tests/test_permissions_api.py b/backend/varannos/tests/test_permissions_api.py index 12c0ab92e..474874a5f 100644 --- a/backend/varannos/tests/test_permissions_api.py +++ b/backend/varannos/tests/test_permissions_api.py @@ -1,11 +1,11 @@ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from varannos.models import VarAnnoSet from varannos.tests.factories import VarAnnoSetFactory -class TestVarAnnoSetApiView(TestProjectAPIPermissionBase): +class TestVarAnnoSetApiView(ProjectAPIPermissionTestBase): """Permission tests for the API views dealing with ``VarAnnoSet``.""" def setUp(self): diff --git a/backend/varannos/urls.py b/backend/varannos/urls.py index db9887cf6..68cabcfcd 100644 --- a/backend/varannos/urls.py +++ b/backend/varannos/urls.py @@ -1,16 +1,16 @@ -from django.conf.urls import url +from django.urls import path from varannos import views, views_api app_name = "varannos" ui_urlpatterns = [ - url( - regex=r"^varannoset/list/(?P[0-9a-f-]+)/?$", + path( + "varannoset/list//", view=views.VarAnnoSetListView.as_view(), name="varannoset-list", ), - url( - regex=r"^varannoset/details/(?P[0-9a-f-]+)/?$", + path( + "varannoset/details//", view=views.VarAnnoSetDetailView.as_view(), name="varannoset-detail", ), @@ -19,23 +19,23 @@ ajax_urlpatterns = [] api_urlpatterns = [ - url( - regex=r"^api/varannoset/list-create/(?P[0-9a-f-]+)/?$", + path( + "api/varannoset/list-create//", view=views_api.VarAnnoSetListCreateApiView.as_view(), name="api-varannoset-listcreate", ), - url( - regex=r"^api/varannoset/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "api/varannoset/retrieve-update-destroy//", view=views_api.VarAnnoSetRetrieveUpdateDestroyApiView.as_view(), name="api-varannoset-retrieveupdatedestroy", ), - url( - regex=r"^api/varannosetentry/list-create/(?P[0-9a-f-]+)/?$", + path( + "api/varannosetentry/list-create//", view=views_api.VarAnnoSetEntryListCreateApiView.as_view(), name="api-varannosetentry-listcreate", ), - url( - regex=r"^api/varannosetentry/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "api/varannosetentry/retrieve-update-destroy//", view=views_api.VarAnnoSetEntryRetrieveUpdateDestroyApiView.as_view(), name="api-varannosetentry-retrieveupdatedestroy", ), diff --git a/backend/varfish/templates/users/login.html b/backend/varfish/templates/users/login.html index 80e5d7d45..a55b1755b 100644 --- a/backend/varfish/templates/users/login.html +++ b/backend/varfish/templates/users/login.html @@ -1,110 +1 @@ -{# Custom login page based on SODAR Core v0.10 #} -{% extends 'base.html' %} - -{% load static %} - -{% load cases_tags %} -{% load projectroles_tags %} -{% load projectroles_common_tags %} - -{% get_django_setting 'SITE_INSTANCE_TITLE' as site_title %} - -{% block title %}Login{% endblock title %} - -{% block content %} - -
- - {# Django messages / site app messages #} - {% include 'projectroles/_messages.html' %} - - {# Display error if login was unsuccessful. #} - {% if request.POST %} -
- Login failed. Please make sure the user name, domain and password are correct. - - - -
- {% endif %} - -
-

Login

- - {% autoescape off %} - {% get_login_info %} - {% get_login_page_text %} - {% endautoescape %} - - - {% get_django_setting 'ENABLE_SAML' as enable_saml %} - {% if enable_saml %} -
-

To log in with your SSO provider, please click below.

- - Single Sign-On - - {% endif %} -
-
- -{% endblock content %} - -{% block javascript %} - {{ block.super }} - - - - - {# Tour content #} - -{% endblock javascript %} +{% extends 'projectroles/login.html' %} \ No newline at end of file diff --git a/backend/varfish/users/management/commands/initdev.py b/backend/varfish/users/management/commands/initdev.py index 8424e45b5..e9e0cff02 100644 --- a/backend/varfish/users/management/commands/initdev.py +++ b/backend/varfish/users/management/commands/initdev.py @@ -282,7 +282,7 @@ def _create_project( for setting_name, value in setting_value.items(): if project_settings.get(setting_name) != value: app_settings.set( - app_name="cases_import", + plugin_name="cases_import", setting_name=setting_name, value=value, project=project, diff --git a/backend/varfish/users/urls.py b/backend/varfish/users/urls.py index 12e7099db..0be621cce 100644 --- a/backend/varfish/users/urls.py +++ b/backend/varfish/users/urls.py @@ -1,10 +1,10 @@ -from django.conf.urls import url +from django.urls import path from . import views urlpatterns = [ - url(regex=r"^$", view=views.UserListView.as_view(), name="list"), - url(regex=r"^~redirect/$", view=views.UserRedirectView.as_view(), name="redirect"), - url(regex=r"^(?P[\w.@+-]+)/$", view=views.UserDetailView.as_view(), name="detail"), - url(regex=r"^~update/$", view=views.UserUpdateView.as_view(), name="update"), + path("", view=views.UserListView.as_view(), name="list"), + path("~redirect/", view=views.UserRedirectView.as_view(), name="redirect"), + path("/", view=views.UserDetailView.as_view(), name="detail"), + path("~update/", view=views.UserUpdateView.as_view(), name="update"), ] diff --git a/backend/varfish/vueapp/urls.py b/backend/varfish/vueapp/urls.py index 0307a9bf5..b12c2bb2f 100644 --- a/backend/varfish/vueapp/urls.py +++ b/backend/varfish/vueapp/urls.py @@ -1,11 +1,11 @@ -from django.conf.urls import url +from django.urls import path from varfish.vueapp import views_ajax app_name = "vueapp" ajax_urlpatterns = [ - url( - regex=r"^ajax/user-setting/(?P[0-9a-zA-Z\._-]+)/$", + path( + "ajax/user-setting//", view=views_ajax.UserSettingView.as_view(), name="user-setting", ), diff --git a/backend/variants/migrations/0109_alter_clearexpiredexportedfilesbgjob_bg_job_and_more.py b/backend/variants/migrations/0109_alter_clearexpiredexportedfilesbgjob_bg_job_and_more.py new file mode 100644 index 000000000..3026e0120 --- /dev/null +++ b/backend/variants/migrations/0109_alter_clearexpiredexportedfilesbgjob_bg_job_and_more.py @@ -0,0 +1,141 @@ +# Generated by Django 4.2.16 on 2024-10-07 12:53 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ("bgjobs", "0001_squashed_0006_auto_20200526_1657"), + ("variants", "0108_auto_20240807_0850"), + ] + + operations = [ + migrations.AlterField( + model_name="clearexpiredexportedfilesbgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="clearinactivevariantsetsbgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="clearoldkioskcasesbgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="deletecasebgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="exportfilebgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="exportprojectcasesfilebgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="importvariantsbgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="kioskannotatebgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="projectcasessmallvariantquery", + name="user", + field=models.ForeignKey( + blank=True, + help_text="User who created the query", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(app_label)s_%(class)s_related", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AlterField( + model_name="refreshsmallvariantsummarybgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + migrations.AlterField( + model_name="smallvariantquery", + name="user", + field=models.ForeignKey( + blank=True, + help_text="User who created the query", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="%(app_label)s_%(class)s_related", + to=settings.AUTH_USER_MODEL, + ), + ), + migrations.AlterField( + model_name="synccaselistbgjob", + name="bg_job", + field=models.ForeignKey( + help_text="Background job for state etc.", + on_delete=django.db.models.deletion.CASCADE, + related_name="%(app_label)s_%(class)s_related", + to="bgjobs.backgroundjob", + ), + ), + ] diff --git a/backend/variants/migrations/0110_drop_variant_summary.py b/backend/variants/migrations/0110_drop_variant_summary.py new file mode 100644 index 000000000..845f16ee5 --- /dev/null +++ b/backend/variants/migrations/0110_drop_variant_summary.py @@ -0,0 +1,103 @@ +# Generated by Django 4.2.16 on 2024-10-09 13:00 + +from django.db import connection, migrations, utils +from django.db.migrations.recorder import MigrationRecorder + + +def is_migration_applied(app_name, migration_name): + recorder = MigrationRecorder(connection) + try: + return recorder.migration_qs.filter(app=app_name, name=migration_name).exists() + except utils.ProgrammingError: + return False # migration table does not exist yet + + +if not is_migration_applied("projectroles", "0001_initial"): + run_before = [] # fresh installation, will run projectroles squashed migrations +elif is_migration_applied("projectroles", "0032_alter_appsetting_value"): + run_before = [] # critical projectroles migration already applied +else: + # We will not execute the squashed projectroles migration 0001..0032 and the + # projectroles migration 0032 has not been applied yet. + run_before = [ + ("projectroles", "0032_alter_appsetting_value"), + ] + + +SQL_OUTER = r""" +DROP MATERIALIZED VIEW IF EXISTS variants_smallvariantsummary; + +CREATE MATERIALIZED VIEW variants_smallvariantsummary +AS + %s +WITH NO DATA; + +CREATE UNIQUE INDEX variants_smallvariantsummary_id ON variants_smallvariantsummary(id); +CREATE INDEX variants_smallvariantsummary_coord ON variants_smallvariantsummary( + release, chromosome, start, "end", bin, reference, alternative +); +""" + + +SQL_INNER = r""" +WITH excluded_case_ids AS ( + SELECT DISTINCT variants_case.id AS case_id + FROM variants_case + JOIN projectroles_project ON variants_case.project_id = projectroles_project.id + JOIN projectroles_appsetting ON + projectroles_project.id = projectroles_appsetting.project_id AND + projectroles_appsetting.name = 'exclude_from_inhouse_db' AND + projectroles_appsetting.value = '1' +) +SELECT + row_number() OVER (PARTITION BY true) AS id, + release, + chromosome, + start, + "end", + bin, + reference, + alternative, + sum(num_hom_ref) AS count_hom_ref, + sum(num_het) AS count_het, + sum(num_hom_alt) AS count_hom_alt, + sum(num_hemi_ref) AS count_hemi_ref, + sum(num_hemi_alt) AS count_hemi_alt +FROM ( + SELECT DISTINCT + variants.release, + variants.chromosome, + variants.start, + variants."end", + variants.bin, + variants.reference, + variants.alternative, + variants.num_hom_ref, + variants.num_het, + variants.num_hom_alt, + variants.num_hemi_ref, + variants.num_hemi_alt, + variants.case_id + FROM variants_smallvariant AS variants + WHERE NOT EXISTS (SELECT 1 from excluded_case_ids AS e WHERE e.case_id = variants.case_id) +) AS variants_per_case +GROUP BY (release, chromosome, start, "end", bin, reference, alternative) +""" + + +class Migration(migrations.Migration): + + dependencies = [ + ("variants", "0109_alter_clearexpiredexportedfilesbgjob_bg_job_and_more"), + ] + + run_before = run_before + + operations = [ + migrations.RunSQL( + """ + DROP MATERIALIZED VIEW IF EXISTS variants_smallvariantsummary; + """, + SQL_OUTER % SQL_INNER, + ) + ] diff --git a/backend/variants/migrations/0111_create_variant_summary.py b/backend/variants/migrations/0111_create_variant_summary.py new file mode 100644 index 000000000..76294c0ac --- /dev/null +++ b/backend/variants/migrations/0111_create_variant_summary.py @@ -0,0 +1,80 @@ +# Generated by Django 4.2.16 on 2024-10-09 13:00 + +from django.db import migrations + +SQL_OUTER = r""" +DROP MATERIALIZED VIEW IF EXISTS variants_smallvariantsummary; + +CREATE MATERIALIZED VIEW variants_smallvariantsummary +AS + %s +WITH NO DATA; + +CREATE UNIQUE INDEX variants_smallvariantsummary_id ON variants_smallvariantsummary(id); +CREATE INDEX variants_smallvariantsummary_coord ON variants_smallvariantsummary( + release, chromosome, start, "end", bin, reference, alternative +); +""" + + +SQL_INNER = r""" +WITH excluded_case_ids AS ( + SELECT DISTINCT variants_case.id AS case_id + FROM variants_case + JOIN projectroles_project ON variants_case.project_id = projectroles_project.id + JOIN projectroles_appsetting ON + projectroles_project.id = projectroles_appsetting.project_id AND + projectroles_appsetting.name = 'exclude_from_inhouse_db' AND + projectroles_appsetting.value = '1' +) +SELECT + row_number() OVER (PARTITION BY true) AS id, + release, + chromosome, + start, + "end", + bin, + reference, + alternative, + sum(num_hom_ref) AS count_hom_ref, + sum(num_het) AS count_het, + sum(num_hom_alt) AS count_hom_alt, + sum(num_hemi_ref) AS count_hemi_ref, + sum(num_hemi_alt) AS count_hemi_alt +FROM ( + SELECT DISTINCT + variants.release, + variants.chromosome, + variants.start, + variants."end", + variants.bin, + variants.reference, + variants.alternative, + variants.num_hom_ref, + variants.num_het, + variants.num_hom_alt, + variants.num_hemi_ref, + variants.num_hemi_alt, + variants.case_id + FROM variants_smallvariant AS variants + WHERE NOT EXISTS (SELECT 1 from excluded_case_ids AS e WHERE e.case_id = variants.case_id) +) AS variants_per_case +GROUP BY (release, chromosome, start, "end", bin, reference, alternative) +""" + + +class Migration(migrations.Migration): + + dependencies = [ + ("variants", "0110_drop_variant_summary"), + ("projectroles", "0032_alter_appsetting_value"), + ] + + operations = [ + migrations.RunSQL( + SQL_OUTER % SQL_INNER, + """ + DROP MATERIALIZED VIEW IF EXISTS variants_smallvariantsummary; + """, + ) + ] diff --git a/backend/variants/models/maintenance.py b/backend/variants/models/maintenance.py index dba3999c1..5125af605 100644 --- a/backend/variants/models/maintenance.py +++ b/backend/variants/models/maintenance.py @@ -109,3 +109,80 @@ def refresh_variants_smallvariantsummary(): except utils.NotSupportedError: with transaction.atomic(): cursor.execute("REFRESH MATERIALIZED VIEW variants_smallvariantsummary") + + +def drop_variants_smallvariantsummary(): + """Drop the ``SmallVariantSummary`` materialized view.""" + + with transaction.atomic(): + with connection.cursor() as cursor: + cursor.execute("DROP MATERIALIZED VIEW IF EXISTS variants_smallvariantsummary") + + +SQL_OUTER = r""" +DROP MATERIALIZED VIEW IF EXISTS variants_smallvariantsummary; + +CREATE MATERIALIZED VIEW variants_smallvariantsummary +AS + %s +WITH NO DATA; + +CREATE UNIQUE INDEX variants_smallvariantsummary_id ON variants_smallvariantsummary(id); +CREATE INDEX variants_smallvariantsummary_coord ON variants_smallvariantsummary( + release, chromosome, start, "end", bin, reference, alternative +); +""" + + +SQL_INNER = r""" +WITH excluded_case_ids AS ( + SELECT DISTINCT variants_case.id AS case_id + FROM variants_case + JOIN projectroles_project ON variants_case.project_id = projectroles_project.id + JOIN projectroles_appsetting ON + projectroles_project.id = projectroles_appsetting.project_id AND + projectroles_appsetting.name = 'exclude_from_inhouse_db' AND + projectroles_appsetting.value = '1' +) +SELECT + row_number() OVER (PARTITION BY true) AS id, + release, + chromosome, + start, + "end", + bin, + reference, + alternative, + sum(num_hom_ref) AS count_hom_ref, + sum(num_het) AS count_het, + sum(num_hom_alt) AS count_hom_alt, + sum(num_hemi_ref) AS count_hemi_ref, + sum(num_hemi_alt) AS count_hemi_alt +FROM ( + SELECT DISTINCT + variants.release, + variants.chromosome, + variants.start, + variants."end", + variants.bin, + variants.reference, + variants.alternative, + variants.num_hom_ref, + variants.num_het, + variants.num_hom_alt, + variants.num_hemi_ref, + variants.num_hemi_alt, + variants.case_id + FROM variants_smallvariant AS variants + WHERE NOT EXISTS (SELECT 1 from excluded_case_ids AS e WHERE e.case_id = variants.case_id) +) AS variants_per_case +GROUP BY (release, chromosome, start, "end", bin, reference, alternative) +""" + + +def create_variants_smallvariantsummary(): + """Create the ``SmallVariantSummary`` materialized view.""" + + with transaction.atomic(): + with connection.cursor() as cursor: + cursor.execute(SQL_OUTER % SQL_INNER) diff --git a/backend/variants/tests/helpers.py b/backend/variants/tests/helpers.py index 35b145ac6..89f6a61d4 100644 --- a/backend/variants/tests/helpers.py +++ b/backend/variants/tests/helpers.py @@ -2,8 +2,8 @@ from django.conf import settings from django.test import RequestFactory -from projectroles.tests.test_permissions import TestProjectPermissionBase -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions import ProjectPermissionTestBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from test_plus.test import TestCase from beaconsite.models import Site @@ -31,7 +31,7 @@ def setUp(self): self.request_factory = RequestFactory() -class ApiViewTestBase(ViewTestBaseMixin, TestProjectAPIPermissionBase): +class ApiViewTestBase(ViewTestBaseMixin, ProjectAPIPermissionTestBase): """Base class for API view testing (and file export)""" media_type = settings.SODAR_API_MEDIA_TYPE @@ -44,7 +44,7 @@ def setUp(self): self.knox_token = self.get_token(self.superuser) -class ViewTestBase(ViewTestBaseMixin, TestProjectPermissionBase): +class ViewTestBase(ViewTestBaseMixin, ProjectPermissionTestBase): """Base class for UI view testing (and file export)""" diff --git a/backend/variants/tests/test_file_export.py b/backend/variants/tests/test_file_export.py index d4fb7ba20..cd2a2b58c 100644 --- a/backend/variants/tests/test_file_export.py +++ b/backend/variants/tests/test_file_export.py @@ -15,7 +15,7 @@ from projectroles.models import Project from requests_mock import Mocker from test_plus.test import TestCase -from timeline.models import ProjectEvent +from timeline.models import TimelineEvent from clinvar.tests.factories import ClinvarFactory from cohorts.tests.factories import TestCohortBase @@ -975,7 +975,7 @@ def _run_test(self, file_type): self.assertIsNotNone(self.export_job.export_result) self.assertEquals(self.export_job.export_result.payload, _fake_generate(self)) # Check side effects - self.assertEquals(ProjectEvent.objects.count(), 1) + self.assertEquals(TimelineEvent.objects.count(), 1) @patch.object(file_export.CaseExporterTsv, "generate", new=_fake_generate, create=True) def test_export_tsv(self): diff --git a/backend/variants/tests/test_permissions_ajax.py b/backend/variants/tests/test_permissions_ajax.py index b9152a600..5d23a6fdd 100644 --- a/backend/variants/tests/test_permissions_ajax.py +++ b/backend/variants/tests/test_permissions_ajax.py @@ -3,7 +3,7 @@ import json from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.models import SmallVariantQuery from variants.tests.factories import ( @@ -17,7 +17,7 @@ # expected: 401, got: 403 -class TestSmallVariantQueryListCreateAjaxView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -59,7 +59,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestSmallVariantQueryRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -124,7 +124,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestSmallVariantQueryResultSetListAjaxView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryResultSetListAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -152,7 +152,7 @@ def test_get(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSmallVariantQueryResultSetRetrieveAjaxView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryResultSetRetrieveAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -180,7 +180,7 @@ def test_get(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSmallVariantQueryResultRowListAjaxView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryResultRowListAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) diff --git a/backend/variants/tests/test_permissions_ajax_annos.py b/backend/variants/tests/test_permissions_ajax_annos.py index 3a407bd08..36a419e31 100644 --- a/backend/variants/tests/test_permissions_ajax_annos.py +++ b/backend/variants/tests/test_permissions_ajax_annos.py @@ -1,10 +1,10 @@ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.tests.factories import CaseFactory -class TestCaseUserAnnotatedVariantsAjaxView(TestProjectAPIPermissionBase): +class TestCaseUserAnnotatedVariantsAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) diff --git a/backend/variants/tests/test_permissions_ajax_presets.py b/backend/variants/tests/test_permissions_ajax_presets.py index 2f8aa9d16..ab807ff4b 100644 --- a/backend/variants/tests/test_permissions_ajax_presets.py +++ b/backend/variants/tests/test_permissions_ajax_presets.py @@ -1,5 +1,5 @@ from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.models import QuickPresets from variants.tests.factories import ( @@ -14,7 +14,7 @@ from variants.tests.utils import model_to_dict_for_api -class TestFrequencyPresetsListCreateAjaxView(TestProjectAPIPermissionBase): +class TestFrequencyPresetsListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.frequencypresets = FrequencyPresetsFactory(presetset__project=self.project) @@ -61,7 +61,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestFrequencyPresetsRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestFrequencyPresetsRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.frequencypresets = FrequencyPresetsFactory(presetset__project=self.project) @@ -137,7 +137,7 @@ def test_destroy(self): self.assert_response(url, bad_users_403, 403, method="DELETE") -class TestFrequencyPresetsCloneFactoryDefaultsView(TestProjectAPIPermissionBase): +class TestFrequencyPresetsCloneFactoryDefaultsView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -164,7 +164,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestFrequencyPresetsCloneOtherView(TestProjectAPIPermissionBase): +class TestFrequencyPresetsCloneOtherView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.frequencypreset = FrequencyPresetsFactory(presetset__project=self.project) @@ -192,7 +192,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestImpactPresetsListCreateAjaxView(TestProjectAPIPermissionBase): +class TestImpactPresetsListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.impactpresets = ImpactPresetsFactory(presetset__project=self.project) @@ -239,7 +239,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestImpactPresetsRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestImpactPresetsRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.impactpresets = ImpactPresetsFactory(presetset__project=self.project) @@ -315,7 +315,7 @@ def test_destroy(self): self.assert_response(url, bad_users_403, 403, method="DELETE") -class TestImpactPresetsCloneFactoryDefaultsView(TestProjectAPIPermissionBase): +class TestImpactPresetsCloneFactoryDefaultsView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -342,7 +342,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestImpactPresetsCloneOtherView(TestProjectAPIPermissionBase): +class TestImpactPresetsCloneOtherView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.impactpreset = ImpactPresetsFactory(presetset__project=self.project) @@ -370,7 +370,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestQualityPresetsListCreateAjaxView(TestProjectAPIPermissionBase): +class TestQualityPresetsListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.qualitypresets = QualityPresetsFactory(presetset__project=self.project) @@ -417,7 +417,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestQualityPresetsRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestQualityPresetsRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.qualitypresets = QualityPresetsFactory(presetset__project=self.project) @@ -493,7 +493,7 @@ def test_destroy(self): self.assert_response(url, bad_users_403, 403, method="DELETE") -class TestQualityPresetsCloneFactoryDefaultsView(TestProjectAPIPermissionBase): +class TestQualityPresetsCloneFactoryDefaultsView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -518,7 +518,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestQualityPresetsCloneOtherView(TestProjectAPIPermissionBase): +class TestQualityPresetsCloneOtherView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.qualitypreset = QualityPresetsFactory(presetset__project=self.project) @@ -546,7 +546,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestChromosomePresetsListCreateAjaxView(TestProjectAPIPermissionBase): +class TestChromosomePresetsListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.chromosomepresets = ChromosomePresetsFactory(presetset__project=self.project) @@ -593,7 +593,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestChromosomePresetsRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestChromosomePresetsRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.chromosomepresets = ChromosomePresetsFactory(presetset__project=self.project) @@ -669,7 +669,7 @@ def test_destroy(self): self.assert_response(url, bad_users_403, 403, method="DELETE") -class TestChromosomePresetsCloneFactoryDefaultsView(TestProjectAPIPermissionBase): +class TestChromosomePresetsCloneFactoryDefaultsView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -696,7 +696,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestChromosomePresetsCloneOtherView(TestProjectAPIPermissionBase): +class TestChromosomePresetsCloneOtherView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.chromosomepreset = ChromosomePresetsFactory(presetset__project=self.project) @@ -724,7 +724,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestFlagsEtcPresetsListCreateAjaxView(TestProjectAPIPermissionBase): +class TestFlagsEtcPresetsListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.flagsetcpresets = FlagsEtcPresetsFactory(presetset__project=self.project) @@ -771,7 +771,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestFlagsEtcPresetsRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestFlagsEtcPresetsRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.flagsetcpresets = FlagsEtcPresetsFactory(presetset__project=self.project) @@ -847,7 +847,7 @@ def test_destroy(self): self.assert_response(url, bad_users_403, 403, method="DELETE") -class TestFlagsEtcPresetsCloneFactoryDefaultsView(TestProjectAPIPermissionBase): +class TestFlagsEtcPresetsCloneFactoryDefaultsView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -874,7 +874,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestFlagsEtcPresetsCloneOtherView(TestProjectAPIPermissionBase): +class TestFlagsEtcPresetsCloneOtherView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.flagsetcpreset = FlagsEtcPresetsFactory(presetset__project=self.project) @@ -902,7 +902,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestQuickPresetsListCreateAjaxView(TestProjectAPIPermissionBase): +class TestQuickPresetsListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.quickpresets = QuickPresetsFactory(presetset__project=self.project) @@ -958,7 +958,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestQuickPresetsRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestQuickPresetsRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.quickpresets = QuickPresetsFactory(presetset__project=self.project) @@ -1034,7 +1034,7 @@ def test_destroy(self): self.assert_response(url, bad_users_403, 403, method="DELETE") -class TestQuickPresetsCloneOtherView(TestProjectAPIPermissionBase): +class TestQuickPresetsCloneOtherView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.quickpresets = QuickPresetsFactory(presetset__project=self.project) @@ -1068,7 +1068,7 @@ def get_project(self, *args, **kwargs): return QuickPresets.objects.get(sodar_uuid=self.kwargs["sodar_uuid"]).presetset.project -class TestPresetSetListCreateAjaxView(TestProjectAPIPermissionBase): +class TestPresetSetListCreateAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -1114,7 +1114,7 @@ def test_create(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestPresetSetListAllAjaxView(TestProjectAPIPermissionBase): +class TestPresetSetListAllAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -1138,7 +1138,7 @@ def test_listall(self): self.assert_response(url, bad_users_302, 302, method="GET") -class TestPresetSetRetrieveUpdateDestroyAjaxView(TestProjectAPIPermissionBase): +class TestPresetSetRetrieveUpdateDestroyAjaxView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -1214,7 +1214,7 @@ def test_destroy(self): self.assert_response(url, bad_users_403, 403, method="DELETE") -class TestPresetSetCloneFactoryDefaultsView(TestProjectAPIPermissionBase): +class TestPresetSetCloneFactoryDefaultsView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) @@ -1241,7 +1241,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestPresetSetCloneOtherView(TestProjectAPIPermissionBase): +class TestPresetSetCloneOtherView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.presetset = PresetSetFactory(project=self.project) diff --git a/backend/variants/tests/test_permissions_api.py b/backend/variants/tests/test_permissions_api.py index 8039257e4..9aedf8a97 100644 --- a/backend/variants/tests/test_permissions_api.py +++ b/backend/variants/tests/test_permissions_api.py @@ -3,7 +3,7 @@ import json from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.models import SmallVariantQuery from variants.tests.factories import ( @@ -15,7 +15,7 @@ ) -class TestSmallVariantQueryListCreateApiView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryListCreateApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -57,7 +57,7 @@ def test_post(self): self.assert_response(url, bad_users_403, 403, method="POST", data=data) -class TestSmallVariantQueryRetrieveUpdateDestroyApiView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryRetrieveUpdateDestroyApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -122,7 +122,7 @@ def cleanup(): self.assert_response(url, bad_users_403, 403, method="DELETE", cleanup_method=cleanup) -class TestSmallVariantQueryResultSetListApiView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryResultSetListApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -150,7 +150,7 @@ def test_get(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSmallVariantQueryResultSetRetrieveApiView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryResultSetRetrieveApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -178,7 +178,7 @@ def test_get(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSmallVariantQueryResultRowListApiView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryResultRowListApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) @@ -206,7 +206,7 @@ def test_get(self): self.assert_response(url, bad_users_403, 403, method="GET") -class TestSmallVariantQueryResultRowRetrieveApiView(TestProjectAPIPermissionBase): +class TestSmallVariantQueryResultRowRetrieveApiView(ProjectAPIPermissionTestBase): def setUp(self): super().setUp() self.case = CaseFactory(project=self.project) diff --git a/backend/variants/tests/test_ui.py b/backend/variants/tests/test_ui.py index 0ea583c55..e50e09fe1 100644 --- a/backend/variants/tests/test_ui.py +++ b/backend/variants/tests/test_ui.py @@ -161,7 +161,7 @@ def _make_user(cls, user_name, superuser): return user -class TestUIBase(projectroles.tests.test_ui.TestUIBase): +class UITestBase(projectroles.tests.test_ui.UITestBase): """Base class for UI tests""" def compile_url_and_login(self, kwargs={}): diff --git a/backend/variants/tests/test_views_ajax_presets.py b/backend/variants/tests/test_views_ajax_presets.py index c87c5f88c..dba76f253 100644 --- a/backend/variants/tests/test_views_ajax_presets.py +++ b/backend/variants/tests/test_views_ajax_presets.py @@ -1,8 +1,6 @@ -from unittest.mock import MagicMock, patch - from django.conf import settings from django.urls import reverse -from projectroles.tests.test_permissions_api import TestProjectAPIPermissionBase +from projectroles.tests.test_permissions_api import ProjectAPIPermissionTestBase from variants.models import ( ChromosomePresets, @@ -25,7 +23,7 @@ from variants.tests.utils import model_to_dict_for_api -class ApiViewTestBase(TestProjectAPIPermissionBase): +class ApiViewTestBase(ProjectAPIPermissionTestBase): media_type = settings.SODAR_API_MEDIA_TYPE api_version = settings.SODAR_API_DEFAULT_VERSION @@ -121,20 +119,16 @@ def setUp(self): def test_post(self): data = {"presetset": self.presetset.sodar_uuid, "label": "my label"} - with patch( - "variants.models.presets.FrequencyPresetsManager.create_as_copy_of_factory_preset", - MagicMock(return_value=FrequencyPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-frequencypresets-clonefactorypresets", - kwargs={"name": "the-name"}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-frequencypresets-clonefactorypresets", + kwargs={"name": "the-name"}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with("the-name", data["label"], self.presetset) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestFrequencyPresetsCloneOtherAjaxView(ApiViewTestBase): @@ -149,22 +143,16 @@ def test_post(self): "presetset": self.presetset.sodar_uuid, "label": "my label", } - with patch( - "variants.models.presets.FrequencyPresetsManager.create_as_copy_of_other_preset", - MagicMock(return_value=FrequencyPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-frequencypresets-cloneother", - kwargs={"frequencypresets": self.frequencypresets.sodar_uuid}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-frequencypresets-cloneother", + kwargs={"frequencypresets": self.frequencypresets.sodar_uuid}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with( - self.frequencypresets, presetset=self.presetset, label=data["label"] - ) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestImpactPresetsListCreateAjaxView(ApiViewTestBase): @@ -253,20 +241,16 @@ def setUp(self): def test_post(self): data = {"presetset": self.presetset.sodar_uuid, "label": "my label"} - with patch( - "variants.models.presets.ImpactPresetsManager.create_as_copy_of_factory_preset", - MagicMock(return_value=ImpactPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-impactpresets-clonefactorypresets", - kwargs={"name": "the-name"}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-impactpresets-clonefactorypresets", + kwargs={"name": "the-name"}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with("the-name", data["label"], self.presetset) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestImpactPresetsCloneOtherAjaxView(ApiViewTestBase): @@ -281,22 +265,16 @@ def test_post(self): "presetset": self.presetset.sodar_uuid, "label": "my label", } - with patch( - "variants.models.presets.ImpactPresetsManager.create_as_copy_of_other_preset", - MagicMock(return_value=ImpactPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-impactpresets-cloneother", - kwargs={"impactpresets": self.impactpresets.sodar_uuid}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-impactpresets-cloneother", + kwargs={"impactpresets": self.impactpresets.sodar_uuid}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with( - self.impactpresets, presetset=self.presetset, label=data["label"] - ) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestQualityPresetsListCreateAjaxView(ApiViewTestBase): @@ -385,20 +363,16 @@ def setUp(self): def test_post(self): data = {"presetset": self.presetset.sodar_uuid, "label": "my label"} - with patch( - "variants.models.presets.QualityPresetsManager.create_as_copy_of_factory_preset", - MagicMock(return_value=QualityPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-qualitypresets-clonefactorypresets", - kwargs={"name": "the-name"}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-qualitypresets-clonefactorypresets", + kwargs={"name": "the-name"}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with("the-name", data["label"], self.presetset) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestQualityPresetsCloneOtherAjaxView(ApiViewTestBase): @@ -413,22 +387,16 @@ def test_post(self): "presetset": self.presetset.sodar_uuid, "label": "my label", } - with patch( - "variants.models.presets.QualityPresetsManager.create_as_copy_of_other_preset", - MagicMock(return_value=QualityPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-qualitypresets-cloneother", - kwargs={"qualitypresets": self.qualitypresets.sodar_uuid}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-qualitypresets-cloneother", + kwargs={"qualitypresets": self.qualitypresets.sodar_uuid}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with( - self.qualitypresets, presetset=self.presetset, label=data["label"] - ) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestChromosomePresetsListCreateAjaxView(ApiViewTestBase): @@ -517,20 +485,16 @@ def setUp(self): def test_post(self): data = {"presetset": self.presetset.sodar_uuid, "label": "my label"} - with patch( - "variants.models.presets.ChromosomePresetsManager.create_as_copy_of_factory_preset", - MagicMock(return_value=ChromosomePresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-chromosomepresets-clonefactorypresets", - kwargs={"name": "the-name"}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-chromosomepresets-clonefactorypresets", + kwargs={"name": "the-name"}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with("the-name", data["label"], self.presetset) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestChromosomePresetsCloneOtherAjaxView(ApiViewTestBase): @@ -545,22 +509,16 @@ def test_post(self): "presetset": self.presetset.sodar_uuid, "label": "my label", } - with patch( - "variants.models.presets.ChromosomePresetsManager.create_as_copy_of_other_preset", - MagicMock(return_value=ChromosomePresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-chromosomepresets-cloneother", - kwargs={"chromosomepresets": self.chromosomepresets.sodar_uuid}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-chromosomepresets-cloneother", + kwargs={"chromosomepresets": self.chromosomepresets.sodar_uuid}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with( - self.chromosomepresets, presetset=self.presetset, label=data["label"] - ) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestFlagsEtcPresetsListCreateAjaxView(ApiViewTestBase): @@ -649,20 +607,16 @@ def setUp(self): def test_post(self): data = {"presetset": self.presetset.sodar_uuid, "label": "my label"} - with patch( - "variants.models.presets.FlagsEtcPresetsManager.create_as_copy_of_factory_preset", - MagicMock(return_value=FlagsEtcPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-flagsetcpresets-clonefactorypresets", - kwargs={"name": "the-name"}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-flagsetcpresets-clonefactorypresets", + kwargs={"name": "the-name"}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with("the-name", data["label"], self.presetset) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestFlagsEtcPresetsCloneOtherAjaxView(ApiViewTestBase): @@ -677,22 +631,16 @@ def test_post(self): "presetset": self.presetset.sodar_uuid, "label": "my label", } - with patch( - "variants.models.presets.FlagsEtcPresetsManager.create_as_copy_of_other_preset", - MagicMock(return_value=FlagsEtcPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-flagsetcpresets-cloneother", - kwargs={"flagsetcpresets": self.flagsetcpresets.sodar_uuid}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-flagsetcpresets-cloneother", + kwargs={"flagsetcpresets": self.flagsetcpresets.sodar_uuid}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with( - self.flagsetcpresets, presetset=self.presetset, label=data["label"] - ) + self.assertEqual(response.json()["presetset"], str(self.presetset.sodar_uuid)) class TestQuickPresetsListCreateAjaxView(ApiViewTestBase): @@ -781,20 +729,16 @@ def setUp(self): def test_post(self): data = {"label": "my label"} - with patch( - "variants.models.presets.QuickPresetsManager.create_as_copy_of_other_preset", - MagicMock(return_value=QuickPresetsFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-quickpresets-cloneother", - kwargs={"quickpresets": self.quickpresets.sodar_uuid}, - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-quickpresets-cloneother", + kwargs={"quickpresets": self.quickpresets.sodar_uuid}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with(self.quickpresets, label=data["label"]) + self.assertEqual(response.json()["presetset"], str(self.quickpresets.presetset.sodar_uuid)) class TestPresetSetListCreateAjaxView(ApiViewTestBase): @@ -895,19 +839,16 @@ def test_delete(self): class TestPresetSetCloneFactoryPresetsAjaxView(ApiViewTestBase): def test_post(self): data = {"project": self.project.sodar_uuid, "label": "my label"} - with patch( - "variants.models.presets.PresetSetManager.create_as_copy_of_factory_preset_set", - MagicMock(return_value=PresetSetFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-presetset-clonefactorypresets", - ), - data=data, - ) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-presetset-clonefactorypresets", + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with(project=self.project, label=data["label"]) + self.assertEqual(response.json()["project"], str(self.project.sodar_uuid)) + self.assertEqual(PresetSet.objects.count(), 1) class TestPresetSetCloneOtherAjaxView(ApiViewTestBase): @@ -917,17 +858,15 @@ def setUp(self): def test_post(self): data = {"project": self.project.sodar_uuid, "label": "my label"} - with patch( - "variants.models.presets.PresetSetManager.create_as_copy_of_other_preset_set", - MagicMock(return_value=PresetSetFactory.build()), - ) as mock_create: - with self.login(self.superuser): - response = self.client.post( - reverse( - "variants:ajax-presetset-cloneother", - kwargs={"presetset": self.presetset.sodar_uuid}, - ), - data=data, - ) + self.assertEqual(PresetSet.objects.count(), 1) + with self.login(self.superuser): + response = self.client.post( + reverse( + "variants:ajax-presetset-cloneother", + kwargs={"presetset": self.presetset.sodar_uuid}, + ), + data=data, + ) self.assertEqual(response.status_code, 201) - mock_create.assert_called_with(self.presetset, project=self.project, label=data["label"]) + self.assertEqual(response.json()["project"], str(self.project.sodar_uuid)) + self.assertEqual(PresetSet.objects.count(), 2) diff --git a/backend/variants/urls/__init__.py b/backend/variants/urls/__init__.py index 659a8df36..7838f5844 100644 --- a/backend/variants/urls/__init__.py +++ b/backend/variants/urls/__init__.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import path from variants import views from variants.urls.annos import annos_ajax_urlpatterns @@ -9,143 +9,143 @@ app_name = "variants" ui_urlpatterns = [ # Views for Case - url( - regex=r"^(?P[0-9a-f-]+)/case-delete-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/case-delete-job/detail//", view=views.CaseDeleteJobDetailView.as_view(), name="case-delete-job-detail", ), # View for list background jobs - url( - regex=r"^(?P[0-9a-f-]+)/jobs/list/(?P[0-9a-f-]+)/?$", + path( + "/jobs/list//", view=views.BackgroundJobListView.as_view(), name="job-list", ), # Views for project sync jobs. - url( - regex=r"^(?P[0-9a-f-]+)/sync-job/(?P[0-9a-f-]+)/?$", + path( + "/sync-job//", view=views.SyncJobDetailView.as_view(), name="sync-job-detail", ), # Views for variants import job. - url( - regex=r"^(?P[0-9a-f-]+)/import/(?P[0-9a-f-]+)/?$", + path( + "/import//", view=views.ImportVariantsJobDetailView.as_view(), name="import-job-detail", ), # Views for single-case file export jobs. - url( - regex=r"^(?P[0-9a-f-]+)/export-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/export-job/detail//", view=views.ExportFileJobDetailView.as_view(), name="export-job-detail", ), - url( - regex=r"^(?P[0-9a-f-]+)/export-job/resubmit/(?P[0-9a-f-]+)/?$", + path( + "/export-job/resubmit//", view=views.ExportFileJobResubmitView.as_view(), name="export-job-resubmit", ), - url( - regex=r"^(?P[0-9a-f-]+)/export-job/download/(?P[0-9a-f-]+)/?$", + path( + "/export-job/download//", view=views.ExportFileJobDownloadView.as_view(), name="export-job-download", ), # Views for project-wide cases file export jobs. - url( - regex=r"^(?P[0-9a-f-]+)/project-cases-export-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/project-cases-export-job/detail//", view=views.ExportProjectCasesFileJobDetailView.as_view(), name="project-cases-export-job-detail", ), - url( - regex=r"^(?P[0-9a-f-]+)/project-cases-export-job/resubmit/(?P[0-9a-f-]+)/?$", + path( + "/project-cases-export-job/resubmit//", view=views.ExportProjectCasesFileJobResubmitView.as_view(), name="project-cases-export-job-resubmit", ), - url( - regex=r"^(?P[0-9a-f-]+)/project-cases-export-job/download/(?P[0-9a-f-]+)/?$", + path( + "/project-cases-export-job/download//", view=views.ExportProjectCasesFileJobDownloadView.as_view(), name="project-cases-export-job-download", ), # Views for MutationDistiller submission jobs - url( - regex=r"^(?P[0-9a-f-]+)/distiller-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/distiller-job/detail//", view=views.DistillerSubmissionJobDetailView.as_view(), name="distiller-job-detail", ), - url( - regex=r"^(?P[0-9a-f-]+)/distiller-job/resubmit/(?P[0-9a-f-]+)/?$", + path( + "/distiller-job/resubmit//", view=views.DistillerSubmissionJobResubmitView.as_view(), name="distiller-job-resubmit", ), # Views for CADD submission jobs - url( - regex=r"^(?P[0-9a-f-]+)/cadd-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/cadd-job/detail//", view=views.CaddSubmissionJobDetailView.as_view(), name="cadd-job-detail", ), - url( - regex=r"^(?P[0-9a-f-]+)/cadd-job/resubmit/(?P[0-9a-f-]+)/?$", + path( + "/cadd-job/resubmit//", view=views.CaddSubmissionJobResubmitView.as_view(), name="cadd-job-resubmit", ), # Views for SPANR submission jobs - url( - regex=r"^(?P[0-9a-f-]+)/spanr-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/spanr-job/detail//", view=views.SpanrSubmissionJobDetailView.as_view(), name="spanr-job-detail", ), - url( - regex=r"^(?P[0-9a-f-]+)/spanr-job/resubmit/(?P[0-9a-f-]+)/?$", + path( + "/spanr-job/resubmit//", view=views.SpanrSubmissionJobResubmitView.as_view(), name="spanr-job-resubmit", ), # Views for Project-wide Statistics Computation submission jobs - url( - regex=r"^(?P[0-9a-f-]+)/project-stats-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/project-stats-job/detail//", view=views.ProjectStatsJobDetailView.as_view(), name="project-stats-job-detail", ), # Views for filtering and storing case query results jobs - url( - regex=r"^(?P[0-9a-f-]+)/filter-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/filter-job/detail//", view=views.FilterJobDetailView.as_view(), name="filter-job-detail", ), - url( - regex=r"^(?P[0-9a-f-]+)/filter-job/resubmit/(?P[0-9a-f-]+)/?$", + path( + "/filter-job/resubmit//", view=views.FilterJobResubmitView.as_view(), name="filter-job-resubmit", ), # Views for filtering and storing project cases query results jobs - url( - regex=r"^(?P[0-9a-f-]+)/project-cases-filter-job/detail/(?P[0-9a-f-]+)/?$", + path( + "/project-cases-filter-job/detail//", view=views.ProjectCasesFilterJobDetailView.as_view(), name="project-cases-filter-job-detail", ), - url( - regex=r"^(?P[0-9a-f-]+)/project-cases-filter-job/resubmit/(?P[0-9a-f-]+)/?$", + path( + "/project-cases-filter-job/resubmit//", view=views.ProjectCasesFilterJobResubmitView.as_view(), name="project-cases-filter-job-resubmit", ), # Set last seen changelog version for user and redirect to changelog. # TODO: move to sodar-core? - url(regex=r"^new-features/?$", view=views.NewFeaturesView.as_view(), name="new-features"), + path("new-features/", view=views.NewFeaturesView.as_view(), name="new-features"), #: Detail views for site-wide maintenance jobs. - url( - regex=r"^clear-expired-job/(?P[0-9a-f-]+)/?$", + path( + "clear-expired-job//", view=views.ClearExpiredExportedFilesJobDetailView.as_view(), name="clear-expired-job-detail", ), - url( - regex=r"^clear-inactive-variant-set-job/(?P[0-9a-f-]+)/?$", + path( + "clear-inactive-variant-set-job//", view=views.ClearInactiveVariantSetsJobDetailView.as_view(), name="clear-inactive-variant-set-job", ), - url( - regex=r"^clear-old-kiosk-cases-job/(?P[0-9a-f-]+)/?$", + path( + "clear-old-kiosk-cases-job//", view=views.ClearOldKioskCasesJobDetailView.as_view(), name="clear-old-kiosk-cases-job-detail", ), - url( - regex=r"^refresh-small-variant-summaries-job/(?P[0-9a-f-]+)/?$", + path( + "refresh-small-variant-summaries-job//", view=views.RefreshSmallVariantSummaryJobDetailView.as_view(), name="refresh-small-variant-summaries-job-detail", ), @@ -153,301 +153,301 @@ # Ajax API views ajax_urlpatterns = [ - url( - regex=r"^ajax/project/qc/(?P[0-9a-f-]+)/?$", + path( + "ajax/project/qc//", view=views_ajax.CaseListQcStatsAjaxView.as_view(), name="ajax-project-qc", ), - url( - regex=r"^ajax/case/retrieve/(?P[0-9a-f-]+)/?$", + path( + "ajax/case/retrieve//", view=views_ajax.CaseRetrieveAjaxView.as_view(), name="ajax-case-retrieve", ), - url( - regex=r"^ajax/query-case/list/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/list//", view=views_ajax.SmallVariantQueryListAjaxView.as_view(), name="ajax-query-case-list", ), - url( - regex=r"^ajax/query/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/query/list-create//", view=views_ajax.SmallVariantQueryListCreateAjaxView.as_view(), name="ajax-query-list-create", ), - url( - regex=r"^ajax/query/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/query/retrieve-update-destroy//", view=views_ajax.SmallVariantQueryRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-query-retrieve-update-destroy", ), - url( - regex=r"^ajax/query-result-set/list/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-result-set/list//", view=views_ajax.SmallVariantQueryResultSetListAjaxView.as_view(), name="ajax-query-result-set-list", ), - url( - regex=r"^ajax/query-result-set/retrieve/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-result-set/retrieve//", view=views_ajax.SmallVariantQueryResultSetRetrieveAjaxView.as_view(), name="ajax-query-result-set-retrieve", ), - url( - regex=r"^ajax/query-result-row/list/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-result-row/list//", view=views_ajax.SmallVariantQueryResultRowListAjaxView.as_view(), name="ajax-query-result-row-list", ), - url( - regex=r"^ajax/query-result-row/retrieve/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-result-row/retrieve//", view=views_ajax.SmallVariantQueryResultRowRetrieveAjaxView.as_view(), name="ajax-query-result-row-retrieve", ), - url( - r"^ajax/query-case/query-settings-shortcut/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/query-settings-shortcut//", view=views_ajax.SmallVariantQuerySettingsShortcutAjaxView.as_view(), name="ajax-query-settings-shortcut", ), - url( - r"^ajax/query-case/download/generate/tsv/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/download/generate/tsv//", view=views_ajax.SmallVariantQueryDownloadGenerateAjaxView.as_view(), name="ajax-query-case-download-generate-tsv", ), - url( - r"^ajax/query-case/download/generate/vcf/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/download/generate/vcf//", view=views_ajax.SmallVariantQueryDownloadGenerateAjaxView.as_view(), name="ajax-query-case-download-generate-vcf", ), - url( - r"^ajax/query-case/download/generate/xlsx/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/download/generate/xlsx//", view=views_ajax.SmallVariantQueryDownloadGenerateAjaxView.as_view(), name="ajax-query-case-download-generate-xlsx", ), - url( - r"^ajax/query-case/download/serve/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/download/serve//", view=views_ajax.SmallVariantQueryDownloadServeAjaxView.as_view(), name="ajax-query-case-download-serve", ), - url( - r"^ajax/query-case/download/status/(?P[0-9a-f-]+)/?$", + path( + "ajax/query-case/download/status//", view=views_ajax.SmallVariantQueryDownloadStatusAjaxView.as_view(), name="ajax-query-case-download-status", ), - url( - r"^ajax/small-variant-comment/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/small-variant-comment/list-create//", view=views_ajax.SmallVariantCommentListCreateAjaxView.as_view(), name="ajax-small-variant-comment-list-create", ), - url( - r"^ajax/small-variant-comment/list-project/(?P[0-9a-f-]+)/?$", + path( + "ajax/small-variant-comment/list-project//", view=views_ajax.SmallVariantCommentListProjectAjaxView.as_view(), name="ajax-small-variant-comment-list-project", ), - url( - r"^ajax/small-variant-comment/update/(?P[0-9a-f-]+)/?$", + path( + "ajax/small-variant-comment/update//", view=views_ajax.SmallVariantCommentUpdateAjaxView.as_view(), name="ajax-small-variant-comment-update", ), - url( - r"^ajax/small-variant-comment/delete/(?P[0-9a-f-]+)/?$", + path( + "ajax/small-variant-comment/delete//", view=views_ajax.SmallVariantCommentDeleteAjaxView.as_view(), name="ajax-small-variant-comment-delete", ), - url( - r"^ajax/small-variant-flags/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/small-variant-flags/list-create//", view=views_ajax.SmallVariantFlagsListCreateAjaxView.as_view(), name="ajax-small-variant-flags-list-create", ), - url( - r"^ajax/small-variant-flags/list-project/(?P[0-9a-f-]+)/?$", + path( + "ajax/small-variant-flags/list-project//", view=views_ajax.SmallVariantFlagsListProjectAjaxView.as_view(), name="ajax-small-variant-flags-list-project", ), - url( - r"^ajax/small-variant-flags/update/(?P[0-9a-f-]+)/?$", + path( + "ajax/small-variant-flags/update//", view=views_ajax.SmallVariantFlagsUpdateAjaxView.as_view(), name="ajax-small-variant-flags-update", ), - url( - r"^ajax/small-variant-flags/delete/(?P[0-9a-f-]+)/?$", + path( + "ajax/small-variant-flags/delete//", view=views_ajax.SmallVariantFlagsDeleteAjaxView.as_view(), name="ajax-small-variant-flags-delete", ), - url( - r"^ajax/acmg-criteria-rating/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/acmg-criteria-rating/list-create//", view=views_ajax.AcmgCriteriaRatingListCreateAjaxView.as_view(), name="ajax-acmg-criteria-rating-list-create", ), - url( - r"^ajax/acmg-criteria-rating/update/(?P[0-9a-f-]+)/?$", + path( + "ajax/acmg-criteria-rating/update//", view=views_ajax.AcmgCriteriaRatingUpdateAjaxView.as_view(), name="ajax-acmg-criteria-rating-update", ), - url( - r"^ajax/acmg-criteria-rating/delete/(?P[0-9a-f-]+)/?$", + path( + "ajax/acmg-criteria-rating/delete//", view=views_ajax.AcmgCriteriaRatingDeleteAjaxView.as_view(), name="ajax-acmg-criteria-rating-delete", ), - url( - r"^ajax/extra-anno-fields/?$", + path( + "ajax/extra-anno-fields/", view=views_ajax.ExtraAnnoFieldsApiView.as_view(), name="ajax-extra-anno-fields", ), - url( - regex=r"^ajax/project-settings/retrieve/(?P[0-9a-f-]+)/?$", + path( + "ajax/project-settings/retrieve//", view=views_ajax.ProjectSettingsRetrieveAjaxView.as_view(), name="ajax-project-settings-retrieve", ), ] api_urlpatterns = [ - url( - regex=r"^api/project/qc/(?P[0-9a-f-]+)/?$", + path( + "api/project/qc//", view=views_api.CaseListQcStatsApiView.as_view(), name="api-project-qc", ), - url( - regex=r"^api/case/retrieve/(?P[0-9a-f-]+)/?$", + path( + "api/case/retrieve//", view=views_api.CaseRetrieveApiView.as_view(), name="api-case-retrieve", ), - url( - regex=r"^api/query-case/list/(?P[0-9a-f-]+)/?$", + path( + "api/query-case/list//", view=views_api.SmallVariantQueryListApiView.as_view(), name="api-query-case-list", ), - url( - regex=r"^api/query/list-create/(?P[0-9a-f-]+)/?$", + path( + "api/query/list-create//", view=views_api.SmallVariantQueryListCreateApiView.as_view(), name="api-query-list-create", ), - url( - regex=r"^api/query/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "api/query/retrieve-update-destroy//", view=views_api.SmallVariantQueryRetrieveUpdateDestroyApiView.as_view(), name="api-query-retrieve-update-destroy", ), - url( - regex=r"^api/query-result-set/list/(?P[0-9a-f-]+)/?$", + path( + "api/query-result-set/list//", view=views_api.SmallVariantQueryResultSetListApiView.as_view(), name="api-query-result-set-list", ), - url( - regex=r"^api/query-result-set/retrieve/(?P[0-9a-f-]+)/?$", + path( + "api/query-result-set/retrieve//", view=views_api.SmallVariantQueryResultSetRetrieveApiView.as_view(), name="api-query-result-set-retrieve", ), - url( - regex=r"^api/query-result-row/list/(?P[0-9a-f-]+)/?$", + path( + "api/query-result-row/list//", view=views_api.SmallVariantQueryResultRowListApiView.as_view(), name="api-query-result-row-list", ), - url( - regex=r"^api/query-result-row/retrieve/(?P[0-9a-f-]+)/?$", + path( + "api/query-result-row/retrieve//", view=views_api.SmallVariantQueryResultRowRetrieveApiView.as_view(), name="api-query-result-row-retrieve", ), - url( - regex=r"^api/query-case/query-settings-shortcut/(?P[0-9a-f-]+)/?$", + path( + "api/query-case/query-settings-shortcut//", view=views_api.SmallVariantQuerySettingsShortcutApiView.as_view(), name="api-query-settings-shortcut", ), - url( - regex=r"^api/query-case/quick-presets/?$", + path( + "api/query-case/quick-presets/", view=views_api.SmallVariantQuickPresetsApiView.as_view(), name="api-quick-presets", ), - url( - regex=r"^api/query-case/category-presets/(?P[a-zA-Z0-9\._-]+)/?$", + path( + "api/query-case/category-presets//", view=views_api.SmallVariantCategoryPresetsApiView.as_view(), name="api-category-presets", ), - url( - regex=r"^api/query-case/inheritance-presets/(?P[0-9a-f-]+)/?$", + path( + "api/query-case/inheritance-presets//", view=views_api.SmallVariantInheritancePresetsApiView.as_view(), name="api-inheritance-presets", ), - url( - regex=r"^api/query-case/download/generate/tsv/(?P[0-9a-f-]+)/?$", + path( + "api/query-case/download/generate/tsv//", view=views_api.SmallVariantQueryDownloadGenerateApiView.as_view(), name="api-query-case-download-generate-tsv", ), - url( - regex=r"^api/query-case/download/generate/vcf/(?P[0-9a-f-]+)/?$", + path( + "api/query-case/download/generate/vcf//", view=views_api.SmallVariantQueryDownloadGenerateApiView.as_view(), name="api-query-case-download-generate-vcf", ), - url( - regex=r"^api/query-case/download/generate/xlsx/(?P[0-9a-f-]+)/?$", + path( + "api/query-case/download/generate/xlsx//", view=views_api.SmallVariantQueryDownloadGenerateApiView.as_view(), name="api-query-case-download-generate-xlsx", ), - url( - regex=r"^api/query-case/download/serve/(?P[0-9a-f-]+)/?$", + path( + "api/query-case/download/serve//", view=views_api.SmallVariantQueryDownloadServeApiView.as_view(), name="api-query-case-download-serve", ), - url( - regex=r"^api/query-case/download/status/(?P[0-9a-f-]+)/?$", + path( + "api/query-case/download/status//", view=views_api.SmallVariantQueryDownloadStatusApiView.as_view(), name="api-query-case-download-status", ), - url( - r"^api/small-variant-comment/list-create/(?P[0-9a-f-]+)/?$", + path( + "api/small-variant-comment/list-create//", view=views_api.SmallVariantCommentListCreateApiView.as_view(), name="api-small-variant-comment-list-create", ), - url( - r"^api/small-variant-comment/list-project/(?P[0-9a-f-]+)/?$", + path( + "api/small-variant-comment/list-project//", view=views_api.SmallVariantCommentListProjectApiView.as_view(), name="api-small-variant-comment-list-project", ), - url( - r"^api/small-variant-comment/update/(?P[0-9a-f-]+)/?$", + path( + "api/small-variant-comment/update//", view=views_api.SmallVariantCommentUpdateApiView.as_view(), name="api-small-variant-comment-update", ), - url( - r"^api/small-variant-comment/delete/(?P[0-9a-f-]+)/?$", + path( + "api/small-variant-comment/delete//", view=views_api.SmallVariantCommentDeleteApiView.as_view(), name="api-small-variant-comment-delete", ), - url( - r"^api/small-variant-flags/list-create/(?P[0-9a-f-]+)/?$", + path( + "api/small-variant-flags/list-create//", view=views_api.SmallVariantFlagsListCreateApiView.as_view(), name="api-small-variant-flags-list-create", ), - url( - r"^api/small-variant-flags/list-project/(?P[0-9a-f-]+)/?$", + path( + "api/small-variant-flags/list-project//", view=views_api.SmallVariantFlagsListProjectApiView.as_view(), name="api-small-variant-flags-list-project", ), - url( - r"^api/small-variant-flags/update/(?P[0-9a-f-]+)/?$", + path( + "api/small-variant-flags/update//", view=views_api.SmallVariantFlagsUpdateApiView.as_view(), name="api-small-variant-flags-update", ), - url( - r"^api/small-variant-flags/delete/(?P[0-9a-f-]+)/?$", + path( + "api/small-variant-flags/delete//", view=views_api.SmallVariantFlagsDeleteApiView.as_view(), name="api-small-variant-flags-delete", ), - url( - r"^api/acmg-criteria-rating/list-create/(?P[0-9a-f-]+)/?$", + path( + "api/acmg-criteria-rating/list-create//", view=views_api.AcmgCriteriaRatingListCreateApiView.as_view(), name="api-acmg-criteria-rating-list-create", ), - url( - r"^api/acmg-criteria-rating/update/(?P[0-9a-f-]+)/?$", + path( + "api/acmg-criteria-rating/update//", view=views_api.AcmgCriteriaRatingUpdateApiView.as_view(), name="api-acmg-criteria-rating-update", ), - url( - r"^api/acmg-criteria-rating/delete/(?P[0-9a-f-]+)/?$", + path( + "api/acmg-criteria-rating/delete//", view=views_api.AcmgCriteriaRatingDeleteApiView.as_view(), name="api-acmg-criteria-rating-delete", ), - url( - r"^api/extra-anno-fields/?$", + path( + "api/extra-anno-fields/", view=views_api.ExtraAnnoFieldsApiView.as_view(), name="api-extra-anno-fields", ), - url( - regex=r"^api/project-settings/retrieve/(?P[0-9a-f-]+)/?$", + path( + "api/project-settings/retrieve//", view=views_api.ProjectSettingsRetrieveApiView.as_view(), name="api-project-settings-retrieve", ), diff --git a/backend/variants/urls/annos.py b/backend/variants/urls/annos.py index 75e9fb7c7..28ba689c3 100644 --- a/backend/variants/urls/annos.py +++ b/backend/variants/urls/annos.py @@ -1,14 +1,14 @@ """User annotation--related urls.""" -from django.conf.urls import url +from django.urls import path from variants.views.ajax.annos import CaseUserAnnotatedVariantsAjaxView ui_urlpatterns = [] ajax_urlpatterns = [ - url( - regex=r"^ajax/smallvariant/user-annotated-case/(?P[0-9a-f-]+)/?$", + path( + "ajax/smallvariant/user-annotated-case//", view=CaseUserAnnotatedVariantsAjaxView.as_view(), name="ajax-smallvariant-userannotatedcase", ), diff --git a/backend/variants/urls/presets.py b/backend/variants/urls/presets.py index 6f806ff83..b1e7dd30e 100644 --- a/backend/variants/urls/presets.py +++ b/backend/variants/urls/presets.py @@ -1,6 +1,6 @@ """Presets-related urls.""" -from django.conf.urls import url +from django.urls import path import variants.views.ajax.presets as views_ajax @@ -9,158 +9,158 @@ ### "Regular" PresetSet members ### ################################### # FrequencyPresets - url( - regex=r"^ajax/frequencypresets/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/frequencypresets/list-create//", view=views_ajax.FrequencyPresetsListCreateAjaxView.as_view(), name="ajax-frequencypresets-listcreate", ), - url( - regex=r"^ajax/frequencypresets/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/frequencypresets/retrieve-update-destroy//", view=views_ajax.FrequencyPresetsRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-frequencypresets-retrieveupdatedestroy", ), - url( - regex=r"^ajax/frequencypresets/clone-factory-presets/(?P[a-zA-Z_-]+)/?$", + path( + "ajax/frequencypresets/clone-factory-presets//", view=views_ajax.FrequencyPresetsCloneFactoryPresetsAjaxView.as_view(), name="ajax-frequencypresets-clonefactorypresets", ), - url( - regex=r"ajax/frequencypresets/clone-other/(?P[0-9a-f-]+)/?$", + path( + "ajax/frequencypresets/clone-other//", view=views_ajax.FrequencyPresetsCloneOtherAjaxView.as_view(), name="ajax-frequencypresets-cloneother", ), # FlagsEtcPresets - url( - regex=r"^ajax/flagsetcpresets/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/flagsetcpresets/list-create//", view=views_ajax.FlagsEtcPresetsListCreateAjaxView.as_view(), name="ajax-flagsetcpresets-listcreate", ), - url( - regex=r"^ajax/flagsetcpresets/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/flagsetcpresets/retrieve-update-destroy//", view=views_ajax.FlagsEtcPresetsRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-flagsetcpresets-retrieveupdatedestroy", ), - url( - regex=r"^ajax/flagsetcpresets/clone-factory-presets/(?P[a-zA-Z_-]+)/?$", + path( + "ajax/flagsetcpresets/clone-factory-presets//", view=views_ajax.FlagsEtcPresetsCloneFactoryPresetsAjaxView.as_view(), name="ajax-flagsetcpresets-clonefactorypresets", ), - url( - regex=r"ajax/flagsetcpresets/clone-other/(?P[0-9a-f-]+)/?$", + path( + "ajax/flagsetcpresets/clone-other//", view=views_ajax.FlagsEtcPresetsCloneOtherAjaxView.as_view(), name="ajax-flagsetcpresets-cloneother", ), # ImpactPresets - url( - regex=r"^ajax/impactpresets/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/impactpresets/list-create//", view=views_ajax.ImpactPresetsListCreateAjaxView.as_view(), name="ajax-impactpresets-listcreate", ), - url( - regex=r"^ajax/impactpresets/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/impactpresets/retrieve-update-destroy//", view=views_ajax.ImpactPresetsRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-impactpresets-retrieveupdatedestroy", ), - url( - regex=r"^ajax/impactpresets/clone-factory-presets/(?P[a-zA-Z_-]+)/?$", + path( + "ajax/impactpresets/clone-factory-presets//", view=views_ajax.ImpactPresetsCloneFactoryPresetsAjaxView.as_view(), name="ajax-impactpresets-clonefactorypresets", ), - url( - regex=r"ajax/impactpresets/clone-other/(?P[0-9a-f-]+)/?$", + path( + "ajax/impactpresets/clone-other//", view=views_ajax.ImpactPresetsCloneOtherAjaxView.as_view(), name="ajax-impactpresets-cloneother", ), # QualityPresets - url( - regex=r"^ajax/qualitypresets/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/qualitypresets/list-create//", view=views_ajax.QualityPresetsListCreateAjaxView.as_view(), name="ajax-qualitypresets-listcreate", ), - url( - regex=r"^ajax/qualitypresets/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/qualitypresets/retrieve-update-destroy//", view=views_ajax.QualityPresetsRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-qualitypresets-retrieveupdatedestroy", ), - url( - regex=r"^ajax/qualitypresets/clone-factory-presets/(?P[a-zA-Z_-]+)/?$", + path( + "ajax/qualitypresets/clone-factory-presets//", view=views_ajax.QualityPresetsCloneFactoryPresetsAjaxView.as_view(), name="ajax-qualitypresets-clonefactorypresets", ), - url( - regex=r"ajax/qualitypresets/clone-other/(?P[0-9a-f-]+)/?$", + path( + "ajax/qualitypresets/clone-other//", view=views_ajax.QualityPresetsCloneOtherAjaxView.as_view(), name="ajax-qualitypresets-cloneother", ), # ChromosomePresets - url( - regex=r"^ajax/chromosomepresets/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/chromosomepresets/list-create//", view=views_ajax.ChromosomePresetsListCreateAjaxView.as_view(), name="ajax-chromosomepresets-listcreate", ), - url( - regex=r"^ajax/chromosomepresets/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/chromosomepresets/retrieve-update-destroy//", view=views_ajax.ChromosomePresetsRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-chromosomepresets-retrieveupdatedestroy", ), - url( - regex=r"^ajax/chromosomepresets/clone-factory-presets/(?P[a-zA-Z_-]+)/?$", + path( + "ajax/chromosomepresets/clone-factory-presets//", view=views_ajax.ChromosomePresetsCloneFactoryPresetsAjaxView.as_view(), name="ajax-chromosomepresets-clonefactorypresets", ), - url( - regex=r"ajax/chromosomepresets/clone-other/(?P[0-9a-f-]+)/?$", + path( + "ajax/chromosomepresets/clone-other//", view=views_ajax.ChromosomePresetsCloneOtherAjaxView.as_view(), name="ajax-chromosomepresets-cloneother", ), ############################################# ### Quick Presets (only clone from other) ### ############################################# - url( - regex=r"^ajax/quickpresets/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/quickpresets/list-create//", view=views_ajax.QuickPresetsListCreateAjaxView.as_view(), name="ajax-quickpresets-listcreate", ), - url( - regex=r"^ajax/quickpresets/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/quickpresets/retrieve-update-destroy//", view=views_ajax.QuickPresetsRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-quickpresets-retrieveupdatedestroy", ), - url( - regex=r"^ajax/quickpresets/clone-other/(?P[0-9a-f-]+)/?$", + path( + "ajax/quickpresets/clone-other//", view=views_ajax.QuickPresetsCloneOtherAjaxView.as_view(), name="ajax-quickpresets-cloneother", ), ################# ### PresetSet ### ################# - url( - regex=r"^ajax/presetset/list/?$", + path( + "ajax/presetset/list/", view=views_ajax.PresetSetListAllAjaxView.as_view(), name="ajax-presetset-listall", ), - url( - regex=r"^ajax/presetset/list-create/(?P[0-9a-f-]+)/?$", + path( + "ajax/presetset/list-create//", view=views_ajax.PresetSetListCreateAjaxView.as_view(), name="ajax-presetset-listcreate", ), - url( - regex=r"^ajax/presetset/retrieve-update-destroy/(?P[0-9a-f-]+)/?$", + path( + "ajax/presetset/retrieve-update-destroy//", view=views_ajax.PresetSetRetrieveUpdateDestroyAjaxView.as_view(), name="ajax-presetset-retrieveupdatedestroy", ), - url( - regex=r"^ajax/presetset/clone-factory-presets/?$", + path( + "ajax/presetset/clone-factory-presets/", view=views_ajax.PresetSetCloneFactoryPresetsAjaxView.as_view(), name="ajax-presetset-clonefactorypresets", ), - url( - regex=r"^ajax/presetset/clone-other/(?P[0-9a-f-]+)/?$", + path( + "ajax/presetset/clone-other//", view=views_ajax.PresetSetCloneOtherAjaxView.as_view(), name="ajax-presetset-cloneother", ), - url( - regex=r"^ajax/project-default-presetset/retrieve/(?P[a-zA-Z0-9\._-]+)/?$", + path( + "ajax/project-default-presetset/retrieve//", view=views_ajax.ProjectDefaultPresetSetRetrieveAjaxView.as_view(), name="ajax-project-default-presetset-retrieve", ), diff --git a/frontend/ext/reev-frontend-lib b/frontend/ext/reev-frontend-lib index 74df3b985..b190d2002 160000 --- a/frontend/ext/reev-frontend-lib +++ b/frontend/ext/reev-frontend-lib @@ -1 +1 @@ -Subproject commit 74df3b985bf02c997487a5f6484e0e31cfcf89ce +Subproject commit b190d20026247c841857284045b27702c18700ac diff --git a/frontend/src/svs/components/SvFilterForm/GenesRegionsPane.vue b/frontend/src/svs/components/SvFilterForm/GenesRegionsPane.vue index 3268a7b75..894bb7873 100644 --- a/frontend/src/svs/components/SvFilterForm/GenesRegionsPane.vue +++ b/frontend/src/svs/components/SvFilterForm/GenesRegionsPane.vue @@ -306,14 +306,14 @@ defineExpose({ :options="genomicsEnglandPanels" placeholder="Add from GE PanelApp" :searchable="true" - @select="insertGenomicsEnglandPanel" style="width: 400px" + @select="insertGenomicsEnglandPanel" />