From d05e48c4391650af8b2a2cd572e4f18ed4489b24 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Tue, 2 Nov 2010 00:35:27 +0100 Subject: [PATCH] Add generic copy method to models (including tests) --- mopidy/models.py | 39 +++++++++++---------------------------- tests/models_test.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 28 deletions(-) diff --git a/mopidy/models.py b/mopidy/models.py index e691ccb7..7dd75660 100644 --- a/mopidy/models.py +++ b/mopidy/models.py @@ -38,6 +38,17 @@ class ImmutableObject(object): def __ne__(self, other): return not self.__eq__(other) + def copy(self, **kwargs): + data = {} + for key in self.__dict__.keys(): + public_key = key.lstrip('_') + data[public_key] = kwargs.pop(public_key, self.__dict__[key]) + for key in kwargs.keys(): + if hasattr(self, key): + data[key] = kwargs.pop(key) + if kwargs: + raise TypeError("copy() got an unexpected keyword argument '%s'" % key) + return self.__class__(**data) class Artist(ImmutableObject): """ @@ -178,31 +189,3 @@ class Playlist(ImmutableObject): def mpd_format(self, *args, **kwargs): return translator.playlist_to_mpd_format(self, *args, **kwargs) - - def copy(self, uri=None, name=None, tracks=None, last_modified=None): - """ - Create a new playlist object with the given values. The values that are - not given are taken from the object the method is called on. - - Does not change the object on which it is called. - - :param uri: playlist URI - :type uri: string - :param name: playlist name - :type name: string - :param tracks: playlist's tracks - :type tracks: list of :class:`Track` elements - :param last_modified: playlist's modification time - :type last_modified: :class:`datetime.datetime` - :rtype: :class:`Playlist` - """ - if uri is None: - uri = self.uri - if name is None: - name = self.name - if tracks is None: - tracks = self.tracks - if last_modified is None: - last_modified = self.last_modified - return Playlist(uri=uri, name=name, tracks=tracks, - last_modified=last_modified) diff --git a/tests/models_test.py b/tests/models_test.py index 1ccf16ea..2c1dfec7 100644 --- a/tests/models_test.py +++ b/tests/models_test.py @@ -5,6 +5,50 @@ from mopidy.models import Artist, Album, Track, Playlist from tests import SkipTest +class GenericCopyTets(unittest.TestCase): + def compare(self, orig, other): + self.assertEqual(orig, other) + self.assertNotEqual(id(orig), id(other)) + + def test_copying_track(self): + track = Track() + self.compare(track, track.copy()) + + def test_copying_artist(self): + artist = Artist() + self.compare(artist, artist.copy()) + + def test_copying_album(self): + album = Album() + self.compare(album, album.copy()) + + def test_copying_playlist(self): + playlist = Playlist() + self.compare(playlist, playlist.copy()) + + def test_copying_track_with_basic_values(self): + track = Track(name='foo', uri='bar') + copy = track.copy(name='baz') + self.assertEqual('baz', copy.name) + self.assertEqual('bar', copy.uri) + + def test_copying_track_with_missing_values(self): + track = Track(uri='bar') + copy = track.copy(name='baz') + self.assertEqual('baz', copy.name) + self.assertEqual('bar', copy.uri) + + def test_copying_track_with_private_internal_value(self): + artists1 = [Artist(name='foo')] + artists2 = [Artist(name='bar')] + track = Track(artists=artists1) + copy = track.copy(artists=artists2) + self.assertEqual(copy.artists, artists2) + + def test_copying_track_with_invalid_key(self): + test = lambda: Track().copy(invalid_key=True) + self.assertRaises(TypeError, test) + class ArtistTest(unittest.TestCase): def test_uri(self): uri = u'an_uri'