Files
BibAPI/src/bibapi/schemas/bookdata.py

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