Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group #4 #14

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
17 changes: 9 additions & 8 deletions library/model/author.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
class Author:

firstname: str
lastname: str
_firstname: str
_lastname: str

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make the code symmetric, you could additionally declare _uid as a member variable here.

def __init__(self, firstname: str, lastname: str):
self.firstname = firstname
self.lastname = lastname
self._firstname = firstname
self._lastname = lastname
self._uid=f"{self._firstname} {self._lastname}"

def get_firstname(self) -> str:
return self.firstname
return self._firstname

def get_lastname(self) -> str:
return self.lastname
return self._lastname

def get_fullname(self) -> str:
return f"{self.firstname} {self.lastname}"
return self._uid

def __eq__(self, other):
"""Overrides the default implementation"""
if isinstance(other, Author):
return self.get_fullname() == other.get_fullname()
return self._uid == other._uid
return NotImplemented
95 changes: 43 additions & 52 deletions library/model/book.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@
from library.model.author import Author
from library.model.genre import Genre
from library.model.publisher import Publisher
from library.model.booktype import BookType, BookTypeProcessor

import xml.etree.ElementTree as et

from library.persistence.storage import LibraryRepository


class Book:
title: str
authors: list[Author]
publisher: Publisher
publication_date: datetime
genres: list[Genre]
genres: set[Genre]
pages: int
isbn: str

existing_items: int
borrowed_items: int

_book_type: str
_book_type: BookType
duration: int = 0

def __init__(self, title, authors, publisher, pub_date, genres, pages, isbn, type, duration=0, existing_items=1, borrowed_items=0):
Expand Down Expand Up @@ -54,38 +54,19 @@ def from_borrowed_book(cls, borrowed_book: "BorrowedBook") -> "Book":
return book

def can_borrow(self) -> bool:
if self._book_type == "Paper":
return self.existing_items - self.borrowed_items > 0
elif self._book_type == "Electronic":
return True
elif self._book_type == "Audio":
return True
else:
raise AttributeError("No such book type...")
return BookTypeProcessor.can_borrow(self)


def get_approximate_duration(self) -> int:
if self._book_type == "Paper":
return self.pages * 3 * 60
elif self._book_type == "Electronic":
return self.pages * 5 * 60
elif self._book_type == "Audio":
return self.duration
else:
raise AttributeError("No such book type...")
return BookTypeProcessor.get_approximate_duration(self)


def get_weekly_fee(self) -> int:
if self._book_type == "Paper":
return 5
elif self._book_type == "Electronic":
return 2
elif self._book_type == "Audio":
return 2
else:
raise AttributeError("No such book type...")

return BookTypeProcessor.get_weekly_fee(self)

def borrow_book(self) -> "BorrowedBook":
if self.can_borrow():
if self._book_type == "Paper":
if BookTypeProcessor.book_check_reqrd(self):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion, the readability of the if statement decreased here. You could follow the prefix pattern (is should need etc) for methods returning a bool.

self.borrowed_items += 1
LibraryRepository.update_book(self)
borrowed_book = BorrowedBook.from_book(self)
Expand Down Expand Up @@ -131,7 +112,7 @@ def renew_rental(self) -> "BorrowedBook":
return self

def return_book(self) -> Book:
if self._book_type == "Paper":
if self._book_type == BookType.PAPER:
self.borrowed_items -= 1
book = Book.from_borrowed_book(self)
LibraryRepository.update_book(book)
Expand All @@ -145,26 +126,36 @@ def __eq__(self, other):


class BookSerializer:
def serialize(self, book: Book, format: str):
if format == "JSON":
book_info = {
"id": book.isbn,
"title": book.title,
"authors": [author.get_fullname() for author in book.authors],
"available_items": book.existing_items - book.borrowed_items,
"borrowed_items": book.borrowed_items,
}
return json.dumps(book_info)
elif format == "XML":
book_info = et.Element("book", attrib={"id": book.isbn})
title = et.SubElement(book_info, "title")
title.text = book.title
authors = et.SubElement(book_info, "authors")
authors.text = ", ".join([author.get_fullname() for author in book.authors])
avail = et.SubElement(book_info, "available")
avail.text = str(book.existing_items - book.borrowed_items)
authors = et.SubElement(book_info, "borrowed")
authors.text = str(book.borrowed_items)
return et.tostring(book_info, encoding="Unicode")

