Example #1
0
 def artists(self):
     try:
         return [ { 'name' : xp(self.attributes, 'Artist')['v'] } ]
     except Exception:
         try:
             return [ { 'name' : xp(self.attributes, 'Creator')['v'] } ]
         except Exception:
             return []
Example #2
0
 def images(self):
     try:
         image_set = xp(self.underlying.data, 'ImageSets','ImageSet')
         image = xp(image_set,'LargeImage','URL')['v']
         if image is not None:
             return [image]
     except Exception:
         pass
     return []
Example #3
0
 def length(self):
     # Traditionally runtime is reported in minutes, but we want it in seconds.
     unitsConversion = 60
     try:
         units = xp(self.attributes, 'RunningTime')['a']['Units']
         if units != 'minutes':
             raise Exception('Unexpected units found on Amazon movie: (%s)' % units)
     except KeyError:
         pass
     try:
         return float(xp(self.attributes, 'RunningTime')['v']) * unitsConversion
     except KeyError:
         return None
Example #4
0
 def _is_video_game(item):
     try:
         if xp(item, 'ItemAttributes', 'ProductGroup')['v'].lower() == "video games":
             return True
     except Exception:
         pass
     
     try:
        if xp(item, 'ItemAttributes', 'ProductTypeName')['v'].lower() == "console_video_game":
            return True
     except Exception:
         pass
     
     return False
Example #5
0
 def publishers(self):
     try:
         return [{
             'name': xp(self.attributes, 'Publisher')['v']
         }]
     except Exception:
         return []
Example #6
0
 def _issueLookup(self):
     # Slightly ugly -- calling ResolverObject method just because we know all _AmazonObject implementations also
     # inherit from ResolverObject. TODO: Get rid of multiple inheritance!
     # We don't catch the LookupRequiredError here because if you are initializing a capped-lookup object without
     # passing in initial data, you are doing it wrong.
     self.countLookupCall('base data')
     raw = globalAmazon().item_lookup(timeout=MERGE_TIMEOUT, **self.__params)
     self.__data = xp(raw, 'ItemLookupResponse','Items','Item')
Example #7
0
 def authors(self):
     try:
         author = xp(self.attributes, 'Author')['v']
         if '-N/A-' in author:
             return []
         return [{ 'name': author }]
     except Exception:
         return []
Example #8
0
 def tracks(self):
     # We might be missing related items data entirely, in which case we start by issuing a lookup there.
     # TODO: This probably could be done as part of one lookup with the one about to be made.
     try:
         tracks = list(xp(self.data, 'RelatedItems')['c']['RelatedItem'])
     except KeyError:
         try:
             self._issueLookup()
         except LookupRequiredError:
             return []
     try:
         tracks = list(xp(self.data, 'RelatedItems')['c']['RelatedItem'])
         page_count = int(xp(self.data, 'RelatedItems', 'RelatedItemPageCount')['v'])
         for i in range(1,page_count):
             page = i+1
             self.countLookupCall('tracks')
             data = globalAmazon().item_lookup(ItemId=self.key,
                                               ResponseGroup='Large,RelatedItems',
                                               RelationshipType='Tracks',
                                               RelatedItemPage=str(page),
                                               timeout=MERGE_TIMEOUT)
             tracks.extend( xp(data, 'ItemLookupResponse', 'Items', 'Item', 'RelatedItems')['c']['RelatedItem'] )
         track_d = {}
         for track in tracks:
             track_d[ int(xp(track, 'Item', 'ItemAttributes', 'TrackSequence')['v']) ] = {
                 'name' : xp(track, 'Item', 'ItemAttributes', 'Title')['v'],
                 'key' : xp(track, 'Item', 'ASIN')['v'],
             }
         return [ track_d[k] for k in sorted(track_d) ]
     except LookupRequiredException:
         return []
     except Exception:
         # TODO: It seems possible that only one of the requests failed; shouldn't we keep the results of the others?
         report()
         return []
Example #9
0
 def trackSource(self, query=None, query_string=None):
     if query_string is None:
         query_string = ' '.join([
             query.name
         ])
     
     return self.__searchGen(AmazonTrack, {
         'test':lambda item:  xp(item, 'ItemAttributes', 'ProductTypeName')['v'] == "DOWNLOADABLE_MUSIC_TRACK",
         'Keywords':query_string
     })
