2023-03-09 19:52:15 +00:00
|
|
|
from collections import defaultdict
|
2023-03-09 17:35:56 +00:00
|
|
|
from typing import Optional, Dict, Type, Tuple, List
|
2022-12-01 12:15:30 +00:00
|
|
|
import uuid
|
|
|
|
|
2023-03-02 06:59:53 +00:00
|
|
|
from ..utils.shared import (
|
2023-02-25 21:16:32 +00:00
|
|
|
SONG_LOGGER as LOGGER
|
2022-12-01 12:15:30 +00:00
|
|
|
)
|
2023-03-10 08:09:35 +00:00
|
|
|
from .metadata import Metadata
|
2023-03-10 20:28:13 +00:00
|
|
|
from .option import Options
|
2022-12-01 12:15:30 +00:00
|
|
|
|
2022-12-06 22:44:42 +00:00
|
|
|
|
2022-12-01 12:15:30 +00:00
|
|
|
class DatabaseObject:
|
2023-03-03 11:13:23 +00:00
|
|
|
COLLECTION_ATTRIBUTES: tuple = tuple()
|
2023-03-18 11:36:53 +00:00
|
|
|
SIMPLE_ATTRIBUTES: dict = dict()
|
|
|
|
|
2023-02-25 21:16:32 +00:00
|
|
|
def __init__(self, _id: str = None, dynamic: bool = False, **kwargs) -> None:
|
2023-03-16 13:36:49 +00:00
|
|
|
self.automatic_id: bool = False
|
2023-03-18 11:36:53 +00:00
|
|
|
|
2023-02-25 21:16:32 +00:00
|
|
|
if _id is None and not dynamic:
|
|
|
|
"""
|
|
|
|
generates a random UUID
|
|
|
|
https://docs.python.org/3/library/uuid.html
|
|
|
|
"""
|
|
|
|
_id = str(uuid.uuid4())
|
2023-03-16 13:36:49 +00:00
|
|
|
self.automatic_id = True
|
2023-03-10 09:54:15 +00:00
|
|
|
LOGGER.debug(f"id for {type(self).__name__} isn't set. Setting to {_id}")
|
2023-02-25 21:16:32 +00:00
|
|
|
|
|
|
|
# The id can only be None, if the object is dynamic (self.dynamic = True)
|
|
|
|
self.id: Optional[str] = _id
|
2023-02-10 12:52:18 +00:00
|
|
|
|
2022-12-12 18:30:18 +00:00
|
|
|
self.dynamic = dynamic
|
2023-03-09 19:52:15 +00:00
|
|
|
|
|
|
|
def __eq__(self, other) -> bool:
|
|
|
|
if not isinstance(other, type(self)):
|
|
|
|
return False
|
|
|
|
|
|
|
|
temp_attribute_map: Dict[str, set] = defaultdict(set)
|
|
|
|
|
|
|
|
# building map with sets
|
|
|
|
for name, value in self.indexing_values:
|
|
|
|
temp_attribute_map[name].add(value)
|
|
|
|
|
|
|
|
# check against the attributes of the other object
|
|
|
|
for name, other_value in other.indexing_values:
|
|
|
|
if other_value in temp_attribute_map[name]:
|
|
|
|
return True
|
|
|
|
|
|
|
|
return False
|
2023-03-18 11:36:53 +00:00
|
|
|
|
2023-03-09 17:19:49 +00:00
|
|
|
@property
|
2023-03-09 17:35:56 +00:00
|
|
|
def indexing_values(self) -> List[Tuple[str, object]]:
|
2023-03-09 17:19:49 +00:00
|
|
|
"""
|
|
|
|
returns a map of the name and values of the attributes.
|
|
|
|
This helps in comparing classes for equal data (eg. being the same song but different attributes)
|
|
|
|
|
|
|
|
Returns:
|
2023-03-09 17:35:56 +00:00
|
|
|
List[Tuple[str, object]]: the first element in the tuple is the name of the attribute, the second the value.
|
2023-03-09 17:19:49 +00:00
|
|
|
"""
|
2023-03-18 11:36:53 +00:00
|
|
|
|
2023-03-09 17:35:56 +00:00
|
|
|
return list()
|
2023-03-18 11:36:53 +00:00
|
|
|
|
2023-03-03 11:13:23 +00:00
|
|
|
def merge(self, other, override: bool = False):
|
2023-03-10 17:38:32 +00:00
|
|
|
if not isinstance(other, type(self)):
|
2023-03-03 11:32:08 +00:00
|
|
|
LOGGER.warning(f"can't merge \"{type(other)}\" into \"{type(self)}\"")
|
|
|
|
return
|
|
|
|
|
|
|
|
for collection in type(self).COLLECTION_ATTRIBUTES:
|
2023-03-10 17:38:32 +00:00
|
|
|
getattr(self, collection).extend(getattr(other, collection))
|
2023-03-03 11:32:08 +00:00
|
|
|
|
2023-03-18 11:36:53 +00:00
|
|
|
for simple_attribute, default_value in type(self).SIMPLE_ATTRIBUTES.items():
|
|
|
|
if getattr(other, simple_attribute) == default_value:
|
2023-03-03 11:32:08 +00:00
|
|
|
continue
|
|
|
|
|
2023-03-18 11:36:53 +00:00
|
|
|
if override or getattr(self, simple_attribute) == default_value:
|
2023-03-03 11:32:08 +00:00
|
|
|
setattr(self, simple_attribute, getattr(other, simple_attribute))
|
2022-12-12 18:30:18 +00:00
|
|
|
|
2023-03-10 08:09:35 +00:00
|
|
|
@property
|
|
|
|
def metadata(self) -> Metadata:
|
|
|
|
return Metadata()
|
|
|
|
|
2023-03-10 09:54:15 +00:00
|
|
|
@property
|
2023-03-10 20:28:13 +00:00
|
|
|
def options(self) -> Options:
|
|
|
|
return Options([self])
|
2023-03-10 09:54:15 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
def option_string(self) -> str:
|
|
|
|
return self.__repr__()
|
2023-03-18 11:36:53 +00:00
|
|
|
|
2023-03-14 10:03:54 +00:00
|
|
|
def compile(self) -> bool:
|
|
|
|
"""
|
|
|
|
compiles the recursive structures,
|
|
|
|
|
|
|
|
Args:
|
|
|
|
traceback (set, optional): Defaults to an empty set.
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
bool: returns true if id has been found in set
|
|
|
|
"""
|
|
|
|
pass
|
2023-03-10 09:54:15 +00:00
|
|
|
|
2022-12-12 18:30:18 +00:00
|
|
|
|
2023-02-25 21:16:32 +00:00
|
|
|
class MainObject(DatabaseObject):
|
|
|
|
"""
|
|
|
|
This is the parent class for all "main" data objects:
|
|
|
|
- Song
|
|
|
|
- Album
|
|
|
|
- Artist
|
|
|
|
- Label
|
2022-12-01 12:15:30 +00:00
|
|
|
|
2023-02-25 21:16:32 +00:00
|
|
|
It has all the functionality of the "DatabaseObject" (it inherits from said class)
|
|
|
|
but also some added functions as well.
|
|
|
|
"""
|
2023-03-18 11:36:53 +00:00
|
|
|
|
2023-02-25 21:16:32 +00:00
|
|
|
def __init__(self, _id: str = None, dynamic: bool = False, **kwargs):
|
2023-03-06 14:20:26 +00:00
|
|
|
DatabaseObject.__init__(self, _id=_id, dynamic=dynamic, **kwargs)
|
2022-12-01 12:15:30 +00:00
|
|
|
|
2023-02-25 21:16:32 +00:00
|
|
|
self.additional_arguments: dict = kwargs
|