@staticmethod
def _serialize_to_json(book: Book):
book_info = {
"id": book.isbn,
"title": book.title,
"authors": [author.get_fullname() for author in book.authors],
"available_items": book.existing_items - book.borrowed_items,
"borrowed_items": book.borrowed_items,
}
return json.dumps(book_info)

@staticmethod
def _serialize_to_xml(book: Book):
book_info = et.Element("book", attrib={"id": book.isbn})
title = et.SubElement(book_info, "title")
title.text = book.title
authors = et.SubElement(book_info, "authors")
authors.text = ", ".join([author.get_fullname() for author in book.authors])
avail = et.SubElement(book_info, "available")
avail.text = str(book.existing_items - book.borrowed_items)
authors = et.SubElement(book_info, "borrowed")
authors.text = str(book.borrowed_items)
return et.tostring(book_info, encoding="Unicode")

@staticmethod
def serialize(book: Book, format: str):
if (format == "JSON"):
return BookSerializer._serialize_to_json(book)
elif (format == "XML"):
return BookSerializer._serialize_to_xml(book)
else:
raise ValueError(format)
51 changes: 51 additions & 0 deletions library/model/booktype.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from enum import Enum
from model.book import Book
seconds_in_a_minute = 60

class BookType(Enum):
PAPER = "Paper"
ELECTRONIC = "Electronic"
AUDIO = "Audio"

class BookTypeProcessor():

@staticmethod
def book_check_reqrd(book:Book):
if book._book_type == BookType.PAPER:
return True
else:
return False

@staticmethod
def can_borrow(book):
if (book._book_type == BookType.PAPER):
return book.existing_items - book.borrowed_item > 0
elif (book._book_type == BookType.ELECTRONIC):
return True
elif (book._book_type == BookType.AUDIO):
return True
else:
raise AttributeError("No such a book...")

@staticmethod
def get_approximate_duration(book):
if (book._book_type == BookType.PAPER):
return book._pages * 3 * seconds_in_a_minute
elif (book._book_type == BookType.ELECTRONIC):
return book._pages * 5 * seconds_in_a_minute
elif (book._book_type == BookType.AUDIO):
return book._duration
else:
raise AttributeError("No such a book...")

@staticmethod
def get_weekly_fee(book):
if (book._book_type == BookType.PAPER):
return 5
elif (book._book_type == BookType.ELECTRONIC):
return 2
elif (book._book_type == BookType.AUDIO):
return 2
else:
raise AttributeError("No such a book...")

6 changes: 3 additions & 3 deletions library/model/publisher.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
class Publisher:
name: str
_name: str

def __init__(self, name):
self.name = name
self._name = name

def __eq__(self, other):
"""Overrides the default implementation"""
if isinstance(other, Publisher):
return self.name == other.name
return self._name == other._name
return NotImplemented
22 changes: 14 additions & 8 deletions library/model/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,19 @@ def __eq__(self, other):
return NotImplemented

def __str__(self):
# formatted tempalte
output_template = "{}, {}, ({}): {}{}/{}\n____BORROWED BOOKS____\n{}\n____READ BOOKS____\n{}\n\nOpen invoices: {}"
borrowed_books = "\n".join(str(book) for book in self.borrowed_books)
read_books = "\n".join(str(book) for book in self.read_books)
return f"""{self.firstname}, {self.lastname} ({self.email}): {self.country_calling_code}{self.area_code}/{self.landline_number}
_______BORROWED BOOKS________
{borrowed_books}
_______READ BOOKS________
{read_books}

Open invoices: {[x.id for x in self.invoices]}
"""
summary = output_template.format(
self.firstname,
self.lastname,
self.email,
self.country_calling_code,
self.area_code,
self.landline_number,
borrowed_books,
read_books,
[invoice.id, for invoice in self.invoices]
)
return summary