Merge remote-tracking branch 'upstream/master'

Conflicts:
	test_pylast.py
This commit is contained in:
hugovk 2014-12-18 21:03:03 +02:00
commit 3e4127bf6a
2 changed files with 98 additions and 22 deletions

View file

@ -122,10 +122,10 @@ RE_XML_ILLEGAL = (u'([\u0000-\u0008\u000b-\u000c\u000e-\u001f\ufffe-\uffff])' +
u'|' +
u'([%s-%s][^%s-%s])|([^%s-%s][%s-%s])|([%s-%s]$)|(^[%s-%s])'
%
(unichr(0xd800), unichr(0xdbff), unichr(0xdc00),
unichr(0xdfff), unichr(0xd800), unichr(0xdbff),
unichr(0xdc00), unichr(0xdfff), unichr(0xd800),
unichr(0xdbff), unichr(0xdc00), unichr(0xdfff)))
(unichr(0xd800), unichr(0xdbff), unichr(0xdc00),
unichr(0xdfff), unichr(0xd800), unichr(0xdbff),
unichr(0xdc00), unichr(0xdfff), unichr(0xd800),
unichr(0xdbff), unichr(0xdc00), unichr(0xdfff)))
XML_ILLEGAL = re.compile(RE_XML_ILLEGAL)
@ -426,12 +426,18 @@ class _Network(object):
params = {}
if long: params["long"] = long
if lat: params["lat"] = lat
if location: params["location"] = location
if limit: params["limit"] = limit
if distance: params["distance"] = distance
if tag: params["tag"] = tag
if long:
params["long"] = long
if lat:
params["lat"] = lat
if location:
params["location"] = location
if limit:
params["limit"] = limit
if distance:
params["distance"] = distance
if tag:
params["tag"] = tag
if festivalsonly:
params["festivalsonly"] = 1
elif not festivalsonly:
@ -672,12 +678,18 @@ class _Network(object):
params = {"track": title, "artist": artist}
if album: params["album"] = album
if album_artist: params["albumArtist"] = album_artist
if context: params["context"] = context
if track_number: params["trackNumber"] = track_number
if mbid: params["mbid"] = mbid
if duration: params["duration"] = duration
if album:
params["album"] = album
if album_artist:
params["albumArtist"] = album_artist
if context:
params["context"] = context
if track_number:
params["trackNumber"] = track_number
if mbid:
params["mbid"] = mbid
if duration:
params["duration"] = duration
_Request(self, "track.updateNowPlaying", params).execute()
@ -1024,7 +1036,7 @@ class _Request(object):
def sign_it(self):
"""Sign this request."""
if not "api_sig" in self.params.keys():
if "api_sig" not in self.params.keys():
self.params['api_sig'] = self._get_signature()
def _get_signature(self):
@ -2091,6 +2103,17 @@ class Artist(_BaseObject, _Taggable):
self._request("artist.Shout", False, params)
def get_band_members(self):
"""Returns a list of band members or None if unknown."""
names = None
doc = self._request(self.ws_prefix + ".getInfo", True)
for node in doc.getElementsByTagName("bandmembers"):
names = _extract_all(node, "name")
return names
class Event(_BaseObject):
"""An event."""
@ -3367,12 +3390,22 @@ class User(_BaseObject, _Chartable):
return Track(artist, title, self.network, self.name)
def get_recent_tracks(self, limit=10, cacheable=True):
def get_recent_tracks(self, limit=10, cacheable=True,
time_from=None, time_to=None):
"""
Returns this user's played track as a sequence of PlayedTrack objects
in reverse order of playtime, all the way back to the first track.
If limit==None, it will try to pull all the available data.
Parameters:
limit : If None, it will try to pull all the available data.
from (Optional) : Beginning timestamp of a range - only display
scrobbles after this time, in UNIX timestamp format (integer
number of seconds since 00:00:00, January 1st 1970 UTC). This
must be in the UTC time zone.
to (Optional) : End timestamp of a range - only display scrobbles
before this time, in UNIX timestamp format (integer number of
seconds since 00:00:00, January 1st 1970 UTC). This must be in
the UTC time zone.
This method uses caching. Enable caching only if you're pulling a
large amount of data.
@ -3384,6 +3417,10 @@ class User(_BaseObject, _Chartable):
params = self._get_params()
if limit:
params['limit'] = limit
if time_from:
params['from'] = time_from
if time_to:
params['to'] = time_to
seq = []
for track in _collect_nodes(
@ -4116,7 +4153,7 @@ def _number(string):
def _unescape_htmlentity(string):
#string = _unicode(string)
# string = _unicode(string)
mapping = htmlentitydefs.name2codepoint
for key in mapping:

View file

@ -1251,7 +1251,7 @@ class TestPyLast(unittest.TestCase):
# Assert
# Check inbox for spam!
#album/artist/event/track/user
# album/artist/event/track/user
def test_album_shouts(self):
# Arrange
@ -1750,7 +1750,6 @@ class TestPyLast(unittest.TestCase):
self.assertEqual(mbid, "a74b1b7f-71a5-4011-9441-d0b5e4122711")
self.assertIsInstance(streamable, bool)
def test_events(self):
# Arrange
event_id_1 = 3162700 # Glasto 2013
@ -1869,6 +1868,46 @@ class TestPyLast(unittest.TestCase):
# Act / Assert
self.assertTrue(event1 != event2)
def test_band_members(self):
# Arrange
artist = pylast.Artist("The Beatles", self.network)
# Act
band_members = artist.get_band_members()
# Assert
self.assertGreaterEqual(len(band_members), 4)
def test_no_band_members(self):
# Arrange
artist = pylast.Artist("John Lennon", self.network)
# Act
band_members = artist.get_band_members()
# Assert
self.assertIsNone(band_members)
def test_get_recent_tracks_from_to(self):
# Arrange
lastfm_user = self.network.get_user("RJ")
from datetime import datetime
start = datetime(2011, 7, 21, 15, 10)
end = datetime(2011, 7, 21, 15, 15)
import calendar
utc_start = calendar.timegm(start.utctimetuple())
utc_end = calendar.timegm(end.utctimetuple())
# Act
tracks = lastfm_user.get_recent_tracks(time_from=utc_start,
time_to=utc_end)
# Assert
self.assertEqual(len(tracks), 1)
self.assertEqual(str(tracks[0].track.artist), "Johnny Cash")
self.assertEqual(str(tracks[0].track.title), "Ring of Fire")
if __name__ == '__main__':
parser = argparse.ArgumentParser(