-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlibrary.py
More file actions
124 lines (95 loc) · 3.82 KB
/
library.py
File metadata and controls
124 lines (95 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from typing import List
from dataclasses import dataclass, field
from pydantic import BaseModel, Field, ValidationError
import json
import os
from app.models import Book
class EBook(Book):
"""An E-Book that inherits from the unified Book model."""
file_format: str
def display_info(self) -> str:
return f"{super().display_info()} [Format: {self.file_format}]"
class AudioBook(Book):
"""An Audio Book that inherits from the unified Book model."""
duration: int
def display_info(self) -> str:
return f"{super().display_info()} [Duration: {self.duration} minutes]"
class Library:
"""Manages a collection of books using composition."""
def __init__(self, name: str, json_path: str = "library.json"):
self.name = name
self._books: List[Book] = []
self.json_path = json_path
self.load_from_json(self.json_path)
def add_book(self, book: Book) -> bool:
"""Add a Book domain object to the library."""
if any(existing.isbn == book.isbn for existing in self._books):
print("Bu ISBN kütüphanede zaten kayıtlı.")
return False
self._books.append(book)
self.save_to_json(self.json_path)
print(f"Kitap eklendi: {book.title} ({book.author})")
return True
def delete_book(self, isbn: str) -> bool:
"""Deleting books by ISBN number"""
for book in self._books:
if book.isbn == isbn:
self._books.remove(book)
self.save_to_json(self.json_path) # Save changes
return True
return False
def list_books(self) -> List[str]:
"""Return a list of human-readable book descriptions."""
return [book.display_info() for book in self._books]
def get_books(self) -> List[Book]:
"""Return all books as domain models."""
return list(self._books)
def find_book(self, title: str | None = None, isbn: str | None = None) -> Book | None:
"""Find a book by title or ISBN."""
for book in self._books:
if title and book.title.lower() == title.lower():
return book
if isbn and book.isbn == isbn:
return book
return None
def save_to_json(self, filename: str):
"""Save books to JSON using model dicts."""
with open(filename, "w", encoding="utf-8") as f:
payload = []
for book in self._books:
data = book.model_dump()
# Persist the concrete type so we can reconstruct EBook/AudioBook later
data["type"] = book.__class__.__name__
payload.append(data)
json.dump(payload, f, ensure_ascii=False, indent=4)
def load_from_json(self, filename: str):
"""Load books from JSON, instantiating the correct model type when possible."""
if not os.path.exists(filename):
return # No file yet, nothing to load
with open(filename, "r", encoding="utf-8") as f:
books_data = json.load(f)
self._books.clear()
for data in books_data:
book_type = data.get("type")
if book_type == "EBook":
book = EBook(**data)
elif book_type == "AudioBook":
book = AudioBook(**data)
else:
book = Book(**data)
self._books.append(book)
@property
def total_books(self) -> int:
return len(self._books)
@dataclass
class Member:
"""Represents a library member using dataclasses"""
name: str
member_id: int
borrowed_books: List[Book] = field(default_factory=list)
class PydanticBook(BaseModel):
"""Book model with Pydantic validation"""
title: str
author: str
isbn: str = Field(..., min_length=10, max_length=13)
publication_year: int = Field(..., gt=1400)