137 lines
4.8 KiB
Python
137 lines
4.8 KiB
Python
"""A dataclass representing book data from the library system and catalogue."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from dataclasses import dataclass, field
|
|
from typing import Any
|
|
|
|
import regex
|
|
|
|
|
|
@dataclass
|
|
class BookData:
|
|
"""A dataclass representing the book object.
|
|
|
|
Returns
|
|
-------
|
|
self : BookData
|
|
The book data object with attributes like title, author, year, etc.
|
|
|
|
"""
|
|
|
|
ppn: str | None = None
|
|
title: str | None = None
|
|
signature: str | None = None
|
|
edition: str | None = None
|
|
link: str | None = None
|
|
isbn: str | list[str] | None = field(default_factory=list[str])
|
|
author: str | None = None
|
|
language: str | list[str] | None = field(default_factory=list[str])
|
|
publisher: str | None = None
|
|
place: str | None = None
|
|
year: int | None = None
|
|
pages: str | None = None
|
|
library_location: str | None = None
|
|
in_apparat: bool | None = False
|
|
adis_idn: str | None = None
|
|
old_book: Any | None = None
|
|
media_type: str | None = None
|
|
in_library: bool | None = None # whether the book is in the library or not
|
|
libraries: list[str] | None = field(default_factory=list[str])
|
|
medianr: int | None = None # media number
|
|
|
|
def __post_init__(self) -> None:
|
|
"""Run Post-initialization processing."""
|
|
self.library_location = (
|
|
str(self.library_location) if self.library_location else None
|
|
)
|
|
if isinstance(self.language, list) and self.language:
|
|
self.language = [lang.strip() for lang in self.language if lang.strip()]
|
|
self.language = ",".join(self.language)
|
|
self.year = regex.sub(r"[^\d]", "", str(self.year)) if self.year else None
|
|
self.in_library = True if self.signature else False
|
|
|
|
def from_dict(self, data: dict[str, Any]) -> BookData:
|
|
for key, value in data.items():
|
|
setattr(self, key, value)
|
|
return self
|
|
|
|
def merge(self, other: BookData) -> BookData:
|
|
for key, value in other.__dict__.items():
|
|
# merge lists, if the attribute is a list, extend it
|
|
if isinstance(value, list):
|
|
current_value = getattr(self, key)
|
|
if current_value is None:
|
|
current_value = []
|
|
elif not isinstance(current_value, list):
|
|
current_value = [current_value]
|
|
# extend the list with the new values, but only if they are not already in the list
|
|
for v in value:
|
|
if v not in current_value:
|
|
current_value.append(v)
|
|
setattr(self, key, current_value)
|
|
if value is not None and (
|
|
getattr(self, key) is None or getattr(self, key) == ""
|
|
):
|
|
setattr(self, key, value)
|
|
# in language, drop all entries that are longer than 3 characters
|
|
if isinstance(self.language, list):
|
|
self.language = [lang for lang in self.language if len(lang) <= 4]
|
|
return self
|
|
|
|
@property
|
|
def to_dict(self) -> str:
|
|
"""Convert the dataclass to a dictionary."""
|
|
data_dict = {
|
|
key: value for key, value in self.__dict__.items() if value is not None
|
|
}
|
|
# remove old_book from data_dict
|
|
data_dict.pop("old_book", None)
|
|
return json.dumps(data_dict, ensure_ascii=False)
|
|
|
|
def from_dataclass(self, dataclass: Any | None) -> None:
|
|
if dataclass is None:
|
|
return
|
|
for key, value in dataclass.__dict__.items():
|
|
setattr(self, key, value)
|
|
|
|
def get_book_type(self) -> str:
|
|
if isinstance(self.media_type, str):
|
|
if "Online" in self.pages:
|
|
return "eBook"
|
|
return "Druckausgabe"
|
|
return None
|
|
|
|
def from_string(self, data: str) -> BookData:
|
|
ndata = json.loads(data)
|
|
|
|
return BookData(**ndata)
|
|
|
|
def from_LehmannsSearchResult(self, result: Any) -> BookData:
|
|
self.title = result.title
|
|
self.author = "; ".join(result.authors) if result.authors else None
|
|
self.edition = str(result.edition) if result.edition else None
|
|
self.link = result.url
|
|
self.isbn = (
|
|
result.isbn13
|
|
if isinstance(result.isbn13, list)
|
|
else [result.isbn13]
|
|
if result.isbn13
|
|
else []
|
|
)
|
|
self.pages = str(result.pages) if result.pages else None
|
|
self.publisher = result.publisher
|
|
self.year = str(result.year) if result.year else None
|
|
# self.pages = str(result.pages) if result.pages else None
|
|
return self
|
|
|
|
@property
|
|
def edition_number(self) -> int | None:
|
|
if self.edition is None:
|
|
return 0
|
|
match = regex.search(r"(\d+)", self.edition)
|
|
if match:
|
|
return int(match.group(1))
|
|
return 0
|