"""
-__version__ = '0.3.1'
+__version__ = '0.4.0'
__author__ = 'Jack Kaliko'
from datetime import datetime, timedelta
from http.client import BadStatusLine
from socket import timeout as SocketTimeOut
-from time import sleep
from xml.etree.cElementTree import ElementTree
+from request import get
+
from sima import LFM
-from sima.utils.utils import getws
-getws(LFM)
+from sima.utils.utils import getws, Throttle, Cache
+if len(LFM.get('apikey')) == 43: # simple hack allowing imp.reload
+ getws(LFM)
# Some definitions
WAIT_BETWEEN_REQUESTS = timedelta(0, 0.4)
-LFM_ERRORS = dict({'2': 'Invalid service -This service does not exist',
- '3': 'Invalid Method - No method with that name in this package',
- '4': 'Authentication Failed - You do not have permissions to access the service',
- '5': "'Invalid format - This service doesn't exist in that format",
- '6': 'Invalid parameters - Your request is missing a required parameter',
- '7': 'Invalid resource specified',
- '9': 'Invalid session key - Please re-authenticate',
- '10': 'Invalid API key - You must be granted a valid key by last.fm',
- '11': 'Service Offline - This service is temporarily offline. Try again later.',
- '12': 'Subscription Error - The user needs to be subscribed in order to do that',
- '13': 'Invalid method signature supplied',
- '26': 'Suspended API key - Access for your account has been suspended, please contact Last.fm',
- })
class XmlFMError(Exception): # Errors
self.expression = (message)
-class Throttle():
- def __init__(self, wait):
- self.wait = wait
- self.last_called = datetime.now()
-
- def __call__(self, func):
- def wrapper(*args, **kwargs):
- while self.last_called + self.wait > datetime.now():
- #print('waiting…')
- sleep(0.1)
- result = func(*args, **kwargs)
- self.last_called = datetime.now()
- return result
- return wrapper
-
-
-class AudioScrobblerCache():
- def __init__(self, elem, last):
- self.elemtree = elem
- self.requestdate = last
-
- def created(self):
- return self.requestdate
-
- def gettree(self):
- return self.elemtree
-
-
class SimaFM():
"""
"""
'info': '?method=artist.getinfo&artist=%s' +\
'api_key={apikey}'.format(**LFM),
})
+ payloads = dict({'similar': {'method':'artist.getsimilar',
+ 'artist':None, 'api_key':LFM.get('apikey'),},
+ 'top': {'method':'artist.gettoptracks',
+ 'artist':None, 'api_key':LFM.get('apikey'),},
+ 'track': {'method':'track.getsimilar',
+ 'artist':None, 'track':None,
+ 'api_key':LFM.get('apikey'),},
+ 'info': {'method':'artist.getinfo', 'artist':None,
+ 'api_key':LFM.get('apikey'),},
+ })
cache = dict({})
timestamp = datetime.utcnow()
count = 0
return
self._fetch_lfm()
+ @Throttle(WAIT_BETWEEN_REQUESTS)
+ def _fetch_ws(self):
+ pass
+
@Throttle(WAIT_BETWEEN_REQUESTS)
def _fetch_lfm(self):
"""Get artists, fetch xml from last.fm"""
fd.close()
self._controls_lfm_answer()
if self.caching:
- SimaFM.cache[self._url] = AudioScrobblerCache(self.current_element,
- datetime.utcnow())
+ SimaFM.cache[self._url] = Cache(self.current_element)
def _controls_lfm_answer(self):
"""Controls last.fm answer.
if status == 'failed':
error = self.current_element.find('error').attrib.get('code')
errormsg = self.current_element.findtext('error')
- #if error in LFM_ERRORS.keys():
- # print LFM_ERRORS.get(error)
raise XmlFMNotFound(errormsg)
def _controls_artist(self, artist):
if now - timestamp > delta:
cache.pop(url)
+ def get_similar_ng(self, artist=None):
+ """
+ """
+ self._controls_artist(artist)
+ # Construct URL
+ self._req = get(SimaFM.root_url, params=None, timeout=5)
+ self._url = req.url
+ if self._is_in_cache():
+ self.current_element = SimaFM.cache.get(self._url).gettree()
+ else:
+ self._fetch_ws()
+ elem = self.current_element
+ for art in elem.getiterator(tag='artist'):
+ yield str(art.findtext('name')), 100 * float(art.findtext('match'))
+
def get_similar(self, artist=None):
"""
"""
from argparse import ArgumentError, Action
from base64 import b64decode as push
from codecs import getencoder
+from datetime import datetime
from os import environ, access, getcwd, W_OK, R_OK
from os.path import dirname, isabs, join, normpath, exists, isdir, isfile
if not access(self._file, W_OK):
self.parser.error('no write access to "{0}"'.format(self._file))
+class Throttle():
+ def __init__(self, wait):
+ self.wait = wait
+ self.last_called = datetime.now()
+
+ def __call__(self, func):
+ def wrapper(*args, **kwargs):
+ while self.last_called + self.wait > datetime.now():
+ sleep(0.1)
+ result = func(*args, **kwargs)
+ self.last_called = datetime.now()
+ return result
+ return wrapper
+
+class Cache():
+ def __init__(self, elem, last=None):
+ self.elem = elem
+ self.requestdate = last
+ if not last:
+ self.requestdate = datetime.utcnow()
+
+ def created(self):
+ return self.requestdate
+
+ def get(self):
+ return self.elem
# VIM MODLINE
# vim: ai ts=4 sw=4 sts=4 expandtab