isbn.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. # coding=utf-8
  2. """
  3. This module is responsible for generating the check digit and formatting
  4. ISBN numbers.
  5. """
  6. class ISBN(object):
  7. MAX_LENGTH = 13
  8. def __init__(self, ean=None, group=None, registrant=None, publication=None):
  9. self.ean = ean
  10. self.group = group
  11. self.registrant = registrant
  12. self.publication = publication
  13. class ISBN13(ISBN):
  14. def __init__(self, *args, **kwargs):
  15. super(ISBN13, self).__init__(*args, **kwargs)
  16. self.check_digit = self._check_digit()
  17. def _check_digit(self):
  18. """ Calculate the check digit for ISBN-13.
  19. See https://en.wikipedia.org/wiki/International_Standard_Book_Number
  20. for calculation.
  21. """
  22. weights = (1 if x % 2 == 0 else 3 for x in range(12))
  23. body = ''.join([self.ean, self.group, self.registrant,
  24. self.publication])
  25. remainder = sum(int(b) * w for b, w in zip(body, weights)) % 10
  26. diff = 10 - remainder
  27. check_digit = 0 if diff == 10 else diff
  28. return str(check_digit)
  29. def format(self, separator=''):
  30. return separator.join([self.ean, self.group, self.registrant,
  31. self.publication, self.check_digit])
  32. class ISBN10(ISBN):
  33. def __init__(self, *args, **kwargs):
  34. super(ISBN10, self).__init__(*args, **kwargs)
  35. self.check_digit = self._check_digit()
  36. def _check_digit(self):
  37. """ Calculate the check digit for ISBN-10.
  38. See https://en.wikipedia.org/wiki/International_Standard_Book_Number
  39. for calculation.
  40. """
  41. weights = range(1, 10)
  42. body = ''.join([self.group, self.registrant, self.publication])
  43. remainder = sum(int(b) * w for b, w in zip(body, weights)) % 11
  44. check_digit = 'X' if remainder == 10 else str(remainder)
  45. return str(check_digit)
  46. def format(self, separator=''):
  47. return separator.join([self.group, self.registrant, self.publication,
  48. self.check_digit])