diff --git a/src/calibre/ebooks/metadata/sources/amazon.py b/src/calibre/ebooks/metadata/sources/amazon.py index 335a43ebb0..b99893ccba 100644 --- a/src/calibre/ebooks/metadata/sources/amazon.py +++ b/src/calibre/ebooks/metadata/sources/amazon.py @@ -322,7 +322,7 @@ class Amazon(Source): # }}} def identify(self, log, result_queue, abort, title=None, authors=None, # {{{ - identifiers={}, timeout=20): + identifiers={}, timeout=30): ''' Note this method will retry without identifiers automatically if no match is found with identifiers. @@ -436,7 +436,7 @@ if __name__ == '__main__': ( # An e-book ISBN not on Amazon, one of the authors is # unknown to Amazon, so no popup wrapper - {'identifiers':{'isbn': '0307459671'}, + {'identifiers':{'isbn': '9780307459671'}, 'title':'Invisible Gorilla', 'authors':['Christopher Chabris']}, [title_test('The Invisible Gorilla: And Other Ways Our Intuitions Deceive Us', exact=True), authors_test(['Christopher Chabris', 'Daniel Simons'])] diff --git a/src/calibre/ebooks/metadata/sources/base.py b/src/calibre/ebooks/metadata/sources/base.py index 3c320d14b6..55cc996cf7 100644 --- a/src/calibre/ebooks/metadata/sources/base.py +++ b/src/calibre/ebooks/metadata/sources/base.py @@ -137,6 +137,16 @@ class Source(Plugin): ''' Identify a book by its title/author/isbn/etc. + If identifiers(s) are specified and no match is found and this metadata + source does not store all related identifiers (for example, all ISBNs + of a book), this method should retry with just the title and author + (assuming they were specified). + + If this metadata source also provides covers, the URL to the cover + should be cached so that a subsequent call to the get covers API with + the same ISBN/special identifier does not need to get the cover URL + again. Use the caching API for this. + :param log: A log object, use it to output debugging information/errors :param result_queue: A result Queue, results should be put into it. Each result is a Metadata object diff --git a/src/calibre/ebooks/metadata/sources/google.py b/src/calibre/ebooks/metadata/sources/google.py index 8dffd3f053..289be1bcc8 100644 --- a/src/calibre/ebooks/metadata/sources/google.py +++ b/src/calibre/ebooks/metadata/sources/google.py @@ -206,7 +206,7 @@ class GoogleBooks(Source): break def identify(self, log, result_queue, abort, title=None, authors=None, # {{{ - identifiers={}, timeout=20): + identifiers={}, timeout=30): query = self.create_query(log, title=title, authors=authors, identifiers=identifiers) br = self.browser @@ -225,6 +225,11 @@ class GoogleBooks(Source): log.exception('Failed to parse identify results') return as_unicode(e) + if not entries and identifiers and title and authors and \ + not abort.is_set(): + return self.identify(log, result_queue, abort, title=title, + authors=authors, timeout=timeout) + # There is no point running these queries in threads as google # throttles requests returning 403 Forbidden errors self.get_all_details(br, log, entries, abort, result_queue, timeout) @@ -235,13 +240,16 @@ class GoogleBooks(Source): if __name__ == '__main__': # To run these test use: calibre-debug -e src/calibre/ebooks/metadata/sources/google.py from calibre.ebooks.metadata.sources.test import (test_identify_plugin, - title_test) + title_test, authors_test) test_identify_plugin(GoogleBooks.name, [ + ( - {'identifiers':{'isbn': '0743273567'}}, - [title_test('The great gatsby', exact=True)] + {'identifiers':{'isbn': '0743273567'}, 'title':'Great Gatsby', + 'authors':['Fitzgerald']}, + [title_test('The great gatsby', exact=True), + authors_test(['Francis Scott Fitzgerald'])] ), #( diff --git a/src/calibre/ebooks/metadata/sources/test.py b/src/calibre/ebooks/metadata/sources/test.py index 69e0c32846..2af9a47078 100644 --- a/src/calibre/ebooks/metadata/sources/test.py +++ b/src/calibre/ebooks/metadata/sources/test.py @@ -46,6 +46,16 @@ def authors_test(authors): return test +def _test_fields(touched_fields, mi): + for key in touched_fields: + if key.startswith('identifier:'): + key = key.partition(':')[-1] + if not mi.has_identifier(key): + return 'identifier: ' + key + elif mi.is_null(key): + return key + + def test_identify_plugin(name, tests): ''' :param name: Plugin name @@ -95,7 +105,7 @@ def test_identify_plugin(name, tests): prints(mi) prints('\n\n') - match_found = None + possibles = [] for mi in results: test_failed = False for tfunc in test_funcs: @@ -103,26 +113,23 @@ def test_identify_plugin(name, tests): test_failed = True break if not test_failed: - match_found = mi - break + possibles.append(mi) - if match_found is None: + if not possibles: prints('ERROR: No results that passed all tests were found') prints('Log saved to', lf) raise SystemExit(1) - for key in plugin.touched_fields: - if key.startswith('identifier:'): - key = key.partition(':')[-1] - if not match_found.has_identifier(key): - prints('Failed to find identifier:', key) - raise SystemExit(1) - elif match_found.is_null(key): - prints('Failed to find', key) + good = [x for x in possibles if _test_fields(plugin.touched_fields, x) is + None] + if not good: + prints('Failed to find', _test_fields(plugin.touched_fields, + possibles[0])) raise SystemExit(1) + prints('Average time per query', sum(times)/len(times)) if os.stat(lf).st_size > 10: - prints('There were some errors, see log', lf) + prints('There were some errors/warnings, see log', lf)