fix: correct collections
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/pr/woodpecker Pipeline was successful

This commit is contained in:
Hazel 2024-05-08 12:09:41 +02:00
parent a97f8872c8
commit 9c63e8e55a
3 changed files with 37 additions and 38 deletions

View File

@ -2,6 +2,8 @@ from __future__ import annotations
from collections import defaultdict from collections import defaultdict
from typing import TypeVar, Generic, Dict, Optional, Iterable, List, Iterator, Tuple, Generator, Union, Any, Set from typing import TypeVar, Generic, Dict, Optional, Iterable, List, Iterator, Tuple, Generator, Union, Any, Set
import copy
from .parents import OuterProxy from .parents import OuterProxy
from ..utils import object_trace from ..utils import object_trace
from ..utils import output, BColors from ..utils import output, BColors
@ -47,8 +49,15 @@ class Collection(Generic[T]):
self.extend(data) self.extend(data)
def __hash__(self) -> int:
return id(self)
@property
def collection_names(self) -> List[str]:
return list(set(self._collection_for.values()))
def __repr__(self) -> str: def __repr__(self) -> str:
return f"Collection({' | '.join(self._collection_for.values())} {id(self)})" return f"Collection({' | '.join(self.collection_names)} {id(self)})"
def _map_element(self, __object: T, no_unmap: bool = False, **kwargs): def _map_element(self, __object: T, no_unmap: bool = False, **kwargs):
if not no_unmap: if not no_unmap:
@ -104,8 +113,9 @@ class Collection(Generic[T]):
""" """
self._data.append(other) self._data.append(other)
other._inner._is_in_collection.add(self)
# all of the existing hooks to get the defined datastructure # all of the existing hooks to get the defined datastructures
for collection_attribute, generator in self.extend_object_to_attribute.items(): for collection_attribute, generator in self.extend_object_to_attribute.items():
other.__getattribute__(collection_attribute).extend(generator, **kwargs) other.__getattribute__(collection_attribute).extend(generator, **kwargs)
@ -148,32 +158,28 @@ class Collection(Generic[T]):
object_trace(f"Appending {other.option_string} to {self}") object_trace(f"Appending {other.option_string} to {self}")
for c in self.pull_from:
r = c._find_object(other)
if r is not None:
output("found pull from", r, other, self, color=BColors.RED, sep="\t")
other.merge(r, **kwargs)
c.remove(r, existing=r, **kwargs)
break
existing_object = self._find_object(other)
# switching collection in the case of push to # switching collection in the case of push to
for c in self.push_to: for c in self.push_to:
r = c._find_object(other) r = c._find_object(other)
if r is not None: if r is not None:
output("found push to", r, other, self, color=BColors.RED, sep="\t") # output("found push to", r, other, c, self, color=BColors.RED, sep="\t")
if existing_object is not None:
self.remove(existing_object)
return c.append(other, **kwargs) return c.append(other, **kwargs)
if existing_object is None: for c in self.pull_from:
r = c._find_object(other)
if r is not None:
# output("found pull from", r, other, c, self, color=BColors.RED, sep="\t")
c.remove(r, existing=r, **kwargs)
existing = self._find_object(other)
if existing is None:
self._append_new_object(other, **kwargs) self._append_new_object(other, **kwargs)
else: else:
existing_object.merge(other, **kwargs) existing.merge(other, **kwargs)
def remove(self, *other_list: List[T], silent: bool = False, existing: Optional[T] = None, **kwargs): def remove(self, *other_list: List[T], silent: bool = False, existing: Optional[T] = None, remove_from_other_collection=True, **kwargs):
other: T
for other in other_list: for other in other_list:
existing: Optional[T] = existing or self._indexed_values["id"].get(other.id, None) existing: Optional[T] = existing or self._indexed_values["id"].get(other.id, None)
if existing is None: if existing is None:
@ -181,14 +187,13 @@ class Collection(Generic[T]):
raise ValueError(f"Object {other} not found in {self}") raise ValueError(f"Object {other} not found in {self}")
return other return other
for collection_attribute, generator in self.extend_object_to_attribute.items(): if remove_from_other_collection:
other.__getattribute__(collection_attribute).remove(*generator, silent=True, **kwargs) for c in copy.copy(other._inner._is_in_collection):
c.remove(other, silent=True, remove_from_other_collection=False, **kwargs)
for attribute, new_object in self.append_object_to_attribute.items(): other._inner._is_in_collection = set()
other.__getattribute__(attribute).remove(new_object, silent=True, **kwargs) else:
self._data.remove(existing)
self._data.remove(existing) self._unmap_element(existing)
self._unmap_element(existing)
def contains(self, __object: T) -> bool: def contains(self, __object: T) -> bool:
return self._find_object(__object) is not None return self._find_object(__object) is not None

View File

@ -29,12 +29,15 @@ class InnerData:
""" """
_refers_to_instances: set = None _refers_to_instances: set = None
_is_in_collection: set = None
""" """
Attribute versions keep track, of if the attribute has been changed. Attribute versions keep track, of if the attribute has been changed.
""" """
def __init__(self, object_type, **kwargs): def __init__(self, object_type, **kwargs):
self._refers_to_instances = set() self._refers_to_instances = set()
self._is_in_collection = set()
self._fetched_from: dict = {} self._fetched_from: dict = {}
# initialize the default values # initialize the default values
@ -58,6 +61,7 @@ class InnerData:
""" """
self._fetched_from.update(__other._fetched_from) self._fetched_from.update(__other._fetched_from)
self._is_in_collection.update(__other._is_in_collection)
for key, value in __other.__dict__.copy().items(): for key, value in __other.__dict__.copy().items():
if key.startswith("_"): if key.startswith("_"):

View File

@ -222,17 +222,9 @@ class Song(Base):
r = OPTION_FOREGROUND.value + self.title_string + BColors.ENDC.value + OPTION_BACKGROUND.value r = OPTION_FOREGROUND.value + self.title_string + BColors.ENDC.value + OPTION_BACKGROUND.value
r += get_collection_string(self.album_collection, " from {}", ignore_titles={self.title}) r += get_collection_string(self.album_collection, " from {}", ignore_titles={self.title})
r += get_collection_string(self.main_artist_collection, " by {}") r += get_collection_string(self.main_artist_collection, " by {}")
r += get_collection_string(self.feature_artist_collection, " feat. {}" if not self.main_artist_collection.empty or True else " by {}") r += get_collection_string(self.feature_artist_collection, " feat. {}")
return r return r
@property
def options(self) -> List[P]:
options = self.main_artist_collection.shallow_list
options.extend(self.feature_artist_collection)
options.extend(self.album_collection)
options.append(self)
return options
@property @property
def tracksort_str(self) -> str: def tracksort_str(self) -> str:
""" """
@ -260,7 +252,6 @@ class Album(Base):
barcode: str barcode: str
albumsort: int albumsort: int
notes: FormattedText notes: FormattedText
artwork: Artwork
source_collection: SourceCollection source_collection: SourceCollection
@ -279,7 +270,6 @@ class Album(Base):
"language": lambda: Language.by_alpha_2("en"), "language": lambda: Language.by_alpha_2("en"),
"date": ID3Timestamp, "date": ID3Timestamp,
"notes": FormattedText, "notes": FormattedText,
"artwork": Artwork,
"source_collection": SourceCollection, "source_collection": SourceCollection,
"artist_collection": Collection, "artist_collection": Collection,