From bdc75f48614ee610367c5fb587d779da0096d7ee Mon Sep 17 00:00:00 2001 From: Lucas Mucidas Date: Wed, 27 Dec 2023 23:38:12 -0300 Subject: [PATCH] ISBN: Fixed linting --- pydantic_extra_types/isbn.py | 33 ++++++++++++++++----------------- tests/test_isbn.py | 24 ++++++++++++------------ 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/pydantic_extra_types/isbn.py b/pydantic_extra_types/isbn.py index a9d64168..ee23ea6b 100644 --- a/pydantic_extra_types/isbn.py +++ b/pydantic_extra_types/isbn.py @@ -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. """ @@ -14,12 +14,13 @@ 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])) @@ -27,6 +28,7 @@ def isbn13_digit_calc(isbn: str) -> str: return str(check_digit) + class ISBN(str): """Represents a ISBN and provides methods for conversion, validation, and serialization. @@ -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(): @@ -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: @@ -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: @@ -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 \ No newline at end of file + return ISBN(value) \ No newline at end of file diff --git a/tests/test_isbn.py b/tests/test_isbn.py index 54ab34c4..2c5dc47f 100644 --- a/tests/test_isbn.py +++ b/tests/test_isbn.py @@ -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) @@ -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 ] @@ -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 @@ -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 @@ -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 ] @@ -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'), ]