summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/faker/providers/isbn/isbn.py
blob: b712a83c01fac62ea34656475571fec0d1453dea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
"""
This module is responsible for generating the check digit and formatting
ISBN numbers.
"""
from typing import Any, Optional


class ISBN:
    MAX_LENGTH = 13

    def __init__(
        self,
        ean: Optional[str] = None,
        group: Optional[str] = None,
        registrant: Optional[str] = None,
        publication: Optional[str] = None,
    ) -> None:
        self.ean = ean
        self.group = group
        self.registrant = registrant
        self.publication = publication


class ISBN13(ISBN):
    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 ISBN-13.
        See https://en.wikipedia.org/wiki/International_Standard_Book_Number
        for calculation.
        """
        weights = (1 if x % 2 == 0 else 3 for x in range(12))
        body = "".join([part for part in [self.ean, self.group, self.registrant, self.publication] if part is not None])
        remainder = sum(int(b) * w for b, w in zip(body, weights)) % 10
        diff = 10 - remainder
        check_digit = 0 if diff == 10 else diff
        return str(check_digit)

    def format(self, separator: str = "") -> str:
        return separator.join(
            [
                part
                for part in [
                    self.ean,
                    self.group,
                    self.registrant,
                    self.publication,
                    self.check_digit,
                ]
                if part is not None
            ]
        )


class ISBN10(ISBN):
    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 ISBN-10.
        See https://en.wikipedia.org/wiki/International_Standard_Book_Number
        for calculation.
        """
        weights = range(1, 10)
        body = "".join([part for part in [self.group, 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.group,
                    self.registrant,
                    self.publication,
                    self.check_digit,
                ]
                if part is not None
            ]
        )