Skip to content

Commit

Permalink
make SpotifyCollectionLoader load item type agnostic + remove Spotify…
Browse files Browse the repository at this point in the history
…Artist override
  • Loading branch information
geo-martino committed Mar 18, 2024
1 parent a710807 commit 50fc009
Show file tree
Hide file tree
Showing 18 changed files with 782 additions and 417 deletions.
4 changes: 2 additions & 2 deletions musify/local/library/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,12 @@ class LocalLibrary(LocalCollection[LocalTrack], Library[LocalTrack]):
)
__attributes_classes__ = (Library, LocalCollection)

# noinspection PyTypeChecker,PyPropertyDefinition
# noinspection PyPropertyDefinition
@classmethod
@property
def name(cls) -> str:
"""The type of library loaded"""
return cls.source
return str(cls.source)

# noinspection PyPropertyDefinition
@classmethod
Expand Down
3 changes: 0 additions & 3 deletions musify/local/track/mp3.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,6 @@ def _write_genres(self, track: LocalTrack, dry_run: bool = True) -> bool:
def _write_images(self, track: LocalTrack, dry_run: bool = True) -> bool:
tag_id_prefix = next(iter(self.tag_map.images), None)

print(self.file.tags.keys())

updated = False
for image_kind, image_link in track.image_links.items():
image = open_image(image_link)
Expand All @@ -112,7 +110,6 @@ def _write_images(self, track: LocalTrack, dry_run: bool = True) -> bool:
track.has_image = tag_id_prefix is not None or track.has_image
updated = tag_id_prefix is not None

print(self.file.tags.keys())
return updated

def _write_comments(self, track: LocalTrack, dry_run: bool = True) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion musify/shared/remote/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def load(
def reload(self, use_cache: bool = True, *args, **kwargs) -> None:
"""
Reload this object from the API, calling all required endpoints
to get a complete set of data for this item type
to get a complete set of data for this item type.
:param use_cache: Use the cache when calling the API endpoint. Set as False to refresh the cached response.
"""
Expand Down
21 changes: 16 additions & 5 deletions musify/shared/remote/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ class RemoteTrack(RemoteItem, Track, metaclass=ABCMeta):

__attributes_classes__ = (Track, RemoteItem)

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


Expand Down Expand Up @@ -78,6 +80,9 @@ def load(
* An object of the same type as this collection.
The remote API JSON response will be used to load a new object.
You may also provide a set of kwargs relating that will extend aspects of the response
before using it to initialise a new object. See :py:meth:`reload` for possible extensions.
:param value: The value representing some remote collection. See description for allowed value types.
:param api: An authorised API object to load the object from.
:param use_cache: Use the cache when calling the API endpoint. Set as False to refresh the cached response.
Expand Down Expand Up @@ -125,8 +130,10 @@ class RemotePlaylist[T: RemoteTrack](Playlist[T], RemoteCollectionLoader[T], met

__attributes_classes__ = (Playlist, RemoteCollectionLoader)

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

@property
Expand Down Expand Up @@ -241,7 +248,7 @@ def sync(
if not dry_run:
added = self.api.add_to_playlist(self.url, items=uri_add, skip_dupes=kind != "refresh")
if reload: # reload the current playlist object from remote
self.reload(use_cache=False)
self.reload(use_cache=False, extend_tracks=True)

return SyncResultRemotePlaylist(
start=len(uri_remote),
Expand Down Expand Up @@ -269,8 +276,10 @@ class RemoteAlbum[T: RemoteTrack](RemoteCollectionLoader[T], Album[T], metaclass

__attributes_classes__ = (Album, RemoteCollectionLoader)

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

@property
Expand All @@ -288,8 +297,10 @@ class RemoteArtist[T: RemoteTrack](Artist[T], RemoteCollectionLoader[T], metacla

__attributes_classes__ = (Artist, RemoteCollectionLoader)

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

@property
Expand Down
3 changes: 2 additions & 1 deletion musify/shared/remote/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ def id(self) -> str:
"""The ID of this item/collection."""
raise NotImplementedError

# noinspection PyPropertyDefinition,PyMethodParameters
@property
@abstractmethod
def kind(self) -> RemoteObjectType:
def kind(cls) -> RemoteObjectType:
"""The type of remote object this python object represents"""
raise NotImplementedError

Expand Down
2 changes: 0 additions & 2 deletions musify/spotify/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,6 @@ class SpotifyAPI(SpotifyAPIMisc, SpotifyAPIItems, SpotifyAPIPlaylists):
:param scopes: The scopes to request access to.
"""

items_key = "items"

@property
def user_id(self) -> str | None:
"""ID of the currently authenticated user"""
Expand Down
5 changes: 5 additions & 0 deletions musify/spotify/api/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ def extend_items(
if self.items_key not in response:
response[self.items_key] = []

if len(response[self.items_key]) == response["total"]: # skip on fully extended response
url = response["href"].split("?")[0]
self.logger.debug(f"{'SKIP':<7}: {url:<43} | Response already extended")
return response[self.items_key]

# this usually happens on the items block of a current user's playlist
if "next" not in response:
response["next"] = response["href"]
Expand Down
1 change: 1 addition & 0 deletions musify/spotify/api/playlist.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def get_playlist_url(self, playlist: str | Mapping[str, Any] | RemoteResponse, u
return self.wrangler.convert(
playlist["uri"], kind=RemoteObjectType.PLAYLIST, type_in=RemoteIDType.URI, type_out=RemoteIDType.URL
)

try:
return self.wrangler.convert(playlist, kind=RemoteObjectType.PLAYLIST, type_out=RemoteIDType.URL)
except RemoteIDTypeError:
Expand Down
2 changes: 1 addition & 1 deletion musify/spotify/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from musify.spotify.api import SpotifyAPI


class SpotifyObject(RemoteObject, metaclass=ABCMeta):
class SpotifyObject(RemoteObject[SpotifyAPI], metaclass=ABCMeta):
"""Generic base class for Spotify-stored objects. Extracts key data from a Spotify API JSON response."""

_url_pad = 71
Expand Down
Loading

0 comments on commit 50fc009

Please sign in to comment.