refactored db objects

This commit is contained in:
Hellow2 2023-02-10 13:52:18 +01:00
parent 7b3f4a2b81
commit 4ecdc6d419
2 changed files with 66 additions and 79 deletions

View File

@ -19,9 +19,16 @@ class Reference:
class DatabaseObject: class DatabaseObject:
def __init__(self, id_: str = None, dynamic: bool = False) -> None: empty: bool
def __init__(self, id_: str = None, dynamic: bool = False, empty: bool = False, **kwargs) -> None:
"""
empty means it is an placeholder.
it makes the object perform the same, it is just the same
"""
self.id_: str | None = id_ self.id_: str | None = id_
self.dynamic = dynamic self.dynamic = dynamic
self.empty = empty
def get_id(self) -> str: def get_id(self) -> str:
""" """
@ -29,8 +36,11 @@ class DatabaseObject:
it returns a randomly generated UUID it returns a randomly generated UUID
https://docs.python.org/3/library/uuid.html https://docs.python.org/3/library/uuid.html
if the object is empty, it returns None
if the object is dynamic, it raises an error if the object is dynamic, it raises an error
""" """
if self.empty:
return None
if self.dynamic: if self.dynamic:
raise ValueError("Dynamic objects have no idea, because they are not in the database") raise ValueError("Dynamic objects have no idea, because they are not in the database")
@ -63,6 +73,8 @@ class DatabaseObject:
id = property(fget=get_id) id = property(fget=get_id)
reference = property(fget=get_reference) reference = property(fget=get_reference)
options = property(fget=get_options)
options_str = property(fget=get_option_string)
class SongAttribute: class SongAttribute:

View File

