Create abstract, internal _Opus class for common stuff used by Album and Track

This commit is contained in:
hugovk 2014-03-07 14:04:37 +02:00
parent d5b536d51c
commit 46b86b57da
2 changed files with 123 additions and 171 deletions

227
pylast.py
View file

@ -1661,8 +1661,8 @@ class NetworkError(Exception):
return "NetworkError: %s" % str(self.underlying_error)
class Album(_BaseObject, _Taggable):
"""An album."""
class _Opus(_BaseObject, _Taggable):
"""An album or track."""
artist = None
title = None
@ -1670,16 +1670,17 @@ class Album(_BaseObject, _Taggable):
__hash__ = _BaseObject.__hash__
def __init__(self, artist, title, network, username=None):
def __init__(self, artist, title, network, ws_prefix, username=None):
"""
Create an album instance.
Create an opus instance.
# Parameters:
* artist: An artist name or an Artist object.
* title: The album title.
* title: The album or track title.
* ws_prefix: 'album' or 'track'
"""
_BaseObject.__init__(self, network, 'album')
_Taggable.__init__(self, 'album')
_BaseObject.__init__(self, network, ws_prefix)
_Taggable.__init__(self, ws_prefix)
if isinstance(artist, Artist):
self.artist = artist
@ -1690,8 +1691,9 @@ class Album(_BaseObject, _Taggable):
self.username = username
def __repr__(self):
return "pylast.Album(%s, %s, %s)" % (
repr(self.artist.name), repr(self.title), repr(self.network))
return "pylast.%s(%s, %s, %s)" % (
self.ws_prefix.title(), repr(self.artist.name),
repr(self.title), repr(self.network))
@_string_output
def __str__(self):
@ -1715,46 +1717,28 @@ class Album(_BaseObject, _Taggable):
def _get_params(self):
return {
'artist': self.get_artist().get_name(),
self.ws_prefix: self.get_title(),
}
self.ws_prefix: self.get_title()}
def get_artist(self):
"""Returns the associated Artist object."""
return self.artist
def get_title(self):
"""Returns the album title."""
def get_title(self, properly_capitalized=False):
"""Returns the artist or track title."""
if properly_capitalized:
self.title = _extract(
self._request(self.ws_prefix + ".getInfo", True), "name")
return self.title
def get_name(self):
"""Returns the album title (alias to Album.get_title)."""
def get_name(self, properly_capitalized=False):
"""Returns the album or track title (alias to get_title())."""
return self.get_title()
def get_release_date(self):
"""Returns the release date of the album."""
return _extract(self._request(
self.ws_prefix + ".getInfo", cacheable=True), "releasedate")
def get_cover_image(self, size=COVER_EXTRA_LARGE):
"""
Returns a uri to the cover image
size can be one of:
COVER_EXTRA_LARGE
COVER_LARGE
COVER_MEDIUM
COVER_SMALL
"""
return _extract_all(
self._request(
self.ws_prefix + ".getInfo", cacheable=True), 'image')[size]
return self.get_title(properly_capitalized)
def get_id(self):
"""Returns the ID"""
"""Returns the ID on the network."""
return _extract(
self._request(self.ws_prefix + ".getInfo", cacheable=True), "id")
@ -1784,6 +1768,41 @@ class Album(_BaseObject, _Taggable):
self._request(
self.ws_prefix + ".getInfo", cacheable=True), "listeners"))
def get_mbid(self):
"""Returns the MusicBrainz ID of the album or track."""
return _extract(
self._request(self.ws_prefix + ".getInfo", cacheable=True), "mbid")
class Album(_Opus):
"""An album."""
__hash__ = _Opus.__hash__
def __init__(self, artist, title, network, username=None):
super(Album, self).__init__(artist, title, network, "album", username)
def get_release_date(self):
"""Returns the release date of the album."""
return _extract(self._request(
self.ws_prefix + ".getInfo", cacheable=True), "releasedate")
def get_cover_image(self, size=COVER_EXTRA_LARGE):
"""
Returns a uri to the cover image
size can be one of:
COVER_EXTRA_LARGE
COVER_LARGE
COVER_MEDIUM
COVER_SMALL
"""
return _extract_all(
self._request(
self.ws_prefix + ".getInfo", cacheable=True), 'image')[size]
def get_tracks(self):
"""Returns the list of Tracks on this album."""
@ -1791,14 +1810,8 @@ class Album(_BaseObject, _Taggable):
return XSPF(uri, self.network).get_tracks()
def get_mbid(self):
"""Returns the MusicBrainz id of the album."""
return _extract(
self._request(self.ws_prefix + ".getInfo", cacheable=True), "mbid")
def get_url(self, domain_name=DOMAIN_ENGLISH):
"""Returns the url of the album page on the network.
"""Returns the URL of the album or track page on the network.
# Parameters:
* domain_name str: The network's language domain. Possible values:
o DOMAIN_ENGLISH
@ -1816,10 +1829,11 @@ class Album(_BaseObject, _Taggable):
"""
artist = _url_safe(self.get_artist().get_name())
album = _url_safe(self.get_title())
title = _url_safe(self.get_title())
return self.network._get_url(
domain_name, "album") % {'artist': artist, self.ws_prefix: album}
domain_name, self.ws_prefix) % {
'artist': artist, 'album': title}
class Artist(_BaseObject, _Taggable):
@ -2886,85 +2900,13 @@ class Tag(_BaseObject):
return self.network._get_url(domain_name, "tag") % {'name': name}
class Track(_BaseObject, _Taggable):
class Track(_Opus):
"""A Last.fm track."""
artist = None
title = None
username = None
__hash__ = _BaseObject.__hash__
__hash__ = _Opus.__hash__
def __init__(self, artist, title, network, username=None):
"""
Create a track instance.
# Parameters:
* artist: An artist name or an Artist object.
* title: The artist title.
"""
_BaseObject.__init__(self, network, 'track')
_Taggable.__init__(self, 'track')
if isinstance(artist, Artist):
self.artist = artist
else:
self.artist = Artist(artist, self.network)
self.title = title
self.username = username
def __repr__(self):
return "pylast.Track(%s, %s, %s)" % (
repr(self.artist.name), repr(self.title), repr(self.network))
@_string_output
def __str__(self):
return self.get_artist().get_name() + ' - ' + self.get_title()
def __eq__(self, other):
a = self.get_title().lower()
b = other.get_title().lower()
c = self.get_artist().get_name().lower()
d = other.get_artist().get_name().lower()
return (a == b) and (c == d)
def __ne__(self, other):
a = self.get_title().lower()
b = other.get_title().lower()
c = self.get_artist().get_name().lower()
d = other.get_artist().get_name().lower()
return (a != b) or (c != d)
def _get_params(self):
return {
'artist': self.get_artist().get_name(),
self.ws_prefix: self.get_title()}
def get_artist(self):
"""Returns the associated Artist object."""
return self.artist
def get_title(self, properly_capitalized=False):
"""Returns the track title."""
if properly_capitalized:
self.title = _extract(
self._request(self.ws_prefix + ".getInfo", True), "name")
return self.title
def get_name(self, properly_capitalized=False):
"""Returns the track title (alias to Track.get_title)."""
return self.get_title(properly_capitalized)
def get_id(self):
"""Returns the track id on the network."""
doc = self._request(self.ws_prefix + ".getInfo", True)
return _extract(doc, "id")
super(Track, self).__init__(artist, title, network, "track", username)
def get_duration(self):
"""Returns the track duration."""
@ -2973,40 +2915,6 @@ class Track(_BaseObject, _Taggable):
return _number(_extract(doc, "duration"))
def get_mbid(self):
"""Returns the MusicBrainz ID of this track."""
doc = self._request(self.ws_prefix + ".getInfo", True)
return _extract(doc, "mbid")
def get_listener_count(self):
"""Returns the listener count."""
if hasattr(self, "listener_count"):
return self.listener_count
else:
doc = self._request(self.ws_prefix + ".getInfo", True)
self.listener_count = _number(_extract(doc, "listeners"))
return self.listener_count
def get_playcount(self):
"""Returns the play count."""
doc = self._request(self.ws_prefix + ".getInfo", True)
return _number(_extract(doc, "playcount"))
def get_userplaycount(self):
"""Returns the number of plays by a given username"""
if not self.username: return
params = self._get_params()
params['username'] = self.username
doc = self._request(self.ws_prefix + ".getInfo", True, params)
return _number(_extract(doc, "userplaycount"))
def get_userloved(self):
"""Whether the user loved this track"""
@ -3080,8 +2988,9 @@ class Track(_BaseObject, _Taggable):
return seq
def get_url(self, domain_name=DOMAIN_ENGLISH):
"""Returns the url of the track page on the network.
* domain_name: The network's language domain. Possible values:
"""Returns the URL of the album or track page on the network.
# Parameters:
* domain_name str: The network's language domain. Possible values:
o DOMAIN_ENGLISH
o DOMAIN_GERMAN
o DOMAIN_SPANISH
@ -3099,8 +3008,8 @@ class Track(_BaseObject, _Taggable):
artist = _url_safe(self.get_artist().get_name())
title = _url_safe(self.get_title())
return self.network._get_url(domain_name, "track") % {
'domain': self.network._get_language_domain(domain_name),
return self.network._get_url(
domain_name, self.ws_prefix) % {
'artist': artist, 'title': title}

View file

@ -1288,6 +1288,49 @@ class TestPyLast(unittest.TestCase):
# Assert
self.helper_two_things_in_list(shouts, pylast.Shout)
def test_album_data(self):
# Arrange
thing = self.network.get_album("Test Artist", "Test Album")
# Act
stringed = str(thing)
repr = thing.__repr__()
title = thing.get_title()
name = thing.get_name()
playcount = thing.get_playcount()
url = thing.get_url()
# Assert
self.assertEqual(stringed, "Test Artist - Test Album")
self.assertIn("pylast.Album('Test Artist', 'Test Album',", repr)
self.assertEqual(title, name)
self.assertIsInstance(playcount, int)
self.assertGreater(playcount, 1)
self.assertEqual(
"http://www.last.fm/music/test%2bartist/test%2balbum", url)
def test_track_data(self):
# Arrange
thing = self.network.get_track("Test Artist", "Test Title")
# Act
stringed = str(thing)
repr = thing.__repr__()
title = thing.get_title()
name = thing.get_name()
playcount = thing.get_playcount()
url = thing.get_url(pylast.DOMAIN_FRENCH)
# Assert
self.assertEqual(stringed, "Test Artist - Test Title")
self.assertIn("pylast.Track('Test Artist', 'Test Title',", repr)
self.assertEqual(title, "Test Title")
self.assertEqual(title, name)
self.assertIsInstance(playcount, int)
self.assertGreater(playcount, 1)
self.assertEqual(
"http://www.lastfm.fr/music/test%2bartist/_/test%2btitle", url)
if __name__ == '__main__':