diff --git a/lib/__init__.py b/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/lib/decorators.py b/lib/decorators.py new file mode 100644 index 0000000..8ffedd8 --- /dev/null +++ b/lib/decorators.py @@ -0,0 +1,17 @@ +import logging + + +def book_added_log(func): + def wrapper(library, book): + res = func(library, book) + logging.info(f"The book has added: {book.get_ribbon()}") + return res + return wrapper + + +def book_exists(func): + def wrapper(library, book): + if book not in library.books: + raise ValueError("Book not exists") + return func(library, book) + return wrapper diff --git a/lib/library.py b/lib/library.py new file mode 100644 index 0000000..88fff2d --- /dev/null +++ b/lib/library.py @@ -0,0 +1,28 @@ +from typing import List, Generator +from .models import Book +from .decorators import book_added_log, book_exists + + +class Library: + def __init__(self, books: List[Book]): + self._books = books + + @property + def books(self) -> List[Book]: + return self._books + + def __iter__(self): + return iter(self._books) + + def books_by_author(self, author: str) -> Generator[Book, None, None]: + return (book for book in self._books if book.author == author) + + @book_added_log + def add(self, book: Book): + self._books.append(book) + + @book_exists + def remove(self, book: Book): + self._books.remove(book) + + diff --git a/lib/models.py b/lib/models.py new file mode 100644 index 0000000..1f20bf7 --- /dev/null +++ b/lib/models.py @@ -0,0 +1,38 @@ +from pydantic import BaseModel + + +class BookModel(BaseModel): + title: str + author: str + year: int + + +class Book: + def __init__(self, model: BookModel): + self._model = model + + @property + def title(self) -> str: + return self._model.title + + @property + def author(self) -> str: + return self._model.author + + @property + def year(self) -> int: + return self._model.year + + def get_ribbon(self) -> str: + return f"{self.title} by {self.author}, published in {self.year}" + + def __str__(self): + return f"Book(title={self.title}, author={self.author}, year={self.year})" + + +class Magazine(Book): + def __init__(self, model: BookModel): + super().__init__(model) + + def get_ribbon(self) -> str: + return f"The {self.title} magazine by {self.author}, published in {self.year}" \ No newline at end of file diff --git a/lib/storage.py b/lib/storage.py new file mode 100644 index 0000000..b16e263 --- /dev/null +++ b/lib/storage.py @@ -0,0 +1,27 @@ +import json +from contextlib import contextmanager +from .library import Library +from .models import Book, BookModel + + +@contextmanager +def file_manager(file_name: str, mode: str): + file = open(file_name, mode) + try: + yield file + finally: + file.close() + + +def save(library: Library, file_name: str): + with file_manager(file_name, 'w') as file: + books_data = [book._model.dict() for book in library] + json.dump(books_data, file) + + +def load(library: Library, file_name: str): + with file_manager(file_name, 'r') as file: + books_data = json.load(file) + for book_data in books_data: + book_model = BookModel(**book_data) + library.add(Book(book_model)) diff --git a/main.py b/main.py index 94e3a87..36d8f0f 100644 --- a/main.py +++ b/main.py @@ -1,16 +1,49 @@ -# This is a sample Python script. +from lib.models import Book, BookModel, Magazine +from lib.library import Library +from lib import storage -# Press ⌃R to execute it or replace it with your code. -# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings. +FILE_NAME = "test.json" -def print_hi(name): - # Use a breakpoint in the code line below to debug your script. - print(f'Hi, {name}') # Press ⌘F8 to toggle the breakpoint. +def print_books(library: Library): + print("===============") + for book in library: + print(f"Book: {book}") -# Press the green button in the gutter to run the script. if __name__ == '__main__': - print_hi('PyCharm') + library = Library([]) -# See PyCharm help at https://www.jetbrains.com/help/pycharm/ + book1 = Book(BookModel(title="To Kill a Mockingbird", author="Harper Lee", + year=1960)) + book2 = Book(BookModel(title="1984", author="George Orwell", + year=1949)) + book3 = Book( + BookModel(title="The Great Gatsby", author="F. Scott Fitzgerald", + year=1925)) + + magazine1 = Magazine( + BookModel(title="National Geographic", author="Multiple Authors", + year=2020)) + magazine2 = Magazine(BookModel(title="Time", author="Multiple Authors", + year=2021)) + + library.add(book1) + library.add(book2) + library.add(book3) + library.add(magazine1) + library.add(magazine2) + + print_books(library) + + print("=========") + for book in library.books_by_author("Multiple Authors"): + print(f"Multiple Authors: {book}") + + storage.save(library, FILE_NAME) + + library.remove(magazine2) + print_books(library) + + storage.load(library, FILE_NAME) + print_books(library) \ No newline at end of file