diff --git a/src/create_custom_objects.py b/src/create_custom_objects.py index de950bb..d8360d3 100644 --- a/src/create_custom_objects.py +++ b/src/create_custom_objects.py @@ -130,7 +130,6 @@ for _id, _object in objects_by_id.items(): print(only_smile) -""" c = Collection([Song(title="hi"), Song(title="hi2"), Song(title="hi3")]) c1 = Collection([Song(title="he"), Song(title="hi5")]) c11 = Collection([Song(title="wow how ultra subby", isrc="hiii")]) @@ -179,4 +178,3 @@ print("b: ", b) print(c.data) print(c._data) -""" diff --git a/src/music_kraken/objects/collection.py b/src/music_kraken/objects/collection.py index ab7642b..519e4cc 100644 --- a/src/music_kraken/objects/collection.py +++ b/src/music_kraken/objects/collection.py @@ -4,6 +4,7 @@ from collections import defaultdict from typing import TypeVar, Generic, Dict, Optional, Iterable, List, Iterator from .parents import OuterProxy + T = TypeVar('T', bound=OuterProxy) @@ -34,7 +35,6 @@ class Collection(Generic[T]): # List of collection attributes that should be modified on append # Key: collection attribute (str) of appended element # Value: main collection to sync to - self.sync_on_append: Dict[str, Collection] = sync_on_append or {} self.contain_given_in_attribute: Dict[str, Collection] = contain_given_in_attribute or {} self.contain_attribute_in_given: Dict[str, Collection] = contain_attribute_in_given or {} self.append_object_to_attribute: Dict[str, T] = append_object_to_attribute or {} @@ -60,11 +60,11 @@ class Collection(Generic[T]): for attribute, new_object in self.contain_given_in_attribute.items(): __object.__getattribute__(attribute).contain_collection_inside(new_object) - for attribute, new_object in self.contain_given_in_attribute.items(): + for attribute, new_object in self.contain_attribute_in_given.items(): new_object.contain_collection_inside(__object.__getattribute__(attribute)) for attribute, new_object in self.append_object_to_attribute.items(): - __object.__getattribute__(attribute).append(new_object, from_map=True) + __object.__getattribute__(attribute).append(new_object) def _unmap_element(self, __object: T): self._contains_ids.remove(__object.id) @@ -94,6 +94,29 @@ class Collection(Generic[T]): return True return False + def _contained_in_sub(self, __object: T, break_at_first: bool = True) -> List[Collection]: + """ + Gets the collection this object is found in, if it is found in any. + + :param __object: + :param break_at_first: + :return: + """ + results = [] + + if self._contained_in_self(__object): + return [self] + + print(len(self.children), id(self), ";".join(str(id(i)) for i in self.children)) + print() + for collection in self.children: + results.extend(collection._contained_in_sub(__object, break_at_first=break_at_first)) + + if break_at_first: + return results + + return results + def _get_root_collections(self) -> List[Collection]: if not len(self.parents): return [self] @@ -107,19 +130,6 @@ class Collection(Generic[T]): def _is_root(self) -> bool: return len(self.parents) <= 0 - def _contained_in_sub(self, __object: T, break_at_first: bool = True) -> List[Collection]: - results = [] - - if self._contained_in_self(__object): - return [self] - - for collection in self.children: - results.extend(collection._contained_in_sub(__object, break_at_first=break_at_first)) - if break_at_first: - return results - - return results - def _get_parents_of_multiple_contained_children(self, __object: T): results = [] if len(self.children) < 2 or self._contained_in_self(__object): @@ -153,6 +163,7 @@ class Collection(Generic[T]): for name, value in __object.indexing_values: if value is None: continue + if value in self._indexed_values[name]: existing_object = self._indexed_to_objects[value][0] if existing_object.id == __object.id: @@ -175,18 +186,16 @@ class Collection(Generic[T]): return len(self._contained_in_sub(__object)) > 0 def _append(self, __object: T, from_map: bool = False): - for attribute, to_sync_with in self.sync_on_append.items(): - to_sync_with.sync_with_other_collection(__object.__getattribute__(attribute)) - self._map_element(__object, from_map=from_map) self._data.append(__object) def append(self, __object: Optional[T], already_is_parent: bool = False, from_map: bool = False): + print(__object) if __object is None or __object.id in self._contains_ids: return exists_in_collection = self._contained_in_sub(__object) - if len(exists_in_collection) > 0 and self is exists_in_collection[0]: + if len(exists_in_collection) and self is exists_in_collection[0]: # assuming that the object already is contained in the correct collections if not already_is_parent: self.merge_into_self(__object, from_map=from_map) @@ -230,15 +239,11 @@ class Collection(Generic[T]): for equal_sub_collection in equal_collection.children: self.contain_collection_inside(equal_sub_collection) - # now the ugly part - # replace all refs of the other element with this one - self = self._risky_merge(equal_collection) - - def contain_collection_inside(self, sub_collection: "Collection"): + def contain_collection_inside(self, sub_collection: Collection): """ This collection will ALWAYS contain everything from the passed in collection """ - if sub_collection in self.children: + if self is sub_collection or sub_collection in self.children: return self.children.append(sub_collection) @@ -257,5 +262,5 @@ class Collection(Generic[T]): return self.__len__() == 0 def __iter__(self) -> Iterator[T]: - for element in self.data: + for element in self._data: yield element diff --git a/src/music_kraken/pages/youtube_music/_list_render.py b/src/music_kraken/pages/youtube_music/_list_render.py index 1acecee..8076e54 100644 --- a/src/music_kraken/pages/youtube_music/_list_render.py +++ b/src/music_kraken/pages/youtube_music/_list_render.py @@ -15,7 +15,6 @@ from ...objects import ( ) from ._music_object_render import parse_run_list, parse_run_element - LOGGER = logging_settings["youtube_music_logger"] @@ -23,20 +22,24 @@ def music_card_shelf_renderer(renderer: dict) -> List[DatabaseObject]: results = parse_run_list(renderer.get("title", {}).get("runs", [])) for sub_renderer in renderer.get("contents", []): - results.extend(parse_renderer(sub_renderer)) + results.extend(parse_renderer(sub_renderer)) return results + def music_responsive_list_item_flex_column_renderer(renderer: dict) -> List[DatabaseObject]: return parse_run_list(renderer.get("text", {}).get("runs", [])) + def music_responsive_list_item_renderer(renderer: dict) -> List[DatabaseObject]: results = [] - for i, collumn in enumerate(renderer.get("flexColumns", [])): - _r = parse_renderer(collumn) + for i, column in enumerate(renderer.get("flexColumns", [])): + _r = parse_renderer(column) if i == 0 and len(_r) == 0: - renderer["text"] = collumn.get("musicResponsiveListItemFlexColumnRenderer", {}).get("text", {}).get("runs", [{}])[0].get("text") - + renderer["text"] = \ + column.get("musicResponsiveListItemFlexColumnRenderer", {}).get("text", {}).get("runs", [{}])[0].get( + "text") + results.extend(_r) _r = parse_run_element(renderer) @@ -54,7 +57,7 @@ def music_responsive_list_item_renderer(renderer: dict) -> List[DatabaseObject]: for song in song_list: song.album_collection.extend(album_list) song.main_artist_collection.extend(artist_list) - + for album in album_list: album.artist_collection.extend(artist_list) @@ -64,19 +67,22 @@ def music_responsive_list_item_renderer(renderer: dict) -> List[DatabaseObject]: return album_list if len(artist_list) > 0: return artist_list - + return results + def music_shelf_renderer(renderer: dict) -> List[DatabaseObject]: result = [] for subrenderer in renderer.get("contents"): result.extend(parse_renderer(subrenderer)) - + return result + def music_carousel_shelf_renderer(renderer: dict): return music_shelf_renderer(renderer=renderer) + def music_two_row_item_renderer(renderer: dict): return parse_run_list(renderer.get("title", {}).get("runs", [])) @@ -92,6 +98,7 @@ RENDERER_PARSERS = { "itemSectionRenderer": lambda _: [], } + def parse_renderer(renderer: dict) -> List[DatabaseObject]: result: List[DatabaseObject] = [] @@ -99,7 +106,7 @@ def parse_renderer(renderer: dict) -> List[DatabaseObject]: if renderer_name not in RENDERER_PARSERS: LOGGER.warning(f"Can't parse the renderer {renderer_name}.") continue - + result.extend(RENDERER_PARSERS[renderer_name](renderer)) - return result \ No newline at end of file + return result diff --git a/src/music_kraken/pages/youtube_music/youtube_music.py b/src/music_kraken/pages/youtube_music/youtube_music.py index 7eb139d..3ed65b3 100644 --- a/src/music_kraken/pages/youtube_music/youtube_music.py +++ b/src/music_kraken/pages/youtube_music/youtube_music.py @@ -261,7 +261,7 @@ class YoutubeMusic(SuperYouTube): results = [] """ - cant use fixed indices, because if something has no entries, the list dissappears + cant use fixed indices, because if something has no entries, the list disappears instead I have to try parse everything, and just reject community playlists and profiles. """