started fixing importand design flaw
This commit is contained in:
parent
d685827fb5
commit
5387301ed2
@ -62,7 +62,7 @@ class Collection:
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def append(self, element: DatabaseObject, merge_on_conflict: bool = True, merge_into_existing: bool = True) -> bool:
|
||||
def append(self, element: DatabaseObject, merge_on_conflict: bool = True, merge_into_existing: bool = True) -> DatabaseObject:
|
||||
"""
|
||||
:param element:
|
||||
:param merge_on_conflict:
|
||||
@ -78,28 +78,33 @@ class Collection:
|
||||
if value in self._attribute_to_object_map[name]:
|
||||
existing_object = self._attribute_to_object_map[name][value]
|
||||
|
||||
if merge_on_conflict:
|
||||
# if the object does already exist
|
||||
# thus merging and don't add it afterwards
|
||||
if merge_into_existing:
|
||||
existing_object.merge(element)
|
||||
# in case any relevant data has been added (e.g. it remaps the old object)
|
||||
self.map_element(existing_object)
|
||||
else:
|
||||
element.merge(existing_object)
|
||||
if not merge_on_conflict:
|
||||
return existing_object
|
||||
|
||||
exists_at = self._data.index(existing_object)
|
||||
self._data[exists_at] = element
|
||||
# if the object does already exist
|
||||
# thus merging and don't add it afterwards
|
||||
if merge_into_existing:
|
||||
existing_object.merge(element)
|
||||
# in case any relevant data has been added (e.g. it remaps the old object)
|
||||
self.map_element(existing_object)
|
||||
return existing_object
|
||||
|
||||
self.unmap_element(existing_object)
|
||||
self.map_element(element)
|
||||
element.merge(existing_object)
|
||||
|
||||
return False
|
||||
exists_at = self._data.index(existing_object)
|
||||
self._data[exists_at] = element
|
||||
|
||||
self.unmap_element(existing_object)
|
||||
self.map_element(element)
|
||||
return element
|
||||
|
||||
self._data.append(element)
|
||||
self.map_element(element)
|
||||
|
||||
return True
|
||||
return element
|
||||
|
||||
def append_is_already_in_collection(self, element: DatabaseObject, merge_on_conflict: bool = True, merge_into_existing: bool = True) -> bool:
|
||||
object_representing_the_data = self.append(element, merge_on_conflict=merge_on_conflict, merge_into_existing=merge_into_existing)
|
||||
|
||||
def extend(self, element_list: Iterable[DatabaseObject], merge_on_conflict: bool = True):
|
||||
for element in element_list:
|
||||
|
@ -1,4 +1,4 @@
|
||||
from typing import Optional
|
||||
from typing import Optional, Union, Type
|
||||
import requests
|
||||
import logging
|
||||
|
||||
@ -16,7 +16,8 @@ from ..objects import (
|
||||
MusicObject,
|
||||
Options,
|
||||
SourcePages,
|
||||
Collection
|
||||
Collection,
|
||||
Label
|
||||
)
|
||||
|
||||
|
||||
@ -138,114 +139,62 @@ class Page:
|
||||
return Options()
|
||||
|
||||
@classmethod
|
||||
def fetch_details(cls, music_object: MusicObject, flat: bool = False) -> MusicObject:
|
||||
def fetch_details(cls, music_object: Union[Song, Album, Artist, Label], stop_at_level: int = 1) -> MusicObject:
|
||||
"""
|
||||
when a music object with laccing data is passed in, it returns
|
||||
the SAME object **(no copy)** with more detailed data.
|
||||
If you for example put in an album, it fetches the tracklist
|
||||
|
||||
:param music_object:
|
||||
:param flat:
|
||||
if it is true it fetches only the most important information (only one level)
|
||||
if an Artist is passed in, it fetches only the discography of the artist, and not the
|
||||
tracklist of every album of the artist.
|
||||
:param stop_at_level:
|
||||
This says the depth of the level the scraper will recurse to.
|
||||
If this is for example set to 2, then the levels could be:
|
||||
1. Level: the album
|
||||
2. Level: every song of the album + every artist of the album
|
||||
If no additional requests are needed to get the data one level below the supposed stop level
|
||||
this gets ignored
|
||||
:return detailed_music_object: IT MODIFIES THE INPUT OBJ
|
||||
"""
|
||||
|
||||
if type(music_object) == Song:
|
||||
song = cls.fetch_song_details(music_object, flat=flat)
|
||||
song.compile()
|
||||
return song
|
||||
new_music_object: MusicObject = type(music_object).__init__()
|
||||
|
||||
if type(music_object) == Album:
|
||||
album = cls.fetch_album_details(music_object, flat=flat)
|
||||
album.compile()
|
||||
return album
|
||||
source: Source
|
||||
for source in music_object.source_collection:
|
||||
new_music_object.merge(cls.fetch_object_from_source(source=source, obj_type=type(music_object), stop_at_level=stop_at_level))
|
||||
|
||||
if type(music_object) == Artist:
|
||||
artist = cls.fetch_artist_details(music_object, flat=flat)
|
||||
artist.compile()
|
||||
return artist
|
||||
|
||||
raise NotImplementedError(f"MusicObject {type(music_object)} has not been implemented yet")
|
||||
|
||||
music_object.merge(new_music_object)
|
||||
music_object.compile()
|
||||
|
||||
return music_object
|
||||
|
||||
@classmethod
|
||||
def fetch_song_from_source(cls, source: Source, flat: bool = False) -> Song:
|
||||
def fetch_object_from_source(cls, source: Source, obj_type: Union[Type[Song], Type[Album], Type[Artist], Type[Label]], stop_at_level: int = 1):
|
||||
if obj_type == Artist:
|
||||
return cls.fetch_artist_from_source(source=source, stop_at_level=stop_at_level)
|
||||
|
||||
if obj_type == Song:
|
||||
return cls.fetch_song_from_source(source=source, stop_at_level=stop_at_level)
|
||||
|
||||
if obj_type == Album:
|
||||
return cls.fetch_album_from_source(source=source, stop_at_level=stop_at_level)
|
||||
|
||||
if obj_type == Label:
|
||||
return cls.fetch_label_from_source(source=source, stop_at_level=stop_at_level)
|
||||
|
||||
@classmethod
|
||||
def fetch_song_from_source(cls, source: Source, stop_at_level: int = 1) -> Song:
|
||||
return Song()
|
||||
|
||||
@classmethod
|
||||
def fetch_song_details(cls, song: Song, flat: bool = False) -> Song:
|
||||
"""
|
||||
for a general description check cls.fetch_details
|
||||
|
||||
:param song: song without much data
|
||||
:param flat:
|
||||
when True it only fetches the artist and the album, and the attributes of those,
|
||||
who can be gotten with one api request
|
||||
when False it fetches everything including, but not limited to:
|
||||
- Lyrics
|
||||
- Album + Tracklist (for tracksort)
|
||||
|
||||
:return detailed_song: it modifies the input song
|
||||
"""
|
||||
|
||||
source: Source
|
||||
for source in song.source_collection.get_sources_from_page(cls.SOURCE_TYPE):
|
||||
new_song = cls.fetch_song_from_source(source, flat)
|
||||
song.merge(new_song)
|
||||
|
||||
return song
|
||||
|
||||
@classmethod
|
||||
def fetch_album_from_source(cls, source: Source, flat: bool = False) -> Album:
|
||||
def fetch_album_from_source(cls, source: Source, stop_at_level: int = 1) -> Album:
|
||||
return Album()
|
||||
|
||||
@classmethod
|
||||
def fetch_album_details(cls, album: Album, flat: bool = False) -> Album:
|
||||
"""
|
||||
for a general description check cls.fetch_details
|
||||
|
||||
:param album: album without much data
|
||||
:param flat:
|
||||
when True it only fetches the artist and the tracklist, and the attributes of those,
|
||||
which can be gotten with one api request
|
||||
when False it fetches everything including, but not limited to:
|
||||
- Lyrics of every song
|
||||
- Artist, Album, Tracklist
|
||||
- every attribute of those
|
||||
|
||||
:return detailed_artist: it modifies the input artist
|
||||
"""
|
||||
|
||||
source: Source
|
||||
for source in album.source_collection.get_sources_from_page(cls.SOURCE_TYPE):
|
||||
new_album: Album = cls.fetch_album_from_source(source, flat)
|
||||
album.merge(new_album)
|
||||
|
||||
return album
|
||||
|
||||
@classmethod
|
||||
def fetch_artist_from_source(cls, source: Source, flat: bool = False) -> Artist:
|
||||
def fetch_artist_from_source(cls, source: Source, stop_at_level: int = 1) -> Artist:
|
||||
return Artist()
|
||||
|
||||
@classmethod
|
||||
def fetch_artist_details(cls, artist: Artist, flat: bool = False) -> Artist:
|
||||
"""
|
||||
for a general description check cls.fetch_details
|
||||
|
||||
:param artist: artist without much data
|
||||
:param flat:
|
||||
when True it only fetches the discographie, meaning every album, but not every tracklist
|
||||
when False it fetches everything including, but not limited to:
|
||||
- the whole discography
|
||||
- the tracklist of every album in the discography
|
||||
|
||||
:return detailed_artist: it modifies the input artist
|
||||
"""
|
||||
|
||||
source: Source
|
||||
for source in artist.source_collection.get_sources_from_page(cls.SOURCE_TYPE):
|
||||
new_artist: Artist = cls.fetch_artist_from_source(source, flat)
|
||||
artist.merge(new_artist)
|
||||
|
||||
return artist
|
||||
def fetch_label_from_source(source: Source, stop_at_level: int = 1) -> Label:
|
||||
return Label()
|
||||
|
Loading…
Reference in New Issue
Block a user