Allow getting venue info through Event.get_venue() as a workaround until the Venue.getInfo API call is added to Last.fm
This commit is contained in:
parent
979447c4f4
commit
797fd66fbf
176
pylast.py
176
pylast.py
|
@ -47,7 +47,7 @@ if sys.version_info[0] == 3:
|
||||||
|
|
||||||
elif sys.version_info[0] == 2:
|
elif sys.version_info[0] == 2:
|
||||||
from httplib import HTTPConnection
|
from httplib import HTTPConnection
|
||||||
import htmlentitydefs
|
import htmlentitydefs
|
||||||
from urllib import splithost as url_split_host
|
from urllib import splithost as url_split_host
|
||||||
from urllib import quote_plus as url_quote_plus
|
from urllib import quote_plus as url_quote_plus
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ class _Network(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.homepage = homepage
|
self.homepage = homepage
|
||||||
self.ws_server = ws_server
|
self.ws_server = ws_server
|
||||||
self.api_key = api_key
|
self.api_key = api_key
|
||||||
self.api_secret = api_secret
|
self.api_secret = api_secret
|
||||||
|
@ -241,13 +241,13 @@ class _Network(object):
|
||||||
|
|
||||||
Quote from http://www.last.fm/api/submissions:
|
Quote from http://www.last.fm/api/submissions:
|
||||||
========
|
========
|
||||||
Client identifiers are used to provide a centrally managed database of
|
Client identifiers are used to provide a centrally managed database of
|
||||||
the client versions, allowing clients to be banned if they are found to
|
the client versions, allowing clients to be banned if they are found to
|
||||||
be behaving undesirably. The client ID is associated with a version
|
be behaving undesirably. The client ID is associated with a version
|
||||||
number on the server, however these are only incremented if a client is
|
number on the server, however these are only incremented if a client is
|
||||||
banned and do not have to reflect the version of the actual client application.
|
banned and do not have to reflect the version of the actual client application.
|
||||||
|
|
||||||
During development, clients which have not been allocated an identifier should
|
During development, clients which have not been allocated an identifier should
|
||||||
use the identifier tst, with a version number of 1.0. Do not distribute code or
|
use the identifier tst, with a version number of 1.0. Do not distribute code or
|
||||||
client implementations which use this test identifier. Do not use the identifiers
|
client implementations which use this test identifier. Do not use the identifiers
|
||||||
used by other clients.
|
used by other clients.
|
||||||
|
@ -257,7 +257,7 @@ class _Network(object):
|
||||||
* Last.fm: submissions@last.fm
|
* Last.fm: submissions@last.fm
|
||||||
* # TODO: list others
|
* # TODO: list others
|
||||||
|
|
||||||
...and provide us with the name of your client and its homepage address.
|
...and provide us with the name of your client and its homepage address.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_deprecation_warning("Use _Network.scrobble(...), _Network.scrobble_many(...), and Netowrk.update_now_playing(...) instead")
|
_deprecation_warning("Use _Network.scrobble(...), _Network.scrobble_many(...), and Netowrk.update_now_playing(...) instead")
|
||||||
|
@ -353,7 +353,7 @@ class _Network(object):
|
||||||
def enable_caching(self, file_path = None):
|
def enable_caching(self, file_path = None):
|
||||||
"""Enables caching request-wide for all cachable calls.
|
"""Enables caching request-wide for all cachable calls.
|
||||||
|
|
||||||
* file_path: A file path for the backend storage file. If
|
* file_path: A file path for the backend storage file. If
|
||||||
None set, a temp file would probably be created, according the backend.
|
None set, a temp file would probably be created, according the backend.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -435,10 +435,10 @@ class _Network(object):
|
||||||
|
|
||||||
return Album(_extract(doc, "artist"), _extract(doc, "name"), self)
|
return Album(_extract(doc, "artist"), _extract(doc, "name"), self)
|
||||||
|
|
||||||
def update_now_playing(self, artist, title, album = None, album_artist = None,
|
def update_now_playing(self, artist, title, album = None, album_artist = None,
|
||||||
duration = None, track_number = None, mbid = None, context = None):
|
duration = None, track_number = None, mbid = None, context = None):
|
||||||
"""
|
"""
|
||||||
Used to notify Last.fm that a user has started listening to a track.
|
Used to notify Last.fm that a user has started listening to a track.
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
artist (Required) : The artist name
|
artist (Required) : The artist name
|
||||||
|
@ -462,7 +462,7 @@ class _Network(object):
|
||||||
|
|
||||||
_Request(self, "track.updateNowPlaying", params).execute()
|
_Request(self, "track.updateNowPlaying", params).execute()
|
||||||
|
|
||||||
def scrobble(self, artist, title, timestamp, album = None, album_artist = None, track_number = None,
|
def scrobble(self, artist, title, timestamp, album = None, album_artist = None, track_number = None,
|
||||||
duration = None, stream_id = None, context = None, mbid = None):
|
duration = None, stream_id = None, context = None, mbid = None):
|
||||||
|
|
||||||
"""Used to add a track-play to a user's profile.
|
"""Used to add a track-play to a user's profile.
|
||||||
|
@ -578,7 +578,7 @@ class LastFMNetwork(_Network):
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "pylast.LastFMNetwork(%s)" %(", ".join(("'%s'" %self.api_key, "'%s'" %self.api_secret, "'%s'" %self.session_key,
|
return "pylast.LastFMNetwork(%s)" %(", ".join(("'%s'" %self.api_key, "'%s'" %self.api_secret, "'%s'" %self.session_key,
|
||||||
"'%s'" %self.username, "'%s'" %self.password_hash)))
|
"'%s'" %self.username, "'%s'" %self.password_hash)))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -661,7 +661,7 @@ class LibreFMNetwork(_Network):
|
||||||
)
|
)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "pylast.LibreFMNetwork(%s)" %(", ".join(("'%s'" %self.api_key, "'%s'" %self.api_secret, "'%s'" %self.session_key,
|
return "pylast.LibreFMNetwork(%s)" %(", ".join(("'%s'" %self.api_key, "'%s'" %self.api_secret, "'%s'" %self.session_key,
|
||||||
"'%s'" %self.username, "'%s'" %self.password_hash)))
|
"'%s'" %self.username, "'%s'" %self.password_hash)))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -788,7 +788,7 @@ class _Request(object):
|
||||||
"Content-type": "application/x-www-form-urlencoded",
|
"Content-type": "application/x-www-form-urlencoded",
|
||||||
'Accept-Charset': 'utf-8',
|
'Accept-Charset': 'utf-8',
|
||||||
'User-Agent': "pylast" + '/' + __version__
|
'User-Agent': "pylast" + '/' + __version__
|
||||||
}
|
}
|
||||||
|
|
||||||
(HOST_NAME, HOST_SUBDIR) = self.network.ws_server
|
(HOST_NAME, HOST_SUBDIR) = self.network.ws_server
|
||||||
|
|
||||||
|
@ -796,7 +796,7 @@ class _Request(object):
|
||||||
conn = HTTPConnection(host = self._get_proxy()[0], port = self._get_proxy()[1])
|
conn = HTTPConnection(host = self._get_proxy()[0], port = self._get_proxy()[1])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
conn.request(method='POST', url="http://" + HOST_NAME + HOST_SUBDIR,
|
conn.request(method='POST', url="http://" + HOST_NAME + HOST_SUBDIR,
|
||||||
body=data, headers=headers)
|
body=data, headers=headers)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise NetworkError(self.network, e)
|
raise NetworkError(self.network, e)
|
||||||
|
@ -864,7 +864,7 @@ class SessionKeyGenerator(object):
|
||||||
manually, unless you want to.
|
manually, unless you want to.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, network):
|
def __init__(self, network):
|
||||||
self.network = network
|
self.network = network
|
||||||
self.web_auth_tokens = {}
|
self.web_auth_tokens = {}
|
||||||
|
|
||||||
|
@ -1272,7 +1272,7 @@ class Album(_BaseObject, _Taggable):
|
||||||
return _extract(self._request("album.getInfo", cacheable = True), "mbid")
|
return _extract(self._request("album.getInfo", cacheable = True), "mbid")
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the album page on the network.
|
"""Returns the url of the album page on the network.
|
||||||
# Parameters:
|
# Parameters:
|
||||||
* domain_name str: The network's language domain. Possible values:
|
* domain_name str: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
|
@ -1537,10 +1537,10 @@ class Artist(_BaseObject, _Taggable):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def share(self, users, message = None):
|
def share(self, users, message = None):
|
||||||
"""Shares this artist (sends out recommendations).
|
"""Shares this artist (sends out recommendations).
|
||||||
# Parameters:
|
# Parameters:
|
||||||
* users [User|str,]: A list that can contain usernames, emails, User objects, or all of them.
|
* users [User|str,]: A list that can contain usernames, emails, User objects, or all of them.
|
||||||
* message str: A message to include in the recommendation message.
|
* message str: A message to include in the recommendation message.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#last.fm currently accepts a max of 10 recipient at a time
|
#last.fm currently accepts a max of 10 recipient at a time
|
||||||
|
@ -1565,7 +1565,7 @@ class Artist(_BaseObject, _Taggable):
|
||||||
self._request('artist.share', False, params)
|
self._request('artist.share', False, params)
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the artist page on the network.
|
"""Returns the url of the artist page on the network.
|
||||||
# Parameters:
|
# Parameters:
|
||||||
* domain_name: The network's language domain. Possible values:
|
* domain_name: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
|
@ -1579,7 +1579,7 @@ class Artist(_BaseObject, _Taggable):
|
||||||
o DOMAIN_TURKISH
|
o DOMAIN_TURKISH
|
||||||
o DOMAIN_RUSSIAN
|
o DOMAIN_RUSSIAN
|
||||||
o DOMAIN_JAPANESE
|
o DOMAIN_JAPANESE
|
||||||
o DOMAIN_CHINESE
|
o DOMAIN_CHINESE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
artist = _url_safe(self.get_name())
|
artist = _url_safe(self.get_name())
|
||||||
|
@ -1675,7 +1675,7 @@ class Event(_BaseObject):
|
||||||
* attending_status: The attending status. Possible values:
|
* attending_status: The attending status. Possible values:
|
||||||
o EVENT_ATTENDING
|
o EVENT_ATTENDING
|
||||||
o EVENT_MAYBE_ATTENDING
|
o EVENT_MAYBE_ATTENDING
|
||||||
o EVENT_NOT_ATTENDING
|
o EVENT_NOT_ATTENDING
|
||||||
"""
|
"""
|
||||||
|
|
||||||
params = self._get_params()
|
params = self._get_params()
|
||||||
|
@ -1735,7 +1735,7 @@ class Event(_BaseObject):
|
||||||
v = doc.getElementsByTagName("venue")[0]
|
v = doc.getElementsByTagName("venue")[0]
|
||||||
venue_id = _number(_extract(v, "id"))
|
venue_id = _number(_extract(v, "id"))
|
||||||
|
|
||||||
return Venue(venue_id, self.network)
|
return Venue(venue_id, self.network, venue_element=v)
|
||||||
|
|
||||||
def get_start_date(self):
|
def get_start_date(self):
|
||||||
"""Returns the date when the event starts."""
|
"""Returns the date when the event starts."""
|
||||||
|
@ -1781,7 +1781,7 @@ class Event(_BaseObject):
|
||||||
return _number(_extract(doc, "reviews"))
|
return _number(_extract(doc, "reviews"))
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the event page on the network.
|
"""Returns the url of the event page on the network.
|
||||||
* domain_name: The network's language domain. Possible values:
|
* domain_name: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
o DOMAIN_GERMAN
|
o DOMAIN_GERMAN
|
||||||
|
@ -1794,15 +1794,15 @@ class Event(_BaseObject):
|
||||||
o DOMAIN_TURKISH
|
o DOMAIN_TURKISH
|
||||||
o DOMAIN_RUSSIAN
|
o DOMAIN_RUSSIAN
|
||||||
o DOMAIN_JAPANESE
|
o DOMAIN_JAPANESE
|
||||||
o DOMAIN_CHINESE
|
o DOMAIN_CHINESE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.network._get_url(domain_name, "event") %{'id': self.get_id()}
|
return self.network._get_url(domain_name, "event") %{'id': self.get_id()}
|
||||||
|
|
||||||
def share(self, users, message = None):
|
def share(self, users, message = None):
|
||||||
"""Shares this event (sends out recommendations).
|
"""Shares this event (sends out recommendations).
|
||||||
* users: A list that can contain usernames, emails, User objects, or all of them.
|
* users: A list that can contain usernames, emails, User objects, or all of them.
|
||||||
* message: A message to include in the recommendation message.
|
* message: A message to include in the recommendation message.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#last.fm currently accepts a max of 10 recipient at a time
|
#last.fm currently accepts a max of 10 recipient at a time
|
||||||
|
@ -1919,7 +1919,7 @@ class Country(_BaseObject):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the event page on the network.
|
"""Returns the url of the event page on the network.
|
||||||
* domain_name: The network's language domain. Possible values:
|
* domain_name: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
o DOMAIN_GERMAN
|
o DOMAIN_GERMAN
|
||||||
|
@ -1932,7 +1932,7 @@ class Country(_BaseObject):
|
||||||
o DOMAIN_TURKISH
|
o DOMAIN_TURKISH
|
||||||
o DOMAIN_RUSSIAN
|
o DOMAIN_RUSSIAN
|
||||||
o DOMAIN_JAPANESE
|
o DOMAIN_JAPANESE
|
||||||
o DOMAIN_CHINESE
|
o DOMAIN_CHINESE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
country_name = _url_safe(self.get_name())
|
country_name = _url_safe(self.get_name())
|
||||||
|
@ -2173,7 +2173,7 @@ class Playlist(_BaseObject):
|
||||||
return _extract(self._get_info_node(), "image")[size]
|
return _extract(self._get_info_node(), "image")[size]
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the playlist on the network.
|
"""Returns the url of the playlist on the network.
|
||||||
* domain_name: The network's language domain. Possible values:
|
* domain_name: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
o DOMAIN_GERMAN
|
o DOMAIN_GERMAN
|
||||||
|
@ -2186,7 +2186,7 @@ class Playlist(_BaseObject):
|
||||||
o DOMAIN_TURKISH
|
o DOMAIN_TURKISH
|
||||||
o DOMAIN_RUSSIAN
|
o DOMAIN_RUSSIAN
|
||||||
o DOMAIN_JAPANESE
|
o DOMAIN_JAPANESE
|
||||||
o DOMAIN_CHINESE
|
o DOMAIN_CHINESE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
english_url = _extract(self._get_info_node(), "url")
|
english_url = _extract(self._get_info_node(), "url")
|
||||||
|
@ -2319,7 +2319,7 @@ class Tag(_BaseObject):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the tag page on the network.
|
"""Returns the url of the tag page on the network.
|
||||||
* domain_name: The network's language domain. Possible values:
|
* domain_name: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
o DOMAIN_GERMAN
|
o DOMAIN_GERMAN
|
||||||
|
@ -2332,7 +2332,7 @@ class Tag(_BaseObject):
|
||||||
o DOMAIN_TURKISH
|
o DOMAIN_TURKISH
|
||||||
o DOMAIN_RUSSIAN
|
o DOMAIN_RUSSIAN
|
||||||
o DOMAIN_JAPANESE
|
o DOMAIN_JAPANESE
|
||||||
o DOMAIN_CHINESE
|
o DOMAIN_CHINESE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = _url_safe(self.get_name())
|
name = _url_safe(self.get_name())
|
||||||
|
@ -2548,9 +2548,9 @@ class Track(_BaseObject, _Taggable):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def share(self, users, message = None):
|
def share(self, users, message = None):
|
||||||
"""Shares this track (sends out recommendations).
|
"""Shares this track (sends out recommendations).
|
||||||
* users: A list that can contain usernames, emails, User objects, or all of them.
|
* users: A list that can contain usernames, emails, User objects, or all of them.
|
||||||
* message: A message to include in the recommendation message.
|
* message: A message to include in the recommendation message.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#last.fm currently accepts a max of 10 recipient at a time
|
#last.fm currently accepts a max of 10 recipient at a time
|
||||||
|
@ -2575,7 +2575,7 @@ class Track(_BaseObject, _Taggable):
|
||||||
self._request('track.share', False, params)
|
self._request('track.share', False, params)
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the track page on the network.
|
"""Returns the url of the track page on the network.
|
||||||
* domain_name: The network's language domain. Possible values:
|
* domain_name: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
o DOMAIN_GERMAN
|
o DOMAIN_GERMAN
|
||||||
|
@ -2588,7 +2588,7 @@ class Track(_BaseObject, _Taggable):
|
||||||
o DOMAIN_TURKISH
|
o DOMAIN_TURKISH
|
||||||
o DOMAIN_RUSSIAN
|
o DOMAIN_RUSSIAN
|
||||||
o DOMAIN_JAPANESE
|
o DOMAIN_JAPANESE
|
||||||
o DOMAIN_CHINESE
|
o DOMAIN_CHINESE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
artist = _url_safe(self.get_artist().get_name())
|
artist = _url_safe(self.get_artist().get_name())
|
||||||
|
@ -2707,7 +2707,7 @@ class Group(_BaseObject):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the group page on the network.
|
"""Returns the url of the group page on the network.
|
||||||
* domain_name: The network's language domain. Possible values:
|
* domain_name: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
o DOMAIN_GERMAN
|
o DOMAIN_GERMAN
|
||||||
|
@ -2720,7 +2720,7 @@ class Group(_BaseObject):
|
||||||
o DOMAIN_TURKISH
|
o DOMAIN_TURKISH
|
||||||
o DOMAIN_RUSSIAN
|
o DOMAIN_RUSSIAN
|
||||||
o DOMAIN_JAPANESE
|
o DOMAIN_JAPANESE
|
||||||
o DOMAIN_CHINESE
|
o DOMAIN_CHINESE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = _url_safe(self.get_name())
|
name = _url_safe(self.get_name())
|
||||||
|
@ -2832,13 +2832,13 @@ class User(_BaseObject):
|
||||||
|
|
||||||
for e_id in ids:
|
for e_id in ids:
|
||||||
events.append(Event(e_id, self.network))
|
events.append(Event(e_id, self.network))
|
||||||
|
|
||||||
return events
|
return events
|
||||||
|
|
||||||
def get_artist_tracks(self, artist):
|
def get_artist_tracks(self, artist):
|
||||||
"""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."
|
||||||
|
|
||||||
params = self._get_params()
|
params = self._get_params()
|
||||||
params['artist'] = artist
|
params['artist'] = artist
|
||||||
|
|
||||||
|
@ -2848,14 +2848,14 @@ class User(_BaseObject):
|
||||||
artist = _extract(track, "artist")
|
artist = _extract(track, "artist")
|
||||||
date = _extract(track, "date")
|
date = _extract(track, "date")
|
||||||
timestamp = track.getElementsByTagName("date")[0].getAttribute("uts")
|
timestamp = track.getElementsByTagName("date")[0].getAttribute("uts")
|
||||||
|
|
||||||
seq.append(PlayedTrack(Track(artist, title, self.network), date, timestamp))
|
seq.append(PlayedTrack(Track(artist, title, self.network), date, timestamp))
|
||||||
|
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def get_friends(self, limit = 50):
|
def get_friends(self, limit = 50):
|
||||||
"""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", False):
|
||||||
seq.append(User(_extract(node, "name"), self.network))
|
seq.append(User(_extract(node, "name"), self.network))
|
||||||
|
@ -3037,13 +3037,13 @@ class User(_BaseObject):
|
||||||
return _number(_extract(doc, "playcount"))
|
return _number(_extract(doc, "playcount"))
|
||||||
|
|
||||||
def get_top_albums(self, period = PERIOD_OVERALL):
|
def get_top_albums(self, period = PERIOD_OVERALL):
|
||||||
"""Returns the top albums played by a user.
|
"""Returns the top albums played by a user.
|
||||||
* period: The period of time. Possible values:
|
* period: The period of time. Possible values:
|
||||||
o PERIOD_OVERALL
|
o PERIOD_OVERALL
|
||||||
o PERIOD_7DAYS
|
o PERIOD_7DAYS
|
||||||
o PERIOD_3MONTHS
|
o PERIOD_3MONTHS
|
||||||
o PERIOD_6MONTHS
|
o PERIOD_6MONTHS
|
||||||
o PERIOD_12MONTHS
|
o PERIOD_12MONTHS
|
||||||
"""
|
"""
|
||||||
|
|
||||||
params = self._get_params()
|
params = self._get_params()
|
||||||
|
@ -3062,13 +3062,13 @@ class User(_BaseObject):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def get_top_artists(self, period = PERIOD_OVERALL):
|
def get_top_artists(self, period = PERIOD_OVERALL):
|
||||||
"""Returns the top artists played by a user.
|
"""Returns the top artists played by a user.
|
||||||
* period: The period of time. Possible values:
|
* period: The period of time. Possible values:
|
||||||
o PERIOD_OVERALL
|
o PERIOD_OVERALL
|
||||||
o PERIOD_7DAYS
|
o PERIOD_7DAYS
|
||||||
o PERIOD_3MONTHS
|
o PERIOD_3MONTHS
|
||||||
o PERIOD_6MONTHS
|
o PERIOD_6MONTHS
|
||||||
o PERIOD_12MONTHS
|
o PERIOD_12MONTHS
|
||||||
"""
|
"""
|
||||||
|
|
||||||
params = self._get_params()
|
params = self._get_params()
|
||||||
|
@ -3086,8 +3086,8 @@ class User(_BaseObject):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def get_top_tags(self, limit=None):
|
def get_top_tags(self, limit=None):
|
||||||
"""Returns a sequence of the top tags used by this user with their counts as TopItem objects.
|
"""Returns a sequence of the top tags used by this user with their counts as TopItem objects.
|
||||||
* limit: The limit of how many tags to return.
|
* limit: The limit of how many tags to return.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
doc = self._request("user.getTopTags", True)
|
doc = self._request("user.getTopTags", True)
|
||||||
|
@ -3102,13 +3102,13 @@ class User(_BaseObject):
|
||||||
return seq
|
return seq
|
||||||
|
|
||||||
def get_top_tracks(self, period = PERIOD_OVERALL):
|
def get_top_tracks(self, period = PERIOD_OVERALL):
|
||||||
"""Returns the top tracks played by a user.
|
"""Returns the top tracks played by a user.
|
||||||
* period: The period of time. Possible values:
|
* period: The period of time. Possible values:
|
||||||
o PERIOD_OVERALL
|
o PERIOD_OVERALL
|
||||||
o PERIOD_7DAYS
|
o PERIOD_7DAYS
|
||||||
o PERIOD_3MONTHS
|
o PERIOD_3MONTHS
|
||||||
o PERIOD_6MONTHS
|
o PERIOD_6MONTHS
|
||||||
o PERIOD_12MONTHS
|
o PERIOD_12MONTHS
|
||||||
"""
|
"""
|
||||||
|
|
||||||
params = self._get_params()
|
params = self._get_params()
|
||||||
|
@ -3230,7 +3230,7 @@ class User(_BaseObject):
|
||||||
return _extract(doc, "image")
|
return _extract(doc, "image")
|
||||||
|
|
||||||
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
def get_url(self, domain_name = DOMAIN_ENGLISH):
|
||||||
"""Returns the url of the user page on the network.
|
"""Returns the url of the user page on the network.
|
||||||
* domain_name: The network's language domain. Possible values:
|
* domain_name: The network's language domain. Possible values:
|
||||||
o DOMAIN_ENGLISH
|
o DOMAIN_ENGLISH
|
||||||
o DOMAIN_GERMAN
|
o DOMAIN_GERMAN
|
||||||
|
@ -3243,7 +3243,7 @@ class User(_BaseObject):
|
||||||
o DOMAIN_TURKISH
|
o DOMAIN_TURKISH
|
||||||
o DOMAIN_RUSSIAN
|
o DOMAIN_RUSSIAN
|
||||||
o DOMAIN_JAPANESE
|
o DOMAIN_JAPANESE
|
||||||
o DOMAIN_CHINESE
|
o DOMAIN_CHINESE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = _url_safe(self.get_name())
|
name = _url_safe(self.get_name())
|
||||||
|
@ -3459,13 +3459,25 @@ class Venue(_BaseObject):
|
||||||
"""A venue where events are held."""
|
"""A venue where events are held."""
|
||||||
|
|
||||||
# TODO: waiting for a venue.getInfo web service to use.
|
# TODO: waiting for a venue.getInfo web service to use.
|
||||||
|
# TODO: As an intermediate use case, can pass the venue DOM element when using
|
||||||
|
# Event.get_venue() to populate the venue info, if the venue.getInfo API
|
||||||
|
# call becomes available this workaround should be removed
|
||||||
|
|
||||||
id = None
|
id = None
|
||||||
|
info = None
|
||||||
|
name = None
|
||||||
|
location = None
|
||||||
|
url = None
|
||||||
|
|
||||||
def __init__(self, id, network):
|
def __init__(self, id, network, venue_element=None):
|
||||||
_BaseObject.__init__(self, network)
|
_BaseObject.__init__(self, network)
|
||||||
|
|
||||||
self.id = _number(id)
|
self.id = _number(id)
|
||||||
|
if venue_element is not None:
|
||||||
|
self.info = _extract_element_tree(venue_element)
|
||||||
|
self.name = self.info.get('name')
|
||||||
|
self.url = self.info.get('url')
|
||||||
|
self.location = self.info.get('location')
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "pylast.Venue(%s, %s)" %(repr(self.id), repr(self.network))
|
return "pylast.Venue(%s, %s)" %(repr(self.id), repr(self.network))
|
||||||
|
@ -3485,6 +3497,21 @@ class Venue(_BaseObject):
|
||||||
|
|
||||||
return self.id
|
return self.id
|
||||||
|
|
||||||
|
def get_name(self):
|
||||||
|
"""Returns the name of the venue."""
|
||||||
|
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_url(self):
|
||||||
|
"""Returns the URL of the venue page."""
|
||||||
|
|
||||||
|
return self.url
|
||||||
|
|
||||||
|
def get_location(self):
|
||||||
|
"""Returns the location of the venue (dictionary)."""
|
||||||
|
|
||||||
|
return self.location
|
||||||
|
|
||||||
def get_upcoming_events(self):
|
def get_upcoming_events(self):
|
||||||
"""Returns the upcoming events in this venue."""
|
"""Returns the upcoming events in this venue."""
|
||||||
|
|
||||||
|
@ -3575,14 +3602,14 @@ def _collect_nodes(limit, sender, method_name, cacheable, params=None):
|
||||||
total_pages = _number(main.getAttribute("totalpages"))
|
total_pages = _number(main.getAttribute("totalpages"))
|
||||||
else:
|
else:
|
||||||
raise Exception("No total pages attribute")
|
raise Exception("No total pages attribute")
|
||||||
|
|
||||||
for node in main.childNodes:
|
for node in main.childNodes:
|
||||||
if not node.nodeType == xml.dom.Node.TEXT_NODE and (not limit or (len(nodes) < limit)):
|
if not node.nodeType == xml.dom.Node.TEXT_NODE and (not limit or (len(nodes) < limit)):
|
||||||
nodes.append(node)
|
nodes.append(node)
|
||||||
|
|
||||||
if page >= total_pages:
|
if page >= total_pages:
|
||||||
end_of_pages = True
|
end_of_pages = True
|
||||||
|
|
||||||
page += 1
|
page += 1
|
||||||
|
|
||||||
return nodes
|
return nodes
|
||||||
|
@ -3598,6 +3625,35 @@ def _extract(node, name, index = 0):
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def _extract_element_tree(node, index = 0):
|
||||||
|
"""Extract an element tree into a multi-level dictionary
|
||||||
|
|
||||||
|
NB: If any elements have text nodes as well as nested
|
||||||
|
elements this will ignore the text nodes"""
|
||||||
|
|
||||||
|
def _recurse_build_tree(rootNode, targetDict):
|
||||||
|
"""Recursively build a multi-level dict"""
|
||||||
|
|
||||||
|
def _has_child_elements(rootNode):
|
||||||
|
"""Check if an element has any nested (child) elements"""
|
||||||
|
|
||||||
|
for node in rootNode.childNodes:
|
||||||
|
if node.nodeType == node.ELEMENT_NODE:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
for node in rootNode.childNodes:
|
||||||
|
if node.nodeType == node.ELEMENT_NODE:
|
||||||
|
if _has_child_elements(node):
|
||||||
|
targetDict[node.tagName] = {}
|
||||||
|
_recurse_build_tree(node, targetDict[node.tagName])
|
||||||
|
else:
|
||||||
|
targetDict[node.tagName] = _unescape_htmlentity(node.firstChild.data.strip())
|
||||||
|
|
||||||
|
return targetDict
|
||||||
|
|
||||||
|
return _recurse_build_tree(node, {})
|
||||||
|
|
||||||
def _extract_all(node, name, limit_count = None):
|
def _extract_all(node, name, limit_count = None):
|
||||||
"""Extracts all the values from the xml string. returning a list."""
|
"""Extracts all the values from the xml string. returning a list."""
|
||||||
|
|
||||||
|
@ -3633,7 +3689,7 @@ def _number(string):
|
||||||
|
|
||||||
def _unescape_htmlentity(string):
|
def _unescape_htmlentity(string):
|
||||||
|
|
||||||
#string = _unicode(string)
|
#string = _unicode(string)
|
||||||
|
|
||||||
mapping = htmlentitydefs.name2codepoint
|
mapping = htmlentitydefs.name2codepoint
|
||||||
for key in mapping:
|
for key in mapping:
|
||||||
|
|
Loading…
Reference in a new issue