home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / calibre-0.7.26.msi / file_947 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-10-31  |  11.4 KB  |  374 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
  6. __docformat__ = 'restructuredtext en'
  7. import traceback
  8. import socket
  9. import re
  10. import sys
  11. from functools import partial
  12. from threading import Thread, Event
  13. from Queue import Queue, Empty
  14. from lxml import etree
  15. import mechanize
  16. from calibre.customize import Plugin
  17. from calibre import browser, prints
  18. from calibre.ebooks.BeautifulSoup import BeautifulSoup
  19. from calibre.constants import preferred_encoding, DEBUG
  20.  
  21. class CoverDownload(Plugin):
  22.     supported_platforms = [
  23.         'windows',
  24.         'osx',
  25.         'linux']
  26.     author = 'Kovid Goyal'
  27.     type = _('Cover download')
  28.     
  29.     def has_cover(self, mi, ans, timeout = 5):
  30.         raise NotImplementedError()
  31.  
  32.     
  33.     def get_covers(self, mi, result_queue, abort, timeout = 5):
  34.         raise NotImplementedError()
  35.  
  36.     
  37.     def exception_to_string(self, ex):
  38.         
  39.         try:
  40.             return unicode(ex)
  41.         except:
  42.             
  43.             try:
  44.                 return str(ex).decode(preferred_encoding, 'replace')
  45.             return repr(ex)
  46.  
  47.  
  48.  
  49.     
  50.     def debug(self, *args, **kwargs):
  51.         if DEBUG:
  52.             prints('\t' + self.name + ':', *args, **kwargs)
  53.         
  54.  
  55.  
  56.  
  57. class HeadRequest(mechanize.Request):
  58.     
  59.     def get_method(self):
  60.         return 'HEAD'
  61.  
  62.  
  63.  
  64. class OpenLibraryCovers(CoverDownload):
  65.     OPENLIBRARY = 'http://covers.openlibrary.org/b/isbn/%s-L.jpg?default=false'
  66.     name = 'openlibrary.org covers'
  67.     description = _('Download covers from openlibrary.org')
  68.     author = 'Kovid Goyal'
  69.     
  70.     def has_cover(self, mi, ans, timeout = 5):
  71.         if not mi.isbn:
  72.             return False
  73.         br = browser()
  74.         br.set_handle_redirect(False)
  75.         
  76.         try:
  77.             br.open_novisit(HeadRequest(self.OPENLIBRARY % mi.isbn), timeout = timeout)
  78.             self.debug('cover for', mi.isbn, 'found')
  79.             ans.set()
  80.         except Exception:
  81.             mi.isbn
  82.             e = mi.isbn
  83.             if callable(getattr(e, 'getcode', None)) and e.getcode() == 302:
  84.                 self.debug('cover for', mi.isbn, 'found')
  85.                 ans.set()
  86.             else:
  87.                 self.debug(e)
  88.         except:
  89.             e.getcode() == 302
  90.  
  91.  
  92.     
  93.     def get_covers(self, mi, result_queue, abort, timeout = 5):
  94.         if not mi.isbn:
  95.             return None
  96.         br = browser()
  97.         
  98.         try:
  99.             ans = br.open(self.OPENLIBRARY % mi.isbn, timeout = timeout).read()
  100.             result_queue.put((True, ans, 'jpg', self.name))
  101.         except Exception:
  102.             mi.isbn
  103.             e = mi.isbn
  104.             if callable(getattr(e, 'getcode', None)) and e.getcode() == 404:
  105.                 result_queue.put((False, _('ISBN: %s not found') % mi.isbn, '', self.name))
  106.             else:
  107.                 result_queue.put((False, self.exception_to_string(e), traceback.format_exc(), self.name))
  108.         except:
  109.             e.getcode() == 404
  110.  
  111.  
  112.  
  113.  
  114. class LibraryThingCovers(CoverDownload):
  115.     name = 'librarything.com covers'
  116.     description = _('Download covers from librarything.com')
  117.     author = 'Kovid Goyal'
  118.     LIBRARYTHING = 'http://www.librarything.com/isbn/'
  119.     
  120.     def get_cover_url(self, isbn, br, timeout = 5):
  121.         
  122.         try:
  123.             src = br.open_novisit('http://www.librarything.com/isbn/' + isbn, timeout = timeout).read().decode('utf-8', 'replace')
  124.         except Exception:
  125.             err = None
  126.             if isinstance(getattr(err, 'args', [
  127.                 None])[0], socket.timeout):
  128.                 err = Exception(_('LibraryThing.com timed out. Try again later.'))
  129.             
  130.             raise err
  131.  
  132.         s = BeautifulSoup(src)
  133.         url = s.find('td', attrs = {
  134.             'class': 'left' })
  135.         if url is None:
  136.             if s.find('div', attrs = {
  137.                 'class': 'highloadwarning' }) is not None:
  138.                 raise Exception(_('Could not fetch cover as server is experiencing high load. Please try again later.'))
  139.             s.find('div', attrs = {
  140.                 'class': 'highloadwarning' }) is not None
  141.             raise Exception(_('ISBN: %s not found') % isbn)
  142.         url is None
  143.         url = url.find('img')
  144.         if url is None:
  145.             raise Exception(_('LibraryThing.com server error. Try again later.'))
  146.         url is None
  147.         url = re.sub('_S[XY]\\d+', '', url['src'])
  148.         return url
  149.  
  150.     
  151.     def has_cover(self, mi, ans, timeout = 5):
  152.         if not mi.isbn:
  153.             return False
  154.         br = browser()
  155.         
  156.         try:
  157.             self.get_cover_url(mi.isbn, br, timeout = timeout)
  158.             self.debug('cover for', mi.isbn, 'found')
  159.             ans.set()
  160.         except Exception:
  161.             mi.isbn
  162.             e = mi.isbn
  163.             self.debug(e)
  164.         except:
  165.             mi.isbn
  166.  
  167.  
  168.     
  169.     def get_covers(self, mi, result_queue, abort, timeout = 5):
  170.         if not mi.isbn:
  171.             return None
  172.         br = browser()
  173.         
  174.         try:
  175.             url = self.get_cover_url(mi.isbn, br, timeout = timeout)
  176.             cover_data = br.open_novisit(url).read()
  177.             result_queue.put((True, cover_data, 'jpg', self.name))
  178.         except Exception:
  179.             mi.isbn
  180.             e = mi.isbn
  181.             result_queue.put((False, self.exception_to_string(e), traceback.format_exc(), self.name))
  182.         except:
  183.             mi.isbn
  184.  
  185.  
  186.  
  187.  
  188. def check_for_cover(mi, timeout = 5):
  189.     cover_sources = cover_sources
  190.     import calibre.customize.ui
  191.     ans = Event()
  192.     checkers = [ partial(p.has_cover, mi, ans, timeout = timeout) for p in cover_sources() ]
  193.     workers = [ Thread(target = c) for c in checkers ]
  194.     for w in workers:
  195.         w.daemon = True
  196.         w.start()
  197.     
  198.     for w in workers:
  199.         if _[3](_[3][int(w.is_alive())]) == 0:
  200.             break
  201.             continue
  202.         []
  203.         []
  204.     return ans.is_set()
  205.  
  206.  
  207. def download_covers(mi, result_queue, max_covers = 50, timeout = 5):
  208.     cover_sources = cover_sources
  209.     import calibre.customize.ui
  210.     abort = Event()
  211.     temp = Queue()
  212.     getters = [ partial(p.get_covers, mi, temp, abort, timeout = timeout) for p in cover_sources() ]
  213.     workers = [ Thread(target = c) for c in getters ]
  214.     for w in workers:
  215.         w.daemon = True
  216.         w.start()
  217.     
  218.     count = 0
  219.     for w in workers:
  220.         if _[3](_[3][int(w.is_alive())]) == 0:
  221.             break
  222.             continue
  223.         []
  224.         []
  225.     abort.set()
  226.     while True:
  227.         
  228.         try:
  229.             result = temp.get_nowait()
  230.             count += 1
  231.             result_queue.put(result)
  232.         continue
  233.         except Empty:
  234.             sum
  235.             sum
  236.             []
  237.             break
  238.             continue
  239.             []
  240.         
  241.  
  242.         sum<EXCEPTION MATCH>Empty
  243.  
  244.  
  245. class DoubanCovers(CoverDownload):
  246.     DOUBAN_ISBN_URL = 'http://api.douban.com/book/subject/isbn/'
  247.     CALIBRE_DOUBAN_API_KEY = '0bd1672394eb1ebf2374356abec15c3d'
  248.     name = 'Douban.com covers'
  249.     description = _('Download covers from Douban.com')
  250.     author = 'Li Fanxi'
  251.     
  252.     def get_cover_url(self, isbn, br, timeout = 5):
  253.         
  254.         try:
  255.             url = self.DOUBAN_ISBN_URL + isbn + '?apikey=' + self.CALIBRE_DOUBAN_API_KEY
  256.             src = br.open(url, timeout = timeout).read()
  257.         except Exception:
  258.             err = None
  259.             if isinstance(getattr(err, 'args', [
  260.                 None])[0], socket.timeout):
  261.                 err = Exception(_('Douban.com API timed out. Try again later.'))
  262.             
  263.             raise err
  264.  
  265.         feed = etree.fromstring(src)
  266.         NAMESPACES = {
  267.             'openSearch': 'http://a9.com/-/spec/opensearchrss/1.0/',
  268.             'atom': 'http://www.w3.org/2005/Atom',
  269.             'db': 'http://www.douban.com/xmlns/' }
  270.         XPath = partial(etree.XPath, namespaces = NAMESPACES)
  271.         entries = XPath('//atom:entry')(feed)
  272.         if len(entries) < 1:
  273.             return None
  274.         
  275.         try:
  276.             cover_url = XPath("descendant::atom:link[@rel='image']/attribute::href")
  277.             u = cover_url(entries[0])[0].replace('/spic/', '/lpic/')
  278.             if u.find('book-default') != -1:
  279.                 return None
  280.         except:
  281.             len(entries) < 1
  282.             return None
  283.  
  284.         return u
  285.  
  286.     
  287.     def has_cover(self, mi, ans, timeout = 5):
  288.         if not mi.isbn:
  289.             return False
  290.         br = browser()
  291.         
  292.         try:
  293.             if self.get_cover_url(mi.isbn, br, timeout = timeout) != None:
  294.                 self.debug('cover for', mi.isbn, 'found')
  295.                 ans.set()
  296.         except Exception:
  297.             mi.isbn
  298.             e = mi.isbn
  299.             self.debug(e)
  300.         except:
  301.             mi.isbn
  302.  
  303.  
  304.     
  305.     def get_covers(self, mi, result_queue, abort, timeout = 5):
  306.         if not mi.isbn:
  307.             return None
  308.         br = browser()
  309.         
  310.         try:
  311.             url = self.get_cover_url(mi.isbn, br, timeout = timeout)
  312.             cover_data = br.open_novisit(url).read()
  313.             result_queue.put((True, cover_data, 'jpg', self.name))
  314.         except Exception:
  315.             mi.isbn
  316.             e = mi.isbn
  317.             result_queue.put((False, self.exception_to_string(e), traceback.format_exc(), self.name))
  318.         except:
  319.             mi.isbn
  320.  
  321.  
  322.  
  323.  
  324. def download_cover(mi, timeout = 5):
  325.     results = Queue()
  326.     download_covers(mi, results, max_covers = 1, timeout = timeout)
  327.     errors = []
  328.     ans = None
  329.     while True:
  330.         
  331.         try:
  332.             x = results.get_nowait()
  333.             if x[0]:
  334.                 ans = x[1]
  335.             else:
  336.                 errors.append(x)
  337.         continue
  338.         except Empty:
  339.             break
  340.             continue
  341.         
  342.  
  343.         None<EXCEPTION MATCH>Empty
  344.     return (ans, errors)
  345.  
  346.  
  347. def test(isbns):
  348.     MetaInformation = MetaInformation
  349.     import calibre.ebooks.metadata
  350.     mi = MetaInformation('test', [
  351.         'test'])
  352.     for isbn in isbns:
  353.         prints('Testing ISBN:', isbn)
  354.         mi.isbn = isbn
  355.         found = check_for_cover(mi)
  356.         prints('Has cover:', found)
  357.         (ans, errors) = download_cover(mi)
  358.         if ans is not None:
  359.             prints('Cover downloaded')
  360.         else:
  361.             prints('Download failed:')
  362.             for err in errors:
  363.                 prints('\t', err[-1] + ':', err[1])
  364.             
  365.         print '\n'
  366.     
  367.  
  368. if __name__ == '__main__':
  369.     isbns = sys.argv[1:] + [
  370.         '9781591025412',
  371.         '9780307272119']
  372.     test(isbns)
  373.  
  374.