This commit is contained in:
Hellow2 2023-03-10 09:09:35 +01:00
parent d6aed75fec
commit 0423cb3139
6 changed files with 168 additions and 180 deletions

View File

@ -84,7 +84,8 @@ class Collection:
return self._data[item] return self._data[item]
def copy(self) -> List: @property
def shallow_list(self) -> List[DatabaseObject]:
""" """
returns a shallow copy of the data list returns a shallow copy of the data list
""" """

View File

@ -3,12 +3,12 @@ from typing import List
import pycountry import pycountry
from .parents import DatabaseObject from .parents import DatabaseObject
from .source import SourceAttribute, Source from .source import Source, SourceCollection
from .metadata import MetadataAttribute from .metadata import Metadata
from .formatted_text import FormattedText from .formatted_text import FormattedText
class Lyrics(DatabaseObject, SourceAttribute, MetadataAttribute): class Lyrics(DatabaseObject):
def __init__( def __init__(
self, self,
text: FormattedText, text: FormattedText,
@ -23,5 +23,4 @@ class Lyrics(DatabaseObject, SourceAttribute, MetadataAttribute):
self.text: FormattedText = text self.text: FormattedText = text
self.language: pycountry.Languages = language self.language: pycountry.Languages = language
if source_list is not None: self.source_collection: SourceCollection = SourceCollection(source_list)
self.source_list = source_list

View File

@ -1,7 +1,6 @@
from enum import Enum from enum import Enum
from typing import List, Dict, Tuple from typing import List, Dict, Tuple
import dateutil.tz
from mutagen import id3 from mutagen import id3
import datetime import datetime
@ -267,12 +266,7 @@ class ID3Timestamp:
timeformat: str = property(fget=get_time_format) timeformat: str = property(fget=get_time_format)
class MetadataAttribute: class Metadata:
"""
This class shall be added to any object, which can return data for tagging
"""
class Metadata:
# it's a null byte for the later concatenation of text frames # it's a null byte for the later concatenation of text frames
NULL_BYTE: str = "\x00" NULL_BYTE: str = "\x00"
# this is pretty self-explanatory # this is pretty self-explanatory
@ -382,11 +376,3 @@ class MetadataAttribute:
for field in self.id3_dict: for field in self.id3_dict:
yield self.get_mutagen_object(field) yield self.get_mutagen_object(field)
def get_metadata(self) -> Metadata:
"""
this is intendet to be overwritten by the child class
"""
return MetadataAttribute.Metadata()
metadata = property(fget=lambda self: self.get_metadata())

View File

@ -5,6 +5,7 @@ import uuid
from ..utils.shared import ( from ..utils.shared import (
SONG_LOGGER as LOGGER SONG_LOGGER as LOGGER
) )
from .metadata import Metadata
class DatabaseObject: class DatabaseObject:
@ -69,6 +70,10 @@ class DatabaseObject:
if override or getattr(self, simple_attribute) is None: if override or getattr(self, simple_attribute) is None:
setattr(self, simple_attribute, getattr(other, simple_attribute)) setattr(self, simple_attribute, getattr(other, simple_attribute))
@property
def metadata(self) -> Metadata:
return Metadata()
class MainObject(DatabaseObject): class MainObject(DatabaseObject):
""" """

View File

@ -5,7 +5,7 @@ import pycountry
from .metadata import ( from .metadata import (
Mapping as id3Mapping, Mapping as id3Mapping,
ID3Timestamp, ID3Timestamp,
MetadataAttribute Metadata
) )
from ..utils.shared import ( from ..utils.shared import (
MUSIC_DIR, MUSIC_DIR,
@ -36,12 +36,10 @@ All Objects dependent
CountryTyping = type(list(pycountry.countries)[0]) CountryTyping = type(list(pycountry.countries)[0])
class Song(MainObject, MetadataAttribute): class Song(MainObject):
""" """
Class representing a song object, with attributes id, mb_id, title, album_name, isrc, length, Class representing a song object, with attributes id, mb_id, title, album_name, isrc, length,
tracksort, genre, source_list, target, lyrics_list, album, main_artist_list, and feature_artist_list. tracksort, genre, source_list, target, lyrics_list, album, main_artist_list, and feature_artist_list.
Inherits from DatabaseObject, SourceAttribute, and MetadataAttribute classes.
""" """
COLLECTION_ATTRIBUTES = ("lyrics_collection", "album_collection", "main_artist_collection", "feature_artist_collection", "source_collection") COLLECTION_ATTRIBUTES = ("lyrics_collection", "album_collection", "main_artist_collection", "feature_artist_collection", "source_collection")
@ -65,9 +63,6 @@ class Song(MainObject, MetadataAttribute):
feature_artist_list: List[Type['Artist']] = None, feature_artist_list: List[Type['Artist']] = None,
**kwargs **kwargs
) -> None: ) -> None:
"""
Initializes the Song object with the following attributes:
"""
MainObject.__init__(self, _id=_id, dynamic=dynamic, **kwargs) MainObject.__init__(self, _id=_id, dynamic=dynamic, **kwargs)
# attributes # attributes
self.title: str = title self.title: str = title
@ -90,6 +85,33 @@ class Song(MainObject, MetadataAttribute):
self.feature_artist_collection = Collection(data=feature_artist_list, element_type=Artist) self.feature_artist_collection = Collection(data=feature_artist_list, element_type=Artist)
@property
def indexing_values(self) -> List[Tuple[str, object]]:
return [
('id', self.id),
('title', self.unified_title),
('isrc', self.isrc.strip()),
*[('url', source.url) for source in self.source_list]
]
@property
def metadata(self) -> Metadata:
metadata = Metadata({
id3Mapping.TITLE: [self.title],
id3Mapping.ISRC: [self.isrc],
id3Mapping.LENGTH: [self.length],
id3Mapping.GENRE: [self.genre],
id3Mapping.TRACKNUMBER: [self.tracksort_str]
})
metadata.merge_many([s.get_song_metadata() for s in self.source_list])
metadata.merge_many([a.metadata for a in self.album_collection])
metadata.merge_many([a.metadata for a in self.main_artist_collection])
metadata.merge_many([a.metadata for a in self.feature_artist_collection])
metadata.merge_many([lyrics.metadata for lyrics in self.lyrics_collection])
return metadata
def __eq__(self, other): def __eq__(self, other):
if type(other) != type(self): if type(other) != type(self):
return False return False
@ -114,39 +136,14 @@ class Song(MainObject, MetadataAttribute):
def __repr__(self) -> str: def __repr__(self) -> str:
return f"Song(\"{self.title}\")" return f"Song(\"{self.title}\")"
def get_tracksort_str(self): @property
def tracksort_str(self) -> str:
""" """
if the album tracklist is empty, it sets it length to 1, this song has to be in the Album 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} :returns id3_tracksort: {song_position}/{album.length_of_tracklist}
""" """
return f"{self.tracksort}/{len(self.album.tracklist) or 1}" return f"{self.tracksort}/{len(self.album.tracklist) or 1}"
@property
def indexing_values(self) -> List[Tuple[str, object]]:
return [
('id', self.id),
('title', self.unified_title),
('isrc', self.isrc.strip()),
*[('url', source.url) for source in self.source_list]
]
def get_metadata(self) -> MetadataAttribute.Metadata:
metadata = MetadataAttribute.Metadata({
id3Mapping.TITLE: [self.title],
id3Mapping.ISRC: [self.isrc],
id3Mapping.LENGTH: [self.length],
id3Mapping.GENRE: [self.genre],
id3Mapping.TRACKNUMBER: [self.tracksort_str]
})
metadata.merge_many([s.get_song_metadata() for s in self.source_list])
metadata.merge_many([a.metadata for a in self.album_collection])
metadata.merge_many([a.metadata for a in self.main_artist_collection])
metadata.merge_many([a.metadata for a in self.feature_artist_collection])
metadata.merge_many([lyrics.metadata for lyrics in self.lyrics_collection])
return metadata
def get_options(self) -> list: def get_options(self) -> list:
""" """
Return a list of related objects including the song object, album object, main artist objects, and feature artist objects. Return a list of related objects including the song object, album object, main artist objects, and feature artist objects.
@ -162,15 +159,13 @@ class Song(MainObject, MetadataAttribute):
def get_option_string(self) -> str: def get_option_string(self) -> str:
return f"Song({self.title}) of Album({self.album.title}) from Artists({self.get_artist_credits()})" return f"Song({self.title}) of Album({self.album.title}) from Artists({self.get_artist_credits()})"
tracksort_str: List[Type['Album']] = property(fget=get_tracksort_str)
""" """
All objects dependent on Album All objects dependent on Album
""" """
class Album(MainObject, MetadataAttribute): class Album(MainObject):
COLLECTION_ATTRIBUTES = ("label_collection", "artist_collection", "song_collection") COLLECTION_ATTRIBUTES = ("label_collection", "artist_collection", "song_collection")
SIMPLE_ATTRIBUTES = ("title", "album_status", "album_type", "language", "date", "barcode", "albumsort") SIMPLE_ATTRIBUTES = ("title", "album_status", "album_type", "language", "date", "barcode", "albumsort")
@ -233,6 +228,16 @@ class Album(MainObject, MetadataAttribute):
*[('url', source.url) for source in self.source_list] *[('url', source.url) for source in self.source_list]
] ]
@property
def metadata(self) -> Metadata:
return Metadata({
id3Mapping.ALBUM: [self.title],
id3Mapping.COPYRIGHT: [self.copyright],
id3Mapping.LANGUAGE: [self.iso_639_2_language],
id3Mapping.ALBUM_ARTIST: [a.name for a in self.artist_collection],
id3Mapping.DATE: [self.date.timestamp]
})
def __repr__(self): def __repr__(self):
return f"Album(\"{self.title}\")" return f"Album(\"{self.title}\")"
@ -268,16 +273,10 @@ class Album(MainObject, MetadataAttribute):
continue continue
song.tracksort = i + 1 song.tracksort = i + 1
def get_metadata(self) -> MetadataAttribute.Metadata:
return MetadataAttribute.Metadata({
id3Mapping.ALBUM: [self.title],
id3Mapping.COPYRIGHT: [self.copyright],
id3Mapping.LANGUAGE: [self.iso_639_2_language],
id3Mapping.ALBUM_ARTIST: [a.name for a in self.artist_collection],
id3Mapping.DATE: [self.date.timestamp]
})
def get_copyright(self) -> str:
@property
def copyright(self) -> str:
if self.date is None: if self.date is None:
return "" return ""
if self.date.has_year or len(self.label_collection) == 0: if self.date.has_year or len(self.label_collection) == 0:
@ -312,17 +311,13 @@ class Album(MainObject, MetadataAttribute):
def get_option_string(self) -> str: def get_option_string(self) -> str:
return f"Album: {self.title}; Artists {', '.join([i.name for i in self.artist_collection])}" return f"Album: {self.title}; Artists {', '.join([i.name for i in self.artist_collection])}"
tracklist: List[Song] = property(fget=lambda self: self.song_collection.copy())
copyright = property(fget=get_copyright)
""" """
All objects dependent on Artist All objects dependent on Artist
""" """
class Artist(MainObject, MetadataAttribute): class Artist(MainObject):
COLLECTION_ATTRIBUTES = ("feature_song_collection", "main_album_collection", "label_collection") COLLECTION_ATTRIBUTES = ("feature_song_collection", "main_album_collection", "label_collection")
SIMPLE_ATTRIBUTES = ("name", "name", "country", "formed_in", "notes", "lyrical_themes", "general_genre") SIMPLE_ATTRIBUTES = ("name", "name", "country", "formed_in", "notes", "lyrical_themes", "general_genre")
@ -382,6 +377,15 @@ class Artist(MainObject, MetadataAttribute):
*[('url', source.url) for source in self.source_list] *[('url', source.url) for source in self.source_list]
] ]
@property
def metadata(self) -> Metadata:
metadata = Metadata({
id3Mapping.ARTIST: [self.name]
})
metadata.merge_many([s.get_artist_metadata() for s in self.source_list])
return metadata
def __str__(self): def __str__(self):
string = self.name or "" string = self.name or ""
plaintext_notes = self.notes.get_plaintext() plaintext_notes = self.notes.get_plaintext()
@ -425,14 +429,6 @@ class Artist(MainObject, MetadataAttribute):
song_list=self.feature_song_collection.copy() song_list=self.feature_song_collection.copy()
) )
def get_metadata(self) -> MetadataAttribute.Metadata:
metadata = MetadataAttribute.Metadata({
id3Mapping.ARTIST: [self.name]
})
metadata.merge_many([s.get_artist_metadata() for s in self.source_list])
return metadata
def get_options(self) -> list: def get_options(self) -> list:
options = [self] options = [self]
options.extend(self.main_album_collection) options.extend(self.main_album_collection)
@ -466,7 +462,7 @@ Label
""" """
class Label(MainObject, SourceAttribute, MetadataAttribute): class Label(MainObject, SourceAttribute):
COLLECTION_ATTRIBUTES = ("album_collection", "current_artist_collection") COLLECTION_ATTRIBUTES = ("album_collection", "current_artist_collection")
SIMPLE_ATTRIBUTES = ("name",) SIMPLE_ATTRIBUTES = ("name",)

View File

@ -2,7 +2,7 @@ from collections import defaultdict
from enum import Enum from enum import Enum
from typing import List, Dict, Tuple from typing import List, Dict, Tuple
from .metadata import Mapping, MetadataAttribute from .metadata import Mapping, Metadata
from .parents import DatabaseObject from .parents import DatabaseObject
from .collection import Collection from .collection import Collection
@ -106,14 +106,15 @@ class Source(DatabaseObject, MetadataAttribute):
Mapping.ARTIST_WEBPAGE_URL: [self.url] Mapping.ARTIST_WEBPAGE_URL: [self.url]
}) })
def get_metadata(self) -> MetadataAttribute.Metadata: @property
def metadata(self) -> Metadata:
if self.type_enum == SourceTypes.SONG: if self.type_enum == SourceTypes.SONG:
return self.get_song_metadata() return self.get_song_metadata()
if self.type_enum == SourceTypes.ARTIST: if self.type_enum == SourceTypes.ARTIST:
return self.get_artist_metadata() return self.get_artist_metadata()
return super().get_metadata() return super().metadata
@property @property
def indexing_values(self) -> List[Tuple[str, object]]: def indexing_values(self) -> List[Tuple[str, object]]: