Coverage for oc_ds_converter / oc_idmanager / issn.py: 90%
39 statements
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-25 18:06 +0000
« prev ^ index » next coverage.py v7.13.4, created at 2026-03-25 18:06 +0000
1# SPDX-FileCopyrightText: 2023-2024 Arcangelo Massari <arcangelo.massari@unibo.it>
2# SPDX-FileCopyrightText: 2024 Arianna Moretti <arianna.moretti4@unibo.it>
3#
4# SPDX-License-Identifier: ISC
7import re
8from re import match, sub
10from oc_ds_converter.oc_idmanager.base import IdentifierManager
13class ISSNManager(IdentifierManager):
14 """This class implements an identifier manager for issn identifier"""
16 def __init__(self, data={}):
17 """ISSN manager constructor."""
18 super(ISSNManager, self).__init__()
19 self._p = "issn:"
20 self._data = data
22 def is_valid(self, id_string, get_extra_info=False):
23 issn = self.normalise(id_string, include_prefix=True)
24 if issn is None:
25 return False
26 else:
27 if issn not in self._data or self._data[issn] is None:
28 self._data[issn] = {"valid":self.check_digit(issn) and self.syntax_ok(issn)}
29 return (
30 self.syntax_ok(issn)
31 and self.check_digit(issn)
32 )
33 return self._data[issn].get("valid")
35 def normalise(self, id_string, include_prefix=False):
36 try:
37 issn_string = sub("[^X0-9]", "", id_string.upper())
38 return "%s%s-%s" % (
39 self._p if include_prefix else "",
40 issn_string[:4],
41 issn_string[4:8],
42 )
43 except: # Any error in processing the ISSN will return None
44 return None
46 def syntax_ok(self, id_string):
47 if not id_string.startswith(self._p):
48 id_string = self._p+id_string
49 return True if match("^issn:[0-9]{4}-[0-9]{3}[0-9X]$", id_string, re.IGNORECASE) else False
51 def check_digit(self,issn):
52 if issn.startswith(self._p):
53 spl = issn.find(self._p) + len(self._p)
54 issn = issn[spl:]
55 issn = issn.replace('-', '')
56 if len(issn) != 8:
57 return False
58 ss = sum([int(digit) * f for digit, f in zip(issn, range(8, 1, -1))])
59 _, mod = divmod(ss, 11)
60 checkdigit = 0 if mod == 0 else 11 - mod
61 if checkdigit == 10:
62 checkdigit = 'X'
63 return '{}'.format(checkdigit) == issn[7]