implemented new methods and check for authenticated method calls.
parent
2565dbb9a1
commit
55680ba9c8
|
@ -96,9 +96,7 @@ class Album(LastfmBase, Cacheable, Searchable, Taggable):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def streamable(self):
|
def streamable(self):
|
||||||
"""is the artist streamable"""
|
"""is the album streamable"""
|
||||||
if self._streamable is None:
|
|
||||||
self._fill_info()
|
|
||||||
return self._streamable
|
return self._streamable
|
||||||
|
|
||||||
@LastfmBase.cached_property
|
@LastfmBase.cached_property
|
||||||
|
|
|
@ -245,14 +245,14 @@ class Api(object):
|
||||||
return urllib.urlencode([(k, self._encode(parameters[k])) for k in keys if parameters[k] is not None])
|
return urllib.urlencode([(k, self._encode(parameters[k])) for k in keys if parameters[k] is not None])
|
||||||
|
|
||||||
def _read_url_data(self, opener, url, data = None):
|
def _read_url_data(self, opener, url, data = None):
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
delta = now - self._last_fetch_time
|
delta = now - self._last_fetch_time
|
||||||
delta = delta.seconds + float(delta.microseconds)/1000000
|
delta = delta.seconds + float(delta.microseconds)/1000000
|
||||||
if delta < Api.FETCH_INTERVAL:
|
if delta < Api.FETCH_INTERVAL:
|
||||||
time.sleep(Api.FETCH_INTERVAL - delta)
|
time.sleep(Api.FETCH_INTERVAL - delta)
|
||||||
url_data = opener.open(url, data).read()
|
url_data = opener.open(url, data).read()
|
||||||
self._last_fetch_time = datetime.now()
|
self._last_fetch_time = datetime.now()
|
||||||
return url_data
|
return url_data
|
||||||
|
|
||||||
def _fetch_url(self,
|
def _fetch_url(self,
|
||||||
url,
|
url,
|
||||||
|
@ -307,6 +307,7 @@ class Api(object):
|
||||||
sign = False,
|
sign = False,
|
||||||
session = False,
|
session = False,
|
||||||
no_cache = False):
|
no_cache = False):
|
||||||
|
params = params.copy()
|
||||||
params['api_key'] = self.api_key
|
params['api_key'] = self.api_key
|
||||||
|
|
||||||
if session:
|
if session:
|
||||||
|
@ -325,9 +326,9 @@ class Api(object):
|
||||||
url,
|
url,
|
||||||
parameters):
|
parameters):
|
||||||
url = self._build_url(url)
|
url = self._build_url(url)
|
||||||
if self._debug:
|
|
||||||
print url
|
|
||||||
data = self._encode_parameters(parameters)
|
data = self._encode_parameters(parameters)
|
||||||
|
if self._debug:
|
||||||
|
print data
|
||||||
opener = self._get_opener(url)
|
opener = self._get_opener(url)
|
||||||
url_data = self._read_url_data(opener, url, data)
|
url_data = self._read_url_data(opener, url, data)
|
||||||
return url_data
|
return url_data
|
||||||
|
@ -350,6 +351,7 @@ class Api(object):
|
||||||
keys.sort()
|
keys.sort()
|
||||||
sig = unicode()
|
sig = unicode()
|
||||||
for name in keys:
|
for name in keys:
|
||||||
|
if name == 'api_sig': continue
|
||||||
sig += ("%s%s" % (name, params[name]))
|
sig += ("%s%s" % (name, params[name]))
|
||||||
sig += self.secret
|
sig += self.secret
|
||||||
hashed_sig = md5.new(sig).hexdigest()
|
hashed_sig = md5.new(sig).hexdigest()
|
||||||
|
|
|
@ -37,6 +37,7 @@ class Artist(LastfmBase, Cacheable, Sharable, Shoutable, Searchable, Taggable):
|
||||||
subject = self,
|
subject = self,
|
||||||
listeners = stats.listeners,
|
listeners = stats.listeners,
|
||||||
playcount = stats.playcount,
|
playcount = stats.playcount,
|
||||||
|
weight = stats.weight,
|
||||||
match = stats.match,
|
match = stats.match,
|
||||||
rank = stats.rank
|
rank = stats.rank
|
||||||
)
|
)
|
||||||
|
|
|
@ -33,6 +33,24 @@ class LastfmBase(object):
|
||||||
return cache_attribute
|
return cache_attribute
|
||||||
|
|
||||||
return property(fget = wrapper, doc = func.__doc__)
|
return property(fget = wrapper, doc = func.__doc__)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def autheticate(func):
|
||||||
|
def wrapper(self, *args, **kwargs):
|
||||||
|
from lastfm.user import User
|
||||||
|
user = None
|
||||||
|
if isinstance(self, User):
|
||||||
|
user = self.name
|
||||||
|
if self.autheticated:
|
||||||
|
return func(self, *args, **kwargs)
|
||||||
|
elif hasattr(self, 'user'):
|
||||||
|
user = self.user.name
|
||||||
|
if self.user.autheticated:
|
||||||
|
return func(self, *args, **kwargs)
|
||||||
|
|
||||||
|
raise AuthenticationFailedError(
|
||||||
|
"user '%s' does not have permissions to access the service" % user)
|
||||||
|
return wrapper
|
||||||
|
|
||||||
def __gt__(self, other):
|
def __gt__(self, other):
|
||||||
return not (self.__lt__(other) or self.__eq(other))
|
return not (self.__lt__(other) or self.__eq(other))
|
||||||
|
@ -47,4 +65,4 @@ class LastfmBase(object):
|
||||||
return not self.__gt__(other)
|
return not self.__gt__(other)
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
from lastfm.error import LastfmError
|
from lastfm.error import LastfmError, AuthenticationFailedError
|
|
@ -57,6 +57,9 @@ class ServiceOfflineError(LastfmError):#11
|
||||||
class SubscribersOnlyError(LastfmError):#12
|
class SubscribersOnlyError(LastfmError):#12
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class InvalidMethodSignatureError(LastfmError):#13
|
||||||
|
pass
|
||||||
|
|
||||||
class TokenNotAuthorizedError(LastfmError):#14
|
class TokenNotAuthorizedError(LastfmError):#14
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -76,6 +79,7 @@ error_map = {
|
||||||
10: InvalidApiKeyError,
|
10: InvalidApiKeyError,
|
||||||
11: ServiceOfflineError,
|
11: ServiceOfflineError,
|
||||||
12: SubscribersOnlyError,
|
12: SubscribersOnlyError,
|
||||||
|
13: InvalidMethodSignatureError,
|
||||||
14: TokenNotAuthorizedError,
|
14: TokenNotAuthorizedError,
|
||||||
15: TokenExpiredError
|
15: TokenExpiredError
|
||||||
}
|
}
|
247
lastfm/geo.py
247
lastfm/geo.py
|
@ -257,6 +257,253 @@ class Location(LastfmBase, Cacheable):
|
||||||
|
|
||||||
class Country(LastfmBase, Cacheable):
|
class Country(LastfmBase, Cacheable):
|
||||||
"""A class representing a country."""
|
"""A class representing a country."""
|
||||||
|
ISO_CODES = {
|
||||||
|
'AD': 'Andorra',
|
||||||
|
'AE': 'United Arab Emirates',
|
||||||
|
'AF': 'Afghanistan',
|
||||||
|
'AG': 'Antigua and Barbuda',
|
||||||
|
'AI': 'Anguilla',
|
||||||
|
'AL': 'Albania',
|
||||||
|
'AM': 'Armenia',
|
||||||
|
'AN': 'Netherlands Antilles',
|
||||||
|
'AO': 'Angola',
|
||||||
|
'AQ': 'Antarctica',
|
||||||
|
'AR': 'Argentina',
|
||||||
|
'AS': 'American Samoa',
|
||||||
|
'AT': 'Austria',
|
||||||
|
'AU': 'Australia',
|
||||||
|
'AW': 'Aruba',
|
||||||
|
'AX': 'land Islands',
|
||||||
|
'AZ': 'Azerbaijan',
|
||||||
|
'BA': 'Bosnia and Herzegovina',
|
||||||
|
'BB': 'Barbados',
|
||||||
|
'BD': 'Bangladesh',
|
||||||
|
'BE': 'Belgium',
|
||||||
|
'BF': 'Burkina Faso',
|
||||||
|
'BG': 'Bulgaria',
|
||||||
|
'BH': 'Bahrain',
|
||||||
|
'BI': 'Burundi',
|
||||||
|
'BJ': 'Benin',
|
||||||
|
'BL': 'Saint Barthlemy',
|
||||||
|
'BM': 'Bermuda',
|
||||||
|
'BN': 'Brunei Darussalam',
|
||||||
|
'BO': 'Bolivia',
|
||||||
|
'BR': 'Brazil',
|
||||||
|
'BS': 'Bahamas',
|
||||||
|
'BT': 'Bhutan',
|
||||||
|
'BV': 'Bouvet Island',
|
||||||
|
'BW': 'Botswana',
|
||||||
|
'BY': 'Belarus',
|
||||||
|
'BZ': 'Belize',
|
||||||
|
'CA': 'Canada',
|
||||||
|
'CC': 'Cocos (Keeling) Islands',
|
||||||
|
'CD': 'Congo, The Democratic Republic of the',
|
||||||
|
'CF': 'Central African Republic',
|
||||||
|
'CG': 'Congo',
|
||||||
|
'CH': 'Switzerland',
|
||||||
|
'CI': "Cte d'Ivoire",
|
||||||
|
'CK': 'Cook Islands',
|
||||||
|
'CL': 'Chile',
|
||||||
|
'CM': 'Cameroon',
|
||||||
|
'CN': 'China',
|
||||||
|
'CO': 'Colombia',
|
||||||
|
'CR': 'Costa Rica',
|
||||||
|
'CU': 'Cuba',
|
||||||
|
'CV': 'Cape Verde',
|
||||||
|
'CX': 'Christmas Island',
|
||||||
|
'CY': 'Cyprus',
|
||||||
|
'CZ': 'Czech Republic',
|
||||||
|
'DE': 'Germany',
|
||||||
|
'DJ': 'Djibouti',
|
||||||
|
'DK': 'Denmark',
|
||||||
|
'DM': 'Dominica',
|
||||||
|
'DO': 'Dominican Republic',
|
||||||
|
'DZ': 'Algeria',
|
||||||
|
'EC': 'Ecuador',
|
||||||
|
'EE': 'Estonia',
|
||||||
|
'EG': 'Egypt',
|
||||||
|
'EH': 'Western Sahara',
|
||||||
|
'ER': 'Eritrea',
|
||||||
|
'ES': 'Spain',
|
||||||
|
'ET': 'Ethiopia',
|
||||||
|
'FI': 'Finland',
|
||||||
|
'FJ': 'Fiji',
|
||||||
|
'FK': 'Falkland Islands (Malvinas)',
|
||||||
|
'FM': 'Micronesia, Federated States of',
|
||||||
|
'FO': 'Faroe Islands',
|
||||||
|
'FR': 'France',
|
||||||
|
'GA': 'Gabon',
|
||||||
|
'GB': 'United Kingdom',
|
||||||
|
'GD': 'Grenada',
|
||||||
|
'GE': 'Georgia',
|
||||||
|
'GF': 'French Guiana',
|
||||||
|
'GG': 'Guernsey',
|
||||||
|
'GH': 'Ghana',
|
||||||
|
'GI': 'Gibraltar',
|
||||||
|
'GL': 'Greenland',
|
||||||
|
'GM': 'Gambia',
|
||||||
|
'GN': 'Guinea',
|
||||||
|
'GP': 'Guadeloupe',
|
||||||
|
'GQ': 'Equatorial Guinea',
|
||||||
|
'GR': 'Greece',
|
||||||
|
'GS': 'South Georgia and the South Sandwich Islands',
|
||||||
|
'GT': 'Guatemala',
|
||||||
|
'GU': 'Guam',
|
||||||
|
'GW': 'Guinea-Bissau',
|
||||||
|
'GY': 'Guyana',
|
||||||
|
'HK': 'Hong Kong',
|
||||||
|
'HM': 'Heard Island and McDonald Islands',
|
||||||
|
'HN': 'Honduras',
|
||||||
|
'HR': 'Croatia',
|
||||||
|
'HT': 'Haiti',
|
||||||
|
'HU': 'Hungary',
|
||||||
|
'ID': 'Indonesia',
|
||||||
|
'IE': 'Ireland',
|
||||||
|
'IL': 'Israel',
|
||||||
|
'IM': 'Isle of Man',
|
||||||
|
'IN': 'India',
|
||||||
|
'IO': 'British Indian Ocean Territory',
|
||||||
|
'IQ': 'Iraq',
|
||||||
|
'IR': 'Iran, Islamic Republic of',
|
||||||
|
'IS': 'Iceland',
|
||||||
|
'IT': 'Italy',
|
||||||
|
'JE': 'Jersey',
|
||||||
|
'JM': 'Jamaica',
|
||||||
|
'JO': 'Jordan',
|
||||||
|
'JP': 'Japan',
|
||||||
|
'KE': 'Kenya',
|
||||||
|
'KG': 'Kyrgyzstan',
|
||||||
|
'KH': 'Cambodia',
|
||||||
|
'KI': 'Kiribati',
|
||||||
|
'KM': 'Comoros',
|
||||||
|
'KN': 'Saint Kitts and Nevis',
|
||||||
|
'KP': "Korea, Democratic People's Republic of",
|
||||||
|
'KR': 'Korea, Republic of',
|
||||||
|
'KW': 'Kuwait',
|
||||||
|
'KY': 'Cayman Islands',
|
||||||
|
'KZ': 'Kazakhstan',
|
||||||
|
'LA': "Lao People's Democratic Republic",
|
||||||
|
'LB': 'Lebanon',
|
||||||
|
'LC': 'Saint Lucia',
|
||||||
|
'LI': 'Liechtenstein',
|
||||||
|
'LK': 'Sri Lanka',
|
||||||
|
'LR': 'Liberia',
|
||||||
|
'LS': 'Lesotho',
|
||||||
|
'LT': 'Lithuania',
|
||||||
|
'LU': 'Luxembourg',
|
||||||
|
'LV': 'Latvia',
|
||||||
|
'LY': 'Libyan Arab Jamahiriya',
|
||||||
|
'MA': 'Morocco',
|
||||||
|
'MC': 'Monaco',
|
||||||
|
'MD': 'Moldova',
|
||||||
|
'ME': 'Montenegro',
|
||||||
|
'MF': 'Saint Martin',
|
||||||
|
'MG': 'Madagascar',
|
||||||
|
'MH': 'Marshall Islands',
|
||||||
|
'MK': 'Macedonia, The Former Yugoslav Republic of',
|
||||||
|
'ML': 'Mali',
|
||||||
|
'MM': 'Myanmar',
|
||||||
|
'MN': 'Mongolia',
|
||||||
|
'MO': 'Macao',
|
||||||
|
'MP': 'Northern Mariana Islands',
|
||||||
|
'MQ': 'Martinique',
|
||||||
|
'MR': 'Mauritania',
|
||||||
|
'MS': 'Montserrat',
|
||||||
|
'MT': 'Malta',
|
||||||
|
'MU': 'Mauritius',
|
||||||
|
'MV': 'Maldives',
|
||||||
|
'MW': 'Malawi',
|
||||||
|
'MX': 'Mexico',
|
||||||
|
'MY': 'Malaysia',
|
||||||
|
'MZ': 'Mozambique',
|
||||||
|
'NA': 'Namibia',
|
||||||
|
'NC': 'New Caledonia',
|
||||||
|
'NE': 'Niger',
|
||||||
|
'NF': 'Norfolk Island',
|
||||||
|
'NG': 'Nigeria',
|
||||||
|
'NI': 'Nicaragua',
|
||||||
|
'NL': 'Netherlands',
|
||||||
|
'NO': 'Norway',
|
||||||
|
'NP': 'Nepal',
|
||||||
|
'NR': 'Nauru',
|
||||||
|
'NU': 'Niue',
|
||||||
|
'NZ': 'New Zealand',
|
||||||
|
'OM': 'Oman',
|
||||||
|
'PA': 'Panama',
|
||||||
|
'PE': 'Peru',
|
||||||
|
'PF': 'French Polynesia',
|
||||||
|
'PG': 'Papua New Guinea',
|
||||||
|
'PH': 'Philippines',
|
||||||
|
'PK': 'Pakistan',
|
||||||
|
'PL': 'Poland',
|
||||||
|
'PM': 'Saint Pierre and Miquelon',
|
||||||
|
'PN': 'Pitcairn',
|
||||||
|
'PR': 'Puerto Rico',
|
||||||
|
'PS': 'Palestinian Territory, Occupied',
|
||||||
|
'PT': 'Portugal',
|
||||||
|
'PW': 'Palau',
|
||||||
|
'PY': 'Paraguay',
|
||||||
|
'QA': 'Qatar',
|
||||||
|
'RE': 'Runion',
|
||||||
|
'RO': 'Romania',
|
||||||
|
'RS': 'Serbia',
|
||||||
|
'RU': 'Russian Federation',
|
||||||
|
'RW': 'Rwanda',
|
||||||
|
'SA': 'Saudi Arabia',
|
||||||
|
'SB': 'Solomon Islands',
|
||||||
|
'SC': 'Seychelles',
|
||||||
|
'SD': 'Sudan',
|
||||||
|
'SE': 'Sweden',
|
||||||
|
'SG': 'Singapore',
|
||||||
|
'SH': 'Saint Helena',
|
||||||
|
'SI': 'Slovenia',
|
||||||
|
'SJ': 'Svalbard and Jan Mayen',
|
||||||
|
'SK': 'Slovakia',
|
||||||
|
'SL': 'Sierra Leone',
|
||||||
|
'SM': 'San Marino',
|
||||||
|
'SN': 'Senegal',
|
||||||
|
'SO': 'Somalia',
|
||||||
|
'SR': 'Suriname',
|
||||||
|
'ST': 'Sao Tome and Principe',
|
||||||
|
'SV': 'El Salvador',
|
||||||
|
'SY': 'Syrian Arab Republic',
|
||||||
|
'SZ': 'Swaziland',
|
||||||
|
'TC': 'Turks and Caicos Islands',
|
||||||
|
'TD': 'Chad',
|
||||||
|
'TF': 'French Southern Territories',
|
||||||
|
'TG': 'Togo',
|
||||||
|
'TH': 'Thailand',
|
||||||
|
'TJ': 'Tajikistan',
|
||||||
|
'TK': 'Tokelau',
|
||||||
|
'TL': 'Timor-Leste',
|
||||||
|
'TM': 'Turkmenistan',
|
||||||
|
'TN': 'Tunisia',
|
||||||
|
'TO': 'Tonga',
|
||||||
|
'TR': 'Turkey',
|
||||||
|
'TT': 'Trinidad and Tobago',
|
||||||
|
'TV': 'Tuvalu',
|
||||||
|
'TW': 'Taiwan, Province of China',
|
||||||
|
'TZ': 'Tanzania, United Republic of',
|
||||||
|
'UA': 'Ukraine',
|
||||||
|
'UG': 'Uganda',
|
||||||
|
'UM': 'United States Minor Outlying Islands',
|
||||||
|
'US': 'United States',
|
||||||
|
'UY': 'Uruguay',
|
||||||
|
'UZ': 'Uzbekistan',
|
||||||
|
'VA': 'Holy See (Vatican City State)',
|
||||||
|
'VC': 'Saint Vincent and the Grenadines',
|
||||||
|
'VE': 'Venezuela',
|
||||||
|
'VG': 'Virgin Islands, British',
|
||||||
|
'VI': 'Virgin Islands, U.S.',
|
||||||
|
'VN': 'Viet Nam',
|
||||||
|
'VU': 'Vanuatu',
|
||||||
|
'WF': 'Wallis and Futuna',
|
||||||
|
'WS': 'Samoa',
|
||||||
|
'YE': 'Yemen',
|
||||||
|
'YT': 'Mayotte',
|
||||||
|
'ZA': 'South Africa',
|
||||||
|
'ZM': 'Zambia',
|
||||||
|
'ZW': 'Zimbabwe'}
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
name = None):
|
name = None):
|
||||||
|
|
|
@ -97,6 +97,36 @@ class Group(LastfmBase, Cacheable):
|
||||||
yield self.get_weekly_track_chart(wc.start, wc.end)
|
yield self.get_weekly_track_chart(wc.start, wc.end)
|
||||||
return gen()
|
return gen()
|
||||||
|
|
||||||
|
@LastfmBase.cached_property
|
||||||
|
def members(self):
|
||||||
|
params = self._default_params({'method': 'group.getMembers'})
|
||||||
|
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
data = self._api._fetch_data(params).find('members')
|
||||||
|
total_pages = int(data.attrib['totalPages'])
|
||||||
|
|
||||||
|
@lazylist
|
||||||
|
def gen2(lst, data):
|
||||||
|
for u in data.findall('user'):
|
||||||
|
yield User(
|
||||||
|
self._api,
|
||||||
|
name = u.findtext('name'),
|
||||||
|
real_name = u.findtext('realname'),
|
||||||
|
image = dict([(i.get('size'), i.text) for i in u.findall('image')]),
|
||||||
|
url = u.findtext('url')
|
||||||
|
)
|
||||||
|
|
||||||
|
for u in gen2(data):
|
||||||
|
yield u
|
||||||
|
|
||||||
|
for page in xrange(1, total_pages+1):
|
||||||
|
params.update({'page': page})
|
||||||
|
data = self._api._fetch_data(params).find('members')
|
||||||
|
for u in gen2(data):
|
||||||
|
yield u
|
||||||
|
return gen()
|
||||||
|
|
||||||
def _default_params(self, extra_params = {}):
|
def _default_params(self, extra_params = {}):
|
||||||
if not self.name:
|
if not self.name:
|
||||||
raise InvalidParametersError("group has to be provided.")
|
raise InvalidParametersError("group has to be provided.")
|
||||||
|
@ -125,4 +155,5 @@ class Group(LastfmBase, Cacheable):
|
||||||
|
|
||||||
from lastfm.api import Api
|
from lastfm.api import Api
|
||||||
from lastfm.error import InvalidParametersError
|
from lastfm.error import InvalidParametersError
|
||||||
|
from lastfm.user import User
|
||||||
from lastfm.weeklychart import WeeklyChart, WeeklyAlbumChart, WeeklyArtistChart, WeeklyTrackChart
|
from lastfm.weeklychart import WeeklyChart, WeeklyAlbumChart, WeeklyArtistChart, WeeklyTrackChart
|
||||||
|
|
|
@ -169,6 +169,43 @@ class Tag(LastfmBase, Cacheable, Searchable):
|
||||||
return Playlist.fetch(self._api,
|
return Playlist.fetch(self._api,
|
||||||
"lastfm://playlist/tag/%s/freetracks" % self.name)
|
"lastfm://playlist/tag/%s/freetracks" % self.name)
|
||||||
|
|
||||||
|
@LastfmBase.cached_property
|
||||||
|
def weekly_chart_list(self):
|
||||||
|
params = self._default_params({'method': 'tag.getWeeklyChartList'})
|
||||||
|
data = self._api._fetch_data(params).find('weeklychartlist')
|
||||||
|
return [
|
||||||
|
WeeklyChart.create_from_data(self._api, self, c)
|
||||||
|
for c in data.findall('chart')
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_weekly_artist_chart(self,
|
||||||
|
start = None,
|
||||||
|
end = None,
|
||||||
|
limit = None):
|
||||||
|
params = self._default_params({'method': 'tag.getWeeklyArtistChart'})
|
||||||
|
if limit is not None:
|
||||||
|
params['limit'] = limit
|
||||||
|
params = WeeklyArtistChart._check_weekly_chart_params(params, start, end)
|
||||||
|
data = self._api._fetch_data(params).find('weeklyartistchart')
|
||||||
|
return WeeklyArtistChart.create_from_data(self._api, self, data)
|
||||||
|
|
||||||
|
@LastfmBase.cached_property
|
||||||
|
def recent_weekly_artist_chart(self):
|
||||||
|
return self.get_weekly_artist_chart()
|
||||||
|
|
||||||
|
@LastfmBase.cached_property
|
||||||
|
def weekly_artist_chart_list(self):
|
||||||
|
wcl = list(self.weekly_chart_list)
|
||||||
|
wcl.reverse()
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
for wc in wcl:
|
||||||
|
try:
|
||||||
|
yield self.get_weekly_artist_chart(wc.start, wc.end)
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
return gen()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_top_tags(api):
|
def get_top_tags(api):
|
||||||
params = {'method': 'tag.getTopTags'}
|
params = {'method': 'tag.getTopTags'}
|
||||||
|
@ -227,7 +264,8 @@ class Tag(LastfmBase, Cacheable, Searchable):
|
||||||
from lastfm.album import Album
|
from lastfm.album import Album
|
||||||
from lastfm.api import Api
|
from lastfm.api import Api
|
||||||
from lastfm.artist import Artist
|
from lastfm.artist import Artist
|
||||||
from lastfm.error import InvalidParametersError
|
from lastfm.error import LastfmError, InvalidParametersError
|
||||||
from lastfm.playlist import Playlist
|
from lastfm.playlist import Playlist
|
||||||
from lastfm.stats import Stats
|
from lastfm.stats import Stats
|
||||||
from lastfm.track import Track
|
from lastfm.track import Track
|
||||||
|
from lastfm.weeklychart import WeeklyChart, WeeklyArtistChart
|
192
lastfm/user.py
192
lastfm/user.py
|
@ -14,19 +14,16 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
name = None,
|
name = None,
|
||||||
|
real_name = None,
|
||||||
url = None,
|
url = None,
|
||||||
image = None,
|
image = None,
|
||||||
stats = None,
|
stats = None):
|
||||||
language = None,
|
|
||||||
country = None,
|
|
||||||
age = None,
|
|
||||||
gender = None,
|
|
||||||
subscriber = None):
|
|
||||||
if not isinstance(api, Api):
|
if not isinstance(api, Api):
|
||||||
raise InvalidParametersError("api reference must be supplied as an argument")
|
raise InvalidParametersError("api reference must be supplied as an argument")
|
||||||
Shoutable.init(self, api)
|
Shoutable.init(self, api)
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._real_name = real_name
|
||||||
self._url = url
|
self._url = url
|
||||||
self._image = image
|
self._image = image
|
||||||
self._stats = stats and Stats(
|
self._stats = stats and Stats(
|
||||||
|
@ -36,17 +33,17 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
playcount = stats.playcount
|
playcount = stats.playcount
|
||||||
)
|
)
|
||||||
self._library = User.Library(api, self)
|
self._library = User.Library(api, self)
|
||||||
self._language = language
|
|
||||||
self._country = country
|
|
||||||
self._age = age
|
|
||||||
self._gender = gender
|
|
||||||
self._subscriber = subscriber
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""name of the user"""
|
"""name of the user"""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def real_name(self):
|
||||||
|
"""real name of the user"""
|
||||||
|
return self._real_name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def url(self):
|
def url(self):
|
||||||
"""url of the user's page"""
|
"""url of the user's page"""
|
||||||
|
@ -63,29 +60,39 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
return self._stats
|
return self._stats
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@LastfmBase.autheticate
|
||||||
def language(self):
|
def language(self):
|
||||||
"""lang for the user"""
|
"""lang for the user"""
|
||||||
return self._language
|
return self._language
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@LastfmBase.autheticate
|
||||||
def country(self):
|
def country(self):
|
||||||
"""country for the user"""
|
"""country for the user"""
|
||||||
return self._country
|
return self._country
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@LastfmBase.autheticate
|
||||||
def age(self):
|
def age(self):
|
||||||
"""age for the user"""
|
"""age for the user"""
|
||||||
return self._age
|
return self._age
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@LastfmBase.autheticate
|
||||||
def gender(self):
|
def gender(self):
|
||||||
"""stats for the user"""
|
"""stats for the user"""
|
||||||
return self._gender
|
return self._gender
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@LastfmBase.autheticate
|
||||||
def subscriber(self):
|
def subscriber(self):
|
||||||
"""is the user a subscriber"""
|
"""is the user a subscriber"""
|
||||||
return self._subscriber
|
return self._subscriber
|
||||||
|
|
||||||
|
@property
|
||||||
|
def autheticated(self):
|
||||||
|
"""is the user autheticated"""
|
||||||
|
return self._api.get_authenticated_user() == self
|
||||||
|
|
||||||
@LastfmBase.cached_property
|
@LastfmBase.cached_property
|
||||||
def events(self):
|
def events(self):
|
||||||
|
@ -126,7 +133,37 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
@LastfmBase.cached_property
|
@LastfmBase.cached_property
|
||||||
def past_events(self):
|
def past_events(self):
|
||||||
return self.get_past_events()
|
return self.get_past_events()
|
||||||
|
|
||||||
|
@LastfmBase.autheticate
|
||||||
|
def get_recommended_events(self, limit = None):
|
||||||
|
params = {'method': 'user.getRecommendedEvents'}
|
||||||
|
if limit is not None:
|
||||||
|
params.update({'limit': limit})
|
||||||
|
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
data = self._api._fetch_data(params, sign = True, session = True).find('events')
|
||||||
|
total_pages = int(data.attrib['totalPages'])
|
||||||
|
|
||||||
|
@lazylist
|
||||||
|
def gen2(lst, data):
|
||||||
|
for e in data.findall('event'):
|
||||||
|
yield Event.create_from_data(self._api, e)
|
||||||
|
|
||||||
|
for e in gen2(data):
|
||||||
|
yield e
|
||||||
|
|
||||||
|
for page in xrange(2, total_pages+1):
|
||||||
|
params.update({'page': page})
|
||||||
|
data = self._api._fetch_data(params, sign = True, session = True).find('events')
|
||||||
|
for e in gen2(data):
|
||||||
|
yield e
|
||||||
|
return gen()
|
||||||
|
|
||||||
|
@LastfmBase.cached_property
|
||||||
|
def recommended_events(self):
|
||||||
|
return self.get_recommended_events()
|
||||||
|
|
||||||
def get_friends(self,
|
def get_friends(self,
|
||||||
limit = None):
|
limit = None):
|
||||||
params = self._default_params({'method': 'user.getFriends'})
|
params = self._default_params({'method': 'user.getFriends'})
|
||||||
|
@ -202,6 +239,15 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
for p in data.findall('playlist')
|
for p in data.findall('playlist')
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@LastfmBase.autheticate
|
||||||
|
def create_playlist(self, title, description = None):
|
||||||
|
params = {'method': 'playlist.create',
|
||||||
|
'title': title}
|
||||||
|
if description is not None:
|
||||||
|
params['description'] = description
|
||||||
|
self._api._post_data(params)
|
||||||
|
self._playlists = None
|
||||||
|
|
||||||
@LastfmBase.cached_property
|
@LastfmBase.cached_property
|
||||||
def loved_tracks(self):
|
def loved_tracks(self):
|
||||||
params = self._default_params({'method': 'user.getLovedTracks'})
|
params = self._default_params({'method': 'user.getLovedTracks'})
|
||||||
|
@ -353,7 +399,39 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
def top_artist(self):
|
def top_artist(self):
|
||||||
"""top artist of the user"""
|
"""top artist of the user"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@LastfmBase.cached_property
|
||||||
|
@LastfmBase.autheticate
|
||||||
|
def recommended_artists(self):
|
||||||
|
params = {'method': 'user.getRecommendedArtists'}
|
||||||
|
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
data = self._api._fetch_data(params, sign = True, session = True).find('recommendations')
|
||||||
|
total_pages = int(data.attrib['totalPages'])
|
||||||
|
|
||||||
|
@lazylist
|
||||||
|
def gen2(lst, data):
|
||||||
|
for a in data.findall('artist'):
|
||||||
|
yield Artist(
|
||||||
|
self._api,
|
||||||
|
name = a.findtext('name'),
|
||||||
|
mbid = a.findtext('mbid'),
|
||||||
|
url = a.findtext('url'),
|
||||||
|
streamable = (a.findtext('streamable') == "1"),
|
||||||
|
image = dict([(i.get('size'), i.text) for i in a.findall('image')]),
|
||||||
|
)
|
||||||
|
|
||||||
|
for a in gen2(data):
|
||||||
|
yield a
|
||||||
|
|
||||||
|
for page in xrange(2, total_pages+1):
|
||||||
|
params.update({'page': page})
|
||||||
|
data = self._api._fetch_data(params, sign = True, session = True).find('recommendations')
|
||||||
|
for a in gen2(data):
|
||||||
|
yield a
|
||||||
|
return gen()
|
||||||
|
|
||||||
def get_top_tracks(self, period = None):
|
def get_top_tracks(self, period = None):
|
||||||
params = self._default_params({'method': 'user.getTopTracks'})
|
params = self._default_params({'method': 'user.getTopTracks'})
|
||||||
if period is not None:
|
if period is not None:
|
||||||
|
@ -516,24 +594,23 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
def library(self):
|
def library(self):
|
||||||
return self._library
|
return self._library
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_authenticated_user(api):
|
def get_authenticated_user(api):
|
||||||
data = api._fetch_data({'method': 'user.getInfo'}, sign = True, session = True).find('user')
|
data = api._fetch_data({'method': 'user.getInfo'}, sign = True, session = True).find('user')
|
||||||
return User(
|
user = User(
|
||||||
api,
|
api,
|
||||||
name = data.findtext('name'),
|
name = data.findtext('name'),
|
||||||
url = data.findtext('url'),
|
url = data.findtext('url'),
|
||||||
language = data.findtext('lang'),
|
|
||||||
country = Country(api, name = data.findtext('country')),
|
|
||||||
age = int(data.findtext('age')),
|
|
||||||
gender = data.findtext('gender'),
|
|
||||||
subscriber = (data.findtext('subscriber') == '1'),
|
|
||||||
stats = Stats(
|
|
||||||
subject = data.findtext('name'),
|
|
||||||
playcount = data.findtext('playcount')
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
user._language = data.findtext('lang')
|
||||||
|
user._country = Country(api, name = Country.ISO_CODES[data.findtext('country')])
|
||||||
|
user._age = int(data.findtext('age'))
|
||||||
|
user._gender = data.findtext('gender')
|
||||||
|
user._subscriber = (data.findtext('subscriber') == "1")
|
||||||
|
user._stats = Stats(subject = user, playcount = data.findtext('playcount'))
|
||||||
|
return user
|
||||||
|
|
||||||
def _default_params(self, extra_params = {}):
|
def _default_params(self, extra_params = {}):
|
||||||
if not self.name:
|
if not self.name:
|
||||||
raise InvalidParametersError("user has to be provided.")
|
raise InvalidParametersError("user has to be provided.")
|
||||||
|
@ -589,15 +666,27 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
@property
|
@property
|
||||||
def creator(self):
|
def creator(self):
|
||||||
return self._creator
|
return self._creator
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user(self):
|
||||||
|
return self._creator
|
||||||
|
|
||||||
def add_track(self, track):
|
@LastfmBase.autheticate
|
||||||
|
def add_track(self, track, artist = None):
|
||||||
params = {'method': 'playlist.addTrack', 'playlistID': self.id}
|
params = {'method': 'playlist.addTrack', 'playlistID': self.id}
|
||||||
if not isinstance(track, Track):
|
if isinstance(track, Track):
|
||||||
track = self._api.search_track(track)[0]
|
params['artist'] = track.artist.name
|
||||||
|
params['track'] = track.name
|
||||||
params['artist'] = track.artist.name
|
else:
|
||||||
params['track'] = track.name
|
if artist is None:
|
||||||
|
track = self._api.search_track(track)[0]
|
||||||
|
params['artist'] = track.artist.name
|
||||||
|
params['track'] = track.name
|
||||||
|
else:
|
||||||
|
params['artist'] = isinstance(artist, Artist) and artist.name or artist
|
||||||
|
params['track'] = track
|
||||||
self._api._post_data(params)
|
self._api._post_data(params)
|
||||||
|
self._data = None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _hash_func(*args, **kwds):
|
def _hash_func(*args, **kwds):
|
||||||
|
@ -673,7 +762,25 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
@LastfmBase.cached_property
|
@LastfmBase.cached_property
|
||||||
def albums(self):
|
def albums(self):
|
||||||
return self.get_albums()
|
return self.get_albums()
|
||||||
|
|
||||||
|
@LastfmBase.autheticate
|
||||||
|
def add_album(self, album, artist = None):
|
||||||
|
params = {'method': 'library.addAlbum'}
|
||||||
|
if isinstance(album, Album):
|
||||||
|
params['artist'] = album.artist.name
|
||||||
|
params['album'] = album.name
|
||||||
|
else:
|
||||||
|
if artist is None:
|
||||||
|
album = self._api.search_album(album)[0]
|
||||||
|
params['artist'] = album.artist.name
|
||||||
|
params['album'] = album.name
|
||||||
|
else:
|
||||||
|
params['artist'] = isinstance(artist, Artist) and artist.name or artist
|
||||||
|
params['album'] = album
|
||||||
|
|
||||||
|
self._api._post_data(params)
|
||||||
|
self._albums = None
|
||||||
|
|
||||||
def get_artists(self,
|
def get_artists(self,
|
||||||
limit = None):
|
limit = None):
|
||||||
params = self._default_params({'method': 'library.getArtists'})
|
params = self._default_params({'method': 'library.getArtists'})
|
||||||
|
@ -720,6 +827,16 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
def artists(self):
|
def artists(self):
|
||||||
return self.get_artists()
|
return self.get_artists()
|
||||||
|
|
||||||
|
@LastfmBase.autheticate
|
||||||
|
def add_artist(self, artist):
|
||||||
|
params = {'method': 'library.addArtist'}
|
||||||
|
if isinstance(artist, Artist):
|
||||||
|
params['artist'] = artist.name
|
||||||
|
else:
|
||||||
|
params['artist'] = artist
|
||||||
|
self._api._post_data(params)
|
||||||
|
self._artists = None
|
||||||
|
|
||||||
def get_tracks(self,
|
def get_tracks(self,
|
||||||
limit = None):
|
limit = None):
|
||||||
params = self._default_params({'method': 'library.getTracks'})
|
params = self._default_params({'method': 'library.getTracks'})
|
||||||
|
@ -774,6 +891,23 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
def tracks(self):
|
def tracks(self):
|
||||||
return self.get_tracks()
|
return self.get_tracks()
|
||||||
|
|
||||||
|
@LastfmBase.autheticate
|
||||||
|
def add_track(self, track, artist = None):
|
||||||
|
params = {'method': 'library.addTrack'}
|
||||||
|
if isinstance(track, Track):
|
||||||
|
params['artist'] = track.artist.name
|
||||||
|
params['track'] = track.name
|
||||||
|
else:
|
||||||
|
if artist is None:
|
||||||
|
track = self._api.search_track(track)[0]
|
||||||
|
params['artist'] = track.artist.name
|
||||||
|
params['track'] = track.name
|
||||||
|
else:
|
||||||
|
params['artist'] = isinstance(artist, Artist) and artist.name or artist
|
||||||
|
params['track'] = track
|
||||||
|
self._api._post_data(params)
|
||||||
|
self._tracks = None
|
||||||
|
|
||||||
def _default_params(self, extra_params = {}):
|
def _default_params(self, extra_params = {}):
|
||||||
if not self.user.name:
|
if not self.user.name:
|
||||||
raise InvalidParametersError("user has to be provided.")
|
raise InvalidParametersError("user has to be provided.")
|
||||||
|
|
|
@ -170,19 +170,19 @@ class WeeklyArtistChart(WeeklyChart):
|
||||||
start = datetime.utcfromtimestamp(int(data.attrib['from'])),
|
start = datetime.utcfromtimestamp(int(data.attrib['from'])),
|
||||||
end = datetime.utcfromtimestamp(int(data.attrib['to'])),
|
end = datetime.utcfromtimestamp(int(data.attrib['to'])),
|
||||||
)
|
)
|
||||||
|
count_attribute = data.find('artist').findtext('playcount') and 'playcount' or 'weight'
|
||||||
|
def get_count_attribute(artist):
|
||||||
|
return {count_attribute: int(eval(artist.findtext(count_attribute)))}
|
||||||
|
def get_count_attribute_sum(artists):
|
||||||
|
return {count_attribute: reduce(lambda x,y:(x + int(eval(y.findtext(count_attribute)))), artists, 0)}
|
||||||
|
|
||||||
return WeeklyArtistChart(
|
return WeeklyArtistChart(
|
||||||
subject = subject,
|
subject = subject,
|
||||||
start = datetime.utcfromtimestamp(int(data.attrib['from'])),
|
start = datetime.utcfromtimestamp(int(data.attrib['from'])),
|
||||||
end = datetime.utcfromtimestamp(int(data.attrib['to'])),
|
end = datetime.utcfromtimestamp(int(data.attrib['to'])),
|
||||||
stats = Stats(
|
stats = Stats(
|
||||||
subject = subject,
|
subject = subject,
|
||||||
playcount = reduce(
|
**get_count_attribute_sum(data.findall('artist'))
|
||||||
lambda x,y:(
|
|
||||||
x + int(y.findtext('playcount'))
|
|
||||||
),
|
|
||||||
data.findall('artist'),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
artists = [
|
artists = [
|
||||||
Artist(
|
Artist(
|
||||||
|
@ -193,7 +193,7 @@ class WeeklyArtistChart(WeeklyChart):
|
||||||
stats = Stats(
|
stats = Stats(
|
||||||
subject = a.findtext('name'),
|
subject = a.findtext('name'),
|
||||||
rank = int(a.attrib['rank']),
|
rank = int(a.attrib['rank']),
|
||||||
playcount = int(a.findtext('playcount')),
|
**get_count_attribute(a)
|
||||||
),
|
),
|
||||||
url = a.findtext('url'),
|
url = a.findtext('url'),
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue