From 7252cd786ebc007ecf5461649273ece401ffe8a6 Mon Sep 17 00:00:00 2001 From: Harris Tzovanakis Date: Tue, 5 Dec 2023 09:42:17 +0100 Subject: [PATCH] articles: addition of compliance check * ref cern-sis/issues-scoap3#255 --- Makefile | 6 + poetry.lock | 367 +++++++++++++++++- pyproject.toml | 6 + scoap3/articles/admin.py | 216 ++++++++++- .../migrations/0012_compliancereport.py | 41 ++ ...check_article_type_description_and_more.py | 37 ++ scoap3/articles/models.py | 42 +- scoap3/articles/tasks.py | 161 ++++++++ ...ArticleCompliance.test_create_article.yaml | 338 ++++++++++++++++ ...te_article_with_missing_compliant_doi.yaml | 158 ++++++++ ...cle_with_not_compliant_arxiv_category.yaml | 86 ++++ ...create_article_with_not_compliant_doi.yaml | 278 +++++++++++++ ...rticle_with_not_compliant_file_format.yaml | 86 ++++ ...eate_article_with_not_compliant_title.yaml | 86 ++++ .../articles/tests/test_article_compliance.py | 140 +++++++ scoap3/conftest.py | 11 + ...etch_doi_registration_date_happy_case.yaml | 192 +++++++++ ...tch_doi_registration_date_invalid_doi.yaml | 53 +++ scoap3/misc/tests/test_misc_utils.py | 18 + scoap3/misc/utils.py | 18 + scoap3/utils/tests/conftest.py | 29 ++ 21 files changed, 2362 insertions(+), 7 deletions(-) create mode 100644 scoap3/articles/migrations/0012_compliancereport.py create mode 100644 scoap3/articles/migrations/0013_compliancereport_check_article_type_description_and_more.py create mode 100644 scoap3/articles/tasks.py create mode 100644 scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article.yaml create mode 100644 scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_missing_compliant_doi.yaml create mode 100644 scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_arxiv_category.yaml create mode 100644 scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_doi.yaml create mode 100644 scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_file_format.yaml create mode 100644 scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_title.yaml create mode 100644 scoap3/articles/tests/test_article_compliance.py create mode 100644 scoap3/misc/tests/cassettes/TestFetchDOIRegistrationDate.test_fetch_doi_registration_date_happy_case.yaml create mode 100644 scoap3/misc/tests/cassettes/TestFetchDOIRegistrationDate.test_fetch_doi_registration_date_invalid_doi.yaml create mode 100644 scoap3/misc/tests/test_misc_utils.py create mode 100644 scoap3/misc/utils.py create mode 100644 scoap3/utils/tests/conftest.py diff --git a/Makefile b/Makefile index 1b1da5f8a..75d490dae 100644 --- a/Makefile +++ b/Makefile @@ -30,3 +30,9 @@ shell: flush: poetry run python manage.py flush + +make-migrations: + poetry run python manage.py makemigrations + +migrate: + poetry run python manage.py migrate diff --git a/poetry.lock b/poetry.lock index e6d14ebc9..64eda5d05 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -997,6 +997,20 @@ files = [ [package.dependencies] Django = ">=3.2" +[[package]] +name = "django-lifecycle" +version = "1.1.2" +description = "Declarative model lifecycle hooks." +optional = false +python-versions = "*" +files = [ + {file = "django-lifecycle-1.1.2.tar.gz", hash = "sha256:c127392cf3fe7099362afaca5eef0b79460b73380e807733b3ff9648ce92c6ea"}, + {file = "django_lifecycle-1.1.2-py3-none-any.whl", hash = "sha256:6083cb2969071f06762316e81441e9cd586b59737e968a27e68710fee874c4d9"}, +] + +[package.dependencies] +Django = ">=3.2" + [[package]] name = "django-model-utils" version = "4.3.1" @@ -1376,6 +1390,20 @@ prometheus-client = ">=0.8.0" pytz = "*" tornado = ">=5.0.0,<7.0.0" +[[package]] +name = "freezegun" +version = "1.3.1" +description = "Let your Python tests travel through time" +optional = false +python-versions = ">=3.7" +files = [ + {file = "freezegun-1.3.1-py3-none-any.whl", hash = "sha256:065e77a12624d05531afa87ade12a0b9bdb53495c4573893252a055b545ce3ea"}, + {file = "freezegun-1.3.1.tar.gz", hash = "sha256:48984397b3b58ef5dfc645d6a304b0060f612bcecfdaaf45ce8aff0077a6cb6a"}, +] + +[package.dependencies] +python-dateutil = ">=2.7" + [[package]] name = "gunicorn" version = "20.1.0" @@ -1396,6 +1424,25 @@ gevent = ["gevent (>=1.4.0)"] setproctitle = ["setproctitle"] tornado = ["tornado (>=0.2)"] +[[package]] +name = "habanero" +version = "1.2.3" +description = "Low Level Client for Crossref Search API" +optional = false +python-versions = ">=3.7" +files = [ + {file = "habanero-1.2.3-py2.py3-none-any.whl", hash = "sha256:b95dd0af36893888a2def276a3d5e16a8c133ed8906d08a2772cdaa7d1e7617c"}, + {file = "habanero-1.2.3.tar.gz", hash = "sha256:196f9e01b42dad2cd829dc5d0bbe466232daf6ad5f1b0ee7098a57927b17e908"}, +] + +[package.dependencies] +requests = ">=2.7.0" +tqdm = "*" + +[package.extras] +all = ["pytest"] +test = ["pytest"] + [[package]] name = "hiredis" version = "2.2.3" @@ -1859,6 +1906,89 @@ files = [ {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, ] +[[package]] +name = "multidict" +version = "6.0.4" +description = "multidict implementation" +optional = false +python-versions = ">=3.7" +files = [ + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, + {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, + {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, + {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, + {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, + {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, + {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, + {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, + {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, + {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, + {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, + {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, + {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, + {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, + {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, + {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, + {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, + {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, + {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, + {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, + {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, + {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, + {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, + {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, + {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, + {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, + {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, +] + [[package]] name = "mypy" version = "1.5.1" @@ -2450,6 +2580,21 @@ termcolor = ">=2.1.0" [package.extras] dev = ["black", "flake8", "pre-commit"] +[[package]] +name = "pytest-vcr" +version = "1.0.2" +description = "Plugin for managing VCR.py cassettes" +optional = false +python-versions = "*" +files = [ + {file = "pytest-vcr-1.0.2.tar.gz", hash = "sha256:23ee51b75abbcc43d926272773aae4f39f93aceb75ed56852d0bf618f92e1896"}, + {file = "pytest_vcr-1.0.2-py2.py3-none-any.whl", hash = "sha256:2f316e0539399bea0296e8b8401145c62b6f85e9066af7e57b6151481b0d6d9c"}, +] + +[package.dependencies] +pytest = ">=3.6.0" +vcrpy = "*" + [[package]] name = "python-crontab" version = "3.0.0" @@ -3113,6 +3258,26 @@ files = [ {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"}, ] +[[package]] +name = "tqdm" +version = "4.66.1" +description = "Fast, Extensible Progress Meter" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tqdm-4.66.1-py3-none-any.whl", hash = "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386"}, + {file = "tqdm-4.66.1.tar.gz", hash = "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +dev = ["pytest (>=6)", "pytest-cov", "pytest-timeout", "pytest-xdist"] +notebook = ["ipywidgets (>=6)"] +slack = ["slack-sdk"] +telegram = ["requests"] + [[package]] name = "traitlets" version = "5.10.1" @@ -3234,6 +3399,22 @@ brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[[package]] +name = "vcrpy" +version = "5.1.0" +description = "Automatically mock your HTTP interactions to simplify and speed up testing" +optional = false +python-versions = ">=3.8" +files = [ + {file = "vcrpy-5.1.0-py2.py3-none-any.whl", hash = "sha256:605e7b7a63dcd940db1df3ab2697ca7faf0e835c0852882142bafb19649d599e"}, + {file = "vcrpy-5.1.0.tar.gz", hash = "sha256:bbf1532f2618a04f11bce2a99af3a9647a32c880957293ff91e0a5f187b6b3d2"}, +] + +[package.dependencies] +PyYAML = "*" +wrapt = "*" +yarl = "*" + [[package]] name = "vine" version = "5.0.0" @@ -3381,7 +3562,189 @@ files = [ [package.extras] brotli = ["Brotli"] +[[package]] +name = "wrapt" +version = "1.16.0" +description = "Module for decorators, wrappers and monkey patching." +optional = false +python-versions = ">=3.6" +files = [ + {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, + {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, + {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, + {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, + {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, + {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, + {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, + {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, + {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, + {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, + {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, + {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, + {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, + {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, + {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, + {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, + {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, + {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, + {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, + {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, + {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, + {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, + {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, + {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, + {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, + {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, + {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, + {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, + {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, + {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, + {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, + {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, + {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, + {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, + {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, + {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, + {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, +] + +[[package]] +name = "yarl" +version = "1.9.4" +description = "Yet another URL library" +optional = false +python-versions = ">=3.7" +files = [ + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a8c1df72eb746f4136fe9a2e72b0c9dc1da1cbd23b5372f94b5820ff8ae30e0e"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a3a6ed1d525bfb91b3fc9b690c5a21bb52de28c018530ad85093cc488bee2dd2"}, + {file = "yarl-1.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c38c9ddb6103ceae4e4498f9c08fac9b590c5c71b0370f98714768e22ac6fa66"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d9e09c9d74f4566e905a0b8fa668c58109f7624db96a2171f21747abc7524234"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8477c1ee4bd47c57d49621a062121c3023609f7a13b8a46953eb6c9716ca392"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5ff2c858f5f6a42c2a8e751100f237c5e869cbde669a724f2062d4c4ef93551"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:357495293086c5b6d34ca9616a43d329317feab7917518bc97a08f9e55648455"}, + {file = "yarl-1.9.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54525ae423d7b7a8ee81ba189f131054defdb122cde31ff17477951464c1691c"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:801e9264d19643548651b9db361ce3287176671fb0117f96b5ac0ee1c3530d53"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e516dc8baf7b380e6c1c26792610230f37147bb754d6426462ab115a02944385"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:7d5aaac37d19b2904bb9dfe12cdb08c8443e7ba7d2852894ad448d4b8f442863"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:54beabb809ffcacbd9d28ac57b0db46e42a6e341a030293fb3185c409e626b8b"}, + {file = "yarl-1.9.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bac8d525a8dbc2a1507ec731d2867025d11ceadcb4dd421423a5d42c56818541"}, + {file = "yarl-1.9.4-cp310-cp310-win32.whl", hash = "sha256:7855426dfbddac81896b6e533ebefc0af2f132d4a47340cee6d22cac7190022d"}, + {file = "yarl-1.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:848cd2a1df56ddbffeb375535fb62c9d1645dde33ca4d51341378b3f5954429b"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:35a2b9396879ce32754bd457d31a51ff0a9d426fd9e0e3c33394bf4b9036b099"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c7d56b293cc071e82532f70adcbd8b61909eec973ae9d2d1f9b233f3d943f2c"}, + {file = "yarl-1.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8a1c6c0be645c745a081c192e747c5de06e944a0d21245f4cf7c05e457c36e0"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b3c1ffe10069f655ea2d731808e76e0f452fc6c749bea04781daf18e6039525"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:549d19c84c55d11687ddbd47eeb348a89df9cb30e1993f1b128f4685cd0ebbf8"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7409f968456111140c1c95301cadf071bd30a81cbd7ab829169fb9e3d72eae9"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e23a6d84d9d1738dbc6e38167776107e63307dfc8ad108e580548d1f2c587f42"}, + {file = "yarl-1.9.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d8b889777de69897406c9fb0b76cdf2fd0f31267861ae7501d93003d55f54fbe"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:03caa9507d3d3c83bca08650678e25364e1843b484f19986a527630ca376ecce"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4e9035df8d0880b2f1c7f5031f33f69e071dfe72ee9310cfc76f7b605958ceb9"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:c0ec0ed476f77db9fb29bca17f0a8fcc7bc97ad4c6c1d8959c507decb22e8572"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:ee04010f26d5102399bd17f8df8bc38dc7ccd7701dc77f4a68c5b8d733406958"}, + {file = "yarl-1.9.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:49a180c2e0743d5d6e0b4d1a9e5f633c62eca3f8a86ba5dd3c471060e352ca98"}, + {file = "yarl-1.9.4-cp311-cp311-win32.whl", hash = "sha256:81eb57278deb6098a5b62e88ad8281b2ba09f2f1147c4767522353eaa6260b31"}, + {file = "yarl-1.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d1d2532b340b692880261c15aee4dc94dd22ca5d61b9db9a8a361953d36410b1"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0d2454f0aef65ea81037759be5ca9947539667eecebca092733b2eb43c965a81"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:44d8ffbb9c06e5a7f529f38f53eda23e50d1ed33c6c869e01481d3fafa6b8142"}, + {file = "yarl-1.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:aaaea1e536f98754a6e5c56091baa1b6ce2f2700cc4a00b0d49eca8dea471074"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3777ce5536d17989c91696db1d459574e9a9bd37660ea7ee4d3344579bb6f129"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9fc5fc1eeb029757349ad26bbc5880557389a03fa6ada41703db5e068881e5f2"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea65804b5dc88dacd4a40279af0cdadcfe74b3e5b4c897aa0d81cf86927fee78"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa102d6d280a5455ad6a0f9e6d769989638718e938a6a0a2ff3f4a7ff8c62cc4"}, + {file = "yarl-1.9.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09efe4615ada057ba2d30df871d2f668af661e971dfeedf0c159927d48bbeff0"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:008d3e808d03ef28542372d01057fd09168419cdc8f848efe2804f894ae03e51"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:6f5cb257bc2ec58f437da2b37a8cd48f666db96d47b8a3115c29f316313654ff"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:992f18e0ea248ee03b5a6e8b3b4738850ae7dbb172cc41c966462801cbf62cf7"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:0e9d124c191d5b881060a9e5060627694c3bdd1fe24c5eecc8d5d7d0eb6faabc"}, + {file = "yarl-1.9.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3986b6f41ad22988e53d5778f91855dc0399b043fc8946d4f2e68af22ee9ff10"}, + {file = "yarl-1.9.4-cp312-cp312-win32.whl", hash = "sha256:4b21516d181cd77ebd06ce160ef8cc2a5e9ad35fb1c5930882baff5ac865eee7"}, + {file = "yarl-1.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:a9bd00dc3bc395a662900f33f74feb3e757429e545d831eef5bb280252631984"}, + {file = "yarl-1.9.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:63b20738b5aac74e239622d2fe30df4fca4942a86e31bf47a81a0e94c14df94f"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d7f7de27b8944f1fee2c26a88b4dabc2409d2fea7a9ed3df79b67277644e17"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c74018551e31269d56fab81a728f683667e7c28c04e807ba08f8c9e3bba32f14"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ca06675212f94e7a610e85ca36948bb8fc023e458dd6c63ef71abfd482481aa5"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5aef935237d60a51a62b86249839b51345f47564208c6ee615ed2a40878dccdd"}, + {file = "yarl-1.9.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2b134fd795e2322b7684155b7855cc99409d10b2e408056db2b93b51a52accc7"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d25039a474c4c72a5ad4b52495056f843a7ff07b632c1b92ea9043a3d9950f6e"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f7d6b36dd2e029b6bcb8a13cf19664c7b8e19ab3a58e0fefbb5b8461447ed5ec"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:957b4774373cf6f709359e5c8c4a0af9f6d7875db657adb0feaf8d6cb3c3964c"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d7eeb6d22331e2fd42fce928a81c697c9ee2d51400bd1a28803965883e13cead"}, + {file = "yarl-1.9.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6a962e04b8f91f8c4e5917e518d17958e3bdee71fd1d8b88cdce74dd0ebbf434"}, + {file = "yarl-1.9.4-cp37-cp37m-win32.whl", hash = "sha256:f3bc6af6e2b8f92eced34ef6a96ffb248e863af20ef4fde9448cc8c9b858b749"}, + {file = "yarl-1.9.4-cp37-cp37m-win_amd64.whl", hash = "sha256:ad4d7a90a92e528aadf4965d685c17dacff3df282db1121136c382dc0b6014d2"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:ec61d826d80fc293ed46c9dd26995921e3a82146feacd952ef0757236fc137be"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8be9e837ea9113676e5754b43b940b50cce76d9ed7d2461df1af39a8ee674d9f"}, + {file = "yarl-1.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bef596fdaa8f26e3d66af846bbe77057237cb6e8efff8cd7cc8dff9a62278bbf"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2d47552b6e52c3319fede1b60b3de120fe83bde9b7bddad11a69fb0af7db32f1"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc30f71689d7fc9168b92788abc977dc8cefa806909565fc2951d02f6b7d57"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4aa9741085f635934f3a2583e16fcf62ba835719a8b2b28fb2917bb0537c1dfa"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:206a55215e6d05dbc6c98ce598a59e6fbd0c493e2de4ea6cc2f4934d5a18d130"}, + {file = "yarl-1.9.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07574b007ee20e5c375a8fe4a0789fad26db905f9813be0f9fef5a68080de559"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5a2e2433eb9344a163aced6a5f6c9222c0786e5a9e9cac2c89f0b28433f56e23"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6ad6d10ed9b67a382b45f29ea028f92d25bc0bc1daf6c5b801b90b5aa70fb9ec"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6fe79f998a4052d79e1c30eeb7d6c1c1056ad33300f682465e1b4e9b5a188b78"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a825ec844298c791fd28ed14ed1bffc56a98d15b8c58a20e0e08c1f5f2bea1be"}, + {file = "yarl-1.9.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8619d6915b3b0b34420cf9b2bb6d81ef59d984cb0fde7544e9ece32b4b3043c3"}, + {file = "yarl-1.9.4-cp38-cp38-win32.whl", hash = "sha256:686a0c2f85f83463272ddffd4deb5e591c98aac1897d65e92319f729c320eece"}, + {file = "yarl-1.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:a00862fb23195b6b8322f7d781b0dc1d82cb3bcac346d1e38689370cc1cc398b"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:604f31d97fa493083ea21bd9b92c419012531c4e17ea6da0f65cacdcf5d0bd27"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8a854227cf581330ffa2c4824d96e52ee621dd571078a252c25e3a3b3d94a1b1"}, + {file = "yarl-1.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ba6f52cbc7809cd8d74604cce9c14868306ae4aa0282016b641c661f981a6e91"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6327976c7c2f4ee6816eff196e25385ccc02cb81427952414a64811037bbc8b"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8397a3817d7dcdd14bb266283cd1d6fc7264a48c186b986f32e86d86d35fbac5"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e0381b4ce23ff92f8170080c97678040fc5b08da85e9e292292aba67fdac6c34"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23d32a2594cb5d565d358a92e151315d1b2268bc10f4610d098f96b147370136"}, + {file = "yarl-1.9.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ddb2a5c08a4eaaba605340fdee8fc08e406c56617566d9643ad8bf6852778fc7"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:26a1dc6285e03f3cc9e839a2da83bcbf31dcb0d004c72d0730e755b33466c30e"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:18580f672e44ce1238b82f7fb87d727c4a131f3a9d33a5e0e82b793362bf18b4"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:29e0f83f37610f173eb7e7b5562dd71467993495e568e708d99e9d1944f561ec"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:1f23e4fe1e8794f74b6027d7cf19dc25f8b63af1483d91d595d4a07eca1fb26c"}, + {file = "yarl-1.9.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:db8e58b9d79200c76956cefd14d5c90af54416ff5353c5bfd7cbe58818e26ef0"}, + {file = "yarl-1.9.4-cp39-cp39-win32.whl", hash = "sha256:c7224cab95645c7ab53791022ae77a4509472613e839dab722a72abe5a684575"}, + {file = "yarl-1.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:824d6c50492add5da9374875ce72db7a0733b29c2394890aef23d533106e2b15"}, + {file = "yarl-1.9.4-py3-none-any.whl", hash = "sha256:928cecb0ef9d5a7946eb6ff58417ad2fe9375762382f1bf5c55e61645f2c43ad"}, + {file = "yarl-1.9.4.tar.gz", hash = "sha256:566db86717cf8080b99b58b083b773a908ae40f06681e87e589a976faf8246bf"}, +] + +[package.dependencies] +idna = ">=2.0" +multidict = ">=4.0" + [metadata] lock-version = "2.0" python-versions = "~3.11" -content-hash = "d4bc0c36affc213194a44d13c1def0f788a3dbfa4bd5809f04d55dbe2e8ca199" +content-hash = "29e38275ff3e6182ec6e9d1c7766ea42624e2b9bc4da5a58227caa8861c67be8" diff --git a/pyproject.toml b/pyproject.toml index fcee75b15..f97a33429 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -41,6 +41,8 @@ boto3 = "^1.26.161" backoff = "^2.2.1" django-prometheus = "^2.3.1" djangorestframework-csv = "^2.1.1" +habanero = "^1.2.3" +django-lifecycle = "^1.1.2" [tool.poetry.dev-dependencies] Werkzeug = {extras = ["watchdog"], version = "^2.3.4"} @@ -67,6 +69,10 @@ django-extensions = "^3.2.3" django-coverage-plugin = "^3.0.0" pytest-django = "^4.5.2" +[tool.poetry.group.dev.dependencies] +pytest-vcr = "^1.0.2" +freezegun = "^1.3.1" + [tool.isort] profile = "black" multi_line_output = 3 diff --git a/scoap3/articles/admin.py b/scoap3/articles/admin.py index 17015f575..f7db753ed 100644 --- a/scoap3/articles/admin.py +++ b/scoap3/articles/admin.py @@ -1,11 +1,218 @@ -from django.contrib import admin +from django.contrib import admin, messages -from scoap3.articles.models import Article, ArticleFile, ArticleIdentifier +from scoap3.articles.models import ( + Article, + ArticleFile, + ArticleIdentifier, + ComplianceReport, +) +from scoap3.articles.tasks import compliance_checks + + +class ComplianceReportAdmin(admin.ModelAdmin): + list_display = [ + "article_id", + "article_publisher", + "article_journal", + "article_doi", + "check_license", + "check_file_formats", + "check_arxiv_category", + "check_article_type", + "check_doi_registration_time", + "get_is_compliant", + "report_date", + ] + search_fields = [ + "id", + "article__id", + "article__title", + "article__publication_info__journal_title", + ] + fields = [ + "article", + "report_date", + "get_is_compliant", + "check_license", + "check_license_description", + "check_file_formats", + "check_file_formats_description", + "check_arxiv_category", + "check_arxiv_category_description", + "check_article_type", + "check_article_type_description", + "check_doi_registration_time", + "check_doi_registration_time_description", + ] + readonly_fields = [ + "article", + "report_date", + "get_is_compliant", + "check_license", + "check_license_description", + "check_file_formats", + "check_file_formats_description", + "check_arxiv_category", + "check_arxiv_category_description", + "check_article_type", + "check_article_type_description", + "check_doi_registration_time", + "check_doi_registration_time_description", + ] + + @admin.display(description="ID") + def article_id(self, obj): + return obj.article.id + + @admin.display(boolean=True, description="Compliant") + def get_is_compliant(self, obj): + return obj.is_compliant() + + @admin.display(description="DOI") + def article_doi(self, obj): + doi_identifier = obj.article.article_identifiers.filter( + identifier_type="DOI" + ).first() + return [doi_identifier.identifier_value if doi_identifier else "None"] + + @admin.display(description="Publisher") + def article_publisher(self, obj): + return [info.publisher for info in obj.article.publication_info.all()] + + @admin.display(description="Journal") + def article_journal(self, obj): + return [info.journal_title for info in obj.article.publication_info.all()] + + +class ArticleComplianceReportInline(admin.StackedInline): + model = ComplianceReport + readonly_fields = [ + "check_license", + "check_license_description", + "check_file_formats", + "check_file_formats_description", + "check_arxiv_category", + "check_arxiv_category_description", + "check_article_type", + "check_article_type_description", + "check_doi_registration_time", + "check_doi_registration_time_description", + ] + can_delete = False + can_create = False + extra = 0 + max_num = 1 + fieldsets = ( + ( + None, + { + "fields": [ + ("check_license", "check_license_description"), + ("check_file_formats", "check_file_formats_description"), + ("check_arxiv_category", "check_arxiv_category_description"), + ("check_article_type", "check_article_type_description"), + ( + "check_doi_registration_time", + "check_doi_registration_time_description", + ), + ] + }, + ), + ) class ArticleAdmin(admin.ModelAdmin): - list_display = ["id", "title", "subtitle", "_updated_at", "_created_at"] - search_fields = ["title"] + list_display = [ + "id", + "title", + "journal_title", + "doi", + "check_license", + "check_file_formats", + "check_arxiv_category", + "check_article_type", + "check_doi_registration_time", + "_updated_at", + "_created_at", + ] + search_fields = [ + "title", + "id", + "publication_info__journal_title", + "article_identifiers__identifier_value", + ] + actions = ["make_compliance_check"] + list_filter = [ + "_updated_at", + "_created_at", + "publication_info__journal_title", + "report__check_license", + "report__check_file_formats", + "report__check_arxiv_category", + "report__check_article_type", + "report__check_doi_registration_time", + ] + inlines = [ArticleComplianceReportInline] + + @admin.display(description="Journal") + def journal_title(self, obj): + return [info.journal_title for info in obj.publication_info.all()] + + @admin.display(description="DOI") + def doi(self, obj): + return [ + identifier.identifier_value + for identifier in obj.article_identifiers.filter(identifier_type="DOI") + ] + + @admin.action(description="Run compliance checks") + def make_compliance_check(self, request, queryset): + ids = [] + for obj in queryset: + compliance_checks.delay(obj.id) + ids.append(str(obj.id)) + messages.success( + request, + f""" + Selected articles are being processed, it might take some time before seeing + the results in the reports. {', '.join(ids)}. + """, + ) + + @admin.display(boolean=True, description="License") + def check_license(self, obj): + report = obj.report.first() + if report: + return report.check_license + return False + + @admin.display(description="File formats", boolean=True) + def check_file_formats(self, obj): + report = obj.report.first() + if report: + return report.check_file_formats + return False + + @admin.display(description="ArXiv category", boolean=True) + def check_arxiv_category(self, obj): + report = obj.report.first() + if report: + return report.check_arxiv_category + return False + + @admin.display(description="Article type", boolean=True) + def check_article_type(self, obj): + report = obj.report.first() + if report: + return report.check_article_type + return False + + @admin.display(description="DOI registration time", boolean=True) + def check_doi_registration_time(self, obj): + report = obj.report.first() + if report: + return report.check_doi_registration_time + return False class ArticleIdentifierAdmin(admin.ModelAdmin): @@ -30,3 +237,4 @@ def file_size(self, obj): admin.site.register(Article, ArticleAdmin) admin.site.register(ArticleIdentifier, ArticleIdentifierAdmin) admin.site.register(ArticleFile, ArticleFileAdmin) +admin.site.register(ComplianceReport, ComplianceReportAdmin) diff --git a/scoap3/articles/migrations/0012_compliancereport.py b/scoap3/articles/migrations/0012_compliancereport.py new file mode 100644 index 000000000..b0016589f --- /dev/null +++ b/scoap3/articles/migrations/0012_compliancereport.py @@ -0,0 +1,41 @@ +# Generated by Django 4.2.5 on 2023-12-11 07:54 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + dependencies = [ + ("articles", "0011_alter_articleidentifier_article_id"), + ] + + operations = [ + migrations.CreateModel( + name="ComplianceReport", + fields=[ + ( + "id", + models.BigAutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("report_date", models.DateTimeField(auto_now_add=True)), + ("check_license", models.BooleanField(default=False)), + ("check_file_formats", models.BooleanField(default=False)), + ("check_arxiv_category", models.BooleanField(default=False)), + ("check_article_type", models.BooleanField(default=False)), + ("check_doi_registration_time", models.BooleanField(default=False)), + ( + "article", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="report", + to="articles.article", + ), + ), + ], + ), + ] diff --git a/scoap3/articles/migrations/0013_compliancereport_check_article_type_description_and_more.py b/scoap3/articles/migrations/0013_compliancereport_check_article_type_description_and_more.py new file mode 100644 index 000000000..a95b0cfc7 --- /dev/null +++ b/scoap3/articles/migrations/0013_compliancereport_check_article_type_description_and_more.py @@ -0,0 +1,37 @@ +# Generated by Django 4.2.5 on 2023-12-11 08:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("articles", "0012_compliancereport"), + ] + + operations = [ + migrations.AddField( + model_name="compliancereport", + name="check_article_type_description", + field=models.TextField(blank=True, default=""), + ), + migrations.AddField( + model_name="compliancereport", + name="check_arxiv_category_description", + field=models.TextField(blank=True, default=""), + ), + migrations.AddField( + model_name="compliancereport", + name="check_doi_registration_time_description", + field=models.TextField(blank=True, default=""), + ), + migrations.AddField( + model_name="compliancereport", + name="check_file_formats_description", + field=models.TextField(blank=True, default=""), + ), + migrations.AddField( + model_name="compliancereport", + name="check_license_description", + field=models.TextField(blank=True, default=""), + ), + ] diff --git a/scoap3/articles/models.py b/scoap3/articles/models.py index 8e6907ad8..b88039262 100644 --- a/scoap3/articles/models.py +++ b/scoap3/articles/models.py @@ -1,5 +1,6 @@ from django.db import models from django.db.models.fields.files import FieldFile +from django_lifecycle import AFTER_CREATE, AFTER_UPDATE, LifecycleModelMixin, hook class ArticleIdentifierType(models.TextChoices): @@ -24,7 +25,7 @@ class CustomFileField(models.FileField): attr_class = CustomFieldFile -class Article(models.Model): +class Article(LifecycleModelMixin, models.Model): reception_date = models.DateField(blank=True, null=True) acceptance_date = models.DateField(blank=True, null=True) publication_date = models.DateField(blank=True, null=True) @@ -45,6 +46,13 @@ class Article(models.Model): class Meta: ordering = ["id"] + @hook(AFTER_UPDATE, on_commit=True) + @hook(AFTER_CREATE, on_commit=True) + def on_save(self): + from scoap3.articles.tasks import compliance_checks + + compliance_checks.delay(self.id) + class ArticleFile(models.Model): article_id = models.ForeignKey( @@ -75,3 +83,35 @@ class Meta: indexes = [ models.Index(fields=["article_id", "identifier_type", "identifier_value"]) ] + + +class ComplianceReport(models.Model): + article = models.ForeignKey( + Article, on_delete=models.CASCADE, related_name="report" + ) + report_date = models.DateTimeField(auto_now_add=True) + + check_license = models.BooleanField(default=False) + check_license_description = models.TextField(blank=True, default="") + check_file_formats = models.BooleanField(default=False) + check_file_formats_description = models.TextField(blank=True, default="") + check_arxiv_category = models.BooleanField(default=False) + check_arxiv_category_description = models.TextField(blank=True, default="") + check_article_type = models.BooleanField(default=False) + check_article_type_description = models.TextField(blank=True, default="") + check_doi_registration_time = models.BooleanField(default=False) + check_doi_registration_time_description = models.TextField(blank=True, default="") + + def __str__(self): + return f"Compliance Report for {self.article.title} on {self.report_date.strftime('%Y-%m-%d')}" + + def is_compliant(self): + return all( + [ + self.check_license, + self.check_file_formats, + self.check_arxiv_category, + self.check_article_type, + self.check_doi_registration_time, + ] + ) diff --git a/scoap3/articles/tasks.py b/scoap3/articles/tasks.py new file mode 100644 index 000000000..1f532dd10 --- /dev/null +++ b/scoap3/articles/tasks.py @@ -0,0 +1,161 @@ +import logging +from datetime import datetime + +from celery import shared_task + +from scoap3.articles.models import Article, ComplianceReport +from scoap3.misc.utils import fetch_doi_registration_date + +logger = logging.getLogger(__name__) + + +def check_license(obj): + compliant_licenses = ["CC-BY-4.0", "CC-BY-3.0"] + article_licenses = [license.name for license in obj.related_licenses.all()] + + if any(license in compliant_licenses for license in article_licenses): + return True, "License check passed." + else: + return ( + False, + f"Non-compliant licenses: {', '.join(article_licenses)}. Required: {', '.join(compliant_licenses)}.", + ) + + +def check_file_formats(obj): + required_formats = ["pdf", "pdf_a", "xml"] + available_formats = [ + file.file.name.split(".")[-1] for file in obj.related_files.all() + ] + + missing_formats = [f for f in required_formats if f not in available_formats] + + if missing_formats: + return ( + False, + f"Missing required file formats: {', '.join(missing_formats)}.", + ) + return True, "All required file formats are present." + + +def check_article_type(obj): + non_compliant_types = [ + "Erratum", + "Addendum", + "Corrigendum", + "Editorial", + "Obituaries", + ] + for type in non_compliant_types: + if type.lower() in obj.title.lower(): + return ( + False, + f"Article is of non-compliant type: {type}.", + ) + return True, "Article type is compliant." + + +def check_arxiv_category(obj): + partial_journals = ["CPC", "PTEP", "AHEP", "PRC", "PRL", "APPB"] + journal_title = ( + obj.publication_info.first().journal_title + if obj.publication_info.exists() + else None + ) + + if journal_title in partial_journals: + categories = obj.article_arxiv_category.all() + if any(cat.primary and cat.category.startswith("hep") for cat in categories): + return True, "ArXiv category is compliant for partial journal." + return False, "Primary ArXiv category is not compliant for partial journal." + return True, "ArXiv category compliance not applicable." + + +def check_doi_registration_time(obj): + doi_identifier = obj.article_identifiers.filter(identifier_type="DOI").first() + if doi_identifier: + doi_registration_date = fetch_doi_registration_date( + doi_identifier.identifier_value + ) + if doi_registration_date and obj._created_at: + doi_registration_date = datetime.strptime( + doi_registration_date, "%Y-%m-%d" + ).date() + hours_difference = (obj._created_at.date() - doi_registration_date).days + if hours_difference > 1: + logger.info( + "Article %s: DOI:%s registration date is more that 24 hours.", + obj.id, + doi_identifier.identifier_value, + ) + return ( + False, + f"DOI registration time exceeded 24 hours. {hours_difference} passed.", + ) + else: + logger.info( + "Article %s: DOI:%s is created within 24 hours.", + obj.id, + doi_identifier.identifier_value, + ) + return ( + True, + f"DOI registration time is within acceptable range. {hours_difference} passed.", + ) + else: + logger.warning( + "Article %s: DOI (%s) registration date not found.", + obj.id, + doi_identifier.identifier_value, + ) + return False, "DOI registration date not found." + logger.warning( + "Article %s: DOI (%s) not found in our system.", + obj.id, + doi_identifier.identifier_value, + ) + return False, "DOI not found in our system." + + +@shared_task(name="compliance_checks", acks_late=True) +def compliance_checks(article_id): + try: + article = Article.objects.get(id=article_id) + except Article.DoesNotExist: + logger.error("Article %s not found.", article_id) + return "Article not found" + + ( + check_doi_registration_compliance, + check_doi_registration_description, + ) = check_doi_registration_time(article) + check_article_type_compliance, check_article_type_description = check_article_type( + article + ) + ( + check_arxiv_category_compliance, + check_arxiv_category_description, + ) = check_arxiv_category(article) + check_file_formats_compliance, check_file_formats_description = check_file_formats( + article + ) + check_license_compliance, check_license_description = check_license(article) + + article.report.all().delete() + + report = ComplianceReport.objects.create( + article=article, + check_article_type=check_article_type_compliance, + check_article_type_description=check_article_type_description, + check_arxiv_category=check_arxiv_category_compliance, + check_arxiv_category_description=check_arxiv_category_description, + check_doi_registration_time=check_doi_registration_compliance, + check_doi_registration_time_description=check_doi_registration_description, + check_file_formats=check_file_formats_compliance, + check_file_formats_description=check_file_formats_description, + check_license=check_license_compliance, + check_license_description=check_license_description, + ) + report.save() + logger.info("Compliance checks completed for article %s", article_id) + return f"Compliance checks completed for article {article_id}" diff --git a/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article.yaml b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article.yaml new file mode 100644 index 000000000..c395a74a4 --- /dev/null +++ b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article.yaml @@ -0,0 +1,338 @@ +interactions: +- request: + body: '{"index":{"_id":133,"_index":"scoap3-backend-test-articles"}} + + {"id":133,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-09-29T00:00:00+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-09-29T00:00:00+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":24,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"133","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":58,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":134,"_index":"scoap3-backend-test-articles"}} + + {"id":134,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:51:15.809547+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:51:15.809538+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"134","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":59,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":135,"_index":"scoap3-backend-test-articles"}} + + {"id":135,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:51:15.825435+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:51:15.825427+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"135","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":60,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":133,"_index":"scoap3-backend-test-articles"}} + + {"id":133,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[{"url":"https://creativecommons.org/licenses/by/3.0/","name":"CC-BY-3.0"}],"related_materials":[],"related_files":[{"file":"/media/test.pdf","created":"2023-12-12T07:51:15.843569+00:00","updated":"2023-12-12T07:51:15.843578+00:00"},{"file":"/media/test.pdf_a","created":"2023-12-12T07:51:15.844016+00:00","updated":"2023-12-12T07:51:15.844021+00:00"},{"file":"/media/test.xml","created":"2023-12-12T07:51:15.844390+00:00","updated":"2023-12-12T07:51:15.844395+00:00"}],"article_identifiers":[{"identifier_type":"DOI","identifier_value":"10.1016/j.ijheatmasstransfer.2023.124726"},{"identifier_type":"arxiv","identifier_value":" + hep-th/9711200"}],"article_arxiv_category":[],"publication_info":[{"journal_volume":"","journal_issue":"","journal_title":"Physical + Review D","page_start":"","page_end":"","artid":"","volume_year":"","journal_issue_date":null,"publisher":"Elsevier"}],"copyright":[],"authors":[],"_updated_at":"2023-09-29T00:00:00+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-09-29T00:00:00+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":19,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"133","_version":2,"result":"updated","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":61,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":133,"_index":"scoap3-backend-test-articles"}} + + {"id":133,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[{"url":"https://creativecommons.org/licenses/by/3.0/","name":"CC-BY-3.0"}],"related_materials":[],"related_files":[{"file":"/media/test.pdf","created":"2023-12-12T07:51:15.843569+00:00","updated":"2023-12-12T07:51:15.843578+00:00"},{"file":"/media/test.pdf_a","created":"2023-12-12T07:51:15.844016+00:00","updated":"2023-12-12T07:51:15.844021+00:00"},{"file":"/media/test.xml","created":"2023-12-12T07:51:15.844390+00:00","updated":"2023-12-12T07:51:15.844395+00:00"}],"article_identifiers":[{"identifier_type":"DOI","identifier_value":"10.1016/j.ijheatmasstransfer.2023.124726"},{"identifier_type":"arxiv","identifier_value":" + hep-th/9711200"}],"article_arxiv_category":[],"publication_info":[{"journal_volume":"","journal_issue":"","journal_title":"Physical + Review D","page_start":"","page_end":"","artid":"","volume_year":"","journal_issue_date":null,"publisher":"Elsevier"}],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:51:15.874642+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-09-29T00:00:00+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":31,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"133","_version":3,"result":"updated","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":62,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 habanero/1.2.3 + X-USER-AGENT: + - python-requests/2.31.0 habanero/1.2.3 + method: GET + uri: https://api.crossref.org/works/10.1016/j.ijheatmasstransfer.2023.124726 + response: + body: + string: !!binary | + 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 + headers: + access-control-allow-headers: + - X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, + Accept-Ranges, Cache-Control + access-control-allow-origin: + - '*' + access-control-expose-headers: + - Link + connection: + - close + content-encoding: + - gzip + content-length: + - '3678' + content-type: + - application/json + date: + - Tue, 12 Dec 2023 07:51:16 GMT + permissions-policy: + - interest-cohort=() + server: + - Jetty(9.4.40.v20210413) + vary: + - Accept-Encoding + x-api-pool: + - public + x-rate-limit-interval: + - 1s + x-rate-limit-limit: + - '50' + x-ratelimit-interval: + - 1s + x-ratelimit-limit: + - '50' + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":135,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":20,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"135","_version":2,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":63,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '247' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":134,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":12,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"134","_version":2,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":64,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '247' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":133,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":12,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"133","_version":4,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":65,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '247' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +version: 1 diff --git a/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_missing_compliant_doi.yaml b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_missing_compliant_doi.yaml new file mode 100644 index 000000000..e2f6dbcf0 --- /dev/null +++ b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_missing_compliant_doi.yaml @@ -0,0 +1,158 @@ +interactions: +- request: + body: '{"index":{"_id":136,"_index":"scoap3-backend-test-articles"}} + + {"id":136,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-09-29T00:00:00+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-09-29T00:00:00+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"136","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":66,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":137,"_index":"scoap3-backend-test-articles"}} + + {"id":137,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:51:16.460480+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:51:16.460471+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"137","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":67,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":138,"_index":"scoap3-backend-test-articles"}} + + {"id":138,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:51:16.476274+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:51:16.476268+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":12,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"138","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":68,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":138,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"138","_version":2,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":69,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":137,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":8,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"137","_version":2,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":70,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":136,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":21,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"136","_version":2,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":71,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '247' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +version: 1 diff --git a/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_arxiv_category.yaml b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_arxiv_category.yaml new file mode 100644 index 000000000..741f38644 --- /dev/null +++ b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_arxiv_category.yaml @@ -0,0 +1,86 @@ +interactions: +- request: + body: '{"index":{"_id":199,"_index":"scoap3-backend-test-articles"}} + + {"id":199,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-09-29T00:00:00+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-09-29T00:00:00+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":26,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"199","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":84,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":200,"_index":"scoap3-backend-test-articles"}} + + {"id":200,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:59:31.039123+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:59:31.039115+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"200","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":85,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":201,"_index":"scoap3-backend-test-articles"}} + + {"id":201,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:59:31.056094+00:00","title":"Test + editorial Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:59:31.056086+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":9,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"201","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":86,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +version: 1 diff --git a/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_doi.yaml b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_doi.yaml new file mode 100644 index 000000000..17bf96f9b --- /dev/null +++ b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_doi.yaml @@ -0,0 +1,278 @@ +interactions: +- request: + body: '{"index":{"_id":139,"_index":"scoap3-backend-test-articles"}} + + {"id":139,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-09-29T00:00:00+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-09-29T00:00:00+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"139","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":72,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":140,"_index":"scoap3-backend-test-articles"}} + + {"id":140,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:51:16.603406+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:51:16.603398+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"140","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":73,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":141,"_index":"scoap3-backend-test-articles"}} + + {"id":141,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:51:16.619268+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:51:16.619260+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"141","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":74,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '245' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 habanero/1.2.3 + X-USER-AGENT: + - python-requests/2.31.0 habanero/1.2.3 + method: GET + uri: https://api.crossref.org/works/10.1016/j.ijheatmasstransfer.2023.124726 + response: + body: + string: !!binary | + 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 + headers: + access-control-allow-headers: + - X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, + Accept-Ranges, Cache-Control + access-control-allow-origin: + - '*' + access-control-expose-headers: + - Link + connection: + - close + content-encoding: + - gzip + content-length: + - '3678' + content-type: + - application/json + date: + - Tue, 12 Dec 2023 07:51:17 GMT + permissions-policy: + - interest-cohort=() + server: + - Jetty(9.4.40.v20210413) + vary: + - Accept-Encoding + x-api-pool: + - public + x-rate-limit-interval: + - 1s + x-rate-limit-limit: + - '50' + x-ratelimit-interval: + - 1s + x-ratelimit-limit: + - '50' + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":141,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":21,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"141","_version":2,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":75,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '247' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":140,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":6,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"140","_version":2,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":76,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"delete":{"_id":139,"_index":"scoap3-backend-test-articles"}} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":7,"errors":false,"items":[{"delete":{"_index":"scoap3-backend-test-articles","_id":"139","_version":2,"result":"deleted","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":77,"_primary_term":1,"status":200}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +version: 1 diff --git a/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_file_format.yaml b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_file_format.yaml new file mode 100644 index 000000000..eb609c81d --- /dev/null +++ b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_file_format.yaml @@ -0,0 +1,86 @@ +interactions: +- request: + body: '{"index":{"_id":172,"_index":"scoap3-backend-test-articles"}} + + {"id":172,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-09-29T00:00:00+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-09-29T00:00:00+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":25,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"172","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":81,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":173,"_index":"scoap3-backend-test-articles"}} + + {"id":173,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:56:56.092830+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:56:56.092822+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":13,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"173","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":82,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":174,"_index":"scoap3-backend-test-articles"}} + + {"id":174,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:56:56.121937+00:00","title":"Test + editorial Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:56:56.121928+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":10,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"174","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":83,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +version: 1 diff --git a/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_title.yaml b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_title.yaml new file mode 100644 index 000000000..b2996d45c --- /dev/null +++ b/scoap3/articles/tests/cassettes/TestArticleCompliance.test_create_article_with_not_compliant_title.yaml @@ -0,0 +1,86 @@ +interactions: +- request: + body: '{"index":{"_id":160,"_index":"scoap3-backend-test-articles"}} + + {"id":160,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-09-29T00:00:00+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-09-29T00:00:00+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":29,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"160","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":78,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":161,"_index":"scoap3-backend-test-articles"}} + + {"id":161,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:52:58.677943+00:00","title":"Test + Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:52:58.677935+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":22,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"161","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":79,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +- request: + body: '{"index":{"_id":162,"_index":"scoap3-backend-test-articles"}} + + {"id":162,"reception_date":null,"acceptance_date":null,"publication_date":null,"first_online_date":null,"abstract":"Test + Abstract","related_licenses":[],"related_materials":[],"related_files":[],"article_identifiers":[],"article_arxiv_category":[],"publication_info":[],"copyright":[],"authors":[],"_updated_at":"2023-12-12T07:52:58.709528+00:00","title":"Test + editorial Article","subtitle":"Test Subtitle","_created_at":"2023-12-12T07:52:58.709520+00:00"} + + ' + headers: + connection: + - keep-alive + content-type: + - application/json + user-agent: + - opensearch-py/2.3.1 (Python 3.11.4) + method: POST + uri: http://localhost:9200/_bulk?refresh=true + response: + body: + string: '{"took":32,"errors":false,"items":[{"index":{"_index":"scoap3-backend-test-articles","_id":"162","_version":1,"result":"created","forced_refresh":true,"_shards":{"total":2,"successful":1,"failed":0},"_seq_no":80,"_primary_term":1,"status":201}}]}' + headers: + content-length: + - '246' + content-type: + - application/json; charset=UTF-8 + status: + code: 200 + message: OK +version: 1 diff --git a/scoap3/articles/tests/test_article_compliance.py b/scoap3/articles/tests/test_article_compliance.py new file mode 100644 index 000000000..6baa2dfbe --- /dev/null +++ b/scoap3/articles/tests/test_article_compliance.py @@ -0,0 +1,140 @@ +import pytest +from django.test import TestCase +from freezegun import freeze_time + +from scoap3.articles.models import ( + Article, + ArticleFile, + ArticleIdentifier, + ComplianceReport, +) +from scoap3.articles.tasks import compliance_checks +from scoap3.misc.models import License, PublicationInfo, Publisher + + +@pytest.mark.django_db +@pytest.mark.vcr +class TestArticleCompliance(TestCase): + def setUp(self): + self.license = License.objects.create( + name="CC-BY-3.0", url="https://creativecommons.org/licenses/by/3.0/" + ) + self.publisher = Publisher.objects.create( + name="Elsevier", + ) + self.file_formats = ["pdf", "pdf_a", "xml"] + with freeze_time("2023-09-29"): + self.article = Article.objects.create( + title="Test Article", + subtitle="Test Subtitle", + abstract="Test Abstract", + ) + + self.article_with_not_compliant_doi = Article.objects.create( + title="Test Article", + subtitle="Test Subtitle", + abstract="Test Abstract", + ) + + self.article_with_not_compliant_title = Article.objects.create( + title="Test editorial Article", + subtitle="Test Subtitle", + abstract="Test Abstract", + ) + + def test_create_article(self): + self.publication_info = PublicationInfo.objects.create( + journal_title="Physical Review D", + article_id=self.article, + publisher=self.publisher, + ) + ArticleIdentifier.objects.create( + identifier_type="DOI", + identifier_value="10.1016/j.ijheatmasstransfer.2023.124726", + article_id=self.article, + ) + ArticleIdentifier.objects.create( + identifier_type="arxiv", + identifier_value=" hep-th/9711200", + article_id=self.article, + ) + + for file_format in self.file_formats: + ArticleFile.objects.create( + file=f"test.{file_format}", + article_id=self.article, + ) + self.article.related_licenses.add(self.license) + self.article.save() + compliance_checks(self.article.id) + + article = Article.objects.get(id=self.article.id) + report = article.report.first() + + self.assertEqual(report.check_license, True) + self.assertEqual(report.check_file_formats, True) + self.assertEqual(report.check_article_type, True) + self.assertEqual(report.check_arxiv_category, True) + self.assertEqual(report.check_doi_registration_time, True) + + def test_create_article_with_not_compliant_doi(self): + ArticleIdentifier.objects.create( + identifier_type="DOI", + identifier_value="10.1016/j.ijheatmasstransfer.2023.124726", + article_id=self.article_with_not_compliant_doi, + ) + + compliance_checks(self.article_with_not_compliant_doi.id) + article = Article.objects.get(id=self.article_with_not_compliant_doi.id) + report = article.report.first() + + self.assertEqual(report.check_doi_registration_time, False) + + def test_create_article_with_missing_compliant_doi(self): + compliance_checks(self.article_with_not_compliant_doi.id) + article = Article.objects.get(id=self.article_with_not_compliant_doi.id) + report = article.report.first() + + self.assertEqual(report.check_doi_registration_time, False) + + def test_create_article_with_not_compliant_title(self): + compliance_checks(self.article_with_not_compliant_title.id) + article = Article.objects.get(id=self.article_with_not_compliant_title.id) + report = article.report.first() + + self.assertEqual(report.check_article_type, False) + + def test_create_article_with_not_compliant_file_format(self): + for file_format in self.file_formats[:2]: + ArticleFile.objects.create( + file=f"test.{file_format}", + article_id=self.article, + ) + + compliance_checks(self.article.id) + article = Article.objects.get(id=self.article.id) + report = article.report.first() + + self.assertEqual(report.check_file_formats, False) + self.assertEqual( + report.check_file_formats_description, + f"Missing required file formats: {self.file_formats[-1]}.", + ) + + @pytest.mark.skip(reason="Not implemented yet, waiting for requirements") + def test_create_article_with_not_compliant_arxiv_category(self): + ArticleIdentifier.objects.create( + identifier_type="arxiv", + identifier_value="eess.AS/9711200", + article_id=self.article, + ) + compliance_checks(self.article.id) + article = Article.objects.get(id=self.article.id) + report = article.report.first() + self.assertEqual(report.check_arxiv_category, False) + + def tearDown(self): + ArticleIdentifier.objects.all().delete() + ArticleFile.objects.all().delete() + ComplianceReport.objects.all().delete() + PublicationInfo.objects.all().delete() diff --git a/scoap3/conftest.py b/scoap3/conftest.py index b81b52e24..6ab699854 100644 --- a/scoap3/conftest.py +++ b/scoap3/conftest.py @@ -27,3 +27,14 @@ def user(db) -> User: @pytest.fixture def license(db) -> License: return LicenseFactory() + + +@pytest.fixture(scope="session") +def vcr_config(): + return { + "ignore_localhost": True, + "decode_compressed_response": True, + "filter_headers": ("Authorization", "User-Agent"), + "record_mode": "once", + "ignore_hosts": ["127.0.0.1", "localhost"], + } diff --git a/scoap3/misc/tests/cassettes/TestFetchDOIRegistrationDate.test_fetch_doi_registration_date_happy_case.yaml b/scoap3/misc/tests/cassettes/TestFetchDOIRegistrationDate.test_fetch_doi_registration_date_happy_case.yaml new file mode 100644 index 000000000..9e59bcadd --- /dev/null +++ b/scoap3/misc/tests/cassettes/TestFetchDOIRegistrationDate.test_fetch_doi_registration_date_happy_case.yaml @@ -0,0 +1,192 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 habanero/1.2.3 + X-USER-AGENT: + - python-requests/2.31.0 habanero/1.2.3 + method: GET + uri: https://api.crossref.org/works/10.1007/JHEP11(2019)001 + response: + body: + string: !!binary | + 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 + 3pWXv2M4wFOFgJfCvDi5EVf6/wHqFOfbCIEAAA== + headers: + access-control-allow-headers: + - X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, + Accept-Ranges, Cache-Control + access-control-allow-origin: + - '*' + access-control-expose-headers: + - Link + connection: + - close + content-encoding: + - gzip + content-length: + - '7666' + content-type: + - application/json + date: + - Mon, 11 Dec 2023 21:00:25 GMT + permissions-policy: + - interest-cohort=() + server: + - Jetty(9.4.40.v20210413) + vary: + - Accept-Encoding + x-api-pool: + - public + x-rate-limit-interval: + - 1s + x-rate-limit-limit: + - '50' + x-ratelimit-interval: + - 1s + x-ratelimit-limit: + - '50' + status: + code: 200 + message: OK +version: 1 diff --git a/scoap3/misc/tests/cassettes/TestFetchDOIRegistrationDate.test_fetch_doi_registration_date_invalid_doi.yaml b/scoap3/misc/tests/cassettes/TestFetchDOIRegistrationDate.test_fetch_doi_registration_date_invalid_doi.yaml new file mode 100644 index 000000000..c13bf1457 --- /dev/null +++ b/scoap3/misc/tests/cassettes/TestFetchDOIRegistrationDate.test_fetch_doi_registration_date_invalid_doi.yaml @@ -0,0 +1,53 @@ +interactions: +- request: + body: null + headers: + Accept: + - '*/*' + Accept-Encoding: + - gzip, deflate + Connection: + - keep-alive + User-Agent: + - python-requests/2.31.0 habanero/1.2.3 + X-USER-AGENT: + - python-requests/2.31.0 habanero/1.2.3 + method: GET + uri: https://api.crossref.org/works/10.10232332/JHEP11(2019)0010 + response: + body: + string: Resource not found. + headers: + access-control-allow-headers: + - X-Requested-With, Accept, Accept-Encoding, Accept-Charset, Accept-Language, + Accept-Ranges, Cache-Control + access-control-allow-origin: + - '*' + access-control-expose-headers: + - Link + connection: + - close + content-type: + - application/json + date: + - Mon, 11 Dec 2023 21:00:26 GMT + permissions-policy: + - interest-cohort=() + server: + - Jetty(9.4.40.v20210413) + transfer-encoding: + - chunked + x-api-pool: + - public + x-rate-limit-interval: + - 1s + x-rate-limit-limit: + - '50' + x-ratelimit-interval: + - 1s + x-ratelimit-limit: + - '50' + status: + code: 404 + message: Not Found +version: 1 diff --git a/scoap3/misc/tests/test_misc_utils.py b/scoap3/misc/tests/test_misc_utils.py new file mode 100644 index 000000000..79b0bdd88 --- /dev/null +++ b/scoap3/misc/tests/test_misc_utils.py @@ -0,0 +1,18 @@ +import pytest +from django.test import TestCase + +from scoap3.misc.utils import fetch_doi_registration_date + + +class TestFetchDOIRegistrationDate(TestCase): + @pytest.mark.vcr + def test_fetch_doi_registration_date_happy_case(self): + self.assertEqual( + fetch_doi_registration_date("10.1007/JHEP11(2019)001"), "2019-11-11" + ) + + @pytest.mark.vcr + def test_fetch_doi_registration_date_invalid_doi(self): + self.assertEqual( + fetch_doi_registration_date("10.10232332/JHEP11(2019)0010"), None + ) diff --git a/scoap3/misc/utils.py b/scoap3/misc/utils.py new file mode 100644 index 000000000..7f21a47a2 --- /dev/null +++ b/scoap3/misc/utils.py @@ -0,0 +1,18 @@ +import logging + +import backoff +from habanero import Crossref, RequestError + +logger = logging.getLogger(__name__) + + +@backoff.on_exception(backoff.expo, RequestError, max_tries=5) +def fetch_doi_registration_date(doi): + cr = Crossref() + try: + response = cr.works(ids=doi) + registration_date = response["message"]["created"]["date-time"] + return registration_date.split("T")[0] + except Exception as e: + logger.error(f"Failed to fetch DOI registration date for {doi}: {e}") + return None diff --git a/scoap3/utils/tests/conftest.py b/scoap3/utils/tests/conftest.py new file mode 100644 index 000000000..b81b52e24 --- /dev/null +++ b/scoap3/utils/tests/conftest.py @@ -0,0 +1,29 @@ +import pytest +from django.core.management import call_command + +from scoap3.misc.models import License +from scoap3.misc.tests.factories import LicenseFactory +from scoap3.users.models import User +from scoap3.users.tests.factories import UserFactory + + +@pytest.fixture +def rebuild_opensearch_index(): + call_command("opensearch", "index", "rebuild", "--force") + yield + call_command("opensearch", "index", "delete", "--force") + + +@pytest.fixture(autouse=True) +def media_storage(settings, tmpdir): + settings.MEDIA_ROOT = tmpdir.strpath + + +@pytest.fixture +def user(db) -> User: + return UserFactory() + + +@pytest.fixture +def license(db) -> License: + return LicenseFactory()