refactor
This commit is contained in:
parent
d6aed75fec
commit
0423cb3139
@ -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
|
||||||
"""
|
"""
|
||||||
|
@ -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
|
|
||||||
|
@ -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,126 +266,113 @@ class ID3Timestamp:
|
|||||||
timeformat: str = property(fget=get_time_format)
|
timeformat: str = property(fget=get_time_format)
|
||||||
|
|
||||||
|
|
||||||
class MetadataAttribute:
|
class Metadata:
|
||||||
"""
|
# it's a null byte for the later concatenation of text frames
|
||||||
This class shall be added to any object, which can return data for tagging
|
NULL_BYTE: str = "\x00"
|
||||||
"""
|
# this is pretty self-explanatory
|
||||||
|
# the key is an enum from Mapping
|
||||||
|
# the value is a list with each value
|
||||||
|
# the mutagen object for each frame will be generated dynamically
|
||||||
|
id3_dict: Dict[any, list]
|
||||||
|
|
||||||
class Metadata:
|
def __init__(self, id3_dict: Dict[any, list] = None) -> None:
|
||||||
# it's a null byte for the later concatenation of text frames
|
self.id3_dict = dict()
|
||||||
NULL_BYTE: str = "\x00"
|
if id3_dict is not None:
|
||||||
# this is pretty self-explanatory
|
self.add_metadata_dict(id3_dict)
|
||||||
# the key is an enum from Mapping
|
|
||||||
# the value is a list with each value
|
|
||||||
# the mutagen object for each frame will be generated dynamically
|
|
||||||
id3_dict: Dict[any, list]
|
|
||||||
|
|
||||||
def __init__(self, id3_dict: Dict[any, list] = None) -> None:
|
def __setitem__(self, frame, value_list: list, override_existing: bool = True):
|
||||||
self.id3_dict = dict()
|
if type(value_list) != list:
|
||||||
if id3_dict is not None:
|
raise ValueError(f"can only set attribute to list, not {type(value_list)}")
|
||||||
self.add_metadata_dict(id3_dict)
|
|
||||||
|
|
||||||
def __setitem__(self, frame, value_list: list, override_existing: bool = True):
|
new_val = [i for i in value_list if i not in {None, ''}]
|
||||||
if type(value_list) != list:
|
|
||||||
raise ValueError(f"can only set attribute to list, not {type(value_list)}")
|
|
||||||
|
|
||||||
new_val = [i for i in value_list if i not in {None, ''}]
|
if len(new_val) == 0:
|
||||||
|
return
|
||||||
|
|
||||||
if len(new_val) == 0:
|
if override_existing:
|
||||||
|
self.id3_dict[frame] = new_val
|
||||||
|
else:
|
||||||
|
if frame not in self.id3_dict:
|
||||||
|
self.id3_dict[frame] = new_val
|
||||||
return
|
return
|
||||||
|
|
||||||
if override_existing:
|
self.id3_dict[frame].extend(new_val)
|
||||||
self.id3_dict[frame] = new_val
|
|
||||||
else:
|
|
||||||
if frame not in self.id3_dict:
|
|
||||||
self.id3_dict[frame] = new_val
|
|
||||||
return
|
|
||||||
|
|
||||||
self.id3_dict[frame].extend(new_val)
|
def __getitem__(self, key):
|
||||||
|
if key not in self.id3_dict:
|
||||||
|
return None
|
||||||
|
return self.id3_dict[key]
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def delete_field(self, key: str):
|
||||||
if key not in self.id3_dict:
|
if key in self.id3_dict:
|
||||||
return None
|
return self.id3_dict.pop(key)
|
||||||
return self.id3_dict[key]
|
|
||||||
|
|
||||||
def delete_field(self, key: str):
|
def add_metadata_dict(self, metadata_dict: dict, override_existing: bool = True):
|
||||||
if key in self.id3_dict:
|
for field_enum, value in metadata_dict.items():
|
||||||
return self.id3_dict.pop(key)
|
self.__setitem__(field_enum, value, override_existing=override_existing)
|
||||||
|
|
||||||
def add_metadata_dict(self, metadata_dict: dict, override_existing: bool = True):
|
def merge(self, other, override_existing: bool = False):
|
||||||
for field_enum, value in metadata_dict.items():
|
|
||||||
self.__setitem__(field_enum, value, override_existing=override_existing)
|
|
||||||
|
|
||||||
def merge(self, other, override_existing: bool = False):
|
|
||||||
"""
|
|
||||||
adds the values of another metadata obj to this one
|
|
||||||
|
|
||||||
other is a value of the type MetadataAttribute.Metadata
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.add_metadata_dict(other.id3_dict, override_existing=override_existing)
|
|
||||||
|
|
||||||
def merge_many(self, many_other):
|
|
||||||
"""
|
|
||||||
adds the values of many other metadata objects to this one
|
|
||||||
"""
|
|
||||||
|
|
||||||
for other in many_other:
|
|
||||||
self.merge(other)
|
|
||||||
|
|
||||||
def get_id3_value(self, field):
|
|
||||||
if field not in self.id3_dict:
|
|
||||||
return None
|
|
||||||
|
|
||||||
list_data = self.id3_dict[field]
|
|
||||||
|
|
||||||
# convert for example the time objects to timestamps
|
|
||||||
for i, element in enumerate(list_data):
|
|
||||||
# for performance’s sake I don't do other checks if it is already the right type
|
|
||||||
if type(element) == str:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if type(element) in {int}:
|
|
||||||
list_data[i] = str(element)
|
|
||||||
|
|
||||||
if type(element) == ID3Timestamp:
|
|
||||||
list_data[i] = element.timestamp
|
|
||||||
continue
|
|
||||||
|
|
||||||
"""
|
|
||||||
Version 2.4 of the specification prescribes that all text fields (the fields that start with a T, except for TXXX) can contain multiple values separated by a null character.
|
|
||||||
Thus if above conditions are met, I concatenate the list,
|
|
||||||
else I take the first element
|
|
||||||
"""
|
|
||||||
if field.value[0].upper() == "T" and field.value.upper() != "TXXX":
|
|
||||||
return self.NULL_BYTE.join(list_data)
|
|
||||||
|
|
||||||
return list_data[0]
|
|
||||||
|
|
||||||
def get_mutagen_object(self, field):
|
|
||||||
return Mapping.get_mutagen_instance(field, self.get_id3_value(field))
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
rows = []
|
|
||||||
for key, value in self.id3_dict.items():
|
|
||||||
rows.append(f"{key} - {str(value)}")
|
|
||||||
return "\n".join(rows)
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
"""
|
|
||||||
returns a generator, you can iterate through,
|
|
||||||
to directly tagg a file with id3 container.
|
|
||||||
"""
|
|
||||||
# set the tagging timestamp to the current time
|
|
||||||
self.__setitem__(Mapping.TAGGING_TIME, [ID3Timestamp.now()])
|
|
||||||
|
|
||||||
for field in self.id3_dict:
|
|
||||||
yield self.get_mutagen_object(field)
|
|
||||||
|
|
||||||
def get_metadata(self) -> Metadata:
|
|
||||||
"""
|
"""
|
||||||
this is intendet to be overwritten by the child class
|
adds the values of another metadata obj to this one
|
||||||
"""
|
|
||||||
return MetadataAttribute.Metadata()
|
|
||||||
|
|
||||||
metadata = property(fget=lambda self: self.get_metadata())
|
other is a value of the type MetadataAttribute.Metadata
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.add_metadata_dict(other.id3_dict, override_existing=override_existing)
|
||||||
|
|
||||||
|
def merge_many(self, many_other):
|
||||||
|
"""
|
||||||
|
adds the values of many other metadata objects to this one
|
||||||
|
"""
|
||||||
|
|
||||||
|
for other in many_other:
|
||||||
|
self.merge(other)
|
||||||
|
|
||||||
|
def get_id3_value(self, field):
|
||||||
|
if field not in self.id3_dict:
|
||||||
|
return None
|
||||||
|
|
||||||
|
list_data = self.id3_dict[field]
|
||||||
|
|
||||||
|
# convert for example the time objects to timestamps
|
||||||
|
for i, element in enumerate(list_data):
|
||||||
|
# for performance’s sake I don't do other checks if it is already the right type
|
||||||
|
if type(element) == str:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if type(element) in {int}:
|
||||||
|
list_data[i] = str(element)
|
||||||
|
|
||||||
|
if type(element) == ID3Timestamp:
|
||||||
|
list_data[i] = element.timestamp
|
||||||
|
continue
|
||||||
|
|
||||||
|
"""
|
||||||
|
Version 2.4 of the specification prescribes that all text fields (the fields that start with a T, except for TXXX) can contain multiple values separated by a null character.
|
||||||
|
Thus if above conditions are met, I concatenate the list,
|
||||||
|
else I take the first element
|
||||||
|
"""
|
||||||
|
if field.value[0].upper() == "T" and field.value.upper() != "TXXX":
|
||||||
|
return self.NULL_BYTE.join(list_data)
|
||||||
|
|
||||||
|
return list_data[0]
|
||||||
|
|
||||||
|
def get_mutagen_object(self, field):
|
||||||
|
return Mapping.get_mutagen_instance(field, self.get_id3_value(field))
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
rows = []
|
||||||
|
for key, value in self.id3_dict.items():
|
||||||
|
rows.append(f"{key} - {str(value)}")
|
||||||
|
return "\n".join(rows)
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
"""
|
||||||
|
returns a generator, you can iterate through,
|
||||||
|
to directly tagg a file with id3 container.
|
||||||
|
"""
|
||||||
|
# set the tagging timestamp to the current time
|
||||||
|
self.__setitem__(Mapping.TAGGING_TIME, [ID3Timestamp.now()])
|
||||||
|
|
||||||
|
for field in self.id3_dict:
|
||||||
|
yield self.get_mutagen_object(field)
|
||||||
|
@ -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):
|
||||||
"""
|
"""
|
||||||
|
@ -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",)
|
||||||
|
|
||||||
|
@ -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]]:
|
||||||
|
Loading…
Reference in New Issue
Block a user