Move weekly charts getters to _BaseObject, removes duplication between group, tag and user

This commit is contained in:
hugovk 2014-03-06 14:30:02 +02:00
parent 6301a5c670
commit 73cf5b3068
2 changed files with 163 additions and 214 deletions

314
pylast.py
View file

@ -1310,8 +1310,9 @@ class _BaseObject(object):
network = None
def __init__(self, network):
def __init__(self, network, ws_prefix):
self.network = network
self.ws_prefix = ws_prefix
def _request(self, method_name, cacheable=False, params=None):
if not params:
@ -1342,7 +1343,8 @@ class _BaseObject(object):
self, method, thing, thing_type, params = None, cacheable=True):
"""Returns a list of the most played thing_types by this thing."""
doc = self._request(method, cacheable, params)
doc = self._request(
self.ws_prefix + "." + method, cacheable, params)
seq = []
for node in doc.getElementsByTagName(thing):
@ -1355,11 +1357,90 @@ class _BaseObject(object):
return seq
def get_weekly_chart_dates(self):
"""Returns a list of From and To tuples for the available charts."""
doc = self._request(self.ws_prefix + ".getWeeklyChartList", True)
seq = []
for node in doc.getElementsByTagName("chart"):
seq.append((node.getAttribute("from"), node.getAttribute("to")))
return seq
def get_weekly_artist_charts(self, from_date=None, to_date=None):
"""
Returns the weekly artist charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request(
self.ws_prefix + ".getWeeklyArtistChart", True, params)
seq = []
for node in doc.getElementsByTagName("artist"):
item = Artist(_extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
def get_weekly_album_charts(self, from_date=None, to_date=None):
"""
Returns the weekly album charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request(
self.ws_prefix + ".getWeeklyAlbumChart", True, params)
seq = []
for node in doc.getElementsByTagName("album"):
item = Album(
_extract(node, "artist"), _extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
def get_weekly_track_charts(self, from_date=None, to_date=None):
"""
Returns the weekly track charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request(
self.ws_prefix + ".getWeeklyTrackChart", True, params)
seq = []
for node in doc.getElementsByTagName("track"):
item = Track(
_extract(node, "artist"), _extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
class _Taggable(object):
"""Common functions for classes with tags."""
def __init__(self, ws_prefix):
self.ws_prefix = ws_prefix
self.ws_prefix = ws_prefix # TODO move to _BaseObject
def add_tags(self, tags):
"""Adds one or several tags.
@ -1546,7 +1627,7 @@ class Album(_BaseObject, _Taggable):
* title: The album title.
"""
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, 'album')
_Taggable.__init__(self, 'album')
if isinstance(artist, Artist):
@ -1734,7 +1815,7 @@ class Artist(_BaseObject, _Taggable):
* name str: The artist's name.
"""
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, 'artist')
_Taggable.__init__(self, 'artist')
self.name = name
@ -1883,7 +1964,7 @@ class Artist(_BaseObject, _Taggable):
params['limit'] = limit
return self._get_things(
"artist.getTopAlbums", "album", Album, params, cacheable)
"getTopAlbums", "album", Album, params, cacheable)
def get_top_tracks(self, limit=None, cacheable=True):
"""Returns a list of the most played Tracks by this artist."""
@ -1892,7 +1973,7 @@ class Artist(_BaseObject, _Taggable):
params['limit'] = limit
return self._get_things(
"artist.getTopTracks", "track", Track, params, cacheable)
"getTopTracks", "track", Track, params, cacheable)
def get_top_fans(self, limit=None):
"""Returns a list of the Users who played this artist the most.
@ -2037,7 +2118,7 @@ class Event(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, event_id, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, 'event')
self.id = event_id
@ -2250,7 +2331,7 @@ class Country(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, name, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, "geo")
self.name = name
@ -2267,7 +2348,7 @@ class Country(_BaseObject):
def __ne__(self, other):
return self.get_name() != other.get_name()
def _get_params(self):
def _get_params(self): # TODO can move to _BaseObject
return {'country': self.get_name()}
def _get_name_from_code(self, alpha2code):
@ -2302,7 +2383,7 @@ class Country(_BaseObject):
params['limit'] = limit
return self._get_things(
"geo.getTopTracks", "track", Track, params, cacheable)
"getTopTracks", "track", Track, params, cacheable)
def get_url(self, domain_name=DOMAIN_ENGLISH):
"""Returns the url of the event page on the network.
@ -2336,7 +2417,7 @@ class Metro(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, name, country, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, None)
self.name = name
self.country = country
@ -2497,7 +2578,7 @@ class Library(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, user, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, 'library')
if isinstance(user, User):
self.user = user
@ -2665,7 +2746,7 @@ class Playlist(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, user, id, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, "playlist")
if isinstance(user, User):
self.user = user
@ -2801,15 +2882,12 @@ class Playlist(_BaseObject):
class Tag(_BaseObject):
"""A Last.fm object tag."""
# TODO: getWeeklyArtistChart
# (too lazy, i'll wait for when someone requests it)
name = None
__hash__ = _BaseObject.__hash__
def __init__(self, name, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, 'tag')
self.name = name
@ -2872,7 +2950,7 @@ class Tag(_BaseObject):
params['limit'] = limit
return self._get_things(
"tag.getTopTracks", "track", Track, params, cacheable)
"getTopTracks", "track", Track, params, cacheable)
def get_top_artists(self):
"""Returns a sequence of the most played artists."""
@ -2888,38 +2966,6 @@ class Tag(_BaseObject):
return seq
def get_weekly_chart_dates(self):
"""Returns a list of From and To tuples for the available charts."""
doc = self._request("tag.getWeeklyChartList", True)
seq = []
for node in doc.getElementsByTagName("chart"):
seq.append((node.getAttribute("from"), node.getAttribute("to")))
return seq
def get_weekly_artist_charts(self, from_date=None, to_date=None):
"""
Returns the weekly artist charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request("tag.getWeeklyArtistChart", True, params)
seq = []
for node in doc.getElementsByTagName("artist"):
item = Artist(_extract(node, "name"), self.network)
weight = _number(_extract(node, "weight"))
seq.append(TopItem(item, weight))
return seq
def get_url(self, domain_name=DOMAIN_ENGLISH):
"""Returns the url of the tag page on the network.
* domain_name: The network's language domain. Possible values:
@ -2952,7 +2998,7 @@ class Track(_BaseObject, _Taggable):
__hash__ = _BaseObject.__hash__
def __init__(self, artist, title, network, username=None):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, 'track')
_Taggable.__init__(self, 'track')
if isinstance(artist, Artist):
@ -3261,7 +3307,7 @@ class Group(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, group_name, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, 'group')
self.name = group_name
@ -3285,82 +3331,6 @@ class Group(_BaseObject):
"""Returns the group name. """
return self.name
def get_weekly_chart_dates(self):
"""Returns a list of From and To tuples for the available charts."""
doc = self._request("group.getWeeklyChartList", True)
seq = []
for node in doc.getElementsByTagName("chart"):
seq.append((node.getAttribute("from"), node.getAttribute("to")))
return seq
def get_weekly_artist_charts(self, from_date=None, to_date=None):
"""
Returns the weekly artist charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request("group.getWeeklyArtistChart", True, params)
seq = []
for node in doc.getElementsByTagName("artist"):
item = Artist(_extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
def get_weekly_album_charts(self, from_date=None, to_date=None):
"""
Returns the weekly album charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request("group.getWeeklyAlbumChart", True, params)
seq = []
for node in doc.getElementsByTagName("album"):
item = Album(
_extract(node, "artist"), _extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
def get_weekly_track_charts(self, from_date=None, to_date=None):
"""
Returns the weekly track charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request("group.getWeeklyTrackChart", True, params)
seq = []
for node in doc.getElementsByTagName("track"):
item = Track(
_extract(node, "artist"), _extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
def get_url(self, domain_name=DOMAIN_ENGLISH):
"""Returns the url of the group page on the network.
* domain_name: The network's language domain. Possible values:
@ -3406,7 +3376,7 @@ class XSPF(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, uri, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, None)
self.uri = uri
@ -3451,7 +3421,7 @@ class User(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, user_name, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, 'user')
self.name = user_name
@ -3829,83 +3799,7 @@ class User(_BaseObject):
params['limit'] = limit
return self._get_things(
"user.getTopTracks", "track", Track, params, cacheable)
def get_weekly_chart_dates(self):
"""Returns a list of From and To tuples for the available charts."""
doc = self._request("user.getWeeklyChartList", True)
seq = []
for node in doc.getElementsByTagName("chart"):
seq.append((node.getAttribute("from"), node.getAttribute("to")))
return seq
def get_weekly_artist_charts(self, from_date=None, to_date=None):
"""
Returns the weekly artist charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request("user.getWeeklyArtistChart", True, params)
seq = []
for node in doc.getElementsByTagName("artist"):
item = Artist(_extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
def get_weekly_album_charts(self, from_date=None, to_date=None):
"""
Returns the weekly album charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request("user.getWeeklyAlbumChart", True, params)
seq = []
for node in doc.getElementsByTagName("album"):
item = Album(
_extract(node, "artist"), _extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
def get_weekly_track_charts(self, from_date=None, to_date=None):
"""
Returns the weekly track charts for the week starting from the
from_date value to the to_date value.
"""
params = self._get_params()
if from_date and to_date:
params["from"] = from_date
params["to"] = to_date
doc = self._request("user.getWeeklyTrackChart", True, params)
seq = []
for node in doc.getElementsByTagName("track"):
item = Track(
_extract(node, "artist"), _extract(node, "name"), self.network)
weight = _number(_extract(node, "playcount"))
seq.append(TopItem(item, weight))
return seq
"getTopTracks", "track", Track, params, cacheable)
def compare_with_user(self, user, shared_artists_limit=None):
"""
@ -4046,7 +3940,7 @@ class _Search(_BaseObject):
"""An abstract class. Use one of its derivatives."""
def __init__(self, ws_prefix, search_terms, network):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, ws_prefix)
self._ws_prefix = ws_prefix
self.search_terms = search_terms
@ -4219,7 +4113,7 @@ class Venue(_BaseObject):
__hash__ = _BaseObject.__hash__
def __init__(self, id, network, venue_element=None):
_BaseObject.__init__(self, network)
_BaseObject.__init__(self, network, "venue")
self.id = _number(id)
if venue_element is not None:

View file

@ -857,16 +857,20 @@ class TestPyLast(unittest.TestCase):
self.assertEqual(type(event), pylast.Event)
self.assertEqual(event.get_venue().location['city'], "Reading")
def helper_dates_valid(self, dates):
# Assert
self.assertGreaterEqual(len(dates), 1)
self.assertEqual(type(dates[0]), tuple)
(start, end) = dates[0]
self.assertLess(start, end)
def test_get_metro_weekly_chart_dates(self):
# Arrange
# Act
dates = self.network.get_metro_weekly_chart_dates()
# Assert
self.assertGreaterEqual(len(dates), 1)
self.assertEqual(type(dates[0]), tuple)
(start, end) = dates[0]
self.assertLess(start, end)
self.helper_dates_valid(dates)
def helper_geo_chart(self, function_name, expected_type=pylast.Artist):
# Arrange
@ -1122,6 +1126,57 @@ class TestPyLast(unittest.TestCase):
# Assert
self.helper_top_things(things, pylast.Track)
def helper_assert_chart(self, chart, expected_type):
# Assert
self.assertIsNotNone(chart)
self.assertGreater(len(chart), 0)
self.assertEqual(type(chart[0]), pylast.TopItem)
self.assertEqual(type(chart[0].item), expected_type)
def helper_get_assert_charts(self, thing, date):
# Arrange
(from_date, to_date) = date
# Act
artist_chart = thing.get_weekly_artist_charts(from_date, to_date)
if type(thing) is not pylast.Tag:
album_chart = thing.get_weekly_album_charts(from_date, to_date)
track_chart = thing.get_weekly_track_charts(from_date, to_date)
# Assert
self.helper_assert_chart(artist_chart, pylast.Artist)
if type(thing) is not pylast.Tag:
self.helper_assert_chart(album_chart, pylast.Album)
self.helper_assert_chart(track_chart, pylast.Track)
def test_group_charts(self):
# Arrange
group = self.network.get_group("mnml")
dates = group.get_weekly_chart_dates()
self.helper_dates_valid(dates)
# Act/Assert
self.helper_get_assert_charts(group, dates[-1])
def test_tag_charts(self):
# Arrange
tag = self.network.get_tag("rock")
dates = tag.get_weekly_chart_dates()
self.helper_dates_valid(dates)
# Act/Assert
self.helper_get_assert_charts(tag, dates[-1])
def test_user_charts(self):
# Arrange
lastfm_user = self.network.get_user("RJ")
dates = lastfm_user.get_weekly_chart_dates()
self.helper_dates_valid(dates)
# Act/Assert
self.helper_get_assert_charts(lastfm_user, dates[-1])
if __name__ == '__main__':