diff --git a/libremsonic/from_json.py b/libremsonic/from_json.py index 424979a..ddbcb89 100644 --- a/libremsonic/from_json.py +++ b/libremsonic/from_json.py @@ -1,4 +1,5 @@ from datetime import datetime +from enum import EnumMeta import typing from typing import Dict, List, Type @@ -24,6 +25,8 @@ def from_json(cls, data): annotations: Dict[str, Type] = getattr(cls, '__annotations__', {}) + print(type(cls)) + # Handle primitive of objects if data is None: instance = None @@ -33,6 +36,8 @@ def from_json(cls, data): instance = int(data) elif cls == bool: instance = bool(data) + elif type(cls) == EnumMeta: + instance = cls[data] elif cls == datetime: instance = parser.parse(data) diff --git a/libremsonic/server/api_object.py b/libremsonic/server/api_object.py new file mode 100644 index 0000000..36f65d8 --- /dev/null +++ b/libremsonic/server/api_object.py @@ -0,0 +1,29 @@ +""" +Defines the base class for API objects. +""" + +from enum import Enum +from typing import Any, Dict + +from libremsonic.from_json import from_json as _from_json + + +class APIObject: + @classmethod + def from_json(cls, data): + return _from_json(cls, data) + + def get(self, field, default=None): + return getattr(self, field, default) + + def __repr__(self): + if isinstance(self, Enum): + return super().__repr__() + + annotations: Dict[str, Any] = self.get('__annotations__', {}) + typename = type(self).__name__ + fieldstr = ' '.join([ + f'{field}={getattr(self, field)!r}' + for field in annotations.keys() if hasattr(self, field) + ]) + return f'<{typename} {fieldstr}>' diff --git a/libremsonic/server/api_objects.py b/libremsonic/server/api_objects.py index db0b454..e5dd0e4 100644 --- a/libremsonic/server/api_objects.py +++ b/libremsonic/server/api_objects.py @@ -1,25 +1,8 @@ from datetime import datetime -from typing import Any, Dict, List +from typing import List +from enum import Enum -from libremsonic.from_json import from_json as _from_json - - -class APIObject: - @classmethod - def from_json(cls, data): - return _from_json(cls, data) - - def get(self, field, default=None): - return getattr(self, field, default) - - def __repr__(self): - annotations: Dict[str, Any] = self.get('__annotations__', {}) - typename = type(self).__name__ - fieldstr = ' '.join([ - f'{field}={getattr(self, field)!r}' - for field in annotations.keys() if hasattr(self, field) - ]) - return f'<{typename} {fieldstr}>' +from .api_object import APIObject class SubsonicError(APIObject): @@ -41,8 +24,9 @@ class MusicFolder(APIObject): id: int name: str + class MediaType(APIObject, Enum): - + pass class Child(APIObject): @@ -265,9 +249,14 @@ class AlbumList(APIObject): album: List[Album] +class ResponseStatus(APIObject, Enum): + ok = "ok" + failed = "failed" + + class SubsonicResponse(APIObject): # On every Subsonic Response - status: str + status: ResponseStatus version: str # One of these will exist on each SubsonicResponse diff --git a/libremsonic/server/server.py b/libremsonic/server/server.py index 6b3c292..ba3dbb5 100644 --- a/libremsonic/server/server.py +++ b/libremsonic/server/server.py @@ -2,7 +2,7 @@ import requests from typing import List, Optional, Dict from .api_objects import (SubsonicResponse, License, MusicFolder, Indexes, - AlbumInfo, ArtistInfo, VideoInfo, File, Album, + AlbumInfo, ArtistInfo, VideoInfo, Child, Album, Artist, Artists, Directory, Genre) @@ -73,6 +73,7 @@ class Server: Get details about the software license. """ result = self._post(self._make_url('getLicense')) + print(result) return result.license def get_music_folders(self) -> List[MusicFolder]: @@ -149,7 +150,7 @@ class Server: result = self._post(self._make_url('getAlbum'), id=album_id) return result.album - def get_song(self, song_id: int) -> File: + def get_song(self, song_id: int) -> Child: """ Returns details for a song. @@ -158,7 +159,7 @@ class Server: result = self._post(self._make_url('getSong'), id=song_id) return result.song - def get_videos(self) -> Optional[List[File]]: + def get_videos(self) -> Optional[List[Child]]: """ Returns all video files. """ @@ -236,7 +237,7 @@ class Server: result = self._post(self._make_url('getAlbumInfo2'), id=id) return result.albumInfo2 - def get_similar_songs(self, id: int, count: int = None) -> List[File]: + def get_similar_songs(self, id: int, count: int = None) -> List[Child]: """ Returns a random collection of songs from the given artist and similar artists, using data from last.fm. Typically used for artist radio @@ -251,7 +252,7 @@ class Server: count=count) return result.similarSongs.song - def get_similar_songs2(self, id: int, count: int = None) -> List[File]: + def get_similar_songs2(self, id: int, count: int = None) -> List[Child]: """ Similar to getSimilarSongs, but organizes music according to ID3 tags. @@ -264,7 +265,7 @@ class Server: count=count) return result.similarSongs2.song - def get_top_songs(self, artist: str, count: int = None) -> List[File]: + def get_top_songs(self, artist: str, count: int = None) -> List[Child]: """ Returns top songs for the given artist, using data from last.fm. @@ -284,7 +285,7 @@ class Server: from_year: int = None, to_year: int = None, genre: str = None, - music_folder_id: int = None) -> List[File]: + music_folder_id: int = None) -> List[Child]: """ Returns a list of random, newest, highest rated etc. albums. Similar to the album lists on the home page of the Subsonic web interface.