* added Rolling Charts: Monthly, Quaterly, Half-yearly and Yearly; Album, Artist, Track and Tag charts
* refactored the chart related code to mixins.chartable module * made related changes in user, tag and group modulesmaster
parent
42aa35fcbb
commit
d709434a7b
352
lastfm/chart.py
352
lastfm/chart.py
|
@ -10,7 +10,7 @@ from lastfm.mixins import Cacheable
|
||||||
from operator import xor
|
from operator import xor
|
||||||
|
|
||||||
class Chart(LastfmBase, Cacheable):
|
class Chart(LastfmBase, Cacheable):
|
||||||
"""A class for representing the weekly charts"""
|
"""The base class for all the chart classes"""
|
||||||
|
|
||||||
def init(self, subject, start, end, stats = None):
|
def init(self, subject, start, end, stats = None):
|
||||||
self._subject = subject
|
self._subject = subject
|
||||||
|
@ -35,26 +35,16 @@ class Chart(LastfmBase, Cacheable):
|
||||||
return self._stats
|
return self._stats
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_from_data(api, subject, data):
|
def _check_chart_params(params, subject, start = None, end = None):
|
||||||
return Chart(
|
|
||||||
subject = subject,
|
|
||||||
start = datetime.utcfromtimestamp(int(data.attrib['from'])),
|
|
||||||
end = datetime.utcfromtimestamp(int(data.attrib['to']))
|
|
||||||
)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _check_chart_params(params, start = None, end = None):
|
|
||||||
if xor(start is None, end is None):
|
if xor(start is None, end is None):
|
||||||
raise InvalidParametersError("both start and end have to be provided.")
|
raise InvalidParametersError("both start and end have to be provided.")
|
||||||
if start is not None and end is not None:
|
if start is not None and end is not None:
|
||||||
if isinstance(start, datetime) and isinstance(end, datetime):
|
if not (isinstance(start, datetime) and isinstance(end, datetime)):
|
||||||
params.update({
|
|
||||||
'from': int(calendar.timegm(start.timetuple())),
|
|
||||||
'to': int(calendar.timegm(end.timetuple()))
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
raise InvalidParametersError("start and end must be datetime.datetime instances")
|
raise InvalidParametersError("start and end must be datetime.datetime instances")
|
||||||
|
params.update({
|
||||||
|
'from': int(calendar.timegm(start.timetuple())),
|
||||||
|
'to': int(calendar.timegm(end.timetuple()))
|
||||||
|
})
|
||||||
return params
|
return params
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -71,10 +61,10 @@ class Chart(LastfmBase, Cacheable):
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return self.__class__._hash_func(
|
return self.__class__._hash_func(
|
||||||
subject = self.subject,
|
subject = self.subject,
|
||||||
start = self.start,
|
start = self.start,
|
||||||
end = self.end
|
end = self.end
|
||||||
)
|
)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return self.subject == other.subject and \
|
return self.subject == other.subject and \
|
||||||
|
@ -99,21 +89,68 @@ class Chart(LastfmBase, Cacheable):
|
||||||
self.start.strftime("%x"),
|
self.start.strftime("%x"),
|
||||||
self.end.strftime("%x"),
|
self.end.strftime("%x"),
|
||||||
)
|
)
|
||||||
|
|
||||||
class WeeklyChart(Chart):
|
|
||||||
def init(self, subject, start, end, stats = None):
|
|
||||||
super(WeeklyChart, self).init(subject, start, end, stats)
|
|
||||||
|
|
||||||
class WeeklyAlbumChart(WeeklyChart):
|
class AlbumChart(Chart):
|
||||||
"""A class for representing the weekly album charts"""
|
|
||||||
def init(self, subject, start, end, stats, albums):
|
def init(self, subject, start, end, stats, albums):
|
||||||
super(WeeklyAlbumChart, self).init(subject, start, end, stats)
|
super(AlbumChart, self).init(subject, start, end, stats)
|
||||||
self._albums = albums
|
self._albums = albums
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def albums(self):
|
def albums(self):
|
||||||
return self._albums
|
return self._albums
|
||||||
|
|
||||||
|
class ArtistChart(Chart):
|
||||||
|
def init(self, subject, start, end, stats, artists):
|
||||||
|
super(ArtistChart, self).init(subject, start, end, stats)
|
||||||
|
self._artists = artists
|
||||||
|
|
||||||
|
@property
|
||||||
|
def artists(self):
|
||||||
|
return self._artists
|
||||||
|
|
||||||
|
class TrackChart(Chart):
|
||||||
|
def init(self, subject, start, end, tracks, stats):
|
||||||
|
super(TrackChart, self).init(subject, start, end, stats)
|
||||||
|
self._tracks = tracks
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tracks(self):
|
||||||
|
return self._tracks
|
||||||
|
|
||||||
|
class TagChart(Chart):
|
||||||
|
def init(self, subject, start, end, tags, stats):
|
||||||
|
super(TagChart, self).init(subject, start, end, stats)
|
||||||
|
self._tags = tags
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tags(self):
|
||||||
|
return self._tags
|
||||||
|
|
||||||
|
class WeeklyChart(Chart):
|
||||||
|
"""A class for representing the weekly charts"""
|
||||||
|
@staticmethod
|
||||||
|
def create_from_data(api, subject, data):
|
||||||
|
return WeeklyChart(
|
||||||
|
subject = subject,
|
||||||
|
start = datetime.utcfromtimestamp(int(data.attrib['from'])),
|
||||||
|
end = datetime.utcfromtimestamp(int(data.attrib['to']))
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _check_chart_params(params, subject, start = None, end = None):
|
||||||
|
params = Chart._check_chart_params(params, subject, start, end)
|
||||||
|
if start is not None and end is not None:
|
||||||
|
wcl = subject.weekly_chart_list
|
||||||
|
is_valid = False
|
||||||
|
for wc in wcl:
|
||||||
|
if wc.start == start and wc.end == end:
|
||||||
|
is_valid = True
|
||||||
|
if not is_valid:
|
||||||
|
raise InvalidParametersError("%s - %s chart dates are invalid" % (start, end))
|
||||||
|
return params
|
||||||
|
|
||||||
|
class WeeklyAlbumChart(AlbumChart, WeeklyChart):
|
||||||
|
"""A class for representing the weekly album charts"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_from_data(api, subject, data):
|
def create_from_data(api, subject, data):
|
||||||
w = WeeklyChart(
|
w = WeeklyChart(
|
||||||
|
@ -158,16 +195,8 @@ class WeeklyAlbumChart(WeeklyChart):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
class WeeklyArtistChart(WeeklyChart):
|
class WeeklyArtistChart(ArtistChart, WeeklyChart):
|
||||||
"""A class for representing the weekly artist charts"""
|
"""A class for representing the weekly artist charts"""
|
||||||
def init(self, subject, start, end, stats, artists):
|
|
||||||
super(WeeklyArtistChart, self).init(subject, start, end, stats)
|
|
||||||
self._artists = artists
|
|
||||||
|
|
||||||
@property
|
|
||||||
def artists(self):
|
|
||||||
return self._artists
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_from_data(api, subject, data):
|
def create_from_data(api, subject, data):
|
||||||
w = WeeklyChart(
|
w = WeeklyChart(
|
||||||
|
@ -208,16 +237,8 @@ class WeeklyArtistChart(WeeklyChart):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
class WeeklyTrackChart(WeeklyChart):
|
class WeeklyTrackChart(TrackChart, WeeklyChart):
|
||||||
"""A class for representing the weekly track charts"""
|
"""A class for representing the weekly track charts"""
|
||||||
def init(self, subject, start, end, tracks, stats):
|
|
||||||
super(WeeklyTrackChart, self).init(subject, start, end, stats)
|
|
||||||
self._tracks = tracks
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tracks(self):
|
|
||||||
return self._tracks
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_from_data(api, subject, data):
|
def create_from_data(api, subject, data):
|
||||||
w = WeeklyChart(
|
w = WeeklyChart(
|
||||||
|
@ -261,16 +282,8 @@ class WeeklyTrackChart(WeeklyChart):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
class WeeklyTagChart(WeeklyChart):
|
class WeeklyTagChart(TagChart, WeeklyChart):
|
||||||
"""A class for representing the weekly tag charts"""
|
"""A class for representing the weekly tag charts"""
|
||||||
def init(self, subject, start, end, tags, stats):
|
|
||||||
super(WeeklyTagChart, self).init(subject, start, end, stats)
|
|
||||||
self._tags = tags
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tags(self):
|
|
||||||
return self._tags
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_from_data(api, subject, start, end):
|
def create_from_data(api, subject, start, end):
|
||||||
w = WeeklyChart(
|
w = WeeklyChart(
|
||||||
|
@ -356,77 +369,216 @@ class WeeklyTagChart(WeeklyChart):
|
||||||
return wtc
|
return wtc
|
||||||
|
|
||||||
class RollingChart(Chart):
|
class RollingChart(Chart):
|
||||||
pass
|
"""Base class for the rolling charts classes"""
|
||||||
|
@classmethod
|
||||||
|
def _check_chart_params(cls, params, subject, start = None, end = None):
|
||||||
|
duration = cls._period['duration']
|
||||||
|
params = Chart._check_chart_params(params, subject, start, end)
|
||||||
|
if start is not None and end is not None:
|
||||||
|
mcl = MonthlyChart.get_chart_list(subject)
|
||||||
|
is_valid = False
|
||||||
|
for i in xrange(len(mcl)-(duration-1)):
|
||||||
|
if mcl[i].start == start and mcl[i+(duration-1)].end == end:
|
||||||
|
is_valid = True
|
||||||
|
if not is_valid:
|
||||||
|
raise InvalidParametersError("%s - %s chart dates are invalid" % (start, end))
|
||||||
|
return params
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create_from_data(cls, subject, key_func,
|
||||||
|
start = None, end = None):
|
||||||
|
chart_type = cls.mro()[0]._chart_type
|
||||||
|
period = cls.mro()[3]._period
|
||||||
|
globals()["%slyChart" % period['name'].title().replace(' ','')]._check_chart_params({}, subject, start, end)
|
||||||
|
mcl = MonthlyChart.get_chart_list(subject)
|
||||||
|
if start is None and end is None:
|
||||||
|
start = mcl[-period['duration']].start
|
||||||
|
end = mcl[-1].end
|
||||||
|
wcl = subject.weekly_chart_list
|
||||||
|
period_wcl = [wc for wc in wcl
|
||||||
|
if start < wc.start < end or start < wc.end < end]
|
||||||
|
period_wacl = []
|
||||||
|
for wc in period_wcl:
|
||||||
|
try:
|
||||||
|
period_wacl.append(
|
||||||
|
getattr(subject, "get_weekly_%s_chart" % chart_type)(wc.start, wc.end))
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
stats_dict = period_wacl[0].__dict__["_%ss" % chart_type][0].stats.__dict__
|
||||||
|
count_attribute = [k for k in stats_dict.keys()
|
||||||
|
if stats_dict[k] is not None and k not in ['_rank', '_subject']][0]
|
||||||
|
items = {}
|
||||||
|
for wac in period_wacl:
|
||||||
|
for item in wac.__dict__["_%ss" % chart_type]:
|
||||||
|
key = key_func(item)
|
||||||
|
mw_start = max(wac.start, start)
|
||||||
|
mw_end = min(wac.end, end)
|
||||||
|
count = item.stats.__dict__[count_attribute] * (mw_end - mw_start).days / 7.0
|
||||||
|
if key in items:
|
||||||
|
items[key].stats.__dict__[count_attribute] += count
|
||||||
|
else:
|
||||||
|
items[key] = item
|
||||||
|
items[key].stats.__dict__[count_attribute] = count
|
||||||
|
items = items.values()
|
||||||
|
items = [a for a in items if a.stats.__dict__[count_attribute] >= 1]
|
||||||
|
items.sort(key = lambda a: a.stats.__dict__[count_attribute], reverse=True)
|
||||||
|
for i,item in enumerate(items):
|
||||||
|
item.stats._rank = i + 1
|
||||||
|
item.stats.__dict__[count_attribute] = int(item.stats.__dict__[count_attribute])
|
||||||
|
return globals()[
|
||||||
|
"%sly%sChart" % (
|
||||||
|
period['name'].title().replace(' ',''),
|
||||||
|
chart_type.capitalize()
|
||||||
|
)](
|
||||||
|
subject = subject,
|
||||||
|
start = start,
|
||||||
|
end = end,
|
||||||
|
stats = Stats(
|
||||||
|
subject = subject,
|
||||||
|
**{count_attribute[1:]: sum([a.stats.__dict__[count_attribute] for a in items])}
|
||||||
|
),
|
||||||
|
**{"%ss" % chart_type: items}
|
||||||
|
)
|
||||||
|
|
||||||
|
class RollingAlbumChart(AlbumChart):
|
||||||
|
@classmethod
|
||||||
|
def create_from_data(cls, subject, start = None, end = None):
|
||||||
|
key_func = lambda album: "::".join((album.name, album.artist.name))
|
||||||
|
return super(cls.mro()[3], cls).create_from_data(
|
||||||
|
subject, key_func, start, end)
|
||||||
|
|
||||||
|
class RollingArtistChart(ArtistChart):
|
||||||
|
@classmethod
|
||||||
|
def create_from_data(cls, subject, start = None, end = None):
|
||||||
|
key_func = lambda artist: artist.name
|
||||||
|
return super(cls.mro()[3], cls).create_from_data(
|
||||||
|
subject, key_func, start, end)
|
||||||
|
|
||||||
|
class RollingTrackChart(TrackChart):
|
||||||
|
@classmethod
|
||||||
|
def create_from_data(cls, subject, start = None, end = None):
|
||||||
|
key_func = lambda track: "::".join((track.name, track.artist.name))
|
||||||
|
return super(cls.mro()[3], cls).create_from_data(
|
||||||
|
subject, key_func, start, end)
|
||||||
|
|
||||||
|
class RollingTagChart(TagChart):
|
||||||
|
@classmethod
|
||||||
|
def create_from_data(cls, subject, start = None, end = None):
|
||||||
|
key_func = lambda tag: tag.name
|
||||||
|
chart = super(cls.mro()[3], cls).create_from_data(
|
||||||
|
subject, key_func, start, end)
|
||||||
|
count_sum = sum([t.stats.count for t in chart.tags])
|
||||||
|
for t in chart.tags:
|
||||||
|
t.stats.__dict__['_count'] /= count_sum
|
||||||
|
return chart
|
||||||
|
|
||||||
class MonthlyChart(RollingChart):
|
class MonthlyChart(RollingChart):
|
||||||
pass
|
"""A class for representing the monthly charts"""
|
||||||
|
_period = {'name': 'month', 'duration': 1}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_chart_list(subject):
|
||||||
|
wcl = subject.weekly_chart_list
|
||||||
|
months = set()
|
||||||
|
for l in wcl:
|
||||||
|
months.add(l.start.replace(day=1, hour=12, minute=0, second=0))
|
||||||
|
months = list(months)
|
||||||
|
months.sort()
|
||||||
|
months[0] = wcl[0].start.replace(hour=12, minute=0, second=0)
|
||||||
|
months.append(wcl[-1].end.replace(hour=12, minute=0, second=0))
|
||||||
|
|
||||||
class MonthlyAlbumChart(MonthlyChart):
|
return [MonthlyChart(
|
||||||
pass
|
subject=subject,
|
||||||
|
start=months[i],
|
||||||
|
end=months[i+1]
|
||||||
|
)
|
||||||
|
for i in xrange(len(months)-1)]
|
||||||
|
|
||||||
|
class MonthlyAlbumChart(RollingAlbumChart, MonthlyChart):
|
||||||
|
"""A class for representing the monthly album charts"""
|
||||||
|
_chart_type = "album"
|
||||||
|
|
||||||
|
class MonthlyArtistChart(RollingArtistChart, MonthlyChart):
|
||||||
|
"""A class for representing the monthly artist charts"""
|
||||||
|
_chart_type = "artist"
|
||||||
|
|
||||||
class MonthlyArtistChart(MonthlyChart):
|
class MonthlyTrackChart(RollingTrackChart, MonthlyChart):
|
||||||
pass
|
"""A class for representing the monthly track charts"""
|
||||||
|
_chart_type = "track"
|
||||||
|
|
||||||
class MonthlyTrackChart(MonthlyChart):
|
class MonthlyTagChart(RollingTagChart, MonthlyChart):
|
||||||
pass
|
"""A class for representing the monthly tag charts"""
|
||||||
|
_chart_type = "tag"
|
||||||
|
|
||||||
class MonthlyTagChart(MonthlyChart):
|
class QuaterlyChart(RollingChart):
|
||||||
pass
|
"""A class for representing the three monthly charts"""
|
||||||
|
_period = {'name': 'quater', 'duration': 3}
|
||||||
|
|
||||||
class ThreeMonthlyChart(RollingChart):
|
class QuaterlyAlbumChart(RollingAlbumChart, QuaterlyChart):
|
||||||
pass
|
"""A class for representing the three monthly album charts"""
|
||||||
|
_chart_type = "album"
|
||||||
|
|
||||||
class ThreeMonthlyAlbumChart(ThreeMonthlyChart):
|
class QuaterlyArtistChart(RollingArtistChart, QuaterlyChart):
|
||||||
pass
|
"""A class for representing the three monthly artist charts"""
|
||||||
|
_chart_type = "artist"
|
||||||
|
|
||||||
class ThreeMonthlyArtistChart(ThreeMonthlyChart):
|
class QuaterlyTrackChart(RollingTrackChart, QuaterlyChart):
|
||||||
pass
|
"""A class for representing the three monthly track charts"""
|
||||||
|
_chart_type = "track"
|
||||||
|
|
||||||
class ThreeMonthlyTrackChart(ThreeMonthlyChart):
|
class QuaterlyTagChart(RollingTagChart, QuaterlyChart):
|
||||||
pass
|
"""A class for representing the three monthly tag charts"""
|
||||||
|
_chart_type = "tag"
|
||||||
|
|
||||||
class ThreeMonthlyTagChart(ThreeMonthlyChart):
|
class HalfYearlyChart(RollingChart):
|
||||||
pass
|
"""A class for representing the six monthly charts"""
|
||||||
|
_period = {'name': 'half year', 'duration': 6}
|
||||||
|
|
||||||
class SixMonthlyChart(RollingChart):
|
class HalfYearlyAlbumChart(RollingAlbumChart, HalfYearlyChart):
|
||||||
pass
|
"""A class for representing the six monthly album charts"""
|
||||||
|
_chart_type = "album"
|
||||||
|
|
||||||
class SixMonthlyAlbumChart(SixMonthlyChart):
|
class HalfYearlyArtistChart(RollingArtistChart, HalfYearlyChart):
|
||||||
pass
|
"""A class for representing the six monthly artist charts"""
|
||||||
|
_chart_type = "artist"
|
||||||
|
|
||||||
class SixMonthlyArtistChart(SixMonthlyChart):
|
class HalfYearlyTrackChart(RollingTrackChart, HalfYearlyChart):
|
||||||
pass
|
"""A class for representing the six monthly track charts"""
|
||||||
|
_chart_type = "track"
|
||||||
|
|
||||||
class SixMonthlyTrackChart(SixMonthlyChart):
|
class HalfYearlyTagChart(RollingTagChart, HalfYearlyChart):
|
||||||
pass
|
"""A class for representing the six monthly tag charts"""
|
||||||
|
_chart_type = "tag"
|
||||||
class SixMonthlyTagChart(SixMonthlyChart):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class YearlyChart(RollingChart):
|
class YearlyChart(RollingChart):
|
||||||
pass
|
"""A class for representing the yearly charts"""
|
||||||
|
_period = {'name': 'year', 'duration': 12}
|
||||||
|
|
||||||
class YearlyAlbumChart(YearlyChart):
|
class YearlyAlbumChart(RollingAlbumChart, YearlyChart):
|
||||||
pass
|
"""A class for representing the yearly album charts"""
|
||||||
|
_chart_type = "album"
|
||||||
|
|
||||||
class YearlyArtistChart(YearlyChart):
|
class YearlyArtistChart(RollingArtistChart, YearlyChart):
|
||||||
pass
|
"""A class for representing the yearly artist charts"""
|
||||||
|
_chart_type = "artist"
|
||||||
|
|
||||||
class YearlyTrackChart(YearlyChart):
|
class YearlyTrackChart(RollingTrackChart, YearlyChart):
|
||||||
pass
|
"""A class for representing the yearly track charts"""
|
||||||
|
_chart_type = "track"
|
||||||
|
|
||||||
class YearlyTagChart(YearlyChart):
|
class YearlyTagChart(RollingTagChart, YearlyChart):
|
||||||
pass
|
"""A class for representing the yearly tag charts"""
|
||||||
|
_chart_type = "tag"
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'WeeklyChart',
|
'WeeklyChart',
|
||||||
'WeeklyAlbumChart', 'WeeklyArtistChart', 'WeeklyTrackChart', 'WeeklyTagChart',
|
'WeeklyAlbumChart', 'WeeklyArtistChart', 'WeeklyTrackChart', 'WeeklyTagChart',
|
||||||
'MonthlyChart',
|
'MonthlyChart',
|
||||||
'MonthlyAlbumChart', 'MonthlyArtistChart', 'MonthlyTrackChart', 'MonthlyTagChart',
|
'MonthlyAlbumChart', 'MonthlyArtistChart', 'MonthlyTrackChart', 'MonthlyTagChart',
|
||||||
'ThreeMonthlyChart',
|
'QuaterlyChart',
|
||||||
'ThreeMonthlyAlbumChart', 'ThreeMonthlyArtistChart', 'ThreeMonthlyTrackChart', 'ThreeMonthlyTagChart',
|
'QuaterlyAlbumChart', 'QuaterlyArtistChart', 'QuaterlyTrackChart', 'QuaterlyTagChart',
|
||||||
'SixMonthlyChart',
|
'HalfYearlyChart',
|
||||||
'SixMonthlyAlbumChart', 'SixMonthlyArtistChart', 'SixMonthlyTrackChart', 'SixMonthlyTagChart',
|
'HalfYearlyAlbumChart', 'HalfYearlyArtistChart', 'HalfYearlyTrackChart', 'HalfYearlyTagChart',
|
||||||
'YearlyChart',
|
'YearlyChart',
|
||||||
'YearlyAlbumChart', 'YearlyArtistChart', 'YearlyTrackChart', 'YearlyTagChart'
|
'YearlyAlbumChart', 'YearlyArtistChart', 'YearlyTrackChart', 'YearlyTagChart'
|
||||||
]
|
]
|
||||||
|
@ -435,7 +587,7 @@ import calendar
|
||||||
|
|
||||||
from lastfm.album import Album
|
from lastfm.album import Album
|
||||||
from lastfm.artist import Artist
|
from lastfm.artist import Artist
|
||||||
from lastfm.error import InvalidParametersError
|
from lastfm.error import InvalidParametersError, LastfmError
|
||||||
from lastfm.stats import Stats
|
from lastfm.stats import Stats
|
||||||
from lastfm.track import Track
|
from lastfm.track import Track
|
||||||
from lastfm.tag import Tag
|
from lastfm.tag import Tag
|
216
lastfm/group.py
216
lastfm/group.py
|
@ -7,11 +7,13 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixins import Cacheable
|
from lastfm.mixins import (
|
||||||
from lastfm.lazylist import lazylist
|
Cacheable, AlbumChartable, ArtistChartable,
|
||||||
|
TrackChartable, TagChartable)
|
||||||
from lastfm.decorators import cached_property, depaginate
|
from lastfm.decorators import cached_property, depaginate
|
||||||
|
|
||||||
class Group(LastfmBase, Cacheable):
|
class Group(LastfmBase, Cacheable, AlbumChartable,
|
||||||
|
ArtistChartable, TrackChartable, TagChartable):
|
||||||
"""A class representing a group on last.fm."""
|
"""A class representing a group on last.fm."""
|
||||||
def init(self, api, name = None, **kwargs):
|
def init(self, api, name = None, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
@ -27,6 +29,11 @@ class Group(LastfmBase, Cacheable):
|
||||||
"""
|
"""
|
||||||
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")
|
||||||
|
AlbumChartable.init(self, api)
|
||||||
|
ArtistChartable.init(self, api)
|
||||||
|
TrackChartable.init(self, api)
|
||||||
|
TagChartable.init(self, api)
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
self._name = name
|
||||||
|
|
||||||
|
@ -37,209 +44,6 @@ class Group(LastfmBase, Cacheable):
|
||||||
@rtype: L{str}
|
@rtype: L{str}
|
||||||
"""
|
"""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_chart_list(self):
|
|
||||||
"""
|
|
||||||
a list of available weekly charts for this group
|
|
||||||
@rtype: L{list} of L{WeeklyChart}
|
|
||||||
"""
|
|
||||||
params = self._default_params({'method': 'group.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_album_chart(self, start = None, end = None):
|
|
||||||
"""
|
|
||||||
Get an album chart for the group, for a given date range.
|
|
||||||
If no date range is supplied, it will return the most
|
|
||||||
recent album chart for the group.
|
|
||||||
|
|
||||||
@param start: the date at which the chart should start from (optional)
|
|
||||||
@type start: C{datetime.datetime}
|
|
||||||
@param end: the date at which the chart should end on (optional)
|
|
||||||
@type end: C{datetime.datetime}
|
|
||||||
|
|
||||||
@return: an album chart for the group
|
|
||||||
@rtype: L{WeeklyAlbumChart}
|
|
||||||
|
|
||||||
@raise InvalidParametersError: Both start and end parameter have to be either
|
|
||||||
provided or not provided. Providing only one of
|
|
||||||
them will raise an exception.
|
|
||||||
"""
|
|
||||||
params = self._default_params({'method': 'group.getWeeklyAlbumChart'})
|
|
||||||
params = WeeklyChart._check_chart_params(params, start, end)
|
|
||||||
data = self._api._fetch_data(params).find('weeklyalbumchart')
|
|
||||||
return WeeklyAlbumChart.create_from_data(self._api, self, data)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_album_chart(self):
|
|
||||||
"""
|
|
||||||
most recent album chart for the group
|
|
||||||
@rtype: L{WeeklyAlbumChart}
|
|
||||||
"""
|
|
||||||
return self.get_weekly_album_chart()
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_album_chart_list(self):
|
|
||||||
"""
|
|
||||||
a list of all album charts for this group in reverse-chronological
|
|
||||||
order. (that means 0th chart is the most recent chart)
|
|
||||||
@rtype: L{lazylist} of L{WeeklyAlbumChart}
|
|
||||||
"""
|
|
||||||
wcl = list(self.weekly_chart_list)
|
|
||||||
wcl.reverse()
|
|
||||||
@lazylist
|
|
||||||
def gen(lst):
|
|
||||||
for wc in wcl:
|
|
||||||
yield self.get_weekly_album_chart(wc.start, wc.end)
|
|
||||||
return gen()
|
|
||||||
|
|
||||||
def get_weekly_artist_chart(self, start = None, end = None):
|
|
||||||
"""
|
|
||||||
Get an artist chart for the group, for a given date range.
|
|
||||||
If no date range is supplied, it will return the most
|
|
||||||
recent artist chart for the group.
|
|
||||||
|
|
||||||
@param start: the date at which the chart should start from (optional)
|
|
||||||
@type start: C{datetime.datetime}
|
|
||||||
@param end: the date at which the chart should end on (optional)
|
|
||||||
@type end: C{datetime.datetime}
|
|
||||||
|
|
||||||
@return: an artist chart for the group
|
|
||||||
@rtype: L{WeeklyArtistChart}
|
|
||||||
|
|
||||||
@raise InvalidParametersError: Both start and end parameter have to be either
|
|
||||||
provided or not provided. Providing only one of
|
|
||||||
them will raise an exception.
|
|
||||||
"""
|
|
||||||
params = self._default_params({'method': 'group.getWeeklyArtistChart'})
|
|
||||||
params = WeeklyChart._check_chart_params(params, start, end)
|
|
||||||
data = self._api._fetch_data(params).find('weeklyartistchart')
|
|
||||||
return WeeklyArtistChart.create_from_data(self._api, self, data)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_artist_chart(self):
|
|
||||||
"""
|
|
||||||
most recent artist chart for the group
|
|
||||||
@rtype: L{WeeklyArtistChart}
|
|
||||||
"""
|
|
||||||
return self.get_weekly_artist_chart()
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_artist_chart_list(self):
|
|
||||||
"""
|
|
||||||
a list of all artist charts for this group in reverse-chronological
|
|
||||||
order. (that means 0th chart is the most recent chart)
|
|
||||||
@rtype: L{lazylist} of L{WeeklyArtistChart}
|
|
||||||
"""
|
|
||||||
wcl = list(self.weekly_chart_list)
|
|
||||||
wcl.reverse()
|
|
||||||
@lazylist
|
|
||||||
def gen(lst):
|
|
||||||
for wc in wcl:
|
|
||||||
yield self.get_weekly_artist_chart(wc.start, wc.end)
|
|
||||||
return gen()
|
|
||||||
|
|
||||||
def get_weekly_track_chart(self, start = None, end = None):
|
|
||||||
"""
|
|
||||||
Get a track chart for the group, for a given date range.
|
|
||||||
If no date range is supplied, it will return the most
|
|
||||||
recent artist chart for the group.
|
|
||||||
|
|
||||||
@param start: the date at which the chart should start from (optional)
|
|
||||||
@type start: C{datetime.datetime}
|
|
||||||
@param end: the date at which the chart should end on (optional)
|
|
||||||
@type end: C{datetime.datetime}
|
|
||||||
|
|
||||||
@return: a track chart for the group
|
|
||||||
@rtype: L{WeeklyTrackChart}
|
|
||||||
|
|
||||||
@raise InvalidParametersError: Both start and end parameter have to be either
|
|
||||||
provided or not provided. Providing only one of
|
|
||||||
them will raise an exception.
|
|
||||||
"""
|
|
||||||
params = self._default_params({'method': 'group.getWeeklyTrackChart'})
|
|
||||||
params = WeeklyChart._check_chart_params(params, start, end)
|
|
||||||
data = self._api._fetch_data(params).find('weeklytrackchart')
|
|
||||||
return WeeklyTrackChart.create_from_data(self._api, self, data)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_track_chart(self):
|
|
||||||
"""
|
|
||||||
most recent track chart for the group
|
|
||||||
@rtype: L{WeeklyTrackChart}
|
|
||||||
"""
|
|
||||||
return self.get_weekly_track_chart()
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_track_chart_list(self):
|
|
||||||
"""
|
|
||||||
a list of all track charts for this group in reverse-chronological
|
|
||||||
order. (that means 0th chart is the most recent chart)
|
|
||||||
@rtype: L{lazylist} of L{WeeklyTrackChart}
|
|
||||||
"""
|
|
||||||
wcl = list(self.weekly_chart_list)
|
|
||||||
wcl.reverse()
|
|
||||||
@lazylist
|
|
||||||
def gen(lst):
|
|
||||||
for wc in wcl:
|
|
||||||
yield self.get_weekly_track_chart(wc.start, wc.end)
|
|
||||||
return gen()
|
|
||||||
|
|
||||||
def get_weekly_tag_chart(self, start = None, end = None):
|
|
||||||
"""
|
|
||||||
Get a tag chart for the group, for a given date range.
|
|
||||||
If no date range is supplied, it will return the most
|
|
||||||
recent tag chart for the group.
|
|
||||||
|
|
||||||
@param start: the date at which the chart should start from (optional)
|
|
||||||
@type start: C{datetime.datetime}
|
|
||||||
@param end: the date at which the chart should end on (optional)
|
|
||||||
@type end: C{datetime.datetime}
|
|
||||||
|
|
||||||
@return: a tag chart for the group
|
|
||||||
@rtype: L{WeeklyTagChart}
|
|
||||||
|
|
||||||
@raise InvalidParametersError: Both start and end parameter have to be either
|
|
||||||
provided or not provided. Providing only one of
|
|
||||||
them will raise an exception.
|
|
||||||
|
|
||||||
@note: This method is a composite method. It is not provided directly by the
|
|
||||||
last.fm API. It uses other methods to collect the data, analyzes it and
|
|
||||||
creates a chart. So this method is a little heavy to call, as it does
|
|
||||||
mulitple calls to the API.
|
|
||||||
"""
|
|
||||||
WeeklyChart._check_chart_params({}, start, end)
|
|
||||||
return WeeklyTagChart.create_from_data(self._api, self, start, end)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_tag_chart(self):
|
|
||||||
"""
|
|
||||||
most recent tag chart for the group
|
|
||||||
@rtype: L{WeeklyTagChart}
|
|
||||||
"""
|
|
||||||
return self.get_weekly_tag_chart()
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_tag_chart_list(self):
|
|
||||||
"""
|
|
||||||
a list of all tag charts for this group in reverse-chronological
|
|
||||||
order. (that means 0th chart is the most recent chart)
|
|
||||||
@rtype: L{lazylist} of L{WeeklyTagChart}
|
|
||||||
"""
|
|
||||||
wcl = list(self.weekly_chart_list)
|
|
||||||
wcl.reverse()
|
|
||||||
@lazylist
|
|
||||||
def gen(lst):
|
|
||||||
for wc in wcl:
|
|
||||||
try:
|
|
||||||
yield self.get_weekly_tag_chart(wc.start, wc.end)
|
|
||||||
except LastfmError:
|
|
||||||
pass
|
|
||||||
return gen()
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@depaginate
|
@depaginate
|
||||||
|
|
|
@ -10,5 +10,8 @@ from lastfm.mixins.searchable import Searchable
|
||||||
from lastfm.mixins.sharable import Sharable
|
from lastfm.mixins.sharable import Sharable
|
||||||
from lastfm.mixins.shoutable import Shoutable
|
from lastfm.mixins.shoutable import Shoutable
|
||||||
from lastfm.mixins.taggable import Taggable
|
from lastfm.mixins.taggable import Taggable
|
||||||
|
from lastfm.mixins.chartable import (
|
||||||
|
AlbumChartable, ArtistChartable, TrackChartable, TagChartable)
|
||||||
|
|
||||||
__all__ = ['Cacheable', 'Searchable', 'Sharable', 'Shoutable', 'Taggable']
|
__all__ = ['Cacheable', 'Searchable', 'Sharable', 'Shoutable', 'Taggable'
|
||||||
|
'AlbumChartable', 'ArtistChartable', 'TrackChartable', 'TagChartable']
|
|
@ -0,0 +1,432 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
|
||||||
|
__version__ = "0.2"
|
||||||
|
__license__ = "GNU Lesser General Public License"
|
||||||
|
__package__ = "lastfm.mixins"
|
||||||
|
|
||||||
|
from lastfm.lazylist import lazylist
|
||||||
|
from lastfm.decorators import cached_property
|
||||||
|
|
||||||
|
class Chartable(object):
|
||||||
|
def init(self, api):
|
||||||
|
self._api = api
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def weekly_chart_list(self):
|
||||||
|
"""
|
||||||
|
a list of available weekly charts for this group
|
||||||
|
@rtype: L{list} of L{WeeklyChart}
|
||||||
|
"""
|
||||||
|
from lastfm.chart import WeeklyChart
|
||||||
|
params = self._default_params(
|
||||||
|
{'method': '%s.getWeeklyChartList' % self.__class__.__name__.lower()})
|
||||||
|
data = self._api._fetch_data(params).find('weeklychartlist')
|
||||||
|
return [
|
||||||
|
WeeklyChart.create_from_data(self._api, self, c)
|
||||||
|
for c in data.findall('chart')
|
||||||
|
]
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def monthly_chart_list(self):
|
||||||
|
from lastfm.chart import MonthlyChart
|
||||||
|
return MonthlyChart.get_chart_list(self)
|
||||||
|
|
||||||
|
def _default_params(self, extra_params = None):
|
||||||
|
if extra_params is not None:
|
||||||
|
return extra_params
|
||||||
|
else:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
class AlbumChartable(Chartable):
|
||||||
|
def get_weekly_album_chart(self, start = None, end = None):
|
||||||
|
"""
|
||||||
|
Get an album chart for the group, for a given date range.
|
||||||
|
If no date range is supplied, it will return the most
|
||||||
|
recent album chart for the group.
|
||||||
|
|
||||||
|
@param start: the date at which the chart should start from (optional)
|
||||||
|
@type start: C{datetime.datetime}
|
||||||
|
@param end: the date at which the chart should end on (optional)
|
||||||
|
@type end: C{datetime.datetime}
|
||||||
|
|
||||||
|
@return: an album chart for the group
|
||||||
|
@rtype: L{WeeklyAlbumChart}
|
||||||
|
|
||||||
|
@raise InvalidParametersError: Both start and end parameter have to be either
|
||||||
|
provided or not provided. Providing only one of
|
||||||
|
them will raise an exception.
|
||||||
|
"""
|
||||||
|
from lastfm.chart import WeeklyChart, WeeklyAlbumChart
|
||||||
|
params = self._default_params(
|
||||||
|
{'method': '%s.getWeeklyAlbumChart' % self.__class__.__name__.lower()})
|
||||||
|
params = WeeklyChart._check_chart_params(params, self, start, end)
|
||||||
|
data = self._api._fetch_data(params).find('weeklyalbumchart')
|
||||||
|
return WeeklyAlbumChart.create_from_data(self._api, self, data)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_weekly_album_chart(self):
|
||||||
|
"""
|
||||||
|
most recent album chart for the group
|
||||||
|
@rtype: L{WeeklyAlbumChart}
|
||||||
|
"""
|
||||||
|
return self.get_weekly_album_chart()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def weekly_album_chart_list(self):
|
||||||
|
"""
|
||||||
|
a list of all album charts for this group in reverse-chronological
|
||||||
|
order. (that means 0th chart is the most recent chart)
|
||||||
|
@rtype: L{lazylist} of L{WeeklyAlbumChart}
|
||||||
|
"""
|
||||||
|
wcl = list(self.weekly_chart_list)
|
||||||
|
wcl.reverse()
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
for wc in wcl:
|
||||||
|
try:
|
||||||
|
yield self.get_weekly_album_chart(wc.start, wc.end)
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
return gen()
|
||||||
|
|
||||||
|
def get_monthly_album_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import MonthlyAlbumChart
|
||||||
|
return MonthlyAlbumChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_monthly_album_chart(self):
|
||||||
|
return self.get_monthly_album_chart()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def monthly_album_chart_list(self):
|
||||||
|
mcl = list(self.monthly_chart_list)
|
||||||
|
mcl.reverse()
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
for mc in mcl:
|
||||||
|
try:
|
||||||
|
yield self.get_monthly_album_chart(mc.start, mc.end)
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
return gen()
|
||||||
|
|
||||||
|
def get_quaterly_album_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import QuaterlyAlbumChart
|
||||||
|
return QuaterlyAlbumChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_quaterly_album_chart(self):
|
||||||
|
return self.get_quaterly_album_chart()
|
||||||
|
|
||||||
|
def get_half_yearly_album_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import HalfYearlyAlbumChart
|
||||||
|
return HalfYearlyAlbumChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_half_yearly_album_chart(self):
|
||||||
|
return self.get_half_yearly_album_chart()
|
||||||
|
|
||||||
|
def get_yearly_album_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import YearlyAlbumChart
|
||||||
|
return YearlyAlbumChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_yearly_album_chart(self):
|
||||||
|
return self.get_yearly_album_chart()
|
||||||
|
|
||||||
|
class ArtistChartable(Chartable):
|
||||||
|
def get_weekly_artist_chart(self, start = None, end = None):
|
||||||
|
"""
|
||||||
|
Get an artist chart for the group, for a given date range.
|
||||||
|
If no date range is supplied, it will return the most
|
||||||
|
recent artist chart for the group.
|
||||||
|
|
||||||
|
@param start: the date at which the chart should start from (optional)
|
||||||
|
@type start: C{datetime.datetime}
|
||||||
|
@param end: the date at which the chart should end on (optional)
|
||||||
|
@type end: C{datetime.datetime}
|
||||||
|
|
||||||
|
@return: an artist chart for the group
|
||||||
|
@rtype: L{WeeklyArtistChart}
|
||||||
|
|
||||||
|
@raise InvalidParametersError: Both start and end parameter have to be either
|
||||||
|
provided or not provided. Providing only one of
|
||||||
|
them will raise an exception.
|
||||||
|
"""
|
||||||
|
from lastfm.chart import WeeklyChart, WeeklyArtistChart
|
||||||
|
params = self._default_params(
|
||||||
|
{'method': '%s.getWeeklyArtistChart' % self.__class__.__name__.lower()})
|
||||||
|
params = WeeklyChart._check_chart_params(params, self, start, end)
|
||||||
|
data = self._api._fetch_data(params).find('weeklyartistchart')
|
||||||
|
return WeeklyArtistChart.create_from_data(self._api, self, data)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_weekly_artist_chart(self):
|
||||||
|
"""
|
||||||
|
most recent artist chart for the group
|
||||||
|
@rtype: L{WeeklyArtistChart}
|
||||||
|
"""
|
||||||
|
return self.get_weekly_artist_chart()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def weekly_artist_chart_list(self):
|
||||||
|
"""
|
||||||
|
a list of all artist charts for this group in reverse-chronological
|
||||||
|
order. (that means 0th chart is the most recent chart)
|
||||||
|
@rtype: L{lazylist} of L{WeeklyArtistChart}
|
||||||
|
"""
|
||||||
|
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()
|
||||||
|
|
||||||
|
def get_monthly_artist_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import MonthlyArtistChart
|
||||||
|
return MonthlyArtistChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_monthly_artist_chart(self):
|
||||||
|
return self.get_monthly_artist_chart()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def monthly_artist_chart_list(self):
|
||||||
|
mcl = list(self.monthly_chart_list)
|
||||||
|
mcl.reverse()
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
for mc in mcl:
|
||||||
|
try:
|
||||||
|
yield self.get_monthly_artist_chart(mc.start, mc.end)
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
return gen()
|
||||||
|
|
||||||
|
def get_quaterly_artist_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import QuaterlyArtistChart
|
||||||
|
return QuaterlyArtistChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_quaterly_artist_chart(self):
|
||||||
|
return self.get_quaterly_artist_chart()
|
||||||
|
|
||||||
|
def get_half_yearly_artist_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import HalfYearlyArtistChart
|
||||||
|
return HalfYearlyArtistChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_half_yearly_artist_chart(self):
|
||||||
|
return self.get_half_yearly_artist_chart()
|
||||||
|
|
||||||
|
def get_yearly_artist_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import YearlyArtistChart
|
||||||
|
return YearlyArtistChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_yearly_album_chart(self):
|
||||||
|
return self.get_yearly_artist_chart()
|
||||||
|
|
||||||
|
class TrackChartable(Chartable):
|
||||||
|
def get_weekly_track_chart(self, start = None, end = None):
|
||||||
|
"""
|
||||||
|
Get a track chart for the group, for a given date range.
|
||||||
|
If no date range is supplied, it will return the most
|
||||||
|
recent artist chart for the group.
|
||||||
|
|
||||||
|
@param start: the date at which the chart should start from (optional)
|
||||||
|
@type start: C{datetime.datetime}
|
||||||
|
@param end: the date at which the chart should end on (optional)
|
||||||
|
@type end: C{datetime.datetime}
|
||||||
|
|
||||||
|
@return: a track chart for the group
|
||||||
|
@rtype: L{WeeklyTrackChart}
|
||||||
|
|
||||||
|
@raise InvalidParametersError: Both start and end parameter have to be either
|
||||||
|
provided or not provided. Providing only one of
|
||||||
|
them will raise an exception.
|
||||||
|
"""
|
||||||
|
from lastfm.chart import WeeklyChart, WeeklyTrackChart
|
||||||
|
params = self._default_params(
|
||||||
|
{'method': '%s.getWeeklyTrackChart' % self.__class__.__name__.lower()})
|
||||||
|
params = WeeklyChart._check_chart_params(params, self, start, end)
|
||||||
|
data = self._api._fetch_data(params).find('weeklytrackchart')
|
||||||
|
return WeeklyTrackChart.create_from_data(self._api, self, data)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_weekly_track_chart(self):
|
||||||
|
"""
|
||||||
|
most recent track chart for the group
|
||||||
|
@rtype: L{WeeklyTrackChart}
|
||||||
|
"""
|
||||||
|
return self.get_weekly_track_chart()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def weekly_track_chart_list(self):
|
||||||
|
"""
|
||||||
|
a list of all track charts for this group in reverse-chronological
|
||||||
|
order. (that means 0th chart is the most recent chart)
|
||||||
|
@rtype: L{lazylist} of L{WeeklyTrackChart}
|
||||||
|
"""
|
||||||
|
wcl = list(self.weekly_chart_list)
|
||||||
|
wcl.reverse()
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
for wc in wcl:
|
||||||
|
try:
|
||||||
|
yield self.get_weekly_track_chart(wc.start, wc.end)
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
return gen()
|
||||||
|
|
||||||
|
def get_monthly_track_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import MonthlyTrackChart
|
||||||
|
return MonthlyTrackChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_monthly_track_chart(self):
|
||||||
|
return self.get_monthly_track_chart()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def monthly_track_chart_list(self):
|
||||||
|
mcl = list(self.monthly_chart_list)
|
||||||
|
mcl.reverse()
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
for mc in mcl:
|
||||||
|
try:
|
||||||
|
yield self.get_monthly_track_chart(mc.start, mc.end)
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
return gen()
|
||||||
|
|
||||||
|
def get_quaterly_track_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import QuaterlyTrackChart
|
||||||
|
return QuaterlyTrackChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_quaterly_track_chart(self):
|
||||||
|
return self.get_quaterly_track_chart()
|
||||||
|
|
||||||
|
def get_half_yearly_track_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import HalfYearlyTrackChart
|
||||||
|
return HalfYearlyTrackChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_half_yearly_artist_chart(self):
|
||||||
|
return self.get_half_yearly_track_chart()
|
||||||
|
|
||||||
|
def get_yearly_track_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import YearlyTrackChart
|
||||||
|
return YearlyTrackChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_yearly_album_chart(self):
|
||||||
|
return self.get_yearly_track_chart()
|
||||||
|
|
||||||
|
class TagChartable(Chartable):
|
||||||
|
def get_weekly_tag_chart(self, start = None, end = None):
|
||||||
|
"""
|
||||||
|
Get a tag chart for the group, for a given date range.
|
||||||
|
If no date range is supplied, it will return the most
|
||||||
|
recent tag chart for the group.
|
||||||
|
|
||||||
|
@param start: the date at which the chart should start from (optional)
|
||||||
|
@type start: C{datetime.datetime}
|
||||||
|
@param end: the date at which the chart should end on (optional)
|
||||||
|
@type end: C{datetime.datetime}
|
||||||
|
|
||||||
|
@return: a tag chart for the group
|
||||||
|
@rtype: L{WeeklyTagChart}
|
||||||
|
|
||||||
|
@raise InvalidParametersError: Both start and end parameter have to be either
|
||||||
|
provided or not provided. Providing only one of
|
||||||
|
them will raise an exception.
|
||||||
|
|
||||||
|
@note: This method is a composite method. It is not provided directly by the
|
||||||
|
last.fm API. It uses other methods to collect the data, analyzes it and
|
||||||
|
creates a chart. So this method is a little heavy to call, as it does
|
||||||
|
mulitple calls to the API.
|
||||||
|
"""
|
||||||
|
from lastfm.chart import WeeklyChart, WeeklyTagChart
|
||||||
|
WeeklyChart._check_chart_params({}, self, start, end)
|
||||||
|
return WeeklyTagChart.create_from_data(self._api, self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_weekly_tag_chart(self):
|
||||||
|
"""
|
||||||
|
most recent tag chart for the group
|
||||||
|
@rtype: L{WeeklyTagChart}
|
||||||
|
"""
|
||||||
|
return self.get_weekly_tag_chart()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def weekly_tag_chart_list(self):
|
||||||
|
"""
|
||||||
|
a list of all tag charts for this group in reverse-chronological
|
||||||
|
order. (that means 0th chart is the most recent chart)
|
||||||
|
@rtype: L{lazylist} of L{WeeklyTagChart}
|
||||||
|
"""
|
||||||
|
wcl = list(self.weekly_chart_list)
|
||||||
|
wcl.reverse()
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
for wc in wcl:
|
||||||
|
try:
|
||||||
|
yield self.get_weekly_tag_chart(wc.start, wc.end)
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
return gen()
|
||||||
|
|
||||||
|
def get_monthly_tag_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import MonthlyTagChart
|
||||||
|
return MonthlyTagChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_monthly_tag_chart(self):
|
||||||
|
return self.get_monthly_tag_chart()
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def monthly_tag_chart_list(self):
|
||||||
|
mcl = list(self.monthly_chart_list)
|
||||||
|
mcl.reverse()
|
||||||
|
@lazylist
|
||||||
|
def gen(lst):
|
||||||
|
for mc in mcl:
|
||||||
|
try:
|
||||||
|
yield self.get_monthly_tag_chart(mc.start, mc.end)
|
||||||
|
except LastfmError:
|
||||||
|
pass
|
||||||
|
return gen()
|
||||||
|
|
||||||
|
def get_quaterly_tag_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import QuaterlyTagChart
|
||||||
|
return QuaterlyTagChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_quaterly_tag_chart(self):
|
||||||
|
return self.get_quaterly_tag_chart()
|
||||||
|
|
||||||
|
def get_half_yearly_tag_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import HalfYearlyTagChart
|
||||||
|
return HalfYearlyTagChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_half_yearly_artist_chart(self):
|
||||||
|
return self.get_half_yearly_tag_chart()
|
||||||
|
|
||||||
|
def get_yearly_tag_chart(self, start = None, end = None):
|
||||||
|
from lastfm.chart import YearlyTagChart
|
||||||
|
return YearlyTagChart.create_from_data(self, start, end)
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def recent_yearly_album_chart(self):
|
||||||
|
return self.get_yearly_tag_chart()
|
||||||
|
|
||||||
|
from lastfm.error import LastfmError
|
||||||
|
|
|
@ -6,11 +6,11 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixins import Cacheable, Searchable
|
from lastfm.mixins import (
|
||||||
from lastfm.lazylist import lazylist
|
Cacheable, Searchable, ArtistChartable)
|
||||||
from lastfm.decorators import cached_property, top_property
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
class Tag(LastfmBase, Cacheable, Searchable):
|
class Tag(LastfmBase, Cacheable, Searchable, ArtistChartable):
|
||||||
"""A class representing a tag."""
|
"""A class representing a tag."""
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
|
@ -21,6 +21,8 @@ class Tag(LastfmBase, Cacheable, Searchable):
|
||||||
**kwargs):
|
**kwargs):
|
||||||
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")
|
||||||
|
ArtistChartable.init(self, api)
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
self._name = name
|
||||||
self._url = url
|
self._url = url
|
||||||
|
@ -172,44 +174,7 @@ class Tag(LastfmBase, Cacheable, Searchable):
|
||||||
def playlist(self):
|
def playlist(self):
|
||||||
return Playlist.fetch(self._api,
|
return Playlist.fetch(self._api,
|
||||||
"lastfm://playlist/tag/%s/freetracks" % self.name)
|
"lastfm://playlist/tag/%s/freetracks" % self.name)
|
||||||
|
|
||||||
@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_chart_params(params, start, end)
|
|
||||||
data = self._api._fetch_data(params).find('weeklyartistchart')
|
|
||||||
return WeeklyArtistChart.create_from_data(self._api, self, data)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_artist_chart(self):
|
|
||||||
return self.get_weekly_artist_chart()
|
|
||||||
|
|
||||||
@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'}
|
||||||
|
|
125
lastfm/user.py
125
lastfm/user.py
|
@ -6,12 +6,16 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixins import Cacheable, Shoutable
|
from lastfm.mixins import (
|
||||||
from lastfm.lazylist import lazylist
|
Cacheable, Shoutable, AlbumChartable,
|
||||||
|
ArtistChartable, TrackChartable, TagChartable)
|
||||||
import lastfm.playlist
|
import lastfm.playlist
|
||||||
from lastfm.decorators import cached_property, top_property, authentication_required, depaginate
|
from lastfm.decorators import (
|
||||||
|
cached_property, top_property, authentication_required, depaginate)
|
||||||
|
|
||||||
class User(LastfmBase, Cacheable, Shoutable):
|
class User(LastfmBase, Cacheable, Shoutable,
|
||||||
|
AlbumChartable, ArtistChartable,
|
||||||
|
TrackChartable, TagChartable):
|
||||||
"""A class representing an user."""
|
"""A class representing an user."""
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
|
@ -24,6 +28,11 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
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)
|
||||||
|
AlbumChartable.init(self, api)
|
||||||
|
ArtistChartable.init(self, api)
|
||||||
|
TrackChartable.init(self, api)
|
||||||
|
TagChartable.init(self, api)
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
self._name = name
|
||||||
self._real_name = real_name
|
self._real_name = real_name
|
||||||
|
@ -478,113 +487,6 @@ class User(LastfmBase, Cacheable, Shoutable):
|
||||||
"""top tag of the user"""
|
"""top tag of the user"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_chart_list(self):
|
|
||||||
params = self._default_params({'method': 'user.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_album_chart(self,
|
|
||||||
start = None,
|
|
||||||
end = None):
|
|
||||||
params = self._default_params({'method': 'user.getWeeklyAlbumChart'})
|
|
||||||
params = WeeklyChart._check_chart_params(params, start, end)
|
|
||||||
data = self._api._fetch_data(params).find('weeklyalbumchart')
|
|
||||||
return WeeklyAlbumChart.create_from_data(self._api, self, data)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_album_chart(self):
|
|
||||||
return self.get_weekly_album_chart()
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_album_chart_list(self):
|
|
||||||
wcl = list(self.weekly_chart_list)
|
|
||||||
wcl.reverse()
|
|
||||||
@lazylist
|
|
||||||
def gen(lst):
|
|
||||||
for wc in wcl:
|
|
||||||
try:
|
|
||||||
yield self.get_weekly_album_chart(wc.start, wc.end)
|
|
||||||
except LastfmError:
|
|
||||||
pass
|
|
||||||
return gen()
|
|
||||||
|
|
||||||
def get_weekly_artist_chart(self,
|
|
||||||
start = None,
|
|
||||||
end = None):
|
|
||||||
params = self._default_params({'method': 'user.getWeeklyArtistChart'})
|
|
||||||
params = WeeklyChart._check_chart_params(params, start, end)
|
|
||||||
data = self._api._fetch_data(params).find('weeklyartistchart')
|
|
||||||
return WeeklyArtistChart.create_from_data(self._api, self, data)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_artist_chart(self):
|
|
||||||
return self.get_weekly_artist_chart()
|
|
||||||
|
|
||||||
@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()
|
|
||||||
|
|
||||||
def get_weekly_track_chart(self,
|
|
||||||
start = None,
|
|
||||||
end = None):
|
|
||||||
params = self._default_params({'method': 'user.getWeeklyTrackChart'})
|
|
||||||
params = WeeklyChart._check_chart_params(params, start, end)
|
|
||||||
data = self._api._fetch_data(params).find('weeklytrackchart')
|
|
||||||
return WeeklyTrackChart.create_from_data(self._api, self, data)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_track_chart(self):
|
|
||||||
return self.get_weekly_track_chart()
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_track_chart_list(self):
|
|
||||||
wcl = list(self.weekly_chart_list)
|
|
||||||
wcl.reverse()
|
|
||||||
@lazylist
|
|
||||||
def gen(lst):
|
|
||||||
for wc in wcl:
|
|
||||||
try:
|
|
||||||
yield self.get_weekly_track_chart(wc.start, wc.end)
|
|
||||||
except LastfmError:
|
|
||||||
pass
|
|
||||||
return gen()
|
|
||||||
|
|
||||||
def get_weekly_tag_chart(self,
|
|
||||||
start = None,
|
|
||||||
end = None):
|
|
||||||
WeeklyChart._check_chart_params({}, start, end)
|
|
||||||
return WeeklyTagChart.create_from_data(self._api, self, start, end)
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def recent_weekly_tag_chart(self):
|
|
||||||
return self.get_weekly_tag_chart()
|
|
||||||
|
|
||||||
@cached_property
|
|
||||||
def weekly_tag_chart_list(self):
|
|
||||||
wcl = list(self.weekly_chart_list)
|
|
||||||
wcl.reverse()
|
|
||||||
@lazylist
|
|
||||||
def gen(lst):
|
|
||||||
for wc in wcl:
|
|
||||||
try:
|
|
||||||
yield self.get_weekly_tag_chart(wc.start, wc.end)
|
|
||||||
except LastfmError:
|
|
||||||
pass
|
|
||||||
return gen()
|
|
||||||
|
|
||||||
def compare(self, other, limit = None):
|
def compare(self, other, limit = None):
|
||||||
if isinstance(other, User):
|
if isinstance(other, User):
|
||||||
other = other.name
|
other = other.name
|
||||||
|
@ -920,4 +822,3 @@ from lastfm.stats import Stats
|
||||||
from lastfm.tag import Tag
|
from lastfm.tag import Tag
|
||||||
from lastfm.tasteometer import Tasteometer
|
from lastfm.tasteometer import Tasteometer
|
||||||
from lastfm.track import Track
|
from lastfm.track import Track
|
||||||
from lastfm.chart import WeeklyChart, WeeklyAlbumChart, WeeklyArtistChart, WeeklyTrackChart, WeeklyTagChart
|
|
||||||
|
|
Loading…
Reference in New Issue