feat: new attribute system
This commit is contained in:
parent
33f97662d7
commit
ad4328dd11
@ -19,7 +19,7 @@ Additionally it provides an **Interface** to:
|
||||
|
||||
### DatabaseObject.merge()
|
||||
|
||||
To merge the data of two instances of the same type, the attributes defined in `DatabaseObject.COLLECTION_ATTRIBUTES` and `SIMPLE_ATTRIBUTES` are used.
|
||||
To merge the data of two instances of the same type, the attributes defined in `DatabaseObject.COLLECTION_STRING_ATTRIBUTES` and `SIMPLE_STRING_ATTRIBUTES` are used.
|
||||
|
||||
The simple attributes just get carried from the other instance, to the self instance.
|
||||
|
||||
|
@ -5,8 +5,8 @@ from .parents import DatabaseObject
|
||||
|
||||
|
||||
class Contact(DatabaseObject):
|
||||
COLLECTION_ATTRIBUTES = tuple()
|
||||
SIMPLE_ATTRIBUTES = {
|
||||
COLLECTION_STRING_ATTRIBUTES = tuple()
|
||||
SIMPLE_STRING_ATTRIBUTES = {
|
||||
"contact_method": None,
|
||||
"value": None,
|
||||
}
|
||||
|
@ -8,8 +8,8 @@ from .formatted_text import FormattedText
|
||||
|
||||
|
||||
class Lyrics(DatabaseObject):
|
||||
COLLECTION_ATTRIBUTES = ("source_collection",)
|
||||
SIMPLE_ATTRIBUTES = {
|
||||
COLLECTION_STRING_ATTRIBUTES = ("source_collection",)
|
||||
SIMPLE_STRING_ATTRIBUTES = {
|
||||
"text": FormattedText(),
|
||||
"language": None
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import random
|
||||
from collections import defaultdict
|
||||
from typing import Optional, Dict, Tuple, List, Type
|
||||
from typing import Optional, Dict, Tuple, List, Type, Generic, TypeVar, Any
|
||||
from dataclasses import dataclass
|
||||
|
||||
from .metadata import Metadata
|
||||
from .option import Options
|
||||
@ -10,15 +11,46 @@ from ..utils.config import main_settings, logging_settings
|
||||
|
||||
LOGGER = logging_settings["object_logger"]
|
||||
|
||||
T = TypeVar('T')
|
||||
|
||||
@dataclass
|
||||
class StaticAttribute(Generic[T]):
|
||||
name: str
|
||||
|
||||
default_value: Any = None
|
||||
weight: float = 0
|
||||
|
||||
is_simple: bool = True
|
||||
|
||||
is_collection: bool = False
|
||||
is_downwards_collection: bool = False
|
||||
is_upwards_collection: bool = False
|
||||
|
||||
|
||||
|
||||
class Attribute(Generic[T]):
|
||||
def __init__(self, database_object: "DatabaseObject", static_attribute: StaticAttribute) -> None:
|
||||
self.database_object: DatabaseObject = database_object
|
||||
self.static_attribute: StaticAttribute = static_attribute
|
||||
|
||||
def get(self) -> T:
|
||||
return self.database_object.__getattribute__(self.name)
|
||||
|
||||
def set(self, value: T):
|
||||
self.database_object.__setattr__(self.name, value)
|
||||
|
||||
|
||||
|
||||
class DatabaseObject:
|
||||
COLLECTION_ATTRIBUTES: tuple = tuple()
|
||||
SIMPLE_ATTRIBUTES: dict = dict()
|
||||
COLLECTION_STRING_ATTRIBUTES: tuple = tuple()
|
||||
SIMPLE_STRING_ATTRIBUTES: dict = dict()
|
||||
|
||||
# contains all collection attributes, which describe something "smaller"
|
||||
# e.g. album has songs, but not artist.
|
||||
DOWNWARDS_COLLECTION_ATTRIBUTES: tuple = tuple()
|
||||
UPWARDS_COLLECTION_ATTRIBUTES: tuple = tuple()
|
||||
DOWNWARDS_COLLECTION_STRING_ATTRIBUTES: tuple = tuple()
|
||||
UPWARDS_COLLECTION_STRING_ATTRIBUTES: tuple = tuple()
|
||||
|
||||
STATIC_ATTRIBUTES: List[StaticAttribute] = list()
|
||||
|
||||
def __init__(self, _id: int = None, dynamic: bool = False, **kwargs) -> None:
|
||||
self.automatic_id: bool = False
|
||||
@ -33,13 +65,43 @@ class DatabaseObject:
|
||||
self.automatic_id = True
|
||||
# LOGGER.debug(f"Id for {type(self).__name__} isn't set. Setting to {_id}")
|
||||
|
||||
self._attributes: List[Attribute] = []
|
||||
self._simple_attribute_list: List[Attribute] = []
|
||||
self._collection_attributes: List[Attribute] = []
|
||||
self._downwards_collection_attributes: List[Attribute] = []
|
||||
self._upwards_collection_attributes: List[Attribute] = []
|
||||
|
||||
for static_attribute in self.STATIC_ATTRIBUTES:
|
||||
attribute: Attribute = Attribute(self, static_attribute)
|
||||
self._attributes.append(attribute)
|
||||
|
||||
if static_attribute.is_simple:
|
||||
self._simple_attribute_list.append(attribute)
|
||||
else:
|
||||
if static_attribute.is_collection:
|
||||
self._collection_attributes.append(attribute)
|
||||
if static_attribute.is_upwards_collection:
|
||||
self._upwards_collection_attributes.append(attribute)
|
||||
if static_attribute.is_downwards_collection:
|
||||
self._downwards_collection_attributes.append(attribute)
|
||||
|
||||
|
||||
# The id can only be None, if the object is dynamic (self.dynamic = True)
|
||||
self.id: Optional[int] = _id
|
||||
|
||||
self.dynamic = dynamic
|
||||
|
||||
self.build_version = -1
|
||||
|
||||
@property
|
||||
def upwards_collection(self) -> "Collection":
|
||||
for attribute in self._upwards_collection_attributes:
|
||||
yield attribute.get()
|
||||
|
||||
@property
|
||||
def downwards_collection(self) -> "Collection":
|
||||
for attribute in self._downwards_collection_attributes:
|
||||
yield attribute.get()
|
||||
|
||||
def __hash__(self):
|
||||
if self.dynamic:
|
||||
raise TypeError("Dynamic DatabaseObjects are unhashable.")
|
||||
@ -89,10 +151,10 @@ class DatabaseObject:
|
||||
LOGGER.warning(f"can't merge \"{type(other)}\" into \"{type(self)}\"")
|
||||
return
|
||||
|
||||
for collection in type(self).COLLECTION_ATTRIBUTES:
|
||||
for collection in type(self).COLLECTION_STRING_ATTRIBUTES:
|
||||
getattr(self, collection).extend(getattr(other, collection))
|
||||
|
||||
for simple_attribute, default_value in type(self).SIMPLE_ATTRIBUTES.items():
|
||||
for simple_attribute, default_value in type(self).SIMPLE_STRING_ATTRIBUTES.items():
|
||||
if getattr(other, simple_attribute) == default_value:
|
||||
continue
|
||||
|
||||
@ -100,7 +162,7 @@ class DatabaseObject:
|
||||
setattr(self, simple_attribute, getattr(other, simple_attribute))
|
||||
|
||||
def strip_details(self):
|
||||
for collection in type(self).DOWNWARDS_COLLECTION_ATTRIBUTES:
|
||||
for collection in type(self).DOWNWARDS_COLLECTION_STRING_ATTRIBUTES:
|
||||
getattr(self, collection).clear()
|
||||
|
||||
@property
|
||||
|
@ -15,7 +15,7 @@ from .metadata import (
|
||||
Metadata
|
||||
)
|
||||
from .option import Options
|
||||
from .parents import MainObject, DatabaseObject
|
||||
from .parents import MainObject, DatabaseObject, StaticAttribute
|
||||
from .source import Source, SourceCollection
|
||||
from .target import Target
|
||||
from ..utils.string_processing import unify
|
||||
@ -36,10 +36,10 @@ class Song(MainObject):
|
||||
tracksort, genre, source_list, target, lyrics_list, album, main_artist_list, and feature_artist_list.
|
||||
"""
|
||||
|
||||
COLLECTION_ATTRIBUTES = (
|
||||
COLLECTION_STRING_ATTRIBUTES = (
|
||||
"lyrics_collection", "album_collection", "main_artist_collection", "feature_artist_collection",
|
||||
"source_collection")
|
||||
SIMPLE_ATTRIBUTES = {
|
||||
SIMPLE_STRING_ATTRIBUTES = {
|
||||
"title": None,
|
||||
"unified_title": None,
|
||||
"isrc": None,
|
||||
@ -49,7 +49,23 @@ class Song(MainObject):
|
||||
"notes": FormattedText()
|
||||
}
|
||||
|
||||
UPWARDS_COLLECTION_ATTRIBUTES = ("album_collection", "main_artist_collection", "feature_artist_collection")
|
||||
UPWARDS_COLLECTION_STRING_ATTRIBUTES = ("album_collection", "main_artist_collection", "feature_artist_collection")
|
||||
|
||||
STATIC_ATTRIBUTES = [
|
||||
StaticAttribute(name="title", weight=.5),
|
||||
StaticAttribute(name="unified_title", weight=.3),
|
||||
StaticAttribute(name="isrc", weight=1),
|
||||
StaticAttribute(name="length"),
|
||||
StaticAttribute(name="tracksort", default_value=0),
|
||||
StaticAttribute(name="genre"),
|
||||
StaticAttribute(name="notes", default_value=FormattedText()),
|
||||
|
||||
StaticAttribute(name="source_collection", is_collection=True),
|
||||
StaticAttribute(name="lyrics_collection", is_collection=True),
|
||||
StaticAttribute(name="album_collection", is_collection=True, is_upwards_collection=True),
|
||||
StaticAttribute(name="main_artist_collection", is_collection=True, is_upwards_collection=True),
|
||||
StaticAttribute(name="feature_artist_collection", is_collection=True, is_upwards_collection=True)
|
||||
]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -212,8 +228,8 @@ All objects dependent on Album
|
||||
|
||||
|
||||
class Album(MainObject):
|
||||
COLLECTION_ATTRIBUTES = ("label_collection", "artist_collection", "song_collection")
|
||||
SIMPLE_ATTRIBUTES = {
|
||||
COLLECTION_STRING_ATTRIBUTES = ("label_collection", "artist_collection", "song_collection")
|
||||
SIMPLE_STRING_ATTRIBUTES = {
|
||||
"title": None,
|
||||
"unified_title": None,
|
||||
"album_status": None,
|
||||
@ -225,8 +241,25 @@ class Album(MainObject):
|
||||
"notes": FormattedText()
|
||||
}
|
||||
|
||||
DOWNWARDS_COLLECTION_ATTRIBUTES = ("song_collection", )
|
||||
UPWARDS_COLLECTION_ATTRIBUTES = ("artist_collection", "label_collection")
|
||||
DOWNWARDS_COLLECTION_STRING_ATTRIBUTES = ("song_collection", )
|
||||
UPWARDS_COLLECTION_STRING_ATTRIBUTES = ("artist_collection", "label_collection")
|
||||
|
||||
STATIC_ATTRIBUTES = [
|
||||
StaticAttribute(name="title", weight=.5),
|
||||
StaticAttribute(name="unified_title", weight=.3),
|
||||
StaticAttribute(name="language"),
|
||||
StaticAttribute(name="barcode", weight=1),
|
||||
StaticAttribute(name="albumsort"),
|
||||
StaticAttribute(name="album_status"),
|
||||
StaticAttribute(name="album_type", default_value=AlbumType.OTHER),
|
||||
StaticAttribute(name="date", default_value=ID3Timestamp()),
|
||||
StaticAttribute(name="notes", default_value=FormattedText()),
|
||||
|
||||
StaticAttribute(name="source_collection", is_collection=True),
|
||||
StaticAttribute(name="song_collection", is_collection=True, is_downwards_collection=True),
|
||||
StaticAttribute(name="artist_collection", is_collection=True, is_upwards_collection=True),
|
||||
StaticAttribute(name="label_collection", is_collection=True, is_upwards_collection=True),
|
||||
]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -454,13 +487,13 @@ All objects dependent on Artist
|
||||
|
||||
|
||||
class Artist(MainObject):
|
||||
COLLECTION_ATTRIBUTES = (
|
||||
COLLECTION_STRING_ATTRIBUTES = (
|
||||
"feature_song_collection",
|
||||
"main_album_collection",
|
||||
"label_collection",
|
||||
"source_collection"
|
||||
)
|
||||
SIMPLE_ATTRIBUTES = {
|
||||
SIMPLE_STRING_ATTRIBUTES = {
|
||||
"name": None,
|
||||
"unified_name": None,
|
||||
"country": None,
|
||||
@ -471,8 +504,26 @@ class Artist(MainObject):
|
||||
"unformated_location": None,
|
||||
}
|
||||
|
||||
DOWNWARDS_COLLECTION_ATTRIBUTES = ("feature_song_collection", "main_album_collection")
|
||||
UPWARDS_COLLECTION_ATTRIBUTES = ("label_collection", )
|
||||
DOWNWARDS_COLLECTION_STRING_ATTRIBUTES = ("feature_song_collection", "main_album_collection")
|
||||
UPWARDS_COLLECTION_STRING_ATTRIBUTES = ("label_collection", )
|
||||
|
||||
|
||||
STATIC_ATTRIBUTES = [
|
||||
StaticAttribute(name="name", weight=.5),
|
||||
StaticAttribute(name="unified_name", weight=.3),
|
||||
StaticAttribute(name="country"),
|
||||
StaticAttribute(name="formed_in", default_value=ID3Timestamp()),
|
||||
StaticAttribute(name="lyrical_themes", default_value=[]),
|
||||
StaticAttribute(name="general_genre", default_value=""),
|
||||
StaticAttribute(name="notes", default_value=FormattedText()),
|
||||
StaticAttribute(name="unformated_location"),
|
||||
|
||||
StaticAttribute(name="source_collection", is_collection=True),
|
||||
StaticAttribute(name="contact_collection", is_collection=True),
|
||||
StaticAttribute(name="feature_song_collection", is_collection=True, is_downwards_collection=True),
|
||||
StaticAttribute(name="main_album_collection", is_collection=True, is_downwards_collection=True),
|
||||
StaticAttribute(name="label_collection", is_collection=True, is_upwards_collection=True),
|
||||
]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@ -713,14 +764,23 @@ Label
|
||||
|
||||
|
||||
class Label(MainObject):
|
||||
COLLECTION_ATTRIBUTES = ("album_collection", "current_artist_collection")
|
||||
SIMPLE_ATTRIBUTES = {
|
||||
COLLECTION_STRING_ATTRIBUTES = ("album_collection", "current_artist_collection")
|
||||
SIMPLE_STRING_ATTRIBUTES = {
|
||||
"name": None,
|
||||
"unified_name": None,
|
||||
"notes": FormattedText()
|
||||
}
|
||||
|
||||
DOWNWARDS_COLLECTION_ATTRIBUTES = COLLECTION_ATTRIBUTES
|
||||
DOWNWARDS_COLLECTION_STRING_ATTRIBUTES = COLLECTION_STRING_ATTRIBUTES
|
||||
|
||||
STATIC_ATTRIBUTES = [
|
||||
StaticAttribute(name="name", weight=.5),
|
||||
StaticAttribute(name="unified_name", weight=.3),
|
||||
StaticAttribute(name="notes", default_value=FormattedText()),
|
||||
|
||||
StaticAttribute(name="album_collection", is_collection=True, is_downwards_collection=True),
|
||||
StaticAttribute(name="current_artist_collection", is_collection=True, is_downwards_collection=True),
|
||||
]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -19,8 +19,8 @@ class Source(DatabaseObject):
|
||||
Source(src="youtube", url="https://youtu.be/dfnsdajlhkjhsd")
|
||||
```
|
||||
"""
|
||||
COLLECTION_ATTRIBUTES = tuple()
|
||||
SIMPLE_ATTRIBUTES = {
|
||||
COLLECTION_STRING_ATTRIBUTES = tuple()
|
||||
SIMPLE_STRING_ATTRIBUTES = {
|
||||
"page_enum": None,
|
||||
"url": None,
|
||||
"referer_page": None,
|
||||
|
@ -22,11 +22,11 @@ class Target(DatabaseObject):
|
||||
```
|
||||
"""
|
||||
|
||||
SIMPLE_ATTRIBUTES = {
|
||||
SIMPLE_STRING_ATTRIBUTES = {
|
||||
"_file": None,
|
||||
"_path": None
|
||||
}
|
||||
COLLECTION_ATTRIBUTES = tuple()
|
||||
COLLECTION_STRING_ATTRIBUTES = tuple()
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
|
@ -303,7 +303,7 @@ class Page:
|
||||
|
||||
if stop_at_level > 1:
|
||||
collection: Collection
|
||||
for collection_str in music_object.DOWNWARDS_COLLECTION_ATTRIBUTES:
|
||||
for collection_str in music_object.DOWNWARDS_COLLECTION_STRING_ATTRIBUTES:
|
||||
collection = music_object.__getattribute__(collection_str)
|
||||
|
||||
for sub_element in collection:
|
||||
@ -332,7 +332,7 @@ class Page:
|
||||
def fill_naming_objects(naming_music_object: DatabaseObject):
|
||||
nonlocal naming_dict
|
||||
|
||||
for collection_name in naming_music_object.UPWARDS_COLLECTION_ATTRIBUTES:
|
||||
for collection_name in naming_music_object.UPWARDS_COLLECTION_STRING_ATTRIBUTES:
|
||||
collection: Collection = getattr(naming_music_object, collection_name)
|
||||
|
||||
if collection.empty:
|
||||
@ -368,7 +368,7 @@ class Page:
|
||||
|
||||
download_result: DownloadResult = DownloadResult()
|
||||
|
||||
for collection_name in music_object.DOWNWARDS_COLLECTION_ATTRIBUTES:
|
||||
for collection_name in music_object.DOWNWARDS_COLLECTION_STRING_ATTRIBUTES:
|
||||
collection: Collection = getattr(music_object, collection_name)
|
||||
|
||||
sub_ordered_music_object: DatabaseObject
|
||||
|
Loading…
Reference in New Issue
Block a user