from typing import List, Tuple from faker.providers.sbn.rules import RegistrantRule from .. import BaseProvider from .rules import RULES from .sbn import SBN, SBN9 class Provider(BaseProvider): """Generates fake SBNs. These are the precursor to the ISBN and are largely similar to ISBN-10. See https://www.isbn-international.org/content/what-isbn for the format of ISBNs. SBNs have no EAN prefix or Registration Group. """ def _body(self) -> List[str]: """Generate the information required to create an SBN""" reg_pub_len: int = SBN.MAX_LENGTH - 1 # Generate a registrant/publication combination reg_pub: str = self.numerify("#" * reg_pub_len) # Use rules to separate the registrant from the publication rules: List[RegistrantRule] = RULES registrant, publication = self._registrant_publication(reg_pub, rules) return [registrant, publication] @staticmethod def _registrant_publication(reg_pub: str, rules: List[RegistrantRule]) -> Tuple[str, str]: """Separate the registration from the publication in a given string. :param reg_pub: A string of digits representing a registration and publication. :param rules: A list of RegistrantRules which designate where to separate the values in the string. :returns: A (registrant, publication) tuple of strings. """ for rule in rules: if rule.min <= reg_pub[:-1] <= rule.max: reg_len = rule.registrant_length break else: raise Exception("Registrant/Publication not found in registrant rule list.") registrant, publication = reg_pub[:reg_len], reg_pub[reg_len:] return registrant, publication def sbn9(self, separator: str = "-") -> str: registrant, publication = self._body() sbn = SBN9(registrant, publication) return sbn.format(separator)