Got deserialization working properly

This commit is contained in:
Sumner Evans
2019-05-14 22:51:57 -06:00
parent db62c4d46f
commit fa516471e7
3 changed files with 38 additions and 23 deletions

View File

@@ -17,7 +17,7 @@ def main():
password=sys.argv[2]) password=sys.argv[2])
# print(server.ping()) # print(server.ping())
# print(server.get_license()) print(server.get_license())
print(server.get_music_folders()) print(server.get_music_folders())
# print(server.get_indexes()) # print(server.get_indexes())
# print() # print()

View File

@@ -1,5 +1,6 @@
import inspect import inspect
from typing import Dict, List, Any import typing
from typing import Dict, List, Any, Type
from datetime import datetime from datetime import datetime
from dateutil import parser from dateutil import parser
@@ -9,25 +10,37 @@ def _from_json(cls, data):
Approach for deserialization here: Approach for deserialization here:
https://stackoverflow.com/a/40639688/2319844 https://stackoverflow.com/a/40639688/2319844
""" """
print(cls, data) annotations: Dict[str, Type] = getattr(cls, '__annotations__', {})
annotations: Dict[str, Any] = getattr(cls, '__annotations__', {})
# Handle lists of objects. # Handle lists of objects.
if cls == str: if cls == str:
return data instance = data
if issubclass(cls, List): elif cls == int:
list_type = cls.__args__[0] instance = int(data)
instance: List[list_type] = list() elif cls == bool:
for value in data: instance = bool(data)
instance.append(_from_json(list_type, value)) elif cls == datetime:
instance = parser.parse(data)
elif type(cls) == typing._GenericAlias:
# Having to use this because things changed in Python 3.7.
# Handle dictionaries of objects. # No idea what the heck this is, but let's go with it.
elif issubclass(cls, Dict): if cls._name == 'List':
key_type, val_type = cls.__args__ list_type = cls.__args__[0]
instance: Dict[key_type, val_type] = dict() instance: List[list_type] = list()
for key, value in data.items(): for value in data:
instance.update(_from_json(key_type, key), instance.append(_from_json(list_type, value))
_from_json(val_type, value))
elif cls._name == 'Dict':
key_type, val_type = cls.__args__
instance: Dict[key_type, val_type] = dict()
for key, value in data.items():
key = _from_json(key_type, key)
value = _from_json(val_type, value)
instance[key] = value
else:
raise Exception(
'Trying to deserialize an unsupported type: {cls._name}')
# Handle everything else by first instantiating the class, then adding # Handle everything else by first instantiating the class, then adding
# all of the sub-elements, recursively calling from_json on them. # all of the sub-elements, recursively calling from_json on them.
@@ -35,11 +48,10 @@ def _from_json(cls, data):
instance: cls = cls() instance: cls = cls()
for name, value in data.items(): for name, value in data.items():
field_type = annotations.get(name) field_type = annotations.get(name)
print('ohea', field_type, value)
if inspect.isclass(field_type): # Sometimes there are extraneous values, ignore them.
if field_type:
setattr(instance, name, _from_json(field_type, value)) setattr(instance, name, _from_json(field_type, value))
else:
setattr(instance, name, value)
return instance return instance
@@ -74,6 +86,7 @@ class License(APIObject):
valid: bool valid: bool
email: str email: str
licenseExpires: datetime licenseExpires: datetime
trialExpires: datetime
class MusicFolder(APIObject): class MusicFolder(APIObject):
@@ -86,4 +99,4 @@ class SubsonicResponse(APIObject):
version: str version: str
license: License license: License
error: SubsonicError error: SubsonicError
musicFolders: List[MusicFolder] musicFolders: Dict[str, List[MusicFolder]]

View File

@@ -51,7 +51,9 @@ class Server:
def get_music_folders(self): def get_music_folders(self):
result = self._post(self._make_url('getMusicFolders')) result = self._post(self._make_url('getMusicFolders'))
return result.musicFolders # The Airsonic API implementation of this is dumb. It gives totally the
# wrong answer so we have to go in to the 'musicFolder' key here.
return result.musicFolders['musicFolder']
def get_indexes(self): def get_indexes(self):
result = self._post(self._make_url('getIndexes')) result = self._post(self._make_url('getIndexes'))