Source code for checkdigit.isbn
# /usr/bin/env python
# This file is part of checkdigit.
# checkdigit is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# checkdigit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with checkdigit. If not, see <http://www.gnu.org/licenses/>.
"""International Standard Book Number.
ISBN codes are product identifiers used predominantly for books.
Support is provided for both ISBN-10 and ISBN-13.
"""
from checkdigit._data import cleanse, convert, missing_template
[docs]def calculate(data: str) -> str:
"""Calculates ISBN Check Digits.
Args:
data: A string of characters representing an ISBN code without the check digit
Returns:
str: The check digit that was missing
Examples:
>>> from checkdigit import isbn
>>> # ISBN-10
>>> isbn.calculate("043942089")
'X'
>>> # ISBN-13
>>> isbn.calculate("978-1-86197-876")
'9'
"""
data = cleanse(data)
if len(data) == 9:
# ISBN 10 (without the check digit)
# Multiply first digit by 10, second by 9, ... ninth by 2 and take the sum
# Sanity check: len(range(...)) should be the same as len(data)
total_sum = sum(
int(digit) * weight for digit, weight in zip(data, range(10, 1, -1))
)
return convert(11 - (total_sum % 11))
# elif not required since return above (and makes pylint happy)
if len(data) == 12:
# ISBN weights are 3 for even positions and 1 for odd
# Multiply each digit by its weight
total_sum = sum((int(data[i])) * (3 if i % 2 else 1) for i in range(len(data)))
# Return final check digit and type of barcode
return convert(10 - (total_sum % 10), False)
return "Invalid"
[docs]def validate(data: str) -> bool:
"""Validates ISBN check digits.
Args:
data: A string of characters representing a fall ISBN code
Returns:
bool: A boolean representing whether the
check digit validates the data or non
Examples:
>>> from checkdigit import isbn
>>> # ISBN-10
>>> isbn.validate("0198526636")
True
>>> # ISBN-13
>>> isbn.validate("978-1-56619-909-4")
True
"""
# The calculate method already cleanses the data.
# If the return result is 'Invalid', it won't match the check digit (hence false).
return calculate(data[:-1]) == data[-1]
[docs]def missing(data: str) -> str:
"""Calculates a missing digit in an ISBN Code represented by a question mark.
Args:
data: A string of characters representing a full ISBN code
with a question mark representing a missing character
Returns:
str: The missing value that should've been where the question mark was
Examples:
>>> from checkdigit import isbn
>>> # ISBN-10
>>> isbn.missing("15688?111X")
'1'
>>> # ISBN-13
>>> isbn.missing("978186197876?")
'9'
>>> isbn.missing("023456789128")
'Invalid'
"""
return missing_template(data, "isbn")