@ -114,10 +114,11 @@ class Song(DatabaseObject, SourceAttribute, MetadataAttribute):
genre: str = None, genre: str = None,
source_list: List[Source] = None, source_list: List[Source] = None,
target: Target = None, target: Target = None,
lyrics: List[Lyrics] = None, lyrics_list: List[Lyrics] = None,
album=None, album=None,
main_artist_list: list = None, main_artist_list: list = None,
feature_artist_list: list = None feature_artist_list: list = None,
**kwargs
) -> None: ) -> None:
""" """
id: is not NECESARRILY the musicbrainz id, but is DISTINCT for every song id: is not NECESARRILY the musicbrainz id, but is DISTINCT for every song
@ -125,39 +126,36 @@ class Song(DatabaseObject, SourceAttribute, MetadataAttribute):
target: Each Song can have exactly one target which can be either full or empty target: Each Song can have exactly one target which can be either full or empty
lyrics: There can be multiple lyrics. Each Lyrics object can me added to multiple lyrics lyrics: There can be multiple lyrics. Each Lyrics object can me added to multiple lyrics
""" """
super().__init__(id_=id_) super().__init__(id_=id_, **kwargs)
# attributes # attributes
# *private* attributes # *private* attributes
self.title: str = title self.title: str = title
self.isrc: str = isrc self.isrc: str = isrc
self.length: int = length self.length: int = length
self.mb_id: str | None = mb_id self.mb_id: str | None = mb_id
self.album_name: str | None = album_name self.tracksort: int = tracksort or 0
self.tracksort: int | None = tracksort
self.genre: str = genre self.genre: str = genre
if source_list: self.source_list = source_list or []
self.source_list = source_list
self.target = Target() self.target = target or Target()
if target is not None: self.lyrics_list = lyrics_list or []
self.target = target
self.target.add_song(self)
self.lyrics = [] # initialize with either a passed in album, or an empty one,
if lyrics is not None: # so it can at least properly generate dynamic attributes
self.lyrics = lyrics self._album = album or Album(empty=True)
self._album = None
self.album = album self.album = album
self.main_artist_list = [] self.main_artist_collection = Collection(
if main_artist_list is not None: data=main_artist_list or [],
self.main_artist_list = main_artist_list map_attributes=["title"],
element_type=Artist
self.feature_artist_list = [] )
if feature_artist_list is not None: self.feature_artist_collection = Collection(
self.feature_artist_list = feature_artist_list data=feature_artist_list or [],
map_attributes=["title"],
element_type=Artist
)
def __eq__(self, other): def __eq__(self, other):
if type(other) != type(self): if type(other) != type(self):
@ -165,10 +163,12 @@ class Song(DatabaseObject, SourceAttribute, MetadataAttribute):
return self.id == other.id return self.id == other.id
def get_artist_credits(self) -> str: def get_artist_credits(self) -> str:
feature_str = "" main_artists = ", ".join([artist.name for artist in self.main_artist_collection])
if len(self.feature_artist_list) > 0: feature_artists = ", ".join([artist.name for artist in self.feature_artist_collection])
feature_str = " feat. " + ", ".join([artist.name for artist in self.feature_artist_list])
return ", ".join([artist.name for artist in self.main_artist_list]) + feature_str if len(feature_artists) == 0:
return main_artists
return f"{main_artists} feat. {feature_artists}"
def __str__(self) -> str: def __str__(self) -> str:
artist_credit_str = "" artist_credit_str = ""
@ -179,24 +179,14 @@ class Song(DatabaseObject, SourceAttribute, MetadataAttribute):
return f"\"{self.title}\"{artist_credit_str}" return f"\"{self.title}\"{artist_credit_str}"
def __repr__(self) -> str: def __repr__(self) -> str:
return self.__str__() return f"Song(\"{self.title}\")"
def has_isrc(self) -> bool:
return self.isrc is not None
def get_album_id(self):
if self.album is None:
return None
return self.album.id
def get_tracksort_str(self): def get_tracksort_str(self):
if self.tracksort is None: """
return None if the album tracklist is empty, it sets it length to 1, this song has to be in the Album
:returns id3_tracksort: {song_position}/{album.length_of_tracklist}
if self.album is None: """
return str(self.tracksort) return f"{self.tracksort}/{len(self.album.tracklist) or 1}"
return f"{self.tracksort}/{len(self.album.tracklist)}"
def get_metadata(self) -> MetadataAttribute.Metadata: def get_metadata(self) -> MetadataAttribute.Metadata:
metadata = MetadataAttribute.Metadata({ metadata = MetadataAttribute.Metadata({
@ -208,36 +198,27 @@ class Song(DatabaseObject, SourceAttribute, MetadataAttribute):
}) })
metadata.merge_many([s.get_song_metadata() for s in self.source_list]) metadata.merge_many([s.get_song_metadata() for s in self.source_list])
if self.album is not None: if not self.album.empty:
metadata.merge(self.album.metadata) metadata.merge(self.album.metadata)
metadata.merge_many([a.metadata for a in self.main_artist_list]) metadata.merge_many([a.metadata for a in self.main_artist_list])
metadata.merge_many([a.metadata for a in self.feature_artist_list]) metadata.merge_many([a.metadata for a in self.feature_artist_list])
metadata.merge_many([l.metadata for l in self.lyrics]) metadata.merge_many([l.metadata for l in self.lyrics])
return metadata return metadata
def set_album(self, album):
if album is None:
return
self._album = album
if self not in self._album.tracklist:
flat_copy = copy.copy(self)
flat_copy.dynamic = True
self._album.tracklist.append(flat_copy)
def get_options(self) -> list: def get_options(self) -> list:
options = self.main_artist_list.copy() options = self.main_artist_list.copy()
options.extend(self.feature_artist_list.copy()) options.extend(self.feature_artist_list.copy())
if self.album is not None: if not self.album.empty:
options.append(self.album) options.append(self.album)
options.append(self) options.append(self)
return options return options
def get_option_string(self) -> str: def get_option_string(self) -> str:
return f"Song: {self.title}; Album: {self.album.title}; Artists: {self.get_artist_credits()}" return f"Song({self.title}) of Album({self.album.title}) from Artists({self.get_artist_credits()})"
tracksort_str = property(fget=get_tracksort_str) tracksort_str = property(fget=get_tracksort_str)
album = property(fget=lambda self: self._album, fset=set_album) main_artist_list: list = property(fget=lambda self: self.main_artist_collection.copy())
feature_artist_list: list = property(fget=lambda self: self.feature_artist_collection.copy())
""" """
@ -246,20 +227,6 @@ All objects dependent on Album
class Album(DatabaseObject, SourceAttribute, MetadataAttribute): class Album(DatabaseObject, SourceAttribute, MetadataAttribute):
"""
-------DB-FIELDS-------
title TEXT,
copyright TEXT,
album_status TEXT,
language TEXT,
year TEXT,
date TEXT,
country TEXT,
barcode TEXT,
song_id BIGINT,
is_split BOOLEAN NOT NULL DEFAULT 0
"""
def __init__( def __init__(
self, self,
id_: str = None, id_: str = None,
@ -274,11 +241,12 @@ class Album(DatabaseObject, SourceAttribute, MetadataAttribute):
albumsort: int = None, albumsort: int = None,
dynamic: bool = False, dynamic: bool = False,
source_list: List[Source] = None, source_list: List[Source] = None,
artists: list = None, artist_list: list = None,
tracklist: List[Song] = None, tracklist: List[Song] = None,
album_type: str = None album_type: str = None,
**kwargs
) -> None: ) -> None:
DatabaseObject.__init__(self, id_=id_, dynamic=dynamic) DatabaseObject.__init__(self, id_=id_, dynamic=dynamic, **kwargs)
""" """
TODO TODO
@ -290,9 +258,7 @@ class Album(DatabaseObject, SourceAttribute, MetadataAttribute):
self.album_status: str = album_status self.album_status: str = album_status
self.label = label self.label = label
self.language: pycountry.Languages = language self.language: pycountry.Languages = language
self.date: ID3Timestamp = date self.date: ID3Timestamp = date or ID3Timestamp()
if date is None:
self.date = ID3Timestamp()
self.country: str = country self.country: str = country
""" """
TODO TODO
@ -301,6 +267,11 @@ class Album(DatabaseObject, SourceAttribute, MetadataAttribute):
""" """
self.barcode: str = barcode self.barcode: str = barcode
self.is_split: bool = is_split self.is_split: bool = is_split
"""
TODO
implement a function in the Artist class,
to set albumsort with help of the release year
"""
self.albumsort: int | None = albumsort self.albumsort: int | None = albumsort
@ -310,7 +281,11 @@ class Album(DatabaseObject, SourceAttribute, MetadataAttribute):
element_type=Song element_type=Song
) )
self.source_list = source_list or [] self.source_list = source_list or []
self.artists = artists or [] self.artists = Collection(
data=artist_list or [],
map_attributes=["name"],
element_type=Artist
)
def __str__(self) -> str: def __str__(self) -> str: