* renamed lastfm.mixins module to lastfm.mixin

* group utility modules in lastfm.util module
* made related changes
master
Abhinav Sarkar 2009-04-07 11:14:42 +00:00
parent 2219c5b0ad
commit e0c0277336
29 changed files with 815 additions and 24 deletions

View File

@ -23,7 +23,7 @@ from lastfm.event import Event
from lastfm.geo import Location, Country
from lastfm.group import Group
from lastfm.playlist import Playlist
from lastfm.objectcache import ObjectCache
from lastfm.util import ObjectCache
from lastfm.tag import Tag
from lastfm.tasteometer import Tasteometer
from lastfm.track import Track

View File

@ -7,7 +7,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, searchable, taggable, crawlable
from lastfm.mixin import cacheable, searchable, taggable, crawlable
from lastfm.decorators import cached_property, top_property
@crawlable

View File

@ -656,10 +656,7 @@ class Api(object):
self._last_fetch_time = datetime.now()
return url_data
def _fetch_url(self,
url,
parameters = None,
no_cache = False):
def _fetch_url(self, url, parameters = None, no_cache = False):
# Add key/value parameters to the query string of the url
url = self._build_url(url, extra_params=parameters)
if self._debug:
@ -780,7 +777,7 @@ from lastfm.artist import Artist
from lastfm.error import error_map, LastfmError, OperationFailedError, AuthenticationFailedError,\
InvalidParametersError
from lastfm.event import Event
from lastfm.filecache import FileCache
from lastfm.util import FileCache
from lastfm.geo import Location, Country
from lastfm.group import Group
from lastfm.playlist import Playlist

View File

@ -7,7 +7,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, searchable, sharable, shoutable, taggable, crawlable
from lastfm.mixin import cacheable, searchable, sharable, shoutable, taggable, crawlable
from lastfm.decorators import cached_property, top_property
@crawlable

View File

@ -6,8 +6,6 @@ __version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.lazylist import lazylist
class LastfmBase(object):
"""Base class for all the classes in this package"""

View File

@ -7,7 +7,7 @@ __package__ = "lastfm"
from functools import reduce
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable
from lastfm.mixin import cacheable
from operator import xor
@cacheable

View File