Example #10
0
 def underlying(self):
     try:
         versions = xp(self.data, 'AlternateVersions')['c']['AlternateVersion']
         priorities = [
             'Kindle Edition',
             'Hardcover',
             'Paperback',
             'Audio CD',
         ]
         self_kind = xp(self.attributes, 'Binding')['v']
         for kind in priorities:
             if self_kind == kind:
                 return self
             for version in versions:
                 if xp(version, 'Binding')['v'] == kind:
                     return AmazonBook(xp(version, 'ASIN')['v'])
     except Exception:
         pass
     return self
Example #11
0
 def albums(self):
     try:
         album = xp(self.data, 'RelatedItems', 'RelatedItem', 'Item')
     except KeyError:
         try:
             self._issueLookup()
         except LookupRequiredError:
             return []
     try:
         album = xp(self.data, 'RelatedItems', 'RelatedItem', 'Item')
         key = xp(album, 'ASIN')['v']
         attributes = xp(album, 'ItemAttributes')
         return [{
             'name' : xp(attributes, 'Title')['v'],
             'source' : 'amazon',
             'key' : key,
         }]
     except Exception:
         return []
Example #12
0
    def __augmentAlbumResultsWithSongs(self, albums, tracks):
        """
        Boosts the ranks of albums in search if we also see tracks from those albums in the same search results.
        This part is admittedly pretty heinous. Unlike, say, iTunes, Amazon does not tell us the ID or even the name
        of the album for a track, but we can get it through comparing cover art URLs. Ugh.

        Note that albums and tracks are both SearchResult objects. TODO: Should probably change naming to reflect that.

        TODO: We can get tracks now! Use tracks instead.
        """
        picUrlsToAlbums = {}
        for album in albums:
            try:
                largeImageUrl = xp(album.resolverObject.data, 'ImageSets', 'ImageSet', 'LargeImage', 'URL')['v']
                if largeImageUrl in picUrlsToAlbums:
                    logs.warning('Found multiple albums in Amazon results with identical cover art!')
                picUrlsToAlbums[largeImageUrl] = album
            except KeyError:
                pass

        # If there are dupes in the tracks side, we don't want to double-increment artist scores on that basis.
        seenTitlesAndArtists = set()
        for track in tracks:
            simpleTitle = trackSimplify(track.resolverObject.name)
            simpleArtist = ''
            if track.resolverObject.artists:
                simpleArtist = artistSimplify(track.resolverObject.artists[0])
            if (simpleTitle, simpleArtist) in seenTitlesAndArtists:
                continue
            seenTitlesAndArtists.add((simpleTitle, simpleArtist))

            try:
                largeImageUrl = xp(track.resolverObject.data, 'ImageSets', 'ImageSet', 'LargeImage', 'URL')['v']
                if largeImageUrl not in picUrlsToAlbums:
                    continue
                scoreBoost = track.relevance / 5
                album = picUrlsToAlbums[largeImageUrl]
                album.addRelevanceComponentDebugInfo('boost from song %s' % track.resolverObject.name, scoreBoost)
                album.relevance += scoreBoost

            except KeyError:
                pass
Example #13
0
    def __constructMusicObjectFromResult(self, rawResult, maxLookupCalls=None):
        """
        Determines whether the raw result is an album or a track and constructs an _AmazonObject appropriately.
        """
        productTypeName = xp(rawResult, 'ItemAttributes', 'ProductTypeName')['v']
        try:
            binding = xp(rawResult, 'ItemAttributes', 'Binding')['v']
        except KeyError:
            binding = None

        asin = xp(rawResult, 'ASIN')['v']
        if productTypeName == 'DOWNLOADABLE_MUSIC_TRACK':
            return AmazonTrack(asin, data=rawResult, maxLookupCalls=maxLookupCalls)
        elif productTypeName == 'DOWNLOADABLE_MUSIC_ALBUM':
            return AmazonAlbum(asin, data=rawResult, maxLookupCalls=maxLookupCalls)
        elif productTypeName in ['CONTRIBUTOR_AUTHORITY_SET', 'ABIS_DVD', 'VIDEO_VHS', 'DOWNLOADABLE_MUSIC_ARTIST']:
            return None
        elif binding in ['Audio CD', 'Vinyl']:
            return AmazonAlbum(asin, data=rawResult, maxLookupCalls=maxLookupCalls)

        raise AmazonSource.UnknownTypeError('Unknown product type %s seen on result with ASIN %s!' % (productTypeName, asin))
