PageRenderTime 21ms CodeModel.GetById 1ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/pyechonest/pyechonest/catalog.py

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