diff --git a/idutils/detectors.py b/idutils/detectors.py index fd6ec69..75d1f48 100644 --- a/idutils/detectors.py +++ b/idutils/detectors.py @@ -1,4 +1,5 @@ # SPDX-FileCopyrightText: 2024 CERN. +# SPDX-FileCopyrightText: 2026 University of Münster. # SPDX-License-Identifier: BSD-3-Clause # # In applying this license, CERN does not waive the privileges and immunities @@ -52,6 +53,16 @@ def detect_identifier_schemes(val): for viaf_url in validators.viaf_urls: if val.startswith(viaf_url): schemes.remove("handle") + if "isni" in schemes and "url" in schemes: + # check explicitly if it's an isni + for isni_url in validators.isni_urls: + if val.startswith(isni_url): + schemes.remove("url") + if "isni" in schemes and "handle" in schemes: + # check explicitly if it's an isni + for isni_url in validators.isni_urls: + if val.startswith(isni_url): + schemes.remove("handle") scheme_filter = IDUTILS_SCHEME_FILTER + custom_schemes_registry().pick_scheme_key( "filter" diff --git a/idutils/utils.py b/idutils/utils.py index dae49e1..1c78955 100644 --- a/idutils/utils.py +++ b/idutils/utils.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2024 CERN. # SPDX-FileCopyrightText: 2023 abnf-to-regexp AUTHORS # SPDX-FileCopyrightText: 2025 Will Riley. +# SPDX-FileCopyrightText: 2026 University of Münster. # SPDX-License-Identifier: BSD-3-Clause # # In applying this license, CERN does not waive the privileges and immunities @@ -548,7 +549,7 @@ def _convert_x_to_10(x): "ISMR_EM", ) """List of RRID authorities. - + Manually collected from https://rrid.site/, so may not be complete """ @@ -556,3 +557,8 @@ def _convert_x_to_10(x): r"(?i)^(?:rrid:)?({codes})+_[A-Za-z0-9_-]+$".format(codes="|".join(RRID_CODES)) ) """Based on RRID example in the DataCite documentation""" + +isni_urls = ( + "http://isni.org/isni/", + "https://isni.org/isni/", +) diff --git a/idutils/validators.py b/idutils/validators.py index f8cf251..c04479a 100644 --- a/idutils/validators.py +++ b/idutils/validators.py @@ -1,5 +1,6 @@ # SPDX-FileCopyrightText: 2024 CERN. # SPDX-FileCopyrightText: 2025 Will Riley. +# SPDX-FileCopyrightText: 2026 University of Münster. # SPDX-License-Identifier: BSD-3-Clause # # In applying this license, CERN does not waive the privileges and immunities @@ -102,6 +103,11 @@ def is_ean(val): def is_isni(val): """Test if argument is an International Standard Name Identifier.""" + for isni_url in isni_urls: + if val.startswith(isni_url): + val = val[len(isni_url) :] + break + val = val.replace("-", "").replace(" ", "").upper() if len(val) != 16: return False @@ -121,6 +127,10 @@ def is_orcid(val): See http://support.orcid.org/knowledgebase/ articles/116780-structure-of-the-orcid-identifier """ + for isni_url in isni_urls: + if val.startswith(isni_url): + return False + for orcid_url in orcid_urls: if val.startswith(orcid_url): val = val[len(orcid_url) :] diff --git a/tests/test_idutils.py b/tests/test_idutils.py index f67530b..176d78d 100644 --- a/tests/test_idutils.py +++ b/tests/test_idutils.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: 2015-2022 CERN. # SPDX-FileCopyrightText: 2015-2018 Alan Rubin. # SPDX-FileCopyrightText: 2025 Will Riley. +# SPDX-FileCopyrightText: 2026 University of Münster. # SPDX-License-Identifier: BSD-3-Clause # # In applying this license, CERN does not waive the privileges and immunities @@ -310,6 +311,7 @@ "http://orcid.org/0009-0002-4767-9017", ), ("1422-4586-3573-0476", ["isni"], "", ""), + ("https://isni.org/isni/1422-4586-3573-0476", ["isni"], "", ""), ( "arXiv:1310.2590", [ @@ -1078,3 +1080,13 @@ def test_raid(): assert "raid" in idutils.detect_identifier_schemes( "https://raid.org/10.83962/fb5be317" ) + + +def test_isni(): + """Test ISNI validation.""" + assert idutils.is_isni("1422-4586-3573-0476") + assert idutils.is_isni("http://isni.org/isni/1422-4586-3573-0476") + assert idutils.is_isni("https://isni.org/isni/1422-4586-3573-0476") + assert idutils.is_isni("0009-0005-6000-7479") + assert not idutils.is_isni("http://orcid.org/0009-0005-6000-7479") + assert not idutils.is_isni("https://orcid.org/0009-0005-6000-7479")