__init__.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. # coding=utf-8
  2. from __future__ import unicode_literals
  3. from .. import BaseProvider
  4. from .isbn import ISBN, ISBN10, ISBN13
  5. from .rules import RULES
  6. class Provider(BaseProvider):
  7. """ Generates fake ISBNs. ISBN rules vary across languages/regions
  8. so this class makes no attempt at replicating all of the rules. It
  9. only replicates the 978 EAN prefix for the English registration
  10. groups, meaning the first 4 digits of the ISBN-13 will either be
  11. 978-0 or 978-1. Since we are only replicating 978 prefixes, every
  12. ISBN-13 will have a direct mapping to an ISBN-10.
  13. See https://www.isbn-international.org/content/what-isbn for the
  14. format of ISBNs.
  15. See https://www.isbn-international.org/range_file_generation for the
  16. list of rules pertaining to each prefix/registration group.
  17. """
  18. def _body(self):
  19. """ Generate the information required to create an ISBN-10 or
  20. ISBN-13.
  21. """
  22. ean = self.random_element(RULES.keys())
  23. reg_group = self.random_element(RULES[ean].keys())
  24. # Given the chosen ean/group, decide how long the
  25. # registrant/publication string may be.
  26. # We must allocate for the calculated check digit, so
  27. # subtract 1
  28. reg_pub_len = ISBN.MAX_LENGTH - len(ean) - len(reg_group) - 1
  29. # Generate a registrant/publication combination
  30. reg_pub = self.numerify('#' * reg_pub_len)
  31. # Use rules to separate the registrant from the publication
  32. rules = RULES[ean][reg_group]
  33. registrant, publication = self._registrant_publication(reg_pub, rules)
  34. return [ean, reg_group, registrant, publication]
  35. @staticmethod
  36. def _registrant_publication(reg_pub, rules):
  37. """ Separate the registration from the publication in a given
  38. string.
  39. :param reg_pub: A string of digits representing a registration
  40. and publication.
  41. :param rules: A list of RegistrantRules which designate where
  42. to separate the values in the string.
  43. :returns: A (registrant, publication) tuple of strings.
  44. """
  45. for rule in rules:
  46. if rule.min <= reg_pub <= rule.max:
  47. reg_len = rule.registrant_length
  48. break
  49. else:
  50. raise Exception('Registrant/Publication not found in registrant '
  51. 'rule list.')
  52. registrant, publication = reg_pub[:reg_len], reg_pub[reg_len:]
  53. return registrant, publication
  54. def isbn13(self, separator='-'):
  55. ean, group, registrant, publication = self._body()
  56. isbn = ISBN13(ean, group, registrant, publication)
  57. return isbn.format(separator)
  58. def isbn10(self, separator='-'):
  59. ean, group, registrant, publication = self._body()
  60. isbn = ISBN10(ean, group, registrant, publication)
  61. return isbn.format(separator)