1
2
3
4 """
5 Copyright (c) 2010 The Echo Nest. All rights reserved.
6 Created by Scotty Vercoe on 2010-08-25.
7
8 The Catalog module loosely covers http://developer.echonest.com/docs/v4/catalog.html
9 Refer to the official api documentation if you are unsure about something.
10 """
11 try:
12 import json
13 except ImportError:
14 import simplejson as json
15 import datetime
16
17 import warnings
18 import util
19 from proxies import CatalogProxy, ResultList
20 import artist, song
21
22
23 dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else None
24
26 """
27 A Catalog object
28
29 Attributes:
30 id (str): Catalog ID
31
32 name (str): Catalog Name
33
34 read (list): A list of catalog items (objects if they are resolved, else dictionaries)
35
36 feed (list): A list of dictionaries for news, blogs, reviews, audio, video for a catalog's artists
37
38 Create an catalog object like so:
39
40 >>> c = catalog.Catalog('CAGPXKK12BB06F9DE9') # get existing catalog
41 >>> c = catalog.Catalog('test_song_catalog', 'song') # get existing or create new catalog
42
43 """
44 - def __init__(self, id, type=None, **kwargs):
45 """
46 Create a catalog object (get a catalog by ID or get or create one given by name and type)
47
48 Args:
49 id (str): A catalog id or name
50
51 Kwargs:
52 type (str): 'song' or 'artist', specifying the catalog type
53
54 Returns:
55 A catalog object
56
57 Example:
58
59 >>> c = catalog.Catalog('my_songs', type='song')
60 >>> c.id
61 u'CAVKUPC12BCA792120'
62 >>> c.name
63 u'my_songs'
64 >>>
65
66 """
67 super(Catalog, self).__init__(id, type, **kwargs)
68
70 return "<%s - %s>" % (self._object_type.encode('utf-8'), self.name.encode('utf-8'))
71
73 return self.name.encode('utf-8')
74
76 """
77 Update a catalog object
78
79 Args:
80 items (list): A list of dicts describing update data and action codes (see api docs)
81
82 Kwargs:
83
84 Returns:
85 A ticket id
86
87 Example:
88
89 >>> c = catalog.Catalog('my_songs', type='song')
90 >>> items
91 [{'action': 'update',
92 'item': {'artist_name': 'dAn ThE aUtOmAtOr',
93 'disc_number': 1,
94 'genre': 'Instrumental',
95 'item_id': '38937DDF04BC7FC4',
96 'play_count': 5,
97 'release': 'Bombay the Hard Way: Guns, Cars & Sitars',
98 'song_name': 'Inspector Jay From Dehli',
99 'track_number': 9,
100 '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'}}]
101 >>> ticket = c.update(items)
102 >>> ticket
103 u'7dcad583f2a38e6689d48a792b2e4c96'
104 >>> c.status(ticket)
105 {u'ticket_status': u'complete', u'update_info': []}
106 >>>
107
108 """
109 post_data = {}
110 items_json = json.dumps(items, default=dthandler)
111 post_data['data'] = items_json
112
113 response = self.post_attribute("update", data=post_data)
114
115 return response['ticket']
116
118 """
119 Check the status of a catalog update
120
121 Args:
122 ticket (str): A string representing a ticket ID
123
124 Kwargs:
125
126 Returns:
127 A dictionary representing ticket status
128
129 Example:
130
131 >>> ticket
132 u'7dcad583f2a38e6689d48a792b2e4c96'
133 >>> c.status(ticket)
134 {u'ticket_status': u'complete', u'update_info': []}
135 >>>
136
137 """
138 return self.get_attribute_simple("status", ticket=ticket)
139
141 """
142 Check the status of a catalog update
143
144 Args:
145
146 Kwargs:
147
148 Returns:
149 A dictionary representing ticket status
150
151 Example:
152
153 >>> c
154 <catalog - test_song_catalog>
155 >>> c.profile()
156 {u'id': u'CAGPXKK12BB06F9DE9',
157 u'name': u'test_song_catalog',
158 u'pending_tickets': [],
159 u'resolved': 2,
160 u'total': 4,
161 u'type': u'song'}
162 >>>
163
164 """
165 result = self.get_attribute("profile")
166 return result['catalog']
167
168 profile = property(get_profile)
169 - def read_items(self, buckets=None, results=15, start=0,item_ids=None):
170 """
171 Returns data from the catalog; also expanded for the requested buckets.
172 This method is provided for backwards-compatibility
173
174 Args:
175
176 Kwargs:
177 buckets (list): A list of strings specifying which buckets to retrieve
178
179 results (int): An integer number of results to return
180
181 start (int): An integer starting value for the result set
182
183 Returns:
184 A list of objects in the catalog; list contains additional attributes 'start' and 'total'
185
186 Example:
187
188 >>> c
189 <catalog - my_songs>
190 >>> c.read_items(results=1)
191 [<song - Harmonice Mundi II>]
192 >>>
193 """
194 warnings.warn("catalog.read_items() is depreciated. Please use catalog.get_item_dicts() instead.")
195 kwargs = {}
196 kwargs['bucket'] = buckets or []
197 kwargs['item_id'] = item_ids or []
198 response = self.get_attribute("read", results=results, start=start, **kwargs)
199 rval = ResultList([])
200 if item_ids:
201 rval.start=0;
202 rval.total=len(response['catalog']['items'])
203 else:
204 rval.start = response['catalog']['start']
205 rval.total = response['catalog']['total']
206 for item in response['catalog']['items']:
207 new_item = None
208
209 if 'song_id' in item:
210 item['id'] = item.pop('song_id')
211 item['title'] = item.pop('song_name')
212 request = item['request']
213 new_item = song.Song(**util.fix(item))
214 new_item.request = request
215
216 elif 'artist_id' in item:
217 item['id'] = item.pop('artist_id')
218 item['name'] = item.pop('artist_name')
219 request = item['request']
220 new_item = artist.Artist(**util.fix(item))
221 new_item.request = request
222
223 else:
224 new_item = item
225 rval.append(new_item)
226 return rval
227
228 read = property(read_items)
229
230 - def get_item_dicts(self, buckets=None, results=15, start=0,item_ids=None):
231 """
232 Returns data from the catalog; also expanded for the requested buckets
233
234 Args:
235
236 Kwargs:
237 buckets (list): A list of strings specifying which buckets to retrieve
238
239 results (int): An integer number of results to return
240
241 start (int): An integer starting value for the result set
242
243 Returns:
244 A list of dicts representing objects in the catalog; list has additional attributes 'start' and 'total'
245
246 Example:
247
248 >>> c
249 <catalog - my_songs>
250 >>> c.read_items(results=1)
251 [
252 {
253 "artist_id": "AR78KRI1187B98E6F2",
254 "artist_name": "Art of Noise",
255 "date_added": "2012-04-02T16:50:02",
256 "foreign_id": "CAHLYLR13674D1CF83:song:1000",
257 "request": {
258 "artist_name": "The Art Of Noise",
259 "item_id": "1000",
260 "song_name": "Love"
261 },
262 "song_id": "SOSBCTO1311AFE7AE0",
263 "song_name": "Love"
264 }
265 ]
266 """
267 kwargs = {}
268 kwargs['bucket'] = buckets or []
269 kwargs['item_id'] = item_ids or []
270 response = self.get_attribute("read", results=results, start=start, **kwargs)
271 rval = ResultList(response['catalog']['items'])
272 if item_ids:
273 rval.start=0;
274 rval.total=len(response['catalog']['items'])
275 else:
276 rval.start = response['catalog']['start']
277 rval.total = response['catalog']['total']
278 return rval
279
280 item_dicts = property(get_item_dicts)
281
282 - def get_feed(self, buckets=None, since=None, results=15, start=0):
283 """
284 Returns feed (news, blogs, reviews, audio, video) for the catalog artists; response depends on requested buckets
285
286 Args:
287
288 Kwargs:
289 buckets (list): A list of strings specifying which feed items to retrieve
290
291 results (int): An integer number of results to return
292
293 start (int): An integer starting value for the result set
294
295 Returns:
296 A list of news, blogs, reviews, audio or video document dicts;
297
298 Example:
299
300 >>> c
301 <catalog - my_artists>
302 >>> c.get_feed(results=15)
303 {u'date_found': u'2011-02-06T07:50:25',
304 u'date_posted': u'2011-02-06T07:50:23',
305 u'id': u'caec686c0dff361e4c53dceb58fb9d2f',
306 u'name': u'Linkin Park \u2013 \u201cWaiting For The End\u201d + \u201cWhen They Come For Me\u201d 2/5 SNL',
307 u'references': [{u'artist_id': u'ARQUMH41187B9AF699',
308 u'artist_name': u'Linkin Park'}],
309 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 ... ',
310 u'type': u'blogs',
311 u'url': u'http://theaudioperv.com/2011/02/06/linkin-park-waiting-for-the-end-when-they-come-for-me-25-snl/'}
312 >>>
313 """
314 kwargs = {}
315 kwargs['bucket'] = buckets or []
316 if since:
317 kwargs['since']=since
318 response = self.get_attribute("feed", results=results, start=start, **kwargs)
319 rval = ResultList(response['feed'])
320 return rval
321
322 feed = property(get_feed)
323
324
326 """
327 Deletes the entire catalog
328
329 Args:
330
331 Kwargs:
332
333 Returns:
334 The deleted catalog's id.
335
336 Example:
337
338 >>> c
339 <catalog - test_song_catalog>
340 >>> c.delete()
341 {u'id': u'CAXGUPY12BB087A21D'}
342 >>>
343
344 """
345 return self.post_attribute("delete")
346
347 - def play(self, items, plays=None):
349
350 - def skip(self, items, skips=None):
352
353 - def favorite(self, items, favorite=None):
357
358 - def ban(self, items, ban=None):
362
363 - def rate(self, items, rating=None):
365
367 """
368 Returns list of all catalogs created on this API key
369
370 Args:
371
372 Kwargs:
373 results (int): An integer number of results to return
374
375 start (int): An integer starting value for the result set
376
377 Returns:
378 A list of catalog objects
379
380 Example:
381
382 >>> catalog.list()
383 [<catalog - test_artist_catalog>, <catalog - test_song_catalog>, <catalog - my_songs>]
384 >>>
385
386 """
387 result = util.callm("%s/%s" % ('catalog', 'list'), {'results': results, 'start': start})
388 cats = [Catalog(**util.fix(d)) for d in result['response']['catalogs']]
389 start = result['response']['start']
390 total = result['response']['total']
391 return ResultList(cats, start, total)
392