/src/pyechonest/pyechonest/proxies.py

http://echo-nest-remix.googlecode.com/ · Python · 173 lines · 128 code · 26 blank · 19 comment · 54 complexity · 6dbb9617f6d47b2514f8fdb342cfe248 MD5 · raw file

  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. """
  4. Copyright (c) 2010 The Echo Nest. All rights reserved.
  5. Created by Tyler Williams on 2010-04-25.
  6. """
  7. import util
  8. class ResultList(list):
  9. def __init__(self, li, start=0, total=0):
  10. self.extend(li)
  11. self.start = start
  12. if total == 0:
  13. total = len(li)
  14. self.total = total
  15. class GenericProxy(object):
  16. def __init__(self):
  17. self.cache = {}
  18. def get_attribute(self, method_name, **kwargs):
  19. result = util.callm("%s/%s" % (self._object_type, method_name), kwargs)
  20. return result['response']
  21. def post_attribute(self, method_name, **kwargs):
  22. data = kwargs.pop('data') if 'data' in kwargs else {}
  23. result = util.callm("%s/%s" % (self._object_type, method_name), kwargs, POST=True, data=data)
  24. return result['response']
  25. class ArtistProxy(GenericProxy):
  26. def __init__(self, identifier, buckets = None, **kwargs):
  27. super(ArtistProxy, self).__init__()
  28. buckets = buckets or []
  29. self.id = identifier
  30. self._object_type = 'artist'
  31. kwargs = dict((str(k), v) for (k,v) in kwargs.iteritems())
  32. # the following are integral to all artist objects... the rest is up to you!
  33. core_attrs = ['name']
  34. if not all(ca in kwargs for ca in core_attrs):
  35. profile = self.get_attribute('profile', **{'bucket':buckets})
  36. kwargs.update(profile.get('artist'))
  37. [self.__dict__.update({ca:kwargs.pop(ca)}) for ca in core_attrs+['id'] if ca in kwargs]
  38. self.cache.update(kwargs)
  39. def get_attribute(self, *args, **kwargs):
  40. if util.short_regex.match(self.id) or util.long_regex.match(self.id) or util.foreign_regex.match(self.id):
  41. kwargs['id'] = self.id
  42. else:
  43. kwargs['name'] = self.id
  44. return super(ArtistProxy, self).get_attribute(*args, **kwargs)
  45. class CatalogProxy(GenericProxy):
  46. def __init__(self, identifier, type, buckets = None, **kwargs):
  47. super(CatalogProxy, self).__init__()
  48. buckets = buckets or []
  49. self.id = identifier
  50. self._object_type = 'catalog'
  51. kwargs = dict((str(k), v) for (k,v) in kwargs.iteritems())
  52. # the following are integral to all catalog objects... the rest is up to you!
  53. core_attrs = ['name']
  54. if not all(ca in kwargs for ca in core_attrs):
  55. if util.short_regex.match(self.id) or util.long_regex.match(self.id) or util.foreign_regex.match(self.id):
  56. try:
  57. profile = self.get_attribute('profile')
  58. kwargs.update(profile['catalog'])
  59. except util.EchoNestAPIError:
  60. raise Exception('Catalog %s does not exist' % (identifier))
  61. else:
  62. if not type:
  63. raise Exception('You must specify a "type"!')
  64. try:
  65. profile = self.get_attribute('profile')
  66. existing_type = profile['catalog'].get('type', 'Unknown')
  67. if type != existing_type:
  68. raise Exception("Catalog type requested (%s) does not match existing catalog type (%s)" % (type, existing_type))
  69. kwargs.update(profile['catalog'])
  70. except util.EchoNestAPIError:
  71. profile = self.post_attribute('create', type=type, **kwargs)
  72. kwargs.update(profile)
  73. [self.__dict__.update({ca:kwargs.pop(ca)}) for ca in core_attrs+['id'] if ca in kwargs]
  74. self.cache.update(kwargs)
  75. def get_attribute_simple(self, *args, **kwargs):
  76. # omit name/id kwargs for this call
  77. return super(CatalogProxy, self).get_attribute(*args, **kwargs)
  78. def get_attribute(self, *args, **kwargs):
  79. if util.short_regex.match(self.id) or util.long_regex.match(self.id) or util.foreign_regex.match(self.id):
  80. kwargs['id'] = self.id
  81. else:
  82. kwargs['name'] = self.id
  83. return super(CatalogProxy, self).get_attribute(*args, **kwargs)
  84. def post_attribute(self, *args, **kwargs):
  85. if util.short_regex.match(self.id) or util.long_regex.match(self.id) or util.foreign_regex.match(self.id):
  86. kwargs['id'] = self.id
  87. else:
  88. kwargs['name'] = self.id
  89. return super(CatalogProxy, self).post_attribute(*args, **kwargs)
  90. class PlaylistProxy(GenericProxy):
  91. def __init__(self, session_id, buckets = None, **kwargs):
  92. super(PlaylistProxy, self).__init__()
  93. buckets = buckets or []
  94. self._object_type = 'playlist'
  95. kwargs = dict((str(k), v) for (k,v) in kwargs.iteritems())
  96. if session_id:
  97. kwargs['session_id'] = session_id
  98. # the following are integral to all playlist objects... the rest is up to you!
  99. core_attrs = ['session_id']
  100. if not all(ca in kwargs for ca in core_attrs):
  101. profile = self.get_attribute('dynamic', **kwargs)
  102. kwargs.update(profile)
  103. [self.__dict__.update({ca:kwargs.pop(ca)}) for ca in core_attrs if ca in kwargs]
  104. self.cache.update(kwargs)
  105. def get_attribute(self, *args, **kwargs):
  106. return super(PlaylistProxy, self).get_attribute(*args, **kwargs)
  107. class SongProxy(GenericProxy):
  108. def __init__(self, identifier, buckets = None, **kwargs):
  109. super(SongProxy, self).__init__()
  110. buckets = buckets or []
  111. self.id = identifier
  112. self._object_type = 'song'
  113. kwargs = dict((str(k), v) for (k,v) in kwargs.iteritems())
  114. # BAW -- this is debug output from identify that returns a track_id. i am not sure where else to access this..
  115. if kwargs.has_key("track_id"):
  116. self.track_id = kwargs["track_id"]
  117. if kwargs.has_key("tag"):
  118. self.tag = kwargs["tag"]
  119. if kwargs.has_key("score"):
  120. self.score = kwargs["score"]
  121. if kwargs.has_key('audio'):
  122. self.audio = kwargs['audio']
  123. if kwargs.has_key('release_image'):
  124. self.release_image = kwargs['release_image']
  125. # the following are integral to all song objects... the rest is up to you!
  126. core_attrs = ['title', 'artist_name', 'artist_id']
  127. if not all(ca in kwargs for ca in core_attrs):
  128. profile = self.get_attribute('profile', **{'id':self.id, 'bucket':buckets})
  129. kwargs.update(profile.get('songs')[0])
  130. [self.__dict__.update({ca:kwargs.pop(ca)}) for ca in core_attrs]
  131. self.cache.update(kwargs)
  132. def get_attribute(self, *args, **kwargs):
  133. kwargs['id'] = self.id
  134. return super(SongProxy, self).get_attribute(*args, **kwargs)
  135. class TrackProxy(GenericProxy):
  136. def __init__(self, identifier, md5, properties):
  137. """
  138. You should not call this constructor directly, rather use the convenience functions
  139. that are in track.py. For example, call track.track_from_filename
  140. Let's always get the bucket `audio_summary`
  141. """
  142. super(TrackProxy, self).__init__()
  143. self.id = identifier
  144. self.md5 = md5
  145. self._object_type = 'track'
  146. self.__dict__.update(properties)