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])
# print(server.ping())
# print(server.get_license())
print(server.get_license())
print(server.get_music_folders())
# print(server.get_indexes())
# print()

View File

@@ -1,5 +1,6 @@
import inspect
from typing import Dict, List, Any
import typing
from typing import Dict, List, Any, Type
from datetime import datetime
from dateutil import parser
@@ -9,25 +10,37 @@ def _from_json(cls, data):
Approach for deserialization here:
https://stackoverflow.com/a/40639688/2319844
"""
print(cls, data)
annotations: Dict[str, Any] = getattr(cls, '__annotations__', {})
annotations: Dict[str, Type] = getattr(cls, '__annotations__', {})
# Handle lists of objects.
if cls == str:
return data
if issubclass(cls, List):
list_type = cls.__args__[0]
instance: List[list_type] = list()
for value in data:
instance.append(_from_json(list_type, value))
instance = data
elif cls == int:
instance = int(data)
elif cls == bool:
instance = bool(data)
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.
elif issubclass(cls, Dict):
key_type, val_type = cls.__args__
instance: Dict[key_type, val_type] = dict()
for key, value in data.items():
instance.update(_from_json(key_type, key),
_from_json(val_type, value))
# No idea what the heck this is, but let's go with it.
if cls._name == 'List':
list_type = cls.__args__[0]
instance: List[list_type] = list()
for value in data:
instance.append(_from_json(list_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
# all of the sub-elements, recursively calling from_json on them.
@@ -35,11 +48,10 @@ def _from_json(cls, data):
instance: cls = cls()
for name, value in data.items():
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))
else:
setattr(instance, name, value)
return instance
@@ -74,6 +86,7 @@ class License(APIObject):
valid: bool
email: str
licenseExpires: datetime
trialExpires: datetime
class MusicFolder(APIObject):
@@ -86,4 +99,4 @@ class SubsonicResponse(APIObject):
version: str
license: License
error: SubsonicError
musicFolders: List[MusicFolder]
musicFolders: Dict[str, List[MusicFolder]]

View File

@@ -51,7 +51,9 @@ class Server:
def get_music_folders(self):
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):
result = self._post(self._make_url('getIndexes'))