* converted all mixin classes to class decorator functions
* renamed all mixin modules to avoid name conflict * removed mixin classes from class inheritence list and put then as class decoratorsmaster
parent
d709434a7b
commit
c36d689690
|
@ -7,10 +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, Searchable, Taggable
|
from lastfm.mixins import cacheable, searchable, taggable
|
||||||
from lastfm.decorators import cached_property, top_property
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
class Album(LastfmBase, Cacheable, Searchable, Taggable):
|
@taggable
|
||||||
|
@searchable
|
||||||
|
@cacheable
|
||||||
|
class Album(LastfmBase):
|
||||||
"""A class representing an album."""
|
"""A class representing an album."""
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
|
@ -58,7 +61,6 @@ class Album(LastfmBase, Cacheable, Searchable, Taggable):
|
||||||
"""
|
"""
|
||||||
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")
|
||||||
Taggable.init(self, api)
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
self._name = name
|
||||||
self._artist = artist
|
self._artist = artist
|
||||||
|
|
|
@ -7,10 +7,15 @@ __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, Sharable, Shoutable, Taggable
|
from lastfm.mixins import cacheable, searchable, sharable, shoutable, taggable
|
||||||
from lastfm.decorators import cached_property, top_property
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
class Artist(LastfmBase, Cacheable, Sharable, Shoutable, Searchable, Taggable):
|
@shoutable
|
||||||
|
@sharable
|
||||||
|
@taggable
|
||||||
|
@searchable
|
||||||
|
@cacheable
|
||||||
|
class Artist(LastfmBase):
|
||||||
"""A class representing an artist."""
|
"""A class representing an artist."""
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
|
@ -55,9 +60,6 @@ class Artist(LastfmBase, Cacheable, Sharable, Shoutable, Searchable, Taggable):
|
||||||
"""
|
"""
|
||||||
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")
|
||||||
Sharable.init(self, api)
|
|
||||||
Shoutable.init(self, api)
|
|
||||||
Taggable.init(self, api)
|
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._name = name
|
self._name = name
|
||||||
|
@ -402,16 +404,16 @@ class Artist(LastfmBase, Cacheable, Sharable, Shoutable, Searchable, Taggable):
|
||||||
listeners = int(data.findtext('stats/listeners')),
|
listeners = int(data.findtext('stats/listeners')),
|
||||||
playcount = int(data.findtext('stats/playcount'))
|
playcount = int(data.findtext('stats/playcount'))
|
||||||
)
|
)
|
||||||
self._similar = [
|
# self._similar = [
|
||||||
Artist(
|
# Artist(
|
||||||
self._api,
|
# self._api,
|
||||||
subject = self,
|
# subject = self,
|
||||||
name = a.findtext('name'),
|
# name = a.findtext('name'),
|
||||||
url = a.findtext('url'),
|
# url = a.findtext('url'),
|
||||||
image = dict([(i.get('size'), i.text) for i in a.findall('image')])
|
# image = dict([(i.get('size'), i.text) for i in a.findall('image')])
|
||||||
)
|
# )
|
||||||
for a in data.findall('similar/artist')
|
# for a in data.findall('similar/artist')
|
||||||
]
|
# ]
|
||||||
self._top_tags = [
|
self._top_tags = [
|
||||||
Tag(
|
Tag(
|
||||||
self._api,
|
self._api,
|
||||||
|
|
|
@ -6,10 +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
|
from lastfm.mixins import cacheable
|
||||||
from operator import xor
|
from operator import xor
|
||||||
|
|
||||||
class Chart(LastfmBase, Cacheable):
|
@cacheable
|
||||||
|
class Chart(LastfmBase):
|
||||||
"""The base class for all the chart classes"""
|
"""The base class for all the chart classes"""
|
||||||
|
|
||||||
def init(self, subject, start, end, stats = None):
|
def init(self, subject, start, end, stats = None):
|
||||||
|
@ -435,7 +436,7 @@ class RollingChart(Chart):
|
||||||
end = end,
|
end = end,
|
||||||
stats = Stats(
|
stats = Stats(
|
||||||
subject = subject,
|
subject = subject,
|
||||||
**{count_attribute[1:]: sum([a.stats.__dict__[count_attribute] for a in items])}
|
**{count_attribute[1:]: sum(a.stats.__dict__[count_attribute] for a in items)}
|
||||||
),
|
),
|
||||||
**{"%ss" % chart_type: items}
|
**{"%ss" % chart_type: items}
|
||||||
)
|
)
|
||||||
|
@ -467,7 +468,7 @@ class RollingTagChart(TagChart):
|
||||||
key_func = lambda tag: tag.name
|
key_func = lambda tag: tag.name
|
||||||
chart = super(cls.mro()[3], cls).create_from_data(
|
chart = super(cls.mro()[3], cls).create_from_data(
|
||||||
subject, key_func, start, end)
|
subject, key_func, start, end)
|
||||||
count_sum = sum([t.stats.count for t in chart.tags])
|
count_sum = sum(t.stats.count for t in chart.tags)
|
||||||
for t in chart.tags:
|
for t in chart.tags:
|
||||||
t.stats.__dict__['_count'] /= count_sum
|
t.stats.__dict__['_count'] /= count_sum
|
||||||
return chart
|
return chart
|
||||||
|
|
|
@ -7,9 +7,12 @@ __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, Sharable, Shoutable
|
from lastfm.mixins import cacheable, sharable, shoutable
|
||||||
|
|
||||||
class Event(LastfmBase, Cacheable, Sharable, Shoutable):
|
@shoutable
|
||||||
|
@sharable
|
||||||
|
@cacheable
|
||||||
|
class Event(LastfmBase):
|
||||||
"""A class representing an event."""
|
"""A class representing an event."""
|
||||||
STATUS_ATTENDING = 0
|
STATUS_ATTENDING = 0
|
||||||
STATUS_MAYBE = 1
|
STATUS_MAYBE = 1
|
||||||
|
@ -59,8 +62,6 @@ class Event(LastfmBase, Cacheable, Sharable, 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")
|
||||||
Sharable.init(self, api)
|
|
||||||
Shoutable.init(self, api)
|
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._id = id
|
self._id = id
|
||||||
|
|
|
@ -7,7 +7,7 @@ __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 cacheable
|
||||||
from lastfm.decorators import cached_property, top_property, depaginate
|
from lastfm.decorators import cached_property, top_property, depaginate
|
||||||
|
|
||||||
class Geo(object):
|
class Geo(object):
|
||||||
|
@ -145,7 +145,8 @@ class Geo(object):
|
||||||
for t in data.findall('track')
|
for t in data.findall('track')
|
||||||
]
|
]
|
||||||
|
|
||||||
class Location(LastfmBase, Cacheable):
|
@cacheable
|
||||||
|
class Location(LastfmBase):
|
||||||
"""A class representing a location of an event"""
|
"""A class representing a location of an event"""
|
||||||
XMLNS = "http://www.w3.org/2003/01/geo/wgs84_pos#"
|
XMLNS = "http://www.w3.org/2003/01/geo/wgs84_pos#"
|
||||||
|
|
||||||
|
@ -324,7 +325,8 @@ class Location(LastfmBase, Cacheable):
|
||||||
else:
|
else:
|
||||||
return "<lastfm.geo.Location: %s>" % self.city
|
return "<lastfm.geo.Location: %s>" % self.city
|
||||||
|
|
||||||
class Country(LastfmBase, Cacheable):
|
@cacheable
|
||||||
|
class Country(LastfmBase):
|
||||||
"""A class representing a country."""
|
"""A class representing a country."""
|
||||||
ISO_CODES = {
|
ISO_CODES = {
|
||||||
'AD': 'Andorra',
|
'AD': 'Andorra',
|
||||||
|
|
|
@ -7,13 +7,12 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixins import (
|
from lastfm.mixins import cacheable, chartable
|
||||||
Cacheable, AlbumChartable, ArtistChartable,
|
|
||||||
TrackChartable, TagChartable)
|
|
||||||
from lastfm.decorators import cached_property, depaginate
|
from lastfm.decorators import cached_property, depaginate
|
||||||
|
|
||||||
class Group(LastfmBase, Cacheable, AlbumChartable,
|
@chartable(['album', 'artist', 'track', 'tag'])
|
||||||
ArtistChartable, TrackChartable, TagChartable):
|
@cacheable
|
||||||
|
class Group(LastfmBase):
|
||||||
"""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):
|
||||||
"""
|
"""
|
||||||
|
@ -29,11 +28,7 @@ class Group(LastfmBase, Cacheable, AlbumChartable,
|
||||||
"""
|
"""
|
||||||
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
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,12 @@ __version__ = "0.2"
|
||||||
__license__ = "GNU Lesser General Public License"
|
__license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm.mixins"
|
__package__ = "lastfm.mixins"
|
||||||
|
|
||||||
from lastfm.mixins.cacheable import Cacheable
|
from lastfm.mixins._cacheable import cacheable
|
||||||
from lastfm.mixins.searchable import Searchable
|
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 (
|
from lastfm.mixins._chartable import chartable
|
||||||
AlbumChartable, ArtistChartable, TrackChartable, TagChartable)
|
|
||||||
|
|
||||||
__all__ = ['Cacheable', 'Searchable', 'Sharable', 'Shoutable', 'Taggable'
|
__all__ = ['cacheable', 'searchable', 'sharable', 'shoutable', 'taggable'
|
||||||
'AlbumChartable', 'ArtistChartable', 'TrackChartable', 'TagChartable']
|
'chartable']
|
|
@ -10,11 +10,25 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from dummy_threading import Lock
|
from dummy_threading import Lock
|
||||||
|
|
||||||
class Cacheable(object):
|
registry = {}
|
||||||
registry = {}
|
_lock = Lock()
|
||||||
_lock = Lock()
|
|
||||||
|
|
||||||
|
def register(ob, key):
|
||||||
|
if not ob.__class__ in registry:
|
||||||
|
registry[ob.__class__] = {}
|
||||||
|
if key in registry[ob.__class__]:
|
||||||
|
ob = registry[ob.__class__][key]
|
||||||
|
#print "already registered: %s" % repr(ob)
|
||||||
|
return (ob, True)
|
||||||
|
else:
|
||||||
|
#print "not already registered: %s" % ob.__class__
|
||||||
|
registry[ob.__class__][key] = ob
|
||||||
|
return (ob, False)
|
||||||
|
|
||||||
|
def cacheable(cls):
|
||||||
|
@classmethod
|
||||||
def __new__(cls, *args, **kwds):
|
def __new__(cls, *args, **kwds):
|
||||||
|
args = args[1:]
|
||||||
subject = None
|
subject = None
|
||||||
if 'subject' in kwds and not cls.__name__.startswith('Weekly'):
|
if 'subject' in kwds and not cls.__name__.startswith('Weekly'):
|
||||||
subject = kwds['subject']
|
subject = kwds['subject']
|
||||||
|
@ -29,29 +43,19 @@ class Cacheable(object):
|
||||||
key = cls._hash_func(*args, **kwds)
|
key = cls._hash_func(*args, **kwds)
|
||||||
if subject is not None:
|
if subject is not None:
|
||||||
key = (hash(subject), key)
|
key = (hash(subject), key)
|
||||||
|
|
||||||
Cacheable._lock.acquire()
|
with _lock:
|
||||||
try:
|
inst, already_registered = register(object.__new__(cls), key)
|
||||||
inst, already_registered = Cacheable.register(object.__new__(cls), key)
|
|
||||||
if not already_registered:
|
if not already_registered:
|
||||||
inst.init(*args, **kwds)
|
inst.init(*args, **kwds)
|
||||||
finally:
|
|
||||||
Cacheable._lock.release()
|
|
||||||
return inst
|
return inst
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def register(ob, key):
|
|
||||||
if not ob.__class__ in Cacheable.registry:
|
|
||||||
Cacheable.registry[ob.__class__] = {}
|
|
||||||
if key in Cacheable.registry[ob.__class__]:
|
|
||||||
ob = Cacheable.registry[ob.__class__][key]
|
|
||||||
#print "already registered: %s" % repr(ob)
|
|
||||||
return (ob, True)
|
|
||||||
else:
|
|
||||||
#print "not already registered: %s" % ob.__class__
|
|
||||||
Cacheable.registry[ob.__class__][key] = ob
|
|
||||||
return (ob, False)
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _hash_func(*args, **kwds):
|
def _hash_func(*args, **kwds):
|
||||||
raise NotImplementedError("The subclass must override this method")
|
raise NotImplementedError("The subclass must override this method")
|
||||||
|
|
||||||
|
cls.__new__ = __new__
|
||||||
|
if not hasattr(cls, '_hash_func'):
|
||||||
|
cls._hash_func = _hash_func
|
||||||
|
|
||||||
|
return cls
|
|
@ -0,0 +1,445 @@
|
||||||
|
#!/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
|
||||||
|
|
||||||
|
def chartable(chart_types):
|
||||||
|
def wrapper(cls):
|
||||||
|
@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 {}
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
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_artist_chart(self):
|
||||||
|
return self.get_yearly_artist_chart()
|
||||||
|
|
||||||
|
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_track_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_track_chart(self):
|
||||||
|
return self.get_yearly_track_chart()
|
||||||
|
|
||||||
|
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_tag_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_tag_chart(self):
|
||||||
|
return self.get_yearly_tag_chart()
|
||||||
|
|
||||||
|
cls.weekly_chart_list = weekly_chart_list
|
||||||
|
cls.monthly_chart_list = monthly_chart_list
|
||||||
|
if not hasattr(cls, '_default_params'):
|
||||||
|
cls._default_params = _default_params
|
||||||
|
|
||||||
|
method_names = [
|
||||||
|
'get_weekly_%s_chart', 'recent_weekly_%s_chart', 'weekly_%s_chart_list',
|
||||||
|
'get_monthly_%s_chart', 'recent_monthly_%s_chart', 'monthly_%s_chart_list',
|
||||||
|
'get_quaterly_%s_chart', 'recent_quaterly_%s_chart',
|
||||||
|
'get_half_yearly_%s_chart', 'recent_half_yearly_%s_chart',
|
||||||
|
'get_yearly_%s_chart', 'recent_yearly_%s_chart'
|
||||||
|
]
|
||||||
|
for chart_type in chart_types:
|
||||||
|
for method_name in method_names:
|
||||||
|
setattr(cls, method_name % chart_type, locals()[method_name % chart_type])
|
||||||
|
|
||||||
|
return cls
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
from lastfm.error import LastfmError
|
||||||
|
|
|
@ -7,7 +7,7 @@ __package__ = "lastfm.mixins"
|
||||||
|
|
||||||
from lastfm.decorators import depaginate
|
from lastfm.decorators import depaginate
|
||||||
|
|
||||||
class Searchable(object):
|
def searchable(cls):
|
||||||
@classmethod
|
@classmethod
|
||||||
@depaginate
|
@depaginate
|
||||||
def search(cls,
|
def search(cls,
|
||||||
|
@ -40,4 +40,10 @@ class Searchable(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _search_yield_func(api, search_term):
|
def _search_yield_func(api, search_term):
|
||||||
pass
|
raise NotImplementedError("the subclass should implement this method")
|
||||||
|
|
||||||
|
cls.search = search
|
||||||
|
if not hasattr(cls, '_search_yield_func'):
|
||||||
|
cls._search_yield_func = _search_yield_func
|
||||||
|
|
||||||
|
return cls
|
|
@ -5,10 +5,7 @@ __version__ = "0.2"
|
||||||
__license__ = "GNU Lesser General Public License"
|
__license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm.mixins"
|
__package__ = "lastfm.mixins"
|
||||||
|
|
||||||
class Sharable(object):
|
def sharable(cls):
|
||||||
def init(self, api):
|
|
||||||
self._api = api
|
|
||||||
|
|
||||||
def share(self, recipient, message = None):
|
def share(self, recipient, message = None):
|
||||||
from lastfm.user import User
|
from lastfm.user import User
|
||||||
params = self._default_params({'method': '%s.share' % self.__class__.__name__.lower()})
|
params = self._default_params({'method': '%s.share' % self.__class__.__name__.lower()})
|
||||||
|
@ -28,4 +25,10 @@ class Sharable(object):
|
||||||
if extra_params is not None:
|
if extra_params is not None:
|
||||||
return extra_params
|
return extra_params
|
||||||
else:
|
else:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
cls.share = share
|
||||||
|
if not hasattr(cls, '_default_params'):
|
||||||
|
cls._default_params = _default_params
|
||||||
|
|
||||||
|
return cls
|
|
@ -7,13 +7,10 @@ __package__ = "lastfm.mixins"
|
||||||
|
|
||||||
from lastfm.decorators import cached_property, top_property
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
class Shoutable(object):
|
def shoutable(cls):
|
||||||
def init(self, api):
|
|
||||||
self._api = api
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def shouts(self):
|
def shouts(self):
|
||||||
"""shouts for this ssubject"""
|
"""shouts for this %s""" % cls.__name__.lower()
|
||||||
from lastfm.shout import Shout
|
from lastfm.shout import Shout
|
||||||
from lastfm.user import User
|
from lastfm.user import User
|
||||||
params = self._default_params({'method': '%s.getShouts' % self.__class__.__name__.lower()})
|
params = self._default_params({'method': '%s.getShouts' % self.__class__.__name__.lower()})
|
||||||
|
@ -30,7 +27,7 @@ class Shoutable(object):
|
||||||
|
|
||||||
@top_property("shouts")
|
@top_property("shouts")
|
||||||
def recent_shout(self):
|
def recent_shout(self):
|
||||||
"""recent shout for this subject"""
|
"""recent shout for this %s""" % cls.__name__.lower()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _default_params(self, extra_params = None):
|
def _default_params(self, extra_params = None):
|
||||||
|
@ -38,6 +35,13 @@ class Shoutable(object):
|
||||||
return extra_params
|
return extra_params
|
||||||
else:
|
else:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
cls.shouts = shouts
|
||||||
|
cls.recent_shout = recent_shout
|
||||||
|
if not hasattr(cls, '_default_params'):
|
||||||
|
cls._default_params = _default_params
|
||||||
|
|
||||||
|
return cls
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import time
|
import time
|
|
@ -8,10 +8,7 @@ __package__ = "lastfm.mixins"
|
||||||
from lastfm.safelist import SafeList
|
from lastfm.safelist import SafeList
|
||||||
from lastfm.decorators import cached_property, authentication_required
|
from lastfm.decorators import cached_property, authentication_required
|
||||||
|
|
||||||
class Taggable(object):
|
def taggable(cls):
|
||||||
def init(self, api):
|
|
||||||
self._api = api
|
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
@authentication_required
|
@authentication_required
|
||||||
def tags(self):
|
def tags(self):
|
||||||
|
@ -69,4 +66,12 @@ class Taggable(object):
|
||||||
if extra_params is not None:
|
if extra_params is not None:
|
||||||
return extra_params
|
return extra_params
|
||||||
else:
|
else:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
cls.tags = tags
|
||||||
|
cls.add_tags = add_tags
|
||||||
|
cls.remove_tag = remove_tag
|
||||||
|
if not hasattr(cls, '_default_params'):
|
||||||
|
cls._default_params = _default_params
|
||||||
|
|
||||||
|
return cls
|
|
@ -1,432 +0,0 @@
|
||||||
#!/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
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ __package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.album import Album
|
from lastfm.album import Album
|
||||||
from lastfm.artist import Artist
|
from lastfm.artist import Artist
|
||||||
from lastfm.mixins import Cacheable
|
from lastfm.mixins import _cacheable
|
||||||
from lastfm.error import InvalidParametersError
|
from lastfm.error import InvalidParametersError
|
||||||
from lastfm.event import Event
|
from lastfm.event import Event
|
||||||
from lastfm.geo import Location, Country
|
from lastfm.geo import Location, Country
|
||||||
|
@ -29,7 +29,7 @@ class ObjectCache(object):
|
||||||
raise InvalidParametersError("Key does not correspond to a valid class")
|
raise InvalidParametersError("Key does not correspond to a valid class")
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
vals = Cacheable.registry[eval(name)].values()
|
vals = _cacheable.registry[eval(name)].values()
|
||||||
vals.sort()
|
vals.sort()
|
||||||
return vals
|
return vals
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
|
|
@ -6,10 +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
|
from lastfm.mixins import cacheable
|
||||||
from lastfm.decorators import cached_property
|
from lastfm.decorators import cached_property
|
||||||
|
|
||||||
class Playlist(LastfmBase, Cacheable):
|
@cacheable
|
||||||
|
class Playlist(LastfmBase):
|
||||||
"""A class representing an XPSF playlist."""
|
"""A class representing an XPSF playlist."""
|
||||||
def init(self, api, url, **kwargs):
|
def init(self, api, url, **kwargs):
|
||||||
self._api = api
|
self._api = api
|
||||||
|
|
|
@ -6,10 +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
|
from lastfm.mixins import cacheable
|
||||||
from lastfm.decorators import cached_property
|
from lastfm.decorators import cached_property
|
||||||
|
|
||||||
class Shout(LastfmBase, Cacheable):
|
@cacheable
|
||||||
|
class Shout(LastfmBase):
|
||||||
"""A class representing a shout."""
|
"""A class representing a shout."""
|
||||||
|
|
||||||
def init(self,
|
def init(self,
|
||||||
|
|
|
@ -6,11 +6,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 (
|
from lastfm.mixins import cacheable, searchable, chartable
|
||||||
Cacheable, Searchable, ArtistChartable)
|
|
||||||
from lastfm.decorators import cached_property, top_property
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
class Tag(LastfmBase, Cacheable, Searchable, ArtistChartable):
|
@chartable(['artist'])
|
||||||
|
@searchable
|
||||||
|
@cacheable
|
||||||
|
class Tag(LastfmBase):
|
||||||
"""A class representing a tag."""
|
"""A class representing a tag."""
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
|
@ -21,7 +23,6 @@ class Tag(LastfmBase, Cacheable, Searchable, ArtistChartable):
|
||||||
**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
|
||||||
|
|
|
@ -6,10 +6,14 @@ __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, Sharable, Taggable
|
from lastfm.mixins import cacheable, searchable, sharable, taggable
|
||||||
from lastfm.decorators import cached_property, top_property
|
from lastfm.decorators import cached_property, top_property
|
||||||
|
|
||||||
class Track(LastfmBase, Cacheable, Sharable, Searchable, Taggable):
|
@sharable
|
||||||
|
@taggable
|
||||||
|
@searchable
|
||||||
|
@cacheable
|
||||||
|
class Track(LastfmBase):
|
||||||
"""A class representing a track."""
|
"""A class representing a track."""
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
|
@ -30,8 +34,6 @@ class Track(LastfmBase, Cacheable, Sharable, Searchable, Taggable):
|
||||||
subject = None):
|
subject = 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")
|
||||||
Taggable.init(self, api)
|
|
||||||
Sharable.init(self, api)
|
|
||||||
self._api = api
|
self._api = api
|
||||||
self._id = id
|
self._id = id
|
||||||
self._name = name
|
self._name = name
|
||||||
|
|
|
@ -6,16 +6,15 @@ __license__ = "GNU Lesser General Public License"
|
||||||
__package__ = "lastfm"
|
__package__ = "lastfm"
|
||||||
|
|
||||||
from lastfm.base import LastfmBase
|
from lastfm.base import LastfmBase
|
||||||
from lastfm.mixins import (
|
from lastfm.mixins import cacheable, shoutable, chartable
|
||||||
Cacheable, Shoutable, AlbumChartable,
|
|
||||||
ArtistChartable, TrackChartable, TagChartable)
|
|
||||||
import lastfm.playlist
|
import lastfm.playlist
|
||||||
from lastfm.decorators import (
|
from lastfm.decorators import (
|
||||||
cached_property, top_property, authentication_required, depaginate)
|
cached_property, top_property, authentication_required, depaginate)
|
||||||
|
|
||||||
class User(LastfmBase, Cacheable, Shoutable,
|
@chartable(['album', 'artist', 'track', 'tag'])
|
||||||
AlbumChartable, ArtistChartable,
|
@shoutable
|
||||||
TrackChartable, TagChartable):
|
@cacheable
|
||||||
|
class User(LastfmBase):
|
||||||
"""A class representing an user."""
|
"""A class representing an user."""
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
|
@ -27,11 +26,6 @@ class User(LastfmBase, Cacheable, Shoutable,
|
||||||
**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")
|
||||||
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
|
||||||
|
|
|
@ -6,10 +6,12 @@ __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 cacheable, searchable
|
||||||
from lastfm.decorators import cached_property, depaginate
|
from lastfm.decorators import cached_property, depaginate
|
||||||
|
|
||||||
class Venue(LastfmBase, Cacheable, Searchable):
|
@searchable
|
||||||
|
@cacheable
|
||||||
|
class Venue(LastfmBase):
|
||||||
"""A class representing a venue of an event"""
|
"""A class representing a venue of an event"""
|
||||||
def init(self,
|
def init(self,
|
||||||
api,
|
api,
|
||||||
|
|
Loading…
Reference in New Issue