/src/pyechonest/pyechonest/catalog.py

http://echo-nest-remix.googlecode.com/ · Python · 312 lines · 250 code · 30 blank · 32 comment · 13 complexity · d963df1771b8203a8c5316cc0521c3f2 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 Scotty Vercoe on 2010-08-25.
  6. The Catalog module loosely covers http://developer.echonest.com/docs/v4/catalog.html
  7. Refer to the official api documentation if you are unsure about something.
  8. """
  9. try:
  10. import json
  11. except ImportError:
  12. import simplejson as json
  13. import datetime
  14. import util
  15. from proxies import CatalogProxy, ResultList
  16. import artist, song
  17. # deal with datetime in json
  18. dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else None
  19. class Catalog(CatalogProxy):
  20. """
  21. A Catalog object
  22. Attributes:
  23. id (str): Catalog ID
  24. name (str): Catalog Name
  25. read (list): A list of catalog items (objects if they are resolved, else dictionaries)
  26. feed (list): A list of dictionaries for news, blogs, reviews, audio, video for a catalog's artists
  27. Create an catalog object like so:
  28. >>> c = catalog.Catalog('CAGPXKK12BB06F9DE9') # get existing catalog
  29. >>> c = catalog.Catalog('test_song_catalog', 'song') # get existing or create new catalog
  30. """
  31. def __init__(self, id, type=None, **kwargs):
  32. """
  33. Create a catalog object (get a catalog by ID or get or create one given by name and type)
  34. Args:
  35. id (str): A catalog id or name
  36. Kwargs:
  37. type (str): 'song' or 'artist', specifying the catalog type
  38. Returns:
  39. A catalog object
  40. Example:
  41. >>> c = catalog.Catalog('my_songs', type='song')
  42. >>> c.id
  43. u'CAVKUPC12BCA792120'
  44. >>> c.name
  45. u'my_songs'
  46. >>>
  47. """
  48. super(Catalog, self).__init__(id, type, **kwargs)
  49. def __repr__(self):
  50. return "<%s - %s>" % (self._object_type.encode('utf-8'), self.name.encode('utf-8'))
  51. def __str__(self):
  52. return self.name.encode('utf-8')
  53. def update(self, items):
  54. """
  55. Update a catalog object
  56. Args:
  57. items (list): A list of dicts describing update data and action codes (see api docs)
  58. Kwargs:
  59. Returns:
  60. A ticket id
  61. Example:
  62. >>> c = catalog.Catalog('my_songs', type='song')
  63. >>> items
  64. [{'action': 'update',
  65. 'item': {'artist_name': 'dAn ThE aUtOmAtOr',
  66. 'disc_number': 1,
  67. 'genre': 'Instrumental',
  68. 'item_id': '38937DDF04BC7FC4',
  69. 'play_count': 5,
  70. 'release': 'Bombay the Hard Way: Guns, Cars & Sitars',
  71. 'song_name': 'Inspector Jay From Dehli',
  72. 'track_number': 9,
  73. 'url': 'file://localhost/Users/tylerw/Music/iTunes/iTunes%20Media/Music/Dan%20the%20Automator/Bombay%20the%20Hard%20Way_%20Guns,%20Cars%20&%20Sitars/09%20Inspector%20Jay%20From%20Dehli.m4a'}}]
  74. >>> ticket = c.update(items)
  75. >>> ticket
  76. u'7dcad583f2a38e6689d48a792b2e4c96'
  77. >>> c.status(ticket)
  78. {u'ticket_status': u'complete', u'update_info': []}
  79. >>>
  80. """
  81. post_data = {}
  82. items_json = json.dumps(items, default=dthandler)
  83. post_data['data'] = items_json
  84. response = self.post_attribute("update", data=post_data)
  85. return response['ticket']
  86. def status(self, ticket):
  87. """
  88. Check the status of a catalog update
  89. Args:
  90. ticket (str): A string representing a ticket ID
  91. Kwargs:
  92. Returns:
  93. A dictionary representing ticket status
  94. Example:
  95. >>> ticket
  96. u'7dcad583f2a38e6689d48a792b2e4c96'
  97. >>> c.status(ticket)
  98. {u'ticket_status': u'complete', u'update_info': []}
  99. >>>
  100. """
  101. return self.get_attribute_simple("status", ticket=ticket)
  102. def get_profile(self):
  103. """
  104. Check the status of a catalog update
  105. Args:
  106. Kwargs:
  107. Returns:
  108. A dictionary representing ticket status
  109. Example:
  110. >>> c
  111. <catalog - test_song_catalog>
  112. >>> c.profile()
  113. {u'id': u'CAGPXKK12BB06F9DE9',
  114. u'name': u'test_song_catalog',
  115. u'pending_tickets': [],
  116. u'resolved': 2,
  117. u'total': 4,
  118. u'type': u'song'}
  119. >>>
  120. """
  121. result = self.get_attribute("profile")
  122. return result['catalog']
  123. profile = property(get_profile)
  124. def read_items(self, buckets=None, results=15, start=0):
  125. """
  126. Returns data from the catalog; also expanded for the requested buckets
  127. Args:
  128. Kwargs:
  129. buckets (list): A list of strings specifying which buckets to retrieve
  130. results (int): An integer number of results to return
  131. start (int): An integer starting value for the result set
  132. Returns:
  133. A list of objects in the catalog; list contains additional attributes 'start' and 'total'
  134. Example:
  135. >>> c
  136. <catalog - my_songs>
  137. >>> c.read_items(results=1)
  138. [<song - Harmonice Mundi II>]
  139. >>>
  140. """
  141. kwargs = {}
  142. kwargs['bucket'] = buckets or []
  143. response = self.get_attribute("read", results=results, start=start, **kwargs)
  144. rval = ResultList([])
  145. rval.start = response['catalog']['start']
  146. rval.total = response['catalog']['total']
  147. for item in response['catalog']['items']:
  148. new_item = None
  149. # song item
  150. if 'song_id' in item:
  151. item['id'] = item.pop('song_id')
  152. item['title'] = item.pop('song_name')
  153. request = item['request']
  154. new_item = song.Song(**util.fix(item))
  155. new_item.request = request
  156. # artist item
  157. elif 'artist_id' in item:
  158. item['id'] = item.pop('artist_id')
  159. item['name'] = item.pop('artist_name')
  160. request = item['request']
  161. new_item = artist.Artist(**util.fix(item))
  162. new_item.request = request
  163. # unresolved item
  164. else:
  165. new_item = item
  166. rval.append(new_item)
  167. return rval
  168. read = property(read_items)
  169. def get_feed(self, buckets=None, since=None, results=15, start=0):
  170. """
  171. Returns feed (news, blogs, reviews, audio, video) for the catalog artists; response depends on requested buckets
  172. Args:
  173. Kwargs:
  174. buckets (list): A list of strings specifying which feed items to retrieve
  175. results (int): An integer number of results to return
  176. start (int): An integer starting value for the result set
  177. Returns:
  178. A list of news, blogs, reviews, audio or video document dicts;
  179. Example:
  180. >>> c
  181. <catalog - my_artists>
  182. >>> c.get_feed(results=15)
  183. {u'date_found': u'2011-02-06T07:50:25',
  184. u'date_posted': u'2011-02-06T07:50:23',
  185. u'id': u'caec686c0dff361e4c53dceb58fb9d2f',
  186. u'name': u'Linkin Park \u2013 \u201cWaiting For The End\u201d + \u201cWhen They Come For Me\u201d 2/5 SNL',
  187. u'references': [{u'artist_id': u'ARQUMH41187B9AF699',
  188. u'artist_name': u'Linkin Park'}],
  189. u'summary': u'<span>Linkin</span> <span>Park</span> performed "Waiting For The End" and "When They Come For Me" on Saturday Night Live. Watch the videos below and pick up their album A Thousand Suns on iTunes, Amazon MP3, CD Social Bookmarking ... ',
  190. u'type': u'blogs',
  191. u'url': u'http://theaudioperv.com/2011/02/06/linkin-park-waiting-for-the-end-when-they-come-for-me-25-snl/'}
  192. >>>
  193. """
  194. kwargs = {}
  195. kwargs['bucket'] = buckets or []
  196. if since:
  197. kwargs['since']=since
  198. response = self.get_attribute("feed", results=results, start=start, **kwargs)
  199. rval = ResultList(response['feed'])
  200. return rval
  201. feed = property(get_feed)
  202. def delete(self):
  203. """
  204. Deletes the entire catalog
  205. Args:
  206. Kwargs:
  207. Returns:
  208. The deleted catalog's id.
  209. Example:
  210. >>> c
  211. <catalog - test_song_catalog>
  212. >>> c.delete()
  213. {u'id': u'CAXGUPY12BB087A21D'}
  214. >>>
  215. """
  216. return self.post_attribute("delete")
  217. def list(results=30, start=0):
  218. """
  219. Returns list of all catalogs created on this API key
  220. Args:
  221. Kwargs:
  222. results (int): An integer number of results to return
  223. start (int): An integer starting value for the result set
  224. Returns:
  225. A list of catalog objects
  226. Example:
  227. >>> catalog.list()
  228. [<catalog - test_artist_catalog>, <catalog - test_song_catalog>, <catalog - my_songs>]
  229. >>>
  230. """
  231. result = util.callm("%s/%s" % ('catalog', 'list'), {'results': results, 'start': start})
  232. return [Catalog(**util.fix(d)) for d in result['response']['catalogs']]