From 7817402a190e567e2c4b704c00ca0636d7234faf Mon Sep 17 00:00:00 2001 From: Lars Noack Date: Mon, 16 Jan 2023 14:23:33 +0100 Subject: [PATCH] fixed metadata --- src/music_kraken/database/new_database.py | 3 + src/music_kraken/database/objects/metadata.py | 13 +- src/music_kraken/database/objects/parents.py | 3 + src/music_kraken/database/objects/song.py | 155 ++++++------------ test.db | Bin 69632 -> 69632 bytes 5 files changed, 61 insertions(+), 113 deletions(-) diff --git a/src/music_kraken/database/new_database.py b/src/music_kraken/database/new_database.py index b0cf386..fec292a 100644 --- a/src/music_kraken/database/new_database.py +++ b/src/music_kraken/database/new_database.py @@ -182,13 +182,16 @@ class Database: # add sources for source in song.sources: + source.add_song(song) self.push_source(source=source) # add lyrics for single_lyrics in song.lyrics: + single_lyrics.add_song(song) self.push_lyrics(lyrics=single_lyrics) # add target + song.target.add_song(song) self.push_target(target=song.target) for main_artist in song.main_artist_list: diff --git a/src/music_kraken/database/objects/metadata.py b/src/music_kraken/database/objects/metadata.py index 4060c5b..462de15 100644 --- a/src/music_kraken/database/objects/metadata.py +++ b/src/music_kraken/database/objects/metadata.py @@ -253,11 +253,13 @@ class Metadata: call it like a dict to read/write values """ - def __init__(self) -> None: + def __init__(self, id3_dict: dict = None) -> None: # this is pretty self-explanatory # the key is a 4 letter key from the id3 standards like TITL self.id3_attributes: Dict[str, list] = {} + if id3_dict is not None: + self.add_metadata_dict(id3_dict) # its a null byte for the later concatenation of text frames self.null_byte = "\x00" @@ -289,14 +291,13 @@ class Metadata: return None return self.id3_attributes[key] - def add_id3_metadata_obj(self, id3_metadata: ID3Metadata, override_existing: bool = True): - metadata_dict = id3_metadata.get_id3_dict() + def add_metadata_dict(self, metadata_dict: dict, override_existing: bool = True): for field_enum, value in metadata_dict.items(): self.__setitem__(field_enum.value, value, override_existing=override_existing) - def add_many_id3_metadata_obj(self, id3_metadata_list: List[ID3Metadata], override_existing: bool = False): - for id3_metadata in id3_metadata_list: - self.add_id3_metadata_obj(id3_metadata, override_existing=override_existing) + def add_many_metadata_dict(self, id3_metadata_list: List[dict], override_existing: bool = False): + for metadata_dict in id3_metadata_list: + self.add_metadata_dict(metadata_dict, override_existing=override_existing) def delete_item(self, key: str): if key in self.id3_attributes: diff --git a/src/music_kraken/database/objects/parents.py b/src/music_kraken/database/objects/parents.py index d5d4e92..ee2802d 100644 --- a/src/music_kraken/database/objects/parents.py +++ b/src/music_kraken/database/objects/parents.py @@ -67,6 +67,9 @@ class SongAttribute: class ID3Metadata: + def get_metadata(self): + pass + def get_id3_dict(self) -> dict: return {} diff --git a/src/music_kraken/database/objects/song.py b/src/music_kraken/database/objects/song.py index 579a98c..07c7c23 100644 --- a/src/music_kraken/database/objects/song.py +++ b/src/music_kraken/database/objects/song.py @@ -83,14 +83,13 @@ class Lyrics(DatabaseObject, SongAttribute): self.language = language -class Song(DatabaseObject): +class Song(DatabaseObject, ID3Metadata): def __init__( self, id_: str = None, mb_id: str = None, title: str = None, album_name: str = None, - artist_names: List[str] = [], isrc: str = None, length: int = None, tracksort: int = None, @@ -98,8 +97,8 @@ class Song(DatabaseObject): target: Target = None, lyrics: List[Lyrics] = None, album=None, - main_artist_list: list = [], - feature_artist_list: list = [] + main_artist_list: list = None, + feature_artist_list: list = None ) -> None: """ id: is not NECESARRILY the musicbrainz id, but is DISTINCT for every song @@ -110,41 +109,37 @@ class Song(DatabaseObject): super().__init__(id_=id_) # attributes # *private* attributes - self._title = None - self._isrc = None - self._length = None - self._sources: List[Source] = [] - self._album = None - - self.metadata = Metadata() - - self.title = title - self.isrc = isrc - self.length = length - + self.title: str = title + self.isrc: str = isrc + self.length: int = length self.mb_id: str | None = mb_id self.album_name: str | None = album_name - self.artist_names = artist_names self.tracksort: int | None = tracksort + + self.sources: List[Source] = [] + if sources is not None: + self.sources = sources - self.sources = sources self.album = album - if target is None: - target = Target() - self.target: Target = target + self.target = Target() + if target is not None: + self.target = target self.target.add_song(self) - if lyrics is None: - lyrics = [] - self.lyrics: List[Lyrics] = lyrics - for lyrics_ in self.lyrics: - lyrics_.add_song(self) + self.lyrics = [] + if lyrics is not None: + self.lyrics = lyrics self.album = album - self.main_artist_list = main_artist_list - self.feature_artist_list = feature_artist_list + self.main_artist_list = [] + if main_artist_list is not None: + self.main_artist_list = main_artist_list + + self.feature_artist_list = [] + if feature_artist_list is not None: + self.feature_artist_list = feature_artist_list def __eq__(self, other): if type(other) != type(self): @@ -168,92 +163,33 @@ class Song(DatabaseObject): def __repr__(self) -> str: return self.__str__() - def set_simple_metadata(self, name: str, value): - """ - this method is for setting values of attributes, - that directly map to an ID3 value. - A good example is the title or the isrc. - - for more complex data I will use seperate functions - - the naming convention for the name I follow is, to name - the attribute the same as the defined property, but with one underscore infront: - title -> _title - """ - if value is None: - return - - attribute_map = { - "_title": ID3_MAPPING.TITLE, - "_isrc": ID3_MAPPING.ISRC, - "_length": ID3_MAPPING.LENGTH - } - - # if this crashes/raises an error the function is - # called wrongly. I DO NOT CATCH ERRORS DUE TO PERFORMANCE AND DEBUGGING - self.__setattr__(name, value) - - # convert value to id3 value if necessary - id3_value = value - if type(value) == int: - id3_value = str(value) - - self.metadata[attribute_map[name].value] = [id3_value] - - def add_source(self, source_obj: Source): - if source_obj is None: - return - source_obj.add_song(self) - - print(source_obj) - self._sources.append(source_obj) - self.metadata[ID3_MAPPING.FILE_WEBPAGE_URL.value] = source_obj.url - - def set_sources(self, source_list): - if source_list is None: - return - - self._sources = source_list - for source in self._sources: - source.add_song(self) - - self.metadata.add_many_id3_metadata_obj(self._sources) - - def set_album(self, album): - if album is None: - return - - self.metadata.add_id3_metadata_obj(album) - self._album = album - - def get_metadata(self): - return self.metadata.get_all_metadata() - def has_isrc(self) -> bool: - return self._isrc is not None - - def get_artist_names(self) -> List[str]: - return self.artist_names - - def get_length(self): - if self._length is None: - return None - return int(self._length) + return self.isrc is not None def get_album_id(self): if self.album is None: return None return self.album.id - title: str = property(fget=lambda self: self._title, - fset=lambda self, value: self.set_simple_metadata("_title", value)) - isrc: str = property(fget=lambda self: self._isrc, - fset=lambda self, value: self.set_simple_metadata("_isrc", value)) - length: int = property(fget=get_length, fset=lambda self, value: self.set_simple_metadata("_length", value)) - album_id: str = property(fget=get_album_id) + def get_id3_dict(self) -> dict: + return { + ID3_MAPPING.TITLE: [self.title], + ID3_MAPPING.ISRC: [self.isrc], + ID3_MAPPING.LENGTH: [str(self.length)] + } + + def get_metadata(self) -> Metadata: + metadata = Metadata(self.get_id3_dict()) - sources: List[Source] = property(fget=lambda self: self._sources, fset=set_sources) - album = property(fget=lambda self: self._album, fset=set_album) + metadata.add_many_metadata_dict([source.get_id3_dict() for source in self.sources]) + if self.album is not None: + metadata.add_metadata_dict(self.album.get_id3_dict()) + metadata.add_many_metadata_dict([artist.get_id3_dict() for artist in self.main_artist_list]) + metadata.add_many_metadata_dict([artist.get_id3_dict() for artist in self.feature_artist_list]) + + return metadata + + metadata = property(fget=get_metadata) """ @@ -363,7 +299,7 @@ All objects dependent on Artist """ -class Artist(DatabaseObject): +class Artist(DatabaseObject, ID3Metadata): """ main_songs feature_song @@ -436,6 +372,11 @@ class Artist(DatabaseObject): return flat_copy_discography + def get_id3_dict(self) -> dict: + return { + ID3_MAPPING.ARTIST: [self.name] + } + discography: List[Album] = property(fget=get_discography) features: Album = property(fget=get_features) songs: Album = property(fget=get_songs) diff --git a/test.db b/test.db index 56ae8bdcdc38a64ef7ed57097fe5586cc58ee343..a291c6d153c9edbf3040157eb72ebdc147257adb 100644 GIT binary patch delta 2329 zcmd5;J#SQ35Z&G91rrHBTo5851uIzvBs0?enEO=_6H%l9D@4&NBXmCjfovpiq$maJ z%0)V~f51h$6oy@iI{5=hLy;y@TDtHLm|Y=)C9K?%e%`rf&Y3y$_77L~4_BVP{B*>O z(!wx=VKx z+GmN)U_NB$+mU9*3atYu?Kz;b9;{RmM2U*&l59aa{c`K_w>7vwka!nwuAb?NQ7W^j z0rf)Z=n}cYG6<(kVp{Sd()9V(7o!@~+4Xt5UBh$Pf6ddg+fUn3jcxN6cUI3;Rn8v0 zT$_0Bj7~8^Fj@i1Y{3=jKr>9ybBTz##_{dJuZ^D*^gavcYD3FjNp|)nl>Nl@sPkN&OwJ5lHfY162|xP zUf%H2-;XYe8tAu5Q)smZ|HW3QXmsg2ujq8?dky7+*fX%& z8DNI6$n!3Mlsrx7sS}%HE@g_s9BF({1XK zNyn(ba!uGwQFWm;k&>=Wb~Xytx6@aDelq-i5$E&ujc?wBc?GHABFrmZu%{M)Inw73wtwB5H#N-4kZVd>o>NFjLI|;47Aosrcr4@VULer(I h>2>z+14^=re}ft~ZuXn5s{uRC?Bn;2nf;}I?lsxFRdE0S delta 2329 zcmd5-J#SP;6y4qDB_@*nph!SM0*kBylDX1+znKC|lp+OKNff;@itc;?0@+C3NKp!& zD;IQV|A32hDNJ^y)X5)!CWV_wv~=(fa^FTGv4oW=)4gKenRD(r_sss`%KqWX^VgRr zjgia-82~*-P)=xY-Ug6plQljm6>+w9E3 z9zNK)xAD#H&OI-b(NZx$tph05L~z+A&_P>|KE#0e$KeO<*5+u~@~k9diO{7sbXX%e zmK1p9T}07fg*?oDxw0urU_TrT23379sE_M|`ewoUh97FQb>aeBcJ`c_35Mpb$)wMZMyx^{?+q(QexZUkMCB`6`hDxcog6*rJ1}YLxPoHO!C2JCnC4ApF3XW%Kp>3NboYg zB~q65m2iBwOymE}HdTx9;h*cDq~ucM5}c5(FBqgG1S%Mvc`_^q^lmmjy4hueMxcd^ zigLmzG0y7*%q5evi!x_FO?%U{Q?ehsM4hYBnDvs z1u0G{({AV>o%LVb-`$(u7**|sev2BxBQ$|$P?`$e*-Sr6Z*B0*$l&%KKYB1VXR3CS zWsF9N0OS{)Hi^p1L<5cFj;SVC>xOLh_T|O#LH%uC<{MxBUFIdE#(kL=+`!H(pN9hC zBbv(fXU`_{S1;DPl6EP%{cg3=wyPy*Cq#FrSaEkma79nk3AoeHhCR9W(guR