diff --git a/lastfm/mixins/__init__.py b/lastfm/mixins/__init__.py deleted file mode 100644 index 75ec197..0000000 --- a/lastfm/mixins/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Abhinav Sarkar " -__version__ = "0.2" -__license__ = "GNU Lesser General Public License" -__package__ = "lastfm.mixins" - -from lastfm.mixins._cacheable import cacheable -from lastfm.mixins._searchable import searchable -from lastfm.mixins._sharable import sharable -from lastfm.mixins._shoutable import shoutable -from lastfm.mixins._taggable import taggable -from lastfm.mixins._chartable import chartable -from lastfm.mixins._crawlable import crawlable - -__all__ = ['cacheable', 'searchable', 'sharable', 'shoutable', 'taggable' - 'chartable','crawlable'] \ No newline at end of file diff --git a/lastfm/mixins/_cacheable.py b/lastfm/mixins/_cacheable.py deleted file mode 100644 index e74c04c..0000000 --- a/lastfm/mixins/_cacheable.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Abhinav Sarkar " -__version__ = "0.2" -__license__ = "GNU Lesser General Public License" -__package__ = "lastfm.mixins" - -try: - from threading import Lock -except ImportError: - from dummy_threading import Lock -from lastfm.objectcache 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 diff --git a/lastfm/mixins/_chartable.py b/lastfm/mixins/_chartable.py deleted file mode 100644 index 737cf26..0000000 --- a/lastfm/mixins/_chartable.py +++ /dev/null @@ -1,451 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Abhinav Sarkar " -__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 - - 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 - \ No newline at end of file diff --git a/lastfm/mixins/_crawlable.py b/lastfm/mixins/_crawlable.py deleted file mode 100644 index 8f65da5..0000000 --- a/lastfm/mixins/_crawlable.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Abhinav Sarkar " -__version__ = "0.2" -__license__ = "GNU Lesser General Public License" -__package__ = "lastfm.mixins" - -from lastfm.lazylist 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 \ No newline at end of file diff --git a/lastfm/mixins/_searchable.py b/lastfm/mixins/_searchable.py deleted file mode 100644 index ac0a673..0000000 --- a/lastfm/mixins/_searchable.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Abhinav Sarkar " -__version__ = "0.2" -__license__ = "GNU Lesser General Public License" -__package__ = "lastfm.mixins" - -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 diff --git a/lastfm/mixins/_sharable.py b/lastfm/mixins/_sharable.py deleted file mode 100644 index 80db747..0000000 --- a/lastfm/mixins/_sharable.py +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Abhinav Sarkar " -__version__ = "0.2" -__license__ = "GNU Lesser General Public License" -__package__ = "lastfm.mixins" - -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 \ No newline at end of file diff --git a/lastfm/mixins/_shoutable.py b/lastfm/mixins/_shoutable.py deleted file mode 100644 index e8fc1d5..0000000 --- a/lastfm/mixins/_shoutable.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Abhinav Sarkar " -__version__ = "0.2" -__license__ = "GNU Lesser General Public License" -__package__ = "lastfm.mixins" - -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 \ No newline at end of file diff --git a/lastfm/mixins/_taggable.py b/lastfm/mixins/_taggable.py deleted file mode 100644 index adc10d5..0000000 --- a/lastfm/mixins/_taggable.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python - -__author__ = "Abhinav Sarkar " -__version__ = "0.2" -__license__ = "GNU Lesser General Public License" -__package__ = "lastfm.mixins" - -from lastfm.safelist 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 \ No newline at end of file