Merge branch 'feature/model-serialization' into feature/http-frontend

This commit is contained in:
Stein Magnus Jodal 2012-11-18 17:31:13 +01:00
commit 62530be8b4
2 changed files with 100 additions and 12 deletions

View File

@ -1,5 +1,7 @@
from __future__ import unicode_literals
import json
class ImmutableObject(object):
"""
@ -78,6 +80,7 @@ class ImmutableObject(object):
def serialize(self):
data = {}
data['__type__'] = self.__class__.__name__
for key in self.__dict__.keys():
public_key = key.lstrip('_')
value = self.__dict__[key]
@ -90,6 +93,51 @@ class ImmutableObject(object):
return data
class ModelJSONEncoder(json.JSONEncoder):
"""
Automatically serialize Mopidy models to JSON.
Usage::
>>> import json
>>> json.dumps({'a_track': Track(name='name')}, cls=ModelJSONEncoder)
'{"a_track": {"__type__": "Track", "name": "name"}}'
"""
def default(self, obj):
if isinstance(obj, ImmutableObject):
return obj.serialize()
return json.JSONEncoder.default(self, obj)
def model_json_decoder(dct):
"""
Automatically deserialize Mopidy models from JSON.
Usage::
>>> import json
>>> json.loads(
... '{"a_track": {"__type__": "Track", "name": "name"}}',
... object_hook=model_json_decoder)
{u'a_track': Track(artists=[], name=u'name')}
"""
if '__type__' in dct:
obj_type = dct.pop('__type__')
if obj_type == 'Album':
return Album(**dct)
if obj_type == 'Artist':
return Artist(**dct)
if obj_type == 'Playlist':
return Playlist(**dct)
if obj_type == 'TlTrack':
return TlTrack(**dct)
if obj_type == 'Track':
return Track(**dct)
return dct
class Artist(ImmutableObject):
"""
:param uri: artist URI

View File

@ -1,13 +1,16 @@
from __future__ import unicode_literals
import datetime
import json
from mopidy.models import Artist, Album, TlTrack, Track, Playlist
from mopidy.models import (
Artist, Album, TlTrack, Track, Playlist,
ModelJSONEncoder, model_json_decoder)
from tests import unittest
class GenericCopyTets(unittest.TestCase):
class GenericCopyTest(unittest.TestCase):
def compare(self, orig, other):
self.assertEqual(orig, other)
self.assertNotEqual(id(orig), id(other))
@ -83,9 +86,15 @@ class ArtistTest(unittest.TestCase):
def test_serialize(self):
self.assertDictEqual(
{'uri': 'uri', 'name': 'name'},
{'__type__': 'Artist', 'uri': 'uri', 'name': 'name'},
Artist(uri='uri', name='name').serialize())
def test_to_json_and_Back(self):
artist1 = Artist(uri='uri', name='name')
serialized = json.dumps(artist1, cls=ModelJSONEncoder)
artist2 = json.loads(serialized, object_hook=model_json_decoder)
self.assertEqual(artist1, artist2)
def test_eq_name(self):
artist1 = Artist(name='name')
artist2 = Artist(name='name')
@ -195,15 +204,22 @@ class AlbumTest(unittest.TestCase):
def test_serialize_without_artists(self):
self.assertDictEqual(
{'uri': 'uri', 'name': 'name'},
{'__type__': 'Album', 'uri': 'uri', 'name': 'name'},
Album(uri='uri', name='name').serialize())
def test_serialize_with_artists(self):
artist = Artist(name='foo')
self.assertDictEqual(
{'uri': 'uri', 'name': 'name', 'artists': [artist.serialize()]},
{'__type__': 'Album', 'uri': 'uri', 'name': 'name', 'artists':
[artist.serialize()]},
Album(uri='uri', name='name', artists=[artist]).serialize())
def test_to_json_and_back(self):
album1 = Album(uri='uri', name='name', artists=[Artist(name='foo')])
serialized = json.dumps(album1, cls=ModelJSONEncoder)
album2 = json.loads(serialized, object_hook=model_json_decoder)
self.assertEqual(album1, album2)
def test_eq_name(self):
album1 = Album(name='name')
album2 = Album(name='name')
@ -386,21 +402,31 @@ class TrackTest(unittest.TestCase):
def test_serialize_without_artists(self):
self.assertDictEqual(
{'uri': 'uri', 'name': 'name'},
{'__type__': 'Track', 'uri': 'uri', 'name': 'name'},
Track(uri='uri', name='name').serialize())
def test_serialize_with_artists(self):
artist = Artist(name='foo')
self.assertDictEqual(
{'uri': 'uri', 'name': 'name', 'artists': [artist.serialize()]},
{'__type__': 'Track', 'uri': 'uri', 'name': 'name',
'artists': [artist.serialize()]},
Track(uri='uri', name='name', artists=[artist]).serialize())
def test_serialize_with_album(self):
album = Album(name='foo')
self.assertDictEqual(
{'uri': 'uri', 'name': 'name', 'album': album.serialize()},
{'__type__': 'Track', 'uri': 'uri', 'name': 'name',
'album': album.serialize()},
Track(uri='uri', name='name', album=album).serialize())
def test_to_json_and_back(self):
track1 = Track(
uri='uri', name='name', album=Album(name='foo'),
artists=[Artist(name='foo')])
serialized = json.dumps(track1, cls=ModelJSONEncoder)
track2 = json.loads(serialized, object_hook=model_json_decoder)
self.assertEqual(track1, track2)
def test_eq_uri(self):
track1 = Track(uri='uri1')
track2 = Track(uri='uri1')
@ -590,9 +616,16 @@ class TlTrackTest(unittest.TestCase):
repr(TlTrack(tlid=123, track=Track(uri='uri'))))
def test_serialize(self):
track = Track(uri='uri', name='name')
self.assertDictEqual(
{'tlid': 123, 'track': {'uri': 'uri', 'name': 'name'}},
TlTrack(tlid=123, track=Track(uri='uri', name='name')).serialize())
{'__type__': 'TlTrack', 'tlid': 123, 'track': track.serialize()},
TlTrack(tlid=123, track=track).serialize())
def test_to_json_and_back(self):
tl_track1 = TlTrack(tlid=123, track=Track(uri='uri', name='name'))
serialized = json.dumps(tl_track1, cls=ModelJSONEncoder)
tl_track2 = json.loads(serialized, object_hook=model_json_decoder)
self.assertEqual(tl_track1, tl_track2)
def test_eq(self):
tlid = 123
@ -719,15 +752,22 @@ class PlaylistTest(unittest.TestCase):
def test_serialize_without_tracks(self):
self.assertDictEqual(
{'uri': 'uri', 'name': 'name'},
{'__type__': 'Playlist', 'uri': 'uri', 'name': 'name'},
Playlist(uri='uri', name='name').serialize())
def test_serialize_with_tracks(self):
track = Track(name='foo')
self.assertDictEqual(
{'uri': 'uri', 'name': 'name', 'tracks': [track.serialize()]},
{'__type__': 'Playlist', 'uri': 'uri', 'name': 'name',
'tracks': [track.serialize()]},
Playlist(uri='uri', name='name', tracks=[track]).serialize())
def test_to_json_and_back(self):
playlist1 = Playlist(uri='uri', name='name')
serialized = json.dumps(playlist1, cls=ModelJSONEncoder)
playlist2 = json.loads(serialized, object_hook=model_json_decoder)
self.assertEqual(playlist1, playlist2)
def test_eq_name(self):
playlist1 = Playlist(name='name')
playlist2 = Playlist(name='name')