diff --git a/HW/README.md b/HW/README.md new file mode 100644 index 0000000..db2d276 --- /dev/null +++ b/HW/README.md @@ -0,0 +1,118 @@ +# Library Management System + +## Опис + +Цей проєкт реалізує систему управління бібліотекою, використовуючи сучасні концепції Python: + +Ітератори та генератори для зручного обходу колекцій книг і журналів. + +Декоратори для логування та перевірки дій. + +Контекстні менеджери для роботи з файлами. + +Обʼєктно-орієнтоване програмування (інкапсуляція, спадкування, поліморфізм, абстрактні класи). + +Валідація даних за допомогою Pydantic. + +## Особливості + +Класи Book і Journal – наслідуються від абстрактного класу Publication. + +Pydantic-модель BookModel для валідації даних книги або журналу. + +Ітератор для проходження всіх публікацій у бібліотеці. + +Генератор для пошуку публікацій за конкретним автором. + +Декоратори: + +log_addition – логування додавання нових публікацій у файл library.log. + +check_existence – перевірка наявності публікації перед її видаленням. + +Контекстний менеджер LibraryFileManager – автоматичне завантаження та збереження бібліотеки у файл library.json. + +Логування всіх важливих дій у файл library.log у форматі UTF-8. + +## Як працює скрипт: + +- Створюється обʼєкт бібліотеки. +- Створюються екземпляри книг та журналів. +- Додаються у бібліотеку. +- Виводиться список усіх публікацій. +- Можна переглянути публікації певного автора. +- Бібліотека автоматично зберігається у library.json. +- Видаляються книги/журнали за назвою (видалення спочатку у памʼяті, а потім – при збереженні у файл). +- Завантажуються дані з library.json для відновлення бібліотеки. +- Фінальний список публікацій демонструє стан бібліотеки. + +## Реалізація + +- Модель BookModel (Pydantic) + +Валідація атрибутів: title, author, year. + +- Класи Book, Journal + +Наслідування від абстрактного класу Publication. + +Реалізація методу info() для відображення даних. + +Приватні атрибути для інкапсуляції. + +- Клас Library + +Зберігає список публікацій. + +Ітератор для проходження всіх публікацій. + +Генератор books_by_author для пошуку. + +Методи add_book() і remove_book(). + +Поліморфізм – підтримка як книг, так і журналів. + +- Декоратори + +log_addition: логування додавання у library.log. + +check_existence: перевірка існування перед видаленням і логування помилок. + +- Контекстний менеджер LibraryFileManager + +Завантажує бібліотеку з файлу при вході у контекст. + +Зберігає оновлену бібліотеку при виході. + +Файлова робота (JSON) + +Серіалізація/десеріалізація з урахуванням типу публікації (type). + +- Логування + +Усі дії та помилки записуються у library.log з часовими мітками. + +## Файли + +main.py – головний скрипт з реалізацією. + +library.json – файл для збереження бібліотеки у форматі JSON. + +library.log – журнал усіх дій і помилок (створюється автоматично). + +## Логування + +Всі операції (додавання, видалення, помилки) записуються у library.log з часовими позначками. +Файл логів створюється і оновлюється автоматично. + +## Відповідність вимогам + +Валідація даних – Pydantic. + +Ітератори та генератори. + +Декоратори для логування і перевірок. + +Контекстний менеджер для роботи з файлами. + +Принципи ООП: інкапсуляція, спадкування, поліморфізм, абстрактні класи. \ No newline at end of file diff --git a/HW/library.json b/HW/library.json new file mode 100644 index 0000000..0187f55 --- /dev/null +++ b/HW/library.json @@ -0,0 +1,26 @@ +[ + { + "title": "Науковий журнал", + "author": "Іван Іванов", + "year": 2024, + "type": "journal" + }, + { + "title": "Берестечко", + "author": "Ліна Костенко", + "year": 2010, + "type": "book" + }, + { + "title": "Сад нетанучих скульптур", + "author": "Ліна Костенко", + "year": 2019, + "type": "book" + }, + { + "title": "Мистецтво війни", + "author": "Сунь-Цзи", + "year": 500, + "type": "book" + } +] \ No newline at end of file diff --git a/HW/library.log b/HW/library.log new file mode 100644 index 0000000..ee3f566 --- /dev/null +++ b/HW/library.log @@ -0,0 +1,60 @@ +2025-05-27 21:12:22,533 | INFO | [LOG] Додаємо публікацію: Мистецтво війни +2025-05-27 21:12:22,533 | INFO | [LOG] Додаємо публікацію: Науковий журнал +2025-05-27 21:12:22,533 | INFO | [LOG] Додаємо публікацію: Берестечко +2025-05-27 21:12:22,533 | INFO | [LOG] Додаємо публікацію: Сад нетанучих скульптур +2025-05-27 21:12:22,533 | INFO | [INFO] Публікацію 'Мистецтво війни' видалено з бібліотеки. +2025-05-27 21:12:22,535 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-27 21:12:22,551 | INFO | [INFO] Бібліотека завантажена з файлу 'library.json'. +2025-05-27 21:12:22,551 | WARNING | [WARNING] Публікація 'Мистецтво війни' не знайдена в бібліотеці. +2025-05-27 21:12:22,553 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-27 21:12:22,553 | INFO | [INFO] Завершено роботу з файлом бібліотеки. +2025-05-27 21:12:22,554 | INFO | [LOG] Додаємо публікацію: Мистецтво війни +2025-05-27 21:12:22,555 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-27 21:12:22,567 | INFO | [INFO] Бібліотека завантажена з файлу 'library.json'. +2025-05-27 21:12:22,569 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-27 21:12:22,569 | INFO | [INFO] Завершено роботу з файлом бібліотеки. +2025-05-27 21:14:09,315 | INFO | [LOG] Додаємо публікацію: Мистецтво війни +2025-05-27 21:14:09,315 | INFO | [LOG] Додаємо публікацію: Науковий журнал +2025-05-27 21:14:09,315 | INFO | [LOG] Додаємо публікацію: Берестечко +2025-05-27 21:14:09,316 | INFO | [LOG] Додаємо публікацію: Сад нетанучих скульптур +2025-05-27 21:14:09,316 | INFO | [INFO] Публікацію 'Мистецтво війни' видалено з бібліотеки. +2025-05-27 21:14:09,318 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-27 21:14:09,322 | INFO | [INFO] Бібліотека завантажена з файлу 'library.json'. +2025-05-27 21:14:09,322 | WARNING | [WARNING] Публікація 'Мистецтво війни' не знайдена в бібліотеці. +2025-05-27 21:14:09,325 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-27 21:14:09,325 | INFO | [INFO] Завершено роботу з файлом бібліотеки. +2025-05-27 21:14:09,326 | INFO | [LOG] Додаємо публікацію: Мистецтво війни +2025-05-27 21:14:09,327 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-27 21:14:09,330 | INFO | [INFO] Бібліотека завантажена з файлу 'library.json'. +2025-05-27 21:14:09,332 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-27 21:14:09,332 | INFO | [INFO] Завершено роботу з файлом бібліотеки. +2025-05-31 13:43:05,888 | INFO | [LOG] Додаємо публікацію: Мистецтво війни +2025-05-31 13:43:05,888 | INFO | [LOG] Додаємо публікацію: Науковий журнал +2025-05-31 13:43:05,888 | INFO | [LOG] Додаємо публікацію: Берестечко +2025-05-31 13:43:05,889 | INFO | [LOG] Додаємо публікацію: Сад нетанучих скульптур +2025-05-31 13:43:05,889 | INFO | [INFO] Публікацію 'Мистецтво війни' видалено з бібліотеки. +2025-05-31 13:43:05,891 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-31 13:43:05,912 | INFO | [INFO] Бібліотека завантажена з файлу 'library.json'. +2025-05-31 13:43:05,912 | WARNING | [WARNING] Публікація 'Мистецтво війни' не знайдена в бібліотеці. +2025-05-31 13:43:05,914 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-31 13:43:05,915 | INFO | [INFO] Завершено роботу з файлом бібліотеки. +2025-05-31 13:43:05,916 | INFO | [LOG] Додаємо публікацію: Мистецтво війни +2025-05-31 13:43:05,917 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-31 13:43:05,934 | INFO | [INFO] Бібліотека завантажена з файлу 'library.json'. +2025-05-31 13:43:05,937 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-31 13:43:05,937 | INFO | [INFO] Завершено роботу з файлом бібліотеки. +2025-05-31 14:26:57,346 | INFO | [LOG] Додаємо публікацію: Мистецтво війни +2025-05-31 14:26:57,346 | INFO | [LOG] Додаємо публікацію: Науковий журнал +2025-05-31 14:26:57,347 | INFO | [LOG] Додаємо публікацію: Берестечко +2025-05-31 14:26:57,347 | INFO | [LOG] Додаємо публікацію: Сад нетанучих скульптур +2025-05-31 14:26:57,347 | INFO | [INFO] Публікацію 'Мистецтво війни' видалено з бібліотеки. +2025-05-31 14:26:57,352 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-31 14:26:57,362 | INFO | [INFO] Бібліотека завантажена з файлу 'library.json'. +2025-05-31 14:26:57,362 | WARNING | [WARNING] Публікація 'Мистецтво війни' не знайдена в бібліотеці. +2025-05-31 14:26:57,367 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-31 14:26:57,368 | INFO | [INFO] Завершено роботу з файлом бібліотеки. +2025-05-31 14:26:57,370 | INFO | [LOG] Додаємо публікацію: Мистецтво війни +2025-05-31 14:26:57,376 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-31 14:26:57,380 | INFO | [INFO] Бібліотека завантажена з файлу 'library.json'. +2025-05-31 14:26:57,384 | INFO | [INFO] Бібліотека збережена у файл 'library.json'. +2025-05-31 14:26:57,384 | INFO | [INFO] Завершено роботу з файлом бібліотеки. diff --git a/HW/main.py b/HW/main.py new file mode 100644 index 0000000..e015936 --- /dev/null +++ b/HW/main.py @@ -0,0 +1,187 @@ +from pydantic import BaseModel +from abc import ABC, abstractmethod +from typing import Generator, Iterator +from contextlib import contextmanager +import logging +import json + +# Налаштування логування у файл +logging.basicConfig( + level=logging.INFO, + format="%(asctime)s | %(levelname)s | %(message)s", + filename="library.log", + filemode="a", # додаємо до існуючого + encoding="utf-8", # для української мови +) +logger = logging.getLogger(__name__) + +# Pydantic-модель +class BookModel(BaseModel): + title: str + author: str + year: int + type: str + + +# Абстрактний клас Publication +class Publication(ABC): + def __init__(self, model: BookModel) -> None: + self._model = model + + @property + def model(self) -> BookModel: + return self._model + + @abstractmethod + def info(self) -> str: + pass + + +# Клас Book +class Book(Publication): + def info(self) -> str: + return f"Книга: '{self.model.title}', автор: {self.model.author}, рік: {self.model.year}" + + +# Клас Journal +class Journal(Publication): + def info(self) -> str: + return f"Журнал: '{self.model.title}', автор: {self.model.author}, рік: {self.model.year}" + + +# Декоратор для логування +def log_action(func): + def wrapper(self, book: Publication): + logger.info(f"[LOG] Додаємо публікацію: {book.model.title}") + return func(self, book) + return wrapper + + +# Декоратор для перевірки перед видаленням +def check_book_exists(func): + def wrapper(self, title: str): + if not any(b.model.title == title for b in self._books): + logger.warning(f"[WARNING] Публікація '{title}' не знайдена в бібліотеці.") + return + return func(self, title) + return wrapper + + +# Клас Library +class Library: + def __init__(self): + self._books: list[Publication] = [] + + @log_action + def add_book(self, book: Publication) -> None: + self._books.append(book) + + # Внутрішній метод без логування (для завантаження з файлу) + def _add_book_directly(self, book: Publication) -> None: + self._books.append(book) + + @check_book_exists + def remove_book(self, title: str) -> None: + self._books = [b for b in self._books if b.model.title != title] + logger.info(f"[INFO] Публікацію '{title}' видалено з бібліотеки.") + + def __iter__(self) -> Iterator[Publication]: + return iter(self._books) + + def books_by_author(self, author: str) -> Generator[Publication, None, None]: + return (b for b in self._books if b.model.author == author) + + def save_to_file(self, filename: str) -> None: + with open(filename, "w", encoding="utf-8") as f: + json.dump( + [ + {**b.model.model_dump(), "type": "journal" if isinstance(b, Journal) else "book"} + for b in self._books + ], + f, + ensure_ascii=False, + indent=4 + ) + logger.info(f"[INFO] Бібліотека збережена у файл '{filename}'.") + + def load_from_file(self, filename: str) -> None: + with open(filename, "r", encoding="utf-8") as f: + data = json.load(f) + self._books.clear() + for item in data: + if item["type"] == "journal": + self._add_book_directly(Journal(BookModel(**item))) + else: + self._add_book_directly(Book(BookModel(**item))) + logger.info(f"[INFO] Бібліотека завантажена з файлу '{filename}'.") + + +# Контекстний менеджер +@contextmanager +def LibraryFileManager(library: Library, filename: str): + try: + library.load_from_file(filename) + yield library + finally: + library.save_to_file(filename) + logger.info(f"[INFO] Завершено роботу з файлом бібліотеки.") + +# ============================================================================ + +# Основний блок +if __name__ == "__main__": + lib = Library() + + # Створення книги та журналу + book_01 = Book(BookModel(title="Мистецтво війни", author="Сунь-Цзи", year=500, type="book")) + journal_01 = Journal(BookModel(title="Науковий журнал", author="Іван Іванов", year=2024, type="journal")) + book_02 = Book(BookModel(title="Берестечко", author="Ліна Костенко", year=2010, type="book")) + book_03 = Book(BookModel(title="Сад нетанучих скульптур", author="Ліна Костенко", year=2019, type="book")) + + # Додавання + lib.add_book(book_01) + lib.add_book(journal_01) + lib.add_book(book_02) + lib.add_book(book_03) + + # Видалення книги з пам'яті (RAM) без збереження у файл + lib.remove_book("Мистецтво війни") + print("\nСписок публікацій після видалення книги з пам'яті (без збереження у файл):") + for pub in lib: + print(pub.info()) + + # Збереження до файлу + lib.save_to_file("library.json") + + # Виведення всіх публікацій + print("\nСписок всіх публікацій:") + for pub in lib: + print(pub.info()) + + # Виведення книг по автору + print("\nПублікації Ліна Костенко:") + for pub in lib.books_by_author("Ліна Костенко"): + print(pub.info()) + + # Видалення книги та збереження у файлі + with LibraryFileManager(lib, "library.json") as library: + library.remove_book("Мистецтво війни") + print("\nСписок публікацій після видалення книги:") + for pub in library: + print(pub.info()) + + # Виведення всіх публікацій + print("\nСписок всіх публікацій:") + for pub in lib: + print(pub.info()) + + # Додавання книги «Мистецтво війни» назад + book_04 = Book(BookModel(title="Мистецтво війни", author="Сунь-Цзи", year=500, type="book")) + lib.add_book(book_04) + lib.save_to_file("library.json") + + # Завантаження з файлу + with LibraryFileManager(lib, "library.json") as loaded_library: + print("\nСписок публікацій після завантаження з файлу:") + for pub in loaded_library: + print(pub.info()) diff --git a/HW/poetry.lock b/HW/poetry.lock new file mode 100644 index 0000000..45278b4 --- /dev/null +++ b/HW/poetry.lock @@ -0,0 +1,190 @@ +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "logging" +version = "0.4.9.6" +description = "A logging module for Python" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "logging-0.4.9.6.tar.gz", hash = "sha256:26f6b50773f085042d301085bd1bf5d9f3735704db9f37c1ce6d8b85c38f2417"}, +] + +[[package]] +name = "pydantic" +version = "2.11.5" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic-2.11.5-py3-none-any.whl", hash = "sha256:f9c26ba06f9747749ca1e5c94d6a85cb84254577553c8785576fd38fa64dc0f7"}, + {file = "pydantic-2.11.5.tar.gz", hash = "sha256:7f853db3d0ce78ce8bbb148c401c2cdd6431b3473c0cdff2755c7690952a7b7a"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.33.2" +typing-extensions = ">=4.12.2" +typing-inspection = ">=0.4.0" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, + {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "typing-extensions" +version = "4.13.2" +description = "Backported and Experimental Type Hints for Python 3.8+" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c"}, + {file = "typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef"}, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +description = "Runtime typing introspection tools" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51"}, + {file = "typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28"}, +] + +[package.dependencies] +typing-extensions = ">=4.12.0" + +[metadata] +lock-version = "2.1" +python-versions = ">=3.13" +content-hash = "5f850f1c49ee15f64aa9907381c45c0dc03943a0e45bce6f8ef611e4fe273641" diff --git a/HW/pyproject.toml b/HW/pyproject.toml new file mode 100644 index 0000000..7c3e21b --- /dev/null +++ b/HW/pyproject.toml @@ -0,0 +1,17 @@ +[project] +name = "homework-03" +version = "0.1.0" +description = "homework 03 poetry" +authors = [{ name = "Zakatsiura", email = "zakatsiura@gmail.com" }] +license = { text = "MIT" } +readme = "README.md" +requires-python = ">=3.13" + +dependencies = [ + "pydantic>=2.0.0", + "logging>=0.4.9.6,<0.5.0.0" +] + +[build-system] +requires = ["poetry-core>=2.0.0,<3.0.0"] +build-backend = "poetry.core.masonry.api"