Skip to content

Commit

Permalink
ISBN: Fixed linting
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasmucidas committed Dec 28, 2023
1 parent b8fa36f commit bdc75f4
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 29 deletions.
33 changes: 16 additions & 17 deletions pydantic_extra_types/isbn.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
The `pydantic_extra_types.isbn` module provides functionality to recieve and validate ISBN
The `pydantic_extra_types.isbn` module provides functionality to recieve and validate ISBN
(International Standard Book Number) in 10-digit and 13-digit formats. The output is always ISBN-13.
"""

Expand All @@ -14,19 +14,21 @@
def isbn10_digit_calc(isbn: str) -> str:
total = sum(int(digit) * (10 - idx) for idx, digit in enumerate(isbn[:9]))

for check_digit in range(1,11):
for check_digit in range(1, 11):
if (total + check_digit) % 11 == 0:
valid_check_digit = 'X' if check_digit == 10 else str(check_digit)

return valid_check_digit


def isbn13_digit_calc(isbn: str) -> str:
total = sum(int(digit) * (1 if idx % 2 == 0 else 3) for idx, digit in enumerate(isbn[:12]))

check_digit = (10 - (total % 10)) % 10

return str(check_digit)


class ISBN(str):
"""Represents a ISBN and provides methods for conversion, validation, and serialization.
Expand Down Expand Up @@ -74,17 +76,12 @@ def validate_isbn_format(value: str) -> None:
isbn_length = len(value)

if isbn_length not in (10, 13):
raise PydanticCustomError(
'isbn_length',
f'Length for ISBN must be 10 or 13 digits, not {isbn_length}'
)
raise PydanticCustomError('isbn_length', f'Length for ISBN must be 10 or 13 digits, not {isbn_length}')

if isbn_length == 10:

if not value[:-1].isdigit() or ((value[-1] != 'X') and (not value[-1].isdigit())):
raise PydanticCustomError(
'isbn10_invalid_characters', 'First 9 digits of ISBN-10 must be integers'
)
raise PydanticCustomError('isbn10_invalid_characters', 'First 9 digits of ISBN-10 must be integers')

if isbn_length == 13:
if not value.isdigit():
Expand All @@ -94,8 +91,7 @@ def validate_isbn_format(value: str) -> None:
if value[:3] not in ('978', '979'):
raise PydanticCustomError(
'isbn_invalid_early_characters', 'The first 3 digits of ISBN-13 must be 978 or 979'
)

)

