update bots
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
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)
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
from .. import Provider as SBNProvider
|
||||
|
||||
|
||||
class Provider(SBNProvider):
|
||||
pass
|
||||
Binary file not shown.
@@ -0,0 +1,24 @@
|
||||
"""
|
||||
This module exists solely to figure how long a registrant/publication
|
||||
number may be within an SBN. It's the same as the ISBN implementation
|
||||
for ean 978, reg_group 0.
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
from typing import List
|
||||
|
||||
RegistrantRule = namedtuple("RegistrantRule", ["min", "max", "registrant_length"])
|
||||
|
||||
# Structure: RULES = [Rule1, Rule2, ...]
|
||||
RULES: List[RegistrantRule] = [
|
||||
RegistrantRule("0000000", "1999999", 2),
|
||||
RegistrantRule("2000000", "2279999", 3),
|
||||
RegistrantRule("2280000", "2289999", 4),
|
||||
RegistrantRule("2290000", "6479999", 3),
|
||||
RegistrantRule("6480000", "6489999", 7),
|
||||
RegistrantRule("6490000", "6999999", 3),
|
||||
RegistrantRule("7000000", "8499999", 4),
|
||||
RegistrantRule("8500000", "8999999", 5),
|
||||
RegistrantRule("9000000", "9499999", 6),
|
||||
RegistrantRule("9500000", "9999999", 7),
|
||||
]
|
||||
@@ -0,0 +1,50 @@
|
||||
"""
|
||||
This module is responsible for generating the check digit and formatting
|
||||
SBN numbers.
|
||||
"""
|
||||
|
||||
from typing import Any, Optional
|
||||
|
||||
|
||||
class SBN:
|
||||
MAX_LENGTH = 9
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
registrant: Optional[str] = None,
|
||||
publication: Optional[str] = None,
|
||||
) -> None:
|
||||
self.registrant = registrant
|
||||
self.publication = publication
|
||||
|
||||
|
||||
class SBN9(SBN):
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
super().__init__(*args, **kwargs)
|
||||
self.check_digit = self._check_digit()
|
||||
|
||||
def _check_digit(self) -> str:
|
||||
"""Calculate the check digit for SBN-9.
|
||||
SBNs use the same check digit calculation as ISBN. See
|
||||
https://en.wikipedia.org/wiki/International_Standard_Book_Number
|
||||
for calculation. Only modification is weights range from 1 to 9
|
||||
instead of 1 to 10.
|
||||
"""
|
||||
weights = range(1, 9)
|
||||
body = "".join([part for part in [self.registrant, self.publication] if part is not None])
|
||||
remainder = sum(int(b) * w for b, w in zip(body, weights)) % 11
|
||||
check_digit = "X" if remainder == 10 else str(remainder)
|
||||
return str(check_digit)
|
||||
|
||||
def format(self, separator: str = "") -> str:
|
||||
return separator.join(
|
||||
[
|
||||
part
|
||||
for part in [
|
||||
self.registrant,
|
||||
self.publication,
|
||||
self.check_digit,
|
||||
]
|
||||
if part is not None
|
||||
]
|
||||
)
|
||||
Reference in New Issue
Block a user