]> kaliko git repositories - mpd-sima.git/blobdiff - sima/lib/simaecho.py
http client/cache controller refactoring
[mpd-sima.git] / sima / lib / simaecho.py
index caf8b5bfbc12b9e21cbd8a3e193f952621581f82..3f649a6575faf13849006403dd7e1493eb997641 100644 (file)
 Consume EchoNest web service
 """
 
 Consume EchoNest web service
 """
 
-__version__ = '0.0.2'
+__version__ = '0.0.3'
 __author__ = 'Jack Kaliko'
 
 
 __author__ = 'Jack Kaliko'
 
 
-from datetime import datetime, timedelta
-
-from requests import Session, Request, Timeout, ConnectionError
 
 from sima import ECH
 from sima.lib.meta import Artist
 from sima.lib.track import Track
 
 from sima import ECH
 from sima.lib.meta import Artist
 from sima.lib.track import Track
-from sima.lib.http import CacheController
-from sima.utils.utils import WSError, WSNotFound, WSTimeout, WSHTTPError
-from sima.utils.utils import getws, Throttle
+from sima.lib.http import HttpClient
+from sima.utils.utils import WSError, WSNotFound
+from sima.utils.utils import getws
 if len(ECH.get('apikey')) == 23:  # simple hack allowing imp.reload
     getws(ECH)
 
 if len(ECH.get('apikey')) == 23:  # simple hack allowing imp.reload
     getws(ECH)
 
-# Some definitions
-WAIT_BETWEEN_REQUESTS = timedelta(0, 1)
-SOCKET_TIMEOUT = 4
-
 
 class SimaEch:
     """EchoNest http client
     """
     root_url = 'http://{host}/api/{version}'.format(**ECH)
 
 class SimaEch:
     """EchoNest http client
     """
     root_url = 'http://{host}/api/{version}'.format(**ECH)
-    timestamp = datetime.utcnow()
     ratelimit = None
     name = 'EchoNest'
     cache = False
     ratelimit = None
     name = 'EchoNest'
     cache = False
+    stats = {'etag':0,
+             'ccontrol':0,
+             'minrl':120,
+             'total':0}
 
     def __init__(self):
 
     def __init__(self):
-        self._ressource = None
-        self.current_element = None
-        self.controller = CacheController(self.cache)
-
-    def _fetch(self, payload):
-        """Use cached elements or proceed http request"""
-        req = Request('GET', self._ressource, params=payload,
-                      ).prepare()
-        if self.cache:
-            cached_response = self.controller.cached_request(req.url, req.headers)
-            if cached_response:
-                return cached_response.json()
-
-        try:
-            return self._fetch_ws(req)
-        except Timeout:
-            raise WSTimeout('Failed to reach server within {0}s'.format(
-                               SOCKET_TIMEOUT))
-        except ConnectionError as err:
-            raise WSError(err)
-
-    @Throttle(WAIT_BETWEEN_REQUESTS)
-    def _fetch_ws(self, prepreq):
-        """fetch from web service"""
-        sess = Session()
-        resp = sess.send(prepreq, timeout=SOCKET_TIMEOUT)
-        self.__class__.ratelimit = resp.headers.get('x-ratelimit-remaining', None)
-        if resp.status_code is not 200:
-            raise WSHTTPError('{0.status_code}: {0.reason}'.format(resp))
-        ans = resp.json()
-        self._controls_answer(ans)
-        if self.cache:
-            self.controller.cache_response(resp.request, resp)
-        return ans
+        self.http = HttpClient(cache=self.cache, stats=self.stats)
 
     def _controls_answer(self, ans):
         """Controls answer.
 
     def _controls_answer(self, ans):
         """Controls answer.
@@ -121,17 +84,19 @@ class SimaEch:
                 payload.update(artist=name)
             payload.update(results=100)
             payload.update(sort='song_hotttnesss-desc')
                 payload.update(artist=name)
             payload.update(results=100)
             payload.update(sort='song_hotttnesss-desc')
-        return payload
+        # > hashing the URL into a cache key
+        # return a sorted list of 2-tuple to have consistent cache
+        return sorted(payload.items(), key=lambda param: param[0])
 
     def get_similar(self, artist=None):
         """Fetch similar artists
         """
         payload = self._forge_payload(artist)
         # Construct URL
 
     def get_similar(self, artist=None):
         """Fetch similar artists
         """
         payload = self._forge_payload(artist)
         # Construct URL
-        self._ressource = '{0}/artist/similar'.format(SimaEch.root_url)
-        ans = self._fetch(payload)
-        for art in ans.get('response').get('artists'):
-            artist = {}
+        ressource = '{0}/artist/similar'.format(SimaEch.root_url)
+        ans = self.http(ressource, payload)
+        self._controls_answer(ans.json())
+        for art in ans.json().get('response').get('artists'):
             mbid = None
             if 'foreign_ids' in art:
                 for frgnid in art.get('foreign_ids'):
             mbid = None
             if 'foreign_ids' in art:
                 for frgnid in art.get('foreign_ids'):
@@ -145,18 +110,19 @@ class SimaEch:
         """
         payload = self._forge_payload(artist, top=True)
         # Construct URL
         """
         payload = self._forge_payload(artist, top=True)
         # Construct URL
-        self._ressource = '{0}/song/search'.format(SimaEch.root_url)
-        ans = self._fetch(payload)
+        ressource = '{0}/song/search'.format(SimaEch.root_url)
+        ans = self.http(ressource, payload)
+        self._controls_answer(ans.json())
         titles = list()
         titles = list()
-        artist = {
+        art = {
                 'artist': artist.name,
                 'musicbrainz_artistid': artist.mbid,
                 }
                 'artist': artist.name,
                 'musicbrainz_artistid': artist.mbid,
                 }
-        for song in ans.get('response').get('songs'):
+        for song in ans.json().get('response').get('songs'):
             title = song.get('title')
             if title not in titles:
                 titles.append(title)
             title = song.get('title')
             if title not in titles:
                 titles.append(title)
-                yield Track(title=title, **artist)
+                yield Track(title=title, **art)
 
 
 # VIM MODLINE
 
 
 # VIM MODLINE