Skip to content

Commit

Permalink
expand matcher+checker+searcher processor inputs (#50)
Browse files Browse the repository at this point in the history
* expand processor inputs

* update release history
  • Loading branch information
geo-martino authored Mar 30, 2024
1 parent 4ca7de1 commit 0762725
Show file tree
Hide file tree
Showing 33 changed files with 268 additions and 234 deletions.
11 changes: 11 additions & 0 deletions docs/release-history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ Added
-----

* :py:class:`.RemoteAPI` methods now accept :py:class:`.RemoteResponse` objects as input, refreshing them automatically
* Property 'kind' to all objects which have an associated :py:class:`.RemoteObjectType`
* Introduced :py:class:`.MusifyItemSettable` class to allow distinction
between items that can have their properties set and those that can't

Changed
-------
Expand All @@ -51,6 +54,14 @@ Changed
* :py:meth:`.SpotifyArtist.load` now uses the base `load` method from :py:class:`.SpotifyCollectionLoader`
meaning it now takes full advantage of the item filtering this method offers.
As part of this, the base method was made more generic to accommodate all :py:class:`.SpotifyObject` types
* Renamed 'kind' property on :py:class:`.LocalTrack` to 'type' to avoid clashing property names
* :py:class:`.ItemMatcher`, :py:class:`.RemoteItemChecker`, and :py:class:`.RemoteItemSearcher` now accept
all MusifyItem types that may have their URI property set manually.

Fixed
-----

* :py:class:`.Comparer` dynamic processor methods which process string values now cast expected types before processing

0.8.1
=====
Expand Down
17 changes: 17 additions & 0 deletions musify/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,20 @@ def __ne__(self, item: MusifyItem):
def __getitem__(self, key: str) -> Any:
"""Get the value of a given attribute key"""
return getattr(self, key)


# noinspection PyPropertyDefinition
class MusifyItemSettable(MusifyItem, metaclass=ABCMeta):
"""Generic class for storing an item that can have select properties modified."""

@abstractmethod
def _uri_getter(self) -> str | None:
"""URI (Uniform Resource Indicator) is the unique identifier for this item."""
raise NotImplementedError

@abstractmethod
def _uri_setter(self, value: str | None):
"""Set both the ``uri`` property and the ``has_uri`` property ."""
raise NotImplementedError

uri = property(lambda self: self._uri_getter(), lambda self, v: self._uri_setter(v))
4 changes: 2 additions & 2 deletions musify/core/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class Fields(Field):
FILENAME = 3
EXT = 100
SIZE = 7
KIND = 4
TYPE = 4
CHANNELS = 8
BIT_RATE = 10
BIT_DEPTH = 183
Expand Down Expand Up @@ -262,7 +262,7 @@ class TagFields(TagField):
FILENAME = Fields.FILENAME.value
EXT = Fields.EXT.value
SIZE = Fields.SIZE.value
KIND = Fields.KIND.value
TYPE = Fields.TYPE.value
CHANNELS = Fields.CHANNELS.value
BIT_RATE = Fields.BIT_RATE.value
BIT_DEPTH = Fields.BIT_DEPTH.value
Expand Down
25 changes: 25 additions & 0 deletions musify/libraries/core/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from musify.core.base import MusifyItem
from musify.exception import MusifyTypeError
from musify.libraries.core.collection import MusifyCollection
from musify.libraries.remote.core.enum import RemoteObjectType
from musify.libraries.remote.core.processors.wrangle import RemoteDataWrangler
from musify.log.logger import MusifyLogger
from musify.processors.base import Filter
Expand All @@ -25,6 +26,12 @@ class Track(MusifyItem, metaclass=ABCMeta):

__attributes_ignore__ = "name"

# noinspection PyPropertyDefinition
@classmethod
@property
def kind(cls):
return RemoteObjectType.TRACK

@property
def name(self) -> str:
"""This track's title"""
Expand Down Expand Up @@ -170,6 +177,12 @@ class Playlist[T: Track](MusifyCollection[T], metaclass=ABCMeta):
__attributes_classes__ = MusifyCollection
__attributes_ignore__ = "items"

# noinspection PyPropertyDefinition
@classmethod
@property
def kind(cls):
return RemoteObjectType.PLAYLIST

@property
@abstractmethod
def name(self):
Expand Down Expand Up @@ -461,6 +474,12 @@ class Album[T: Track](MusifyCollection[T], metaclass=ABCMeta):
__attributes_classes__ = MusifyCollection
__attributes_ignore__ = ("name", "items")

# noinspection PyPropertyDefinition
@classmethod
@property
def kind(cls):
return RemoteObjectType.ALBUM

@property
@abstractmethod
def name(self) -> str:
Expand Down Expand Up @@ -577,6 +596,12 @@ class Artist[T: Track](MusifyCollection[T], metaclass=ABCMeta):
__attributes_classes__ = MusifyCollection
__attributes_ignore__ = ("name", "items")

# noinspection PyPropertyDefinition
@classmethod
@property
def kind(cls):
return RemoteObjectType.ARTIST

@property
@abstractmethod
def name(self):
Expand Down
6 changes: 3 additions & 3 deletions musify/libraries/local/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
"""
from abc import ABCMeta

from musify.core.base import MusifyItem
from musify.core.base import MusifyItemSettable
from musify.file.base import File


class LocalItem(File, MusifyItem, metaclass=ABCMeta):
class LocalItem(File, MusifyItemSettable, metaclass=ABCMeta):
"""Generic base class for locally-stored items"""

__attributes_classes__ = (File, MusifyItem)
__attributes_classes__ = (File, MusifyItemSettable)
2 changes: 1 addition & 1 deletion musify/libraries/local/library/musicbee.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ def track_to_xml(cls, track: LocalTrack, track_id: int, persistent_id: str | Non
# "Publisher": track.publisher, # currently not supported by this program
# "Encoder": track.encoder, # currently not supported by this program
"Size": track.size,
"Kind": track.kind,
"Kind": track.type,
# "": track.channels, # unknown MusicBee mapping
"Bit Rate": int(track.bit_rate),
# "": track.bit_depth, # unknown MusicBee mapping
Expand Down
2 changes: 1 addition & 1 deletion musify/libraries/local/track/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class LocalTrackField(TrackFieldMixin):
FILENAME = TagFields.FILENAME.value
EXT = TagFields.EXT.value
SIZE = TagFields.SIZE.value
KIND = TagFields.KIND.value
TYPE = TagFields.TYPE.value
CHANNELS = TagFields.CHANNELS.value
BIT_RATE = TagFields.BIT_RATE.value
BIT_DEPTH = TagFields.BIT_DEPTH.value
Expand Down
11 changes: 4 additions & 7 deletions musify/libraries/local/track/track.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,13 +231,10 @@ def comments(self):
def comments(self, value: UnitIterable[str] | None):
self._comments = [value] if isinstance(value, str) else to_collection(value, list)

@property
def uri(self):
def _uri_getter(self):
return self._uri

@uri.setter
def uri(self, value: str | None):
"""Set both the ``uri`` property and the ``has_uri`` property ."""
def _uri_setter(self, value: str | None):
if value is None:
self._uri = None
self._has_uri = None
Expand Down Expand Up @@ -288,8 +285,8 @@ def path(self):
return self._reader.file.filename

@property
def kind(self):
"""The kind of audio file of this track"""
def type(self):
"""The type of audio file of this track"""
return self.__class__.__name__

@property
Expand Down
1 change: 0 additions & 1 deletion musify/libraries/remote/core/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,6 @@ def restore_playlists(
:param dry_run: When True, do not create playlists
and just skip any playlists that are not already currently loaded.
"""
# TODO: expand this function to support all RemoteItem types + update input type
if isinstance(playlists, Library): # get URIs from playlists in library
playlists = {name: [track.uri for track in pl] for name, pl in playlists.playlists.items()}
elif (
Expand Down
29 changes: 2 additions & 27 deletions musify/libraries/remote/core/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,15 @@
from musify.libraries.core.object import Track, Album, Playlist, Artist
from musify.libraries.remote.core.api import RemoteAPI
from musify.libraries.remote.core.base import RemoteObject, RemoteItem
from musify.libraries.remote.core.enum import RemoteObjectType
from musify.libraries.remote.core.exception import RemoteError
from musify.utils import get_most_common_values


class RemoteTrack(RemoteItem, Track, metaclass=ABCMeta):
class RemoteTrack(Track, RemoteItem, metaclass=ABCMeta):
"""Extracts key ``track`` data from a remote API JSON response."""

__attributes_classes__ = (Track, RemoteItem)

# noinspection PyPropertyDefinition
@classmethod
@property
def kind(cls):
return RemoteObjectType.TRACK


class RemoteCollection[T: RemoteObject](MusifyCollection[T], metaclass=ABCMeta):
"""Generic class for storing a collection of remote objects."""
Expand Down Expand Up @@ -129,12 +122,6 @@ class RemotePlaylist[T: RemoteTrack](Playlist[T], RemoteCollectionLoader[T], met

__attributes_classes__ = (Playlist, RemoteCollectionLoader)

# noinspection PyPropertyDefinition
@classmethod
@property
def kind(cls):
return RemoteObjectType.PLAYLIST

@property
@abstractmethod
def owner_id(self) -> str:
Expand Down Expand Up @@ -270,17 +257,11 @@ def merge(self, playlist: Playlist[T]) -> None:
raise NotImplementedError


class RemoteAlbum[T: RemoteTrack](RemoteCollectionLoader[T], Album[T], metaclass=ABCMeta):
class RemoteAlbum[T: RemoteTrack](Album[T], RemoteCollectionLoader[T], metaclass=ABCMeta):
"""Extracts key ``album`` data from a remote API JSON response."""

__attributes_classes__ = (Album, RemoteCollectionLoader)

# noinspection PyPropertyDefinition
@classmethod
@property
def kind(cls):
return RemoteObjectType.ALBUM

@property
def _total(self):
return self.track_total
Expand All @@ -296,12 +277,6 @@ class RemoteArtist[T: RemoteTrack](Artist[T], RemoteCollectionLoader[T], metacla

__attributes_classes__ = (Artist, RemoteCollectionLoader)

# noinspection PyPropertyDefinition
@classmethod
@property
def kind(cls):
return RemoteObjectType.ARTIST

@property
def _total(self):
return 0
Expand Down
Loading

0 comments on commit 0762725

Please sign in to comment.