yessir
This commit is contained in:
107
book_stuff/book.py
Normal file
107
book_stuff/book.py
Normal file
@@ -0,0 +1,107 @@
|
||||
"""
|
||||
This file is the beginnings of a Book class. However, it isn't very well-coded.
|
||||
We want to harden it. We want to enforce the following rules:
|
||||
|
||||
- Title must not be blank, and cannot be longer than 255 characters.
|
||||
- Authors is a list of names. None of the names should be blank or over 255 characters.
|
||||
Names should not have any characters except for alphabetical ones.
|
||||
- ISBN is a string, but it can only contain numbers and there must be 13 of them.
|
||||
- Cost cannot be negative.
|
||||
|
||||
We are going to practice "test-driven development". This means we will write
|
||||
the test cases for our code before we write our code. Enough of the code is
|
||||
already given to you to show you how to use it. Don't update the code until
|
||||
you have written tests to check for all of the above criteria. When your code passes
|
||||
your tests, have your neighbor email you their tests and see if theirs passes as well.
|
||||
If not, modify your code accordingly.
|
||||
"""
|
||||
class Book:
|
||||
def __init__(self, title: str, authors: list[str], isbn: str, cost: float):
|
||||
self.set_title(title)
|
||||
self.set_authors(authors)
|
||||
self.set_isbn(isbn)
|
||||
self.set_cost(cost)
|
||||
|
||||
# --- Title ---
|
||||
def get_title(self) -> str:
|
||||
return self._title
|
||||
|
||||
def set_title(self, title: str) -> None:
|
||||
# check if title is string
|
||||
if not isinstance(title, str):
|
||||
raise TypeError(f'title must be of type str, not {type(title).__name__}')
|
||||
|
||||
# check if title is blank or if the title length is greater than 255 characters
|
||||
title_len = len(title)
|
||||
if title_len < 1 or title_len > 255:
|
||||
raise TypeError(f'title\'s length must be between 1 and 255, not {title_len}')
|
||||
|
||||
self._title = title
|
||||
|
||||
# --- Authors ---
|
||||
def get_authors(self) -> list[str]:
|
||||
return self._authors
|
||||
|
||||
def set_authors(self, authors: list[str]) -> None:
|
||||
# check if authors is a list
|
||||
if not isinstance(authors, list):
|
||||
raise TypeError(f'authors must be of type list, not {type(authors).__name__}')
|
||||
|
||||
# check if authors is empty
|
||||
authors_len = len(authors)
|
||||
if authors_len == 0:
|
||||
raise ValueError('authors list must not be empty')
|
||||
|
||||
for author in authors:
|
||||
# check if each author is a string
|
||||
if not isinstance(author, str):
|
||||
raise TypeError(f'each author within authors must be of type str, not {type(author).__name__}')
|
||||
|
||||
# check if each author is alphanumeric
|
||||
for author_name_part in author.split():
|
||||
# splitting by space to check each part of the author's name, spaces aren't alpha so no author.isalpha()
|
||||
if not author_name_part.isalpha():
|
||||
raise ValueError(f'each part of the author\'s name within authors must be alphanumeric')
|
||||
|
||||
# check if each author's length is greater than 255
|
||||
author_len = len(author)
|
||||
if author_len > 255:
|
||||
raise ValueError(f'each author\'s length within authors must be less than 256 characters')
|
||||
|
||||
self._authors = authors
|
||||
|
||||
# --- ISBN ---
|
||||
def get_isbn(self) -> str:
|
||||
return self._isbn
|
||||
|
||||
def set_isbn(self, isbn: str) -> None:
|
||||
# check is isbn is 13 characters
|
||||
isbn_len = len(isbn)
|
||||
if isbn_len != 13:
|
||||
raise ValueError(f'isbn\'s length must be 13 digits, not {isbn_len}')
|
||||
|
||||
# check if each character is a number
|
||||
if not isbn.isdigit():
|
||||
raise ValueError('each character in isbn must be a digit')
|
||||
|
||||
self._isbn = isbn
|
||||
|
||||
# --- Cost ---
|
||||
def get_cost(self) -> float:
|
||||
return self._cost
|
||||
|
||||
def set_cost(self, cost: float) -> None:
|
||||
# check if cost is float
|
||||
if not isinstance(cost, float):
|
||||
raise ValueError(f'cost must be of type float, not {type(cost).__name__}')
|
||||
|
||||
# check if cost is negative
|
||||
if cost < 0:
|
||||
raise ValueError("cost cannot be negative")
|
||||
|
||||
self._cost = cost
|
||||
|
||||
# --- String representation ---
|
||||
def __str__(self) -> str:
|
||||
authors = ", ".join(self._authors)
|
||||
return f"'{self._title}' by {authors} (ISBN: {self._isbn}, Cost: ${self._cost:.2f})"
|
||||
Reference in New Issue
Block a user