Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2This module is providing funcionality to validate and compute ISBN checksums.
4Taken from
5https://github.com/GLMeece/isbn_validator/blob/master/src/isbn_validator/isbn_validator.py
6because https://pypi.org/project/isbn_validator/ is not maintained.
7Adapted for use with Python3 by casting map() to list().
9See :func:`is_valid_isbn` for details.
11API
12---
13"""
15from functools import wraps
18# Functions & objects =========================================================
19def _clean_isbn(isbn):
20 """
21 Remove all non-digit and non "x" characters from given string.
23 Args:
24 isbn (str/list): ISBN number as string or list of digits
26 Returns:
27 list: array of numbers (if "x" is found, it is converted to 10).
28 """
29 if isinstance(isbn, str):
30 isbn = list(isbn.lower())
32 # filter digits and "x"
33 isbn = filter(lambda x: x.isdigit() or x == "x", isbn)
35 # convert ISBN to numbers
36 return list(map(lambda x: 10 if x == "x" else int(x), isbn))
39def _isbn_cleaner(fn):
40 """
41 Decorator for calling other functions from this module.
43 Purpose of this decorator is to clean the ISBN string from garbage and
44 return list of digits.
46 Args:
47 fn (function): function in which will be :func:`_clean_isbn(isbn)` call
48 wrapped.
49 """
51 @wraps(fn)
52 def wrapper(isbn):
53 return fn(_clean_isbn(isbn))
55 return wrapper
58@_isbn_cleaner
59def get_isbn10_checksum(isbn) -> int:
60 """
61 Args:
62 isbn (str/list): ISBN number as string or list of digits
64 Warning:
65 Function expects that `isbn` is only 9 digits long.
67 Returns:
68 int: Last (checksum) digit for given `isbn`.
69 """
70 return sum([(i + 1) * x for i, x in enumerate(isbn)]) % 11
73@_isbn_cleaner
74def is_isbn10_valid(isbn) -> bool:
75 """
76 Check if given `isbn` 10 is valid.
78 Args:
79 isbn (str/list): ISBN number as string or list of digits.
81 Returns:
82 bool: ``True`` if ISBN is valid.
83 """
84 if len(isbn) != 10:
85 return False
87 return get_isbn10_checksum(isbn[:-1]) == isbn[-1]
90@_isbn_cleaner
91def get_isbn13_checksum(isbn) -> int:
92 """
93 Args:
94 isbn (str/list): ISBN number as string or list of digits.
96 Warning:
97 Function expects that `isbn` is only 12 digits long.
99 Returns:
100 int: Last checksum digit for given `isbn`.
101 """
102 multipliers = map(lambda x: int(x), list("13" * 6))
104 rest = sum([i * x for i, x in zip(multipliers, isbn)]) % 10
106 if rest == 0:
107 return rest
109 return 10 - rest
112@_isbn_cleaner
113def is_isbn13_valid(isbn) -> bool:
114 """
115 Check if given `isbn` 13 is valid.
117 Args:
118 isbn (str/list): ISBN number as string or list of digits.
120 Returns:
121 bool: ``True`` if ISBN is valid.
122 """
123 if len(isbn) != 13:
124 return False
126 return get_isbn13_checksum(isbn[:-1]) == isbn[-1]
129@_isbn_cleaner
130def is_valid_isbn(isbn) -> bool:
131 """
132 Validate given `isbn`. Wrapper for :func:`is_isbn10_valid`/
133 :func:`is_isbn13_valid`.
135 Args:
136 isbn (str/map): ISBN number as string or list of digits.
138 Note:
139 Function doesn't require `isbn` type to be specified (it can be both
140 10/13 isbn's versions).
142 Returns:
143 bool: ``True`` if ISBN is valid.
144 """
145 length = len(list(isbn))
147 if length == 10:
148 return is_isbn10_valid(list(isbn))
149 if length == 13:
150 return is_isbn13_valid(list(isbn))
152 return False