@staticmethod
def validate_isbn_digits(value: str) -> None:
Expand All @@ -109,13 +105,16 @@ def validate_isbn_digits(value: str) -> None:
PydanticCustomError: If the check digit is not valid.
"""

isbn_length = len(value)

if isbn_length not in (10, 13):
raise PydanticCustomError('isbn_length', f'Length for ISBN must be 10 or 13 digits, not {isbn_length}')

validation_functions = {10: isbn10_digit_calc, 13: isbn13_digit_calc}
validate = validation_functions.get(len(value))
validate = validation_functions.get(isbn_length)

if validate(value) != value[-1]:
raise PydanticCustomError(
'isbn_invalid_digit_check_isbn', 'Provided digit is invalid for given ISBN'
)
raise PydanticCustomError('isbn_invalid_digit_check_isbn', 'Provided digit is invalid for given ISBN')

@staticmethod
def convert_isbn10_to_isbn13(value: str) -> str:
Expand All @@ -132,6 +131,6 @@ def convert_isbn10_to_isbn13(value: str) -> str:
if len(value) == 10:
base_isbn = '978' + value[:-1]
isbn13_digit = isbn13_digit_calc(base_isbn)
return f'{base_isbn}{isbn13_digit}'
return ISBN(f'{base_isbn}{isbn13_digit}')

return value
return ISBN(value)
24 changes: 12 additions & 12 deletions tests/test_isbn.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ class Book(BaseModel):
('8537809667', '9788537809662', True), # ISBN-10 as input
('9788537809662', '9788537809662', True), # ISBN-13 as input
('080442957X', '9780804429573', True), # ISBN-10 ending in "X" as input
('9788584390670', '9788584390670', True), #ISBN-13 Starting with 978
('9790306406156', '9790306406156', True), # ISBN-13 starting with 979
('9788584390670', '9788584390670', True), # ISBN-13 Starting with 978
('9790306406156', '9790306406156', True), # ISBN-13 starting with 979
# Invalid ISBNs
('97885843906701', None, False), # Length: 14 (Higher)
('978858439067', None, False), # Length: 12 (In Between)
Expand Down Expand Up @@ -47,7 +47,7 @@ def test_isbn_length(input_isbn: Any, output_isbn: str, valid: bool):
('853780@667', None, False), # Non Integer in [6] position
('8537809@67', None, False), # Non Integer in [7] position
('85378096@7', None, False), # Non Integer in [8] position
('853780966@', None, False) # Non Integer or X in [9] position
('853780966@', None, False), # Non Integer or X in [9] position
]


Expand All @@ -64,8 +64,8 @@ def test_isbn10_digits(input_isbn: Any, output_isbn: str, valid: bool):
# Valid ISBNs
('9788537809662', '9788537809662', True), # ISBN-13 as input
('9780306406157', '9780306406157', True), # ISBN-13 as input
('9788584390670', '9788584390670', True), # ISBN-13 Starting with 978
('9790306406156', '9790306406156', True), # ISBN-13 starting with 979
('9788584390670', '9788584390670', True), # ISBN-13 Starting with 978
('9790306406156', '9790306406156', True), # ISBN-13 starting with 979

# Invalid ISBNs
('@788537809662', None, False), # Non Integer in [0] position
Expand Down Expand Up @@ -95,8 +95,8 @@ def test_isbn13_digits(input_isbn: Any, output_isbn: str, valid: bool):
isbn13_early_digits_test_cases = [
# Valid ISBNs
('9780306406157', '9780306406157', True), # ISBN-13 as input
('9788584390670', '9788584390670', True), # ISBN-13 Starting with 978
('9790306406156', '9790306406156', True), # ISBN-13 starting with 979
('9788584390670', '9788584390670', True), # ISBN-13 Starting with 978
('9790306406156', '9790306406156', True), # ISBN-13 starting with 979

# Invalid ISBNs
('1788584390670', None, False), # Does not start with 978 or 979
Expand All @@ -119,15 +119,15 @@ def test_isbn13_early_digits(input_isbn: Any, output_isbn: str, valid: bool):
('8537809667', '9788537809662', True), # ISBN-10 as input
('9788537809662', '9788537809662', True), # ISBN-13 as input
('080442957X', '9780804429573', True), # ISBN-10 ending in "X" as input
('9788584390670', '9788584390670', True), # ISBN-13 Starting with 978
('9790306406156', '9790306406156', True), # ISBN-13 starting with 979
('9788584390670', '9788584390670', True), # ISBN-13 Starting with 978
('9790306406156', '9790306406156', True), # ISBN-13 starting with 979

# Invalid ISBNs
('8537809663', None, False), # ISBN-10 as input with wrong last digit
('9788537809661', None, False), # ISBN-13 as input with wrong last digit
('080442953X', None, False), # ISBN-10 ending in "X" as input with wrong last digit
('9788584390671', None, False), #ISBN-13 Starting with 978 with wrong last digit
('9790306406155', None, False), # ISBN-13 starting with 979 with wrong last digit
('9788584390671', None, False), # ISBN-13 Starting with 978 with wrong last digit
('9790306406155', None, False), # ISBN-13 starting with 979 with wrong last digit
]


Expand All @@ -144,7 +144,7 @@ def test_isbn_last_digit(input_isbn: Any, output_isbn: str, valid: bool):
('8537809667', '9788537809662'),
('080442957X', '9780804429573'),
('9788584390670', '9788584390670'),
('9790306406156', '9790306406156')
('9790306406156', '9790306406156'),
]


Expand Down

0 comments on commit bdc75f4

Please sign in to comment.