Download this file

easy.py    108 lines (92 with data), 3.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
'''
qobuz.api.easy
~~~~~~~~~~~~~~
Add 'get' to qobuz.api.raw, All requests made trough this method are
cached (see qobuz.cache.qobuz)
:part_of: xbmc-qobuz
:copyright: (c) 2012 by Joachim Basmaison, Cyril Leclerc
:license: GPLv3, see LICENSE for more details.
'''
from qobuz.cache import cache
from qobuz.api.raw import RawApi
class InvalidQuery(Exception):
pass
class EasyApi(RawApi):
def __init__(self):
self.cache_base_path = None
super(EasyApi, self).__init__()
self.is_logged = False
"""Setting default stream format to mp3
"""
self.stream_format = 5
@cache.cached
def get(self, *a, **ka):
"""Wrapper that cache query to our raw api. We are enforcing format
because cache entry key are made based on *a and **ka parameters.
('artist/get' and '/artist/get' will generate different key)
Path are mapped to raw api and raise InvalidQuery on error
::example
from qobuz.api import api
from qobuz.cache import cache
cace.base_path = '/srv/qobuz/cache/'
data = api.get('/artist/get')
data = api.get('/user/login',
username=api.username,
password=api.password)
:: note Named parameters are sorted before we generate our key
::return
Pyton Dictionary on success
None on error
::note api.error will contain last error message
"""
key_to_del = []
for key, value in ka.items():
if value is None or value == '':
key_to_del.append(key)
for key in key_to_del:
del ka[key]
if not a[0] or not a[0].startswith('/'):
raise InvalidQuery("Missing starting << / >>")
path = '/'.join(a)
path.replace('//', '/') # Defected for n / ...
path = path[1:]
if path.endswith('/'):
raise InvalidQuery('Invalid trailing << / >>')
xpath = path.split('/')
if len(xpath) < 1:
raise InvalidQuery(path)
methname = '%s_%s' % (xpath[0], xpath[1])
if not hasattr(self, methname):
raise InvalidQuery(path)
"""Passing user_id create different key for the cache...
"""
for label in self.__clean_ka(xpath[0], xpath[1], **ka):
del ka[label]
return getattr(self, methname)(**ka)
def __clean_ka(self, endpoint, method, **ka):
"""We are removing some key that are not needed by our raw api but
generate different cache entry (Data bound to specific user...)
"""
keys = []
if endpoint == 'track' and method == 'getFileUrl':
if 'user_id' in ka:
keys.append('user_id')
if endpoint == 'purchase' and method == 'getUserPurchases':
if 'user_id' in ka:
keys.append('user_id')
return keys
def login(self, username, password):
"""We are storing our authentication token back to our raw api on
success.
::return
True on success, else False
"""
self.username = username
self.password = password
data = self.get('/user/login', username=username, password=password)
if not data:
return False
user = data['user']
self.set_user_data(user['id'], data['user_auth_token'])
self.is_logged = True
return True