Example #14
0
    def entityProxyFromKey(self, key, **kwargs):
        try:
            lookupData = globalAmazon().item_lookup(ResponseGroup='Large', ItemId=key, timeout=MERGE_TIMEOUT)
            result = _getLookupResult(lookupData)
            kind = xp(result, 'ItemAttributes', 'ProductGroup')['v'].lower()
            logs.debug(kind)

            if kind == 'book' or kind == 'ebooks':
                return AmazonBook(key, result, 0)
            if kind == 'video games':
                return AmazonVideoGame(key, result, 0)
            return self.__constructMusicObjectFromResult(result, 0)
        except KeyError:
            logs.report()
        return None
Example #15
0
 def bookSource(self, query=None, query_string=None):
     if query_string is None:
         query_string = ' '.join([
             query.name
         ])
     
     return self.__searchGen(AmazonBook,
         {
             'Keywords':query_string,
             'SearchIndex':'Books',
             'test': lambda item: xp(item, 'ItemAttributes', 'Binding')['v'] == 'Kindle Edition',
         },
         {
             'Keywords':query_string,
             'SearchIndex':'Books',
         }
     )
Example #16
0
        def gen():
            try:
                for params in queries:
                    test = params.pop('test', lambda x: True)
                    if 'SearchIndex' not in params:
                        params['SearchIndex'] = 'All'
                    if 'ResponseGroup' not in params:
                        params['ResponseGroup'] = "ItemAttributes"
                    results = globalAmazon().item_search(timeout=SEARCH_TIMEOUT, **params)

                    for item in _getSearchResults(results):
                        try:
                            if test == None or test(item):
                                yield xp(item, 'ASIN')['v'], item
                        except Exception:
                            pass
            except GeneratorExit:
                pass
Example #17
0
    def artists(self):
        try:
            return [ { 'name' : xp(self.attributes, 'Artist')['v'] } ]
        except Exception:
            pass

        try:
            return [ { 'name' : xp(self.attributes, 'Creator')['v'] } ]
        except Exception:
            pass

        try:
            album = xp(self.data, 'RelatedItems', 'RelatedItem', 'Item')
            key = xp(album,'ASIN')['v']
            attributes = xp(album, 'ItemAttributes')
            return [ { 'name' : xp(attributes, 'Creator')['v'] } ]
        except Exception:
            return []
Example #18
0
 def raw_name(self):
     return xp(self.attributes, 'Title')['v']
Example #19
0
 def mpaa_rating(self):
     try:
         return xp(self.attributes, 'AudienceRating')['v']
     except KeyError:
         return None
Example #20
0
 def isbn(self):
     try:
         return xp(self.attributes, 'ISBN')['v']
     except KeyError:
         return None
Example #21
0
 def genres(self):
     try:
         return [ xp(self.attributes, 'Genre')['v'] ]
     except KeyError:
         return []
Example #22
0
 def description(self):
     try:
         return xp(self.data, 'EditorialReview', 'Content')['v']
     except Exception:
         return ""
Example #23
0
 def genres(self):
     try:
         return [ xp(self.attributes, 'Genre')['v'] ]
     except Exception:
         return []
Example #24
0
 def sku_number(self):
     try:
         return xp(self.attributes, 'SKU')['v']
     except Exception:
         return None
Example #25
0
 def release_date(self):
     try:
         return parseDateString( xp(self.attributes, 'PublicationDate')['v'] )
     except Exception:
         return None
Example #26
0
 def platform(self):
     try:
         return { 'name': xp(self.attributes, 'Platform')['v'] }
     except Exception:
         return { 'name':'' }
Example #27
0
 def attributes(self):
     return xp(self.data, 'ItemAttributes')
Example #28
0
 def link(self):
     try:
         return xp(self.data, 'ItemLinks', 'ItemLink', 'URL')['v']
     except Exception:
         return None
Example #29
0
 def authors(self):
     try:
         return [ { 'name': xp(self.attributes, 'Author')['v'] } ]
     except Exception:
         return []
Example #30
0
 def description(self):
     # TODO: Many of these attributes are common between a bunch of Amazon types. Put them in _AmazonObject.
     try:
         return xp(self.attributes, 'EditorialReview', 'Content')['v']
     except KeyError:
         return ''