@ -112,7 +112,7 @@ def depaginate(func, *args, **kwargs):
a L{lazylist} of all search results (all pages)
@rtype: C{function}
"""
from lastfm.lazylist import lazylist
from lastfm.util import lazylist
@lazylist
def generator(lst):
gen = func(*args, **kwargs)

View File

@ -7,7 +7,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, sharable, shoutable, crawlable
from lastfm.mixin import cacheable, sharable, shoutable, crawlable
@crawlable
@shoutable

View File

@ -8,7 +8,7 @@ __package__ = "lastfm"
from functools import reduce
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, crawlable
from lastfm.mixin import cacheable, crawlable
from lastfm.decorators import cached_property, top_property, depaginate
class Geo(object):

View File

@ -7,7 +7,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, chartable
from lastfm.mixin import cacheable, chartable
from lastfm.decorators import cached_property, depaginate
@chartable(['album', 'artist', 'track', 'tag'])

17
lastfm/mixin/__init__.py Normal file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
from lastfm.mixin._cacheable import cacheable
from lastfm.mixin._searchable import searchable
from lastfm.mixin._sharable import sharable
from lastfm.mixin._shoutable import shoutable
from lastfm.mixin._taggable import taggable
from lastfm.mixin._chartable import chartable
from lastfm.mixin._crawlable import crawlable
__all__ = ['cacheable', 'searchable', 'sharable', 'shoutable', 'taggable'
'chartable','crawlable']

View File

@ -0,0 +1,53 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
try:
from threading import Lock
except ImportError:
from dummy_threading import Lock
from lastfm.util import ObjectCache
_lock = Lock()
def cacheable(cls):
@classmethod
def __new__(cls, *args, **kwds):
args = args[1:]
subject = None
if 'subject' in kwds and not 'Weekly' in cls.__name__:
subject = kwds['subject']
#del kwds['subject']
if 'bypass_registry' in kwds:
del kwds['bypass_registry']
inst = object.__new__(cls)
inst.init(*args, **kwds)
return inst
key = cls._hash_func(*args, **kwds)
if subject is not None:
key = (hash(subject), key)
with _lock:
inst, already_registered = ObjectCache.register(object.__new__(cls), key)
if not already_registered:
inst.init(*args, **kwds)
return inst
@staticmethod
def _hash_func(*args, **kwds):
raise NotImplementedError("The subclass must override this method")
cls.__new__ = __new__
if not hasattr(cls, '_hash_func'):
cls._hash_func = _hash_func
if not hasattr(cls, '_mixins'):
cls._mixins = []
cls._mixins.append('__new__')
return cls

451
lastfm/mixin/_chartable.py Normal file
View File

@ -0,0 +1,451 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
from lastfm.util 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
if not hasattr(cls, '_mixins'):
cls._mixins = []
cls._mixins.extend(['weekly_chart_list', 'monthly_chart_list'])
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])
cls._mixins.append(method_name % chart_type)
return cls
return wrapper
from lastfm.error import LastfmError

View File

@ -0,0 +1,38 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
from lastfm.util import lazylist
def crawlable(cls):
_get_all = cls._get_all
@staticmethod
def get_all(seed):
seed, hash_attrs, spider_func = _get_all(seed)
@lazylist
def gen(lst):
seen = []
api = seed._api
def hash_dict(item):
return dict((a, getattr(item, a)) for a in hash_attrs)
seen.append(hash_dict(seed))
yield seed
for hsh in seen:
for n in spider_func(api, hsh):
if hash_dict(n) not in seen:
seen.append(hash_dict(n))
yield n
return gen()
cls.get_all = get_all
delattr(cls, '_get_all')
if not hasattr(cls, '_mixins'):
cls._mixins = []
cls._mixins.append('get_all')
return cls

View File

@ -0,0 +1,53 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
from lastfm.decorators import depaginate
def searchable(cls):
@classmethod
@depaginate
def search(cls,
api,
search_item,
limit = None,
page = None,
**kwds):
from lastfm.api import Api
cls_name = cls.__name__.lower()
params = {
'method': '%s.search'%cls_name,
cls_name: search_item
}
for kwd in kwds:
if kwds[kwd] is not None:
params[kwd] = kwds[kwd]
if limit:
params.update({'limit': limit})
if page is not None:
params.update({'page': page})
data = api._fetch_data(params).find('results')
total_pages = int(data.findtext("{%s}totalResults" % Api.SEARCH_XMLNS))/ \
int(data.findtext("{%s}itemsPerPage" % Api.SEARCH_XMLNS)) + 1
yield total_pages
for a in data.findall('%smatches/%s'%(cls_name, cls_name)):
yield cls._search_yield_func(api, a)
@staticmethod
def _search_yield_func(api, search_term):
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
if not hasattr(cls, '_mixins'):
cls._mixins = []
cls._mixins.append('search')
return cls

38
lastfm/mixin/_sharable.py Normal file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
def sharable(cls):
def share(self, recipient, message = None):
from lastfm.user import User
params = self._default_params({'method': '%s.share' % self.__class__.__name__.lower()})
if message is not None:
params['message'] = message
if not isinstance(recipient, list):
recipient = [recipient]
for i in xrange(len(recipient)):
if isinstance(recipient[i], User):
recipient[i] = recipient[i].name
params['recipient'] = ",".join(recipient)
self._api._post_data(params)
def _default_params(self, extra_params = None):
if extra_params is not None:
return extra_params
else:
return {}
cls.share = share
if not hasattr(cls, '_default_params'):
cls._default_params = _default_params
if not hasattr(cls, '_mixins'):
cls._mixins = []
cls._mixins.append('share')
return cls

View File

@ -0,0 +1,51 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
from lastfm.decorators import cached_property, top_property
def shoutable(cls):
@cached_property
def shouts(self):
"""shouts for this %s""" % cls.__name__.lower()
from lastfm.shout import Shout
from lastfm.user import User
params = self._default_params({'method': '%s.getShouts' % self.__class__.__name__.lower()})
data = self._api._fetch_data(params).find('shouts')
return [
Shout(
body = s.findtext('body'),
author = User(self._api, name = s.findtext('author')),
date = s.findtext('date') and s.findtext('date').strip() and \
datetime(*(time.strptime(s.findtext('date').strip(), '%a, %d %b %Y %H:%M:%S')[0:6]))
)
for s in data.findall('shout')
]
@top_property("shouts")
def recent_shout(self):
"""recent shout for this %s""" % cls.__name__.lower()
pass
def _default_params(self, extra_params = None):
if extra_params is not None:
return extra_params
else:
return {}
cls.shouts = shouts
cls.recent_shout = recent_shout
if not hasattr(cls, '_default_params'):
cls._default_params = _default_params
if not hasattr(cls, '_mixins'):
cls._mixins = []
cls._mixins.extend(['shouts', 'recent_shout'])
return cls
from datetime import datetime
import time

81
lastfm/mixin/_taggable.py Normal file
View File

@ -0,0 +1,81 @@
#!/usr/bin/env python
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.mixin"
from lastfm.util import SafeList
from lastfm.decorators import cached_property, authentication_required
def taggable(cls):
@cached_property
@authentication_required
def tags(self):
from lastfm.tag import Tag
params = self._default_params({'method': '%s.getTags' % self.__class__.__name__.lower()})
data = self._api._fetch_data(params, sign = True, session = True, no_cache = True).find('tags')
return SafeList([
Tag(
self._api,
name = t.findtext('name'),
url = t.findtext('url')
)
for t in data.findall('tag')
],
self.add_tags, self.remove_tag)
@authentication_required
def add_tags(self, tags):
from lastfm.tag import Tag
while(len(tags) > 10):
section = tags[0:9]
tags = tags[9:]
self.add_tags(section)
if len(tags) == 0: return
tagnames = []
for tag in tags:
if isinstance(tag, Tag):
tagnames.append(tag.name)
elif isinstance(tag, str):
tagnames.append(tag)
params = self._default_params({
'method': '%s.addTags' % self.__class__.__name__.lower(),
'tags': ",".join(tagnames)
})
self._api._post_data(params)
self._tags = None
@authentication_required
def remove_tag(self, tag):
from lastfm.tag import Tag
if isinstance(tag, Tag):
tag = tag.name
params = self._default_params({
'method': '%s.removeTag' % self.__class__.__name__.lower(),
'tag': tag
})
self._api._post_data(params)
self._tags = None
def _default_params(self, extra_params = None):
if extra_params is not None:
return extra_params
else:
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
if not hasattr(cls, '_mixins'):
cls._mixins = []
cls._mixins.extend(['tags', 'add_tags', 'remove_tag'])
return cls

View File

@ -6,7 +6,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable
from lastfm.mixin import cacheable
from lastfm.decorators import cached_property
@cacheable

View File

@ -6,7 +6,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable
from lastfm.mixin import cacheable
from lastfm.decorators import cached_property
@cacheable

View File

@ -6,7 +6,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, searchable, chartable, crawlable
from lastfm.mixin import cacheable, searchable, chartable, crawlable
from lastfm.decorators import cached_property, top_property
@crawlable

View File

@ -6,7 +6,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, searchable, sharable, taggable, crawlable
from lastfm.mixin import cacheable, searchable, sharable, taggable, crawlable
from lastfm.decorators import cached_property, top_property
@crawlable

View File

@ -6,7 +6,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, shoutable, chartable, crawlable
from lastfm.mixin import cacheable, shoutable, chartable, crawlable
import lastfm.playlist
from lastfm.decorators import (
cached_property, top_property, authentication_required, depaginate)

13
lastfm/util/__init__.py Normal file
View File

@ -0,0 +1,13 @@
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm.util"
from lastfm.util.wormhole import Wormhole
from lastfm.util.lazylist import lazylist
from lastfm.util.safelist import SafeList
from lastfm.util.filecache import FileCache
from lastfm.util.objectcache import ObjectCache
__all__ = ['Wormhole', 'lazylist', 'SafeList',
'FileCache', 'ObjectCache']

View File

@ -4,7 +4,7 @@
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
__package__ = "lastfm.util"
import sys
if sys.version < '2.6':

View File

@ -8,6 +8,7 @@ Backport to python 2.5 by Michael Pust
__author__ = 'Dan Spitz'
__all__ = ('LazyList', 'RecursiveLazyList', 'lazylist')
__package__ = "lastfm.util"
import itertools

View File

@ -3,7 +3,7 @@
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
__package__ = "lastfm.util"
_registry = {}

View File

@ -3,7 +3,7 @@
__author__ = "Abhinav Sarkar <abhinav@abhinavsarkar.net>"
__version__ = "0.2"
__license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
__package__ = "lastfm.util"
import sys
class SafeList(object):

View File

@ -6,7 +6,7 @@ __license__ = "GNU Lesser General Public License"
__package__ = "lastfm"
from lastfm.base import LastfmBase
from lastfm.mixins import cacheable, searchable, crawlable
from lastfm.mixin import cacheable, searchable, crawlable
from lastfm.decorators import cached_property, depaginate
@crawlable