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

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 

5 

6 

7import re 

8from re import match, sub 

9 

10from oc_ds_converter.oc_idmanager.base import IdentifierManager 

11 

12 

13class ISSNManager(IdentifierManager): 

14 """This class implements an identifier manager for issn identifier""" 

15 

16 def __init__(self, data={}): 

17 """ISSN manager constructor.""" 

18 super(ISSNManager, self).__init__() 

19 self._p = "issn:" 

20 self._data = data 

21 

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") 

34 

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 

45 

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 

50 

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]