Add cacheable parameter for 16 functions that call _collect_nodes(). There's some 112 that call _request() and some may be made cacheable, but they can be done if someone asks for it. Closes #88.

This commit is contained in:
hugovk 2014-03-04 13:47:43 +02:00
parent 1fc02a33c5
commit 1d1eba5af7
2 changed files with 136 additions and 31 deletions

View file

@ -1676,13 +1676,13 @@ class Artist(_BaseObject, _Taggable):
) )
return images return images
def get_shouts(self, limit=50): def get_shouts(self, limit=50, cacheable=False):
""" """
Returns a sequqence of Shout objects Returns a sequqence of Shout objects
""" """
shouts = [] shouts = []
for node in _collect_nodes(limit, self, "artist.getShouts", False): for node in _collect_nodes(limit, self, "artist.getShouts", cacheable):
shouts.append(Shout( shouts.append(Shout(
_extract(node, "body"), _extract(node, "body"),
User(_extract(node, "author"), self.network), User(_extract(node, "author"), self.network),
@ -1886,13 +1886,13 @@ class Event(_BaseObject):
self._request('event.share', False, params) self._request('event.share', False, params)
def get_shouts(self, limit=50): def get_shouts(self, limit=50, cacheable=False):
""" """
Returns a sequqence of Shout objects Returns a sequqence of Shout objects
""" """
shouts = [] shouts = []
for node in _collect_nodes(limit, self, "event.getShouts", False): for node in _collect_nodes(limit, self, "event.getShouts", cacheable):
shouts.append(Shout( shouts.append(Shout(
_extract(node, "body"), _extract(node, "body"),
User(_extract(node, "author"), self.network), User(_extract(node, "author"), self.network),
@ -2084,10 +2084,10 @@ class Library(_BaseObject):
self._request("library.addTrack", False, params) self._request("library.addTrack", False, params)
def get_albums(self, artist=None, limit=50): def get_albums(self, artist=None, limit=50, cacheable=True):
""" """
Returns a sequence of Album objects Returns a sequence of Album objects
If no artist is specified, it will return all, sorted by playcount descendingly. If no artist is specified, it will return all, sorted by decreasing play count.
If limit==None it will return all (may take a while) If limit==None it will return all (may take a while)
""" """
@ -2096,7 +2096,7 @@ class Library(_BaseObject):
params["artist"] = artist params["artist"] = artist
seq = [] seq = []
for node in _collect_nodes(limit, self, "library.getAlbums", True, params): for node in _collect_nodes(limit, self, "library.getAlbums", cacheable, params):
name = _extract(node, "name") name = _extract(node, "name")
artist = _extract(node, "name", 1) artist = _extract(node, "name", 1)
playcount = _number(_extract(node, "playcount")) playcount = _number(_extract(node, "playcount"))
@ -2106,14 +2106,14 @@ class Library(_BaseObject):
return seq return seq
def get_artists(self, limit=50): def get_artists(self, limit=50, cacheable=True):
""" """
Returns a sequence of Album objects Returns a sequence of Album objects
if limit==None it will return all (may take a while) if limit==None it will return all (may take a while)
""" """
seq = [] seq = []
for node in _collect_nodes(limit, self, "library.getArtists", True): for node in _collect_nodes(limit, self, "library.getArtists", cacheable):
name = _extract(node, "name") name = _extract(node, "name")
playcount = _number(_extract(node, "playcount")) playcount = _number(_extract(node, "playcount"))
@ -2123,7 +2123,7 @@ class Library(_BaseObject):
return seq return seq
def get_tracks(self, artist=None, album=None, limit=50): def get_tracks(self, artist=None, album=None, limit=50, cacheable=True):
""" """
Returns a sequence of Album objects Returns a sequence of Album objects
If limit==None it will return all (may take a while) If limit==None it will return all (may take a while)
@ -2136,7 +2136,7 @@ class Library(_BaseObject):
params["album"] = album params["album"] = album
seq = [] seq = []
for node in _collect_nodes(limit, self, "library.getTracks", True, params): for node in _collect_nodes(limit, self, "library.getTracks", cacheable, params):
name = _extract(node, "name") name = _extract(node, "name")
artist = _extract(node, "name", 1) artist = _extract(node, "name", 1)
playcount = _number(_extract(node, "playcount")) playcount = _number(_extract(node, "playcount"))
@ -2721,13 +2721,13 @@ class Track(_BaseObject, _Taggable):
return self.network._get_url(domain_name, "track") %{'domain': self.network._get_language_domain(domain_name), 'artist': artist, 'title': title} return self.network._get_url(domain_name, "track") %{'domain': self.network._get_language_domain(domain_name), 'artist': artist, 'title': title}
def get_shouts(self, limit=50): def get_shouts(self, limit=50, cacheable=False):
""" """
Returns a sequqence of Shout objects Returns a sequqence of Shout objects
""" """
shouts = [] shouts = []
for node in _collect_nodes(limit, self, "track.getShouts", False): for node in _collect_nodes(limit, self, "track.getShouts", cacheable):
shouts.append(Shout( shouts.append(Shout(
_extract(node, "body"), _extract(node, "body"),
User(_extract(node, "author"), self.network), User(_extract(node, "author"), self.network),
@ -2854,13 +2854,13 @@ class Group(_BaseObject):
return self.network._get_url(domain_name, "group") %{'name': name} return self.network._get_url(domain_name, "group") %{'name': name}
def get_members(self, limit=50): def get_members(self, limit=50, cacheable=False):
""" """
Returns a sequence of User objects Returns a sequence of User objects
if limit==None it will return all if limit==None it will return all
""" """
nodes = _collect_nodes(limit, self, "group.getMembers", False) nodes = _collect_nodes(limit, self, "group.getMembers", cacheable)
users = [] users = []
@ -2966,7 +2966,7 @@ class User(_BaseObject):
return self._extract_events_from_doc(doc) return self._extract_events_from_doc(doc)
def get_artist_tracks(self, artist): def get_artist_tracks(self, artist, cacheable=False):
"""Get a list of tracks by a given artist scrobbled by this user, including scrobble time.""" """Get a list of tracks by a given artist scrobbled by this user, including scrobble time."""
# Not implemented: "Can be limited to specific timeranges, defaults to all time." # Not implemented: "Can be limited to specific timeranges, defaults to all time."
@ -2974,7 +2974,7 @@ class User(_BaseObject):
params['artist'] = artist params['artist'] = artist
seq = [] seq = []
for track in _collect_nodes(None, self, "user.getArtistTracks", False, params): for track in _collect_nodes(None, self, "user.getArtistTracks", cacheable, params):
title = _extract(track, "name") title = _extract(track, "name")
artist = _extract(track, "artist") artist = _extract(track, "artist")
date = _extract(track, "date") date = _extract(track, "date")
@ -2985,16 +2985,16 @@ class User(_BaseObject):
return seq return seq
def get_friends(self, limit = 50): def get_friends(self, limit = 50, cacheable=False):
"""Returns a list of the user's friends. """ """Returns a list of the user's friends. """
seq = [] seq = []
for node in _collect_nodes(limit, self, "user.getFriends", False): for node in _collect_nodes(limit, self, "user.getFriends", cacheable):
seq.append(User(_extract(node, "name"), self.network)) seq.append(User(_extract(node, "name"), self.network))
return seq return seq
def get_loved_tracks(self, limit=50): def get_loved_tracks(self, limit=50, cacheable=True):
"""Returns this user's loved track as a sequence of LovedTrack objects """Returns this user's loved track as a sequence of LovedTrack objects
in reverse order of their timestamp, all the way back to the first track. in reverse order of their timestamp, all the way back to the first track.
@ -3011,7 +3011,7 @@ class User(_BaseObject):
params['limit'] = limit params['limit'] = limit
seq = [] seq = []
for track in _collect_nodes(limit, self, "user.getLovedTracks", True, params): for track in _collect_nodes(limit, self, "user.getLovedTracks", cacheable, params):
title = _extract(track, "name") title = _extract(track, "name")
artist = _extract(track, "name", 1) artist = _extract(track, "name", 1)
@ -3039,14 +3039,14 @@ class User(_BaseObject):
return seq return seq
def get_past_events(self, limit=50): def get_past_events(self, limit=50, cacheable=False):
""" """
Returns a sequence of Event objects Returns a sequence of Event objects
if limit==None it will return all if limit==None it will return all
""" """
seq = [] seq = []
for n in _collect_nodes(limit, self, "user.getPastEvents", False): for n in _collect_nodes(limit, self, "user.getPastEvents", cacheable):
seq.append(Event(_extract(n, "id"), self.network)) seq.append(Event(_extract(n, "id"), self.network))
return seq return seq
@ -3086,7 +3086,7 @@ class User(_BaseObject):
return Track(artist, title, self.network, self.name) return Track(artist, title, self.network, self.name)
def get_recent_tracks(self, limit = 10): def get_recent_tracks(self, limit=10, cacheable=True):
"""Returns this user's played track as a sequence of PlayedTrack objects """Returns this user's played track as a sequence of PlayedTrack objects
in reverse order of their playtime, all the way back to the first track. in reverse order of their playtime, all the way back to the first track.
@ -3103,7 +3103,7 @@ class User(_BaseObject):
params['limit'] = limit params['limit'] = limit
seq = [] seq = []
for track in _collect_nodes(limit, self, "user.getRecentTracks", True, params): for track in _collect_nodes(limit, self, "user.getRecentTracks", cacheable, params):
if track.hasAttribute('nowplaying'): if track.hasAttribute('nowplaying'):
continue #to prevent the now playing track from sneaking in here continue #to prevent the now playing track from sneaking in here
@ -3412,13 +3412,13 @@ class User(_BaseObject):
return Library(self, self.network) return Library(self, self.network)
def get_shouts(self, limit=50): def get_shouts(self, limit=50, cacheable=False):
""" """
Returns a sequqence of Shout objects Returns a sequqence of Shout objects
""" """
shouts = [] shouts = []
for node in _collect_nodes(limit, self, "user.getShouts", False): for node in _collect_nodes(limit, self, "user.getShouts", cacheable):
shouts.append(Shout( shouts.append(Shout(
_extract(node, "body"), _extract(node, "body"),
User(_extract(node, "author"), self.network), User(_extract(node, "author"), self.network),
@ -3452,26 +3452,26 @@ class AuthenticatedUser(User):
self.name = _extract(doc, "name") self.name = _extract(doc, "name")
return self.name return self.name
def get_recommended_events(self, limit=50): def get_recommended_events(self, limit=50, cacheable=False):
""" """
Returns a sequence of Event objects Returns a sequence of Event objects
if limit==None it will return all if limit==None it will return all
""" """
seq = [] seq = []
for node in _collect_nodes(limit, self, "user.getRecommendedEvents", False): for node in _collect_nodes(limit, self, "user.getRecommendedEvents", cacheable):
seq.append(Event(_extract(node, "id"), self.network)) seq.append(Event(_extract(node, "id"), self.network))
return seq return seq
def get_recommended_artists(self, limit=50): def get_recommended_artists(self, limit=50, cacheable=False):
""" """
Returns a sequence of Event objects Returns a sequence of Event objects
if limit==None it will return all if limit==None it will return all
""" """
seq = [] seq = []
for node in _collect_nodes(limit, self, "user.getRecommendedArtists", False): for node in _collect_nodes(limit, self, "user.getRecommendedArtists", cacheable):
seq.append(Artist(_extract(node, "name"), self.network)) seq.append(Artist(_extract(node, "name"), self.network))
return seq return seq

View file

@ -755,6 +755,111 @@ class TestPyLast(unittest.TestCase):
self.assertEqual(name, "Last.fm Network") self.assertEqual(name, "Last.fm Network")
def test_artist_get_images_deprecated(self):
# Arrange
artist = self.network.get_artist("Test Artist")
# Act/Assert
with self.assertRaisesRegexp(pylast.WSError, 'deprecated'):
artist.get_images()
def helper_validate_results(self, a, b, c):
# Assert
self.assertIsNotNone(a)
self.assertIsNotNone(b)
self.assertIsNotNone(c)
self.assertGreaterEqual(len(a), 0)
self.assertGreaterEqual(len(b), 0)
self.assertGreaterEqual(len(c), 0)
self.assertEqual(a, b)
self.assertEqual(b, c)
def helper_validate_cacheable(self, thing, function_name):
# Arrange
# get thing.function_name()
func = getattr(thing, function_name, None)
# Act
result1 = func(limit = 1, cacheable = False)
result2 = func(limit = 1, cacheable = True)
result3 = func(limit = 1)
# Assert
self.helper_validate_results(result1, result2, result3)
def test_cacheable_artist_get_shouts(self):
# Arrange
artist = self.network.get_artist("Test Artist")
# Act/Assert
self.helper_validate_cacheable(artist, "get_shouts")
def test_cacheable_event_get_shouts(self):
# Arrange
user = self.network.get_user("RJ")
event = user.get_past_events(limit = 1)[0]
# Act/Assert
self.helper_validate_cacheable(event, "get_shouts")
def test_cacheable_track_get_shouts(self):
# Arrange
track = self.network.get_top_tracks()[0]
# Act/Assert
self.helper_validate_cacheable(track, "get_shouts")
def test_cacheable_group_get_members(self):
# Arrange
group = self.network.get_group("Audioscrobbler Beta")
# Act/Assert
self.helper_validate_cacheable(group, "get_members")
def test_cacheable_library(self):
# Arrange
library = pylast.Library(self.username, self.network)
# Act/Assert
self.helper_validate_cacheable(library, "get_albums")
self.helper_validate_cacheable(library, "get_artists")
self.helper_validate_cacheable(library, "get_tracks")
def test_cacheable_user_artist_tracks(self):
# Arrange
lastfm_user = self.network.get_authenticated_user()
# Act
result1 = lastfm_user.get_artist_tracks(artist = "Test Artist", cacheable = False)
result2 = lastfm_user.get_artist_tracks(artist = "Test Artist", cacheable = True)
result3 = lastfm_user.get_artist_tracks(artist = "Test Artist")
# Assert
self.helper_validate_results(result1, result2, result3)
def test_cacheable_user(self):
# Arrange
lastfm_user = self.network.get_authenticated_user()
# Act/Assert
self.helper_validate_cacheable(lastfm_user, "get_friends")
self.helper_validate_cacheable(lastfm_user, "get_loved_tracks")
self.helper_validate_cacheable(lastfm_user, "get_past_events")
self.helper_validate_cacheable(lastfm_user, "get_recent_tracks")
self.helper_validate_cacheable(lastfm_user, "get_recommended_artists")
self.helper_validate_cacheable(lastfm_user, "get_recommended_events")
self.helper_validate_cacheable(lastfm_user, "get_shouts")
if __name__ == '__main__': if __name__ == '__main__':
# For quick testing of a single case (eg. test = "test_scrobble") # For quick testing of a single case (eg. test = "test_scrobble")