draft implemented add_data
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import copy
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Dict, List, Optional, Set, Tuple, Type, TypedDict, Union
|
||||
|
||||
from ..utils import create_dataclass_instance, custom_hash
|
||||
from ..utils.config import main_settings
|
||||
from ..utils.enums import PictureType
|
||||
from ..utils.string_processing import hash_url, unify
|
||||
from .collection import Collection
|
||||
from .metadata import ID3Timestamp
|
||||
@@ -11,37 +15,113 @@ from .metadata import Metadata
|
||||
from .parents import OuterProxy as Base
|
||||
|
||||
|
||||
class ArtworkVariant(TypedDict):
|
||||
@dataclass
|
||||
class ArtworkVariant:
|
||||
url: str
|
||||
width: int
|
||||
height: int
|
||||
deviation: float
|
||||
width: Optional[int] = None
|
||||
height: Optional[int] = None
|
||||
image_format: Optional[str] = ""
|
||||
|
||||
def __hash__(self) -> int:
|
||||
return custom_hash(self.url)
|
||||
|
||||
def __eq__(self, other: ArtworkVariant) -> bool:
|
||||
return hash(self) == hash(other)
|
||||
|
||||
def __contains__(self, other: str) -> bool:
|
||||
return custom_hash(other) == hash(self.url)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Artwork:
|
||||
variants: List[ArtworkVariant] = field(default_factory=list)
|
||||
|
||||
artwork_type: PictureType = PictureType.OTHER
|
||||
|
||||
def search_variant(self, url: str) -> Optional[ArtworkVariant]:
|
||||
if url is None:
|
||||
return None
|
||||
|
||||
for variant in self.variants:
|
||||
if url in variant:
|
||||
return variant
|
||||
|
||||
return None
|
||||
|
||||
def __contains__(self, other: str) -> bool:
|
||||
return self.search_variant(other) is not None
|
||||
|
||||
def add_data(self, **kwargs) -> None:
|
||||
variant = self.search_variant(kwargs.get("url"))
|
||||
|
||||
if variant is None:
|
||||
variant, kwargs = create_dataclass_instance(ArtworkVariant, **kwargs)
|
||||
self.variants.append(variant)
|
||||
|
||||
variant.url = url
|
||||
variant.__dict__.update(kwargs)
|
||||
|
||||
|
||||
class ArtworkCollection:
|
||||
def __init__(self, *variants: List[ArtworkVariant], parent_artworks: Set[ArtworkCollection] = None, crop_images: bool = True) -> None:
|
||||
self.crop_images: bool = crop_images
|
||||
"""
|
||||
Stores all the images/artworks for one data object.
|
||||
|
||||
There could be duplicates before calling ArtworkCollection.compile()
|
||||
_this is called before one object is downloaded automatically._
|
||||
"""
|
||||
|
||||
artwork_type: PictureType = PictureType.OTHER
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*data: List[Union[Artwork, ArtworkVariant, dict]],
|
||||
parent_artworks: Set[ArtworkCollection] = None,
|
||||
crop_images: bool = True
|
||||
) -> None:
|
||||
# this is used for the song artwork, to fall back to the song artwork
|
||||
self.parent_artworks: Set[ArtworkCollection] = parent_artworks or set()
|
||||
self.crop_images: bool = crop_images
|
||||
|
||||
self._variant_mapping: Dict[str, ArtworkVariant] = {}
|
||||
self._data = []
|
||||
|
||||
for variant in variants:
|
||||
self.append(**variant)
|
||||
def search_artwork(self, url: str) -> Optional[ArtworkVariant]:
|
||||
for artwork in self._data:
|
||||
if url in artwork:
|
||||
return artwork
|
||||
|
||||
@staticmethod
|
||||
def _calculate_deviation(*dimensions: List[int]) -> float:
|
||||
return sum(abs(d - main_settings["preferred_artwork_resolution"]) for d in dimensions) / len(dimensions)
|
||||
return None
|
||||
|
||||
def __contains__(self, other: str) -> bool:
|
||||
return self.search_artwork(other) is not None
|
||||
|
||||
def append(self, url: str, width: int = main_settings["preferred_artwork_resolution"], height: int = main_settings["preferred_artwork_resolution"], **kwargs) -> None:
|
||||
if url is None:
|
||||
def _create_new_artwork(self, **kwargs) -> Tuple[Artwork, dict]:
|
||||
kwargs["artwork_type"] = kwargs.get("artwork_type", self.artwork_type)
|
||||
|
||||
return create_dataclass_instance(Artwork, **kwargs)
|
||||
|
||||
def add_data(self, url: str, **kwargs) -> None:
|
||||
kwargs["url"] = url
|
||||
|
||||
artwork = self.search_artwork(url)
|
||||
|
||||
if artwork is None:
|
||||
artwork, kwargs = self._create_new_artwork(url=url, **kwargs)
|
||||
self._data.append(artwork)
|
||||
|
||||
artwork.add_data(url, **kwargs)
|
||||
|
||||
def append(self, value: Union[Artwork, ArtworkVariant, dict], **kwargs):
|
||||
if isinstance(value, dict):
|
||||
kwargs.update(value)
|
||||
value, kwargs = create_dataclass_instance(ArtworkVariant, kwargs)
|
||||
|
||||
if isinstance(value, ArtworkVariant):
|
||||
kwargs["variants"] = [value]
|
||||
value, kwargs = create_dataclass_instance(Artwork, kwargs)
|
||||
|
||||
if isinstance(value, Artwork):
|
||||
self._data.append(value)
|
||||
return
|
||||
|
||||
self._variant_mapping[hash_url(url=url)] = {
|
||||
"url": url,
|
||||
"width": width,
|
||||
"height": height,
|
||||
"deviation": self._calculate_deviation(width, height),
|
||||
}
|
||||
|
||||
@property
|
||||
def flat_empty(self) -> bool:
|
||||
@@ -69,14 +149,6 @@ class ArtworkCollection:
|
||||
def __hash__(self) -> int:
|
||||
return id(self)
|
||||
|
||||
def __eq__(self, other: ArtworkCollection) -> bool:
|
||||
if hash(self) == hash(other):
|
||||
return True
|
||||
|
||||
if not isinstance(other, ArtworkCollection):
|
||||
return False
|
||||
return any(a == b for a, b in zip(self._variant_mapping.keys(), other._variant_mapping.keys()))
|
||||
|
||||
def __iter__(self) -> Generator[ArtworkVariant, None, None]:
|
||||
yield from self._variant_mapping.values()
|
||||
|
||||
|
||||
@@ -184,6 +184,10 @@ class Song(Base):
|
||||
self.album_collection.extend(object_list)
|
||||
return
|
||||
|
||||
def _compile(self):
|
||||
self.artwork.compile()
|
||||
|
||||
|
||||
INDEX_DEPENDS_ON = ("title", "isrc", "source_collection")
|
||||
|
||||
@property
|
||||
|
||||
Reference in New Issue
Block a user