home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2010 November / maximum-cd-2010-11.iso / DiscContents / calibre-0.7.13.msi / file_957 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-08-06  |  10.2 KB  |  277 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. __license__ = 'GPL 3'
  6. __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
  7. __docformat__ = 'restructuredtext en'
  8. import sys
  9. import textwrap
  10. from urllib import urlencode
  11. from functools import partial
  12. from lxml import etree
  13. from calibre import browser, preferred_encoding
  14. from calibre.ebooks.metadata import MetaInformation
  15. from calibre.utils.config import OptionParser
  16. from calibre.utils.date import parse_date, utcnow
  17. NAMESPACES = {
  18.     'openSearch': 'http://a9.com/-/spec/opensearchrss/1.0/',
  19.     'atom': 'http://www.w3.org/2005/Atom',
  20.     'dc': 'http://purl.org/dc/terms' }
  21. XPath = partial(etree.XPath, namespaces = NAMESPACES)
  22. total_results = XPath('//openSearch:totalResults')
  23. start_index = XPath('//openSearch:startIndex')
  24. items_per_page = XPath('//openSearch:itemsPerPage')
  25. entry = XPath('//atom:entry')
  26. entry_id = XPath('descendant::atom:id')
  27. creator = XPath('descendant::dc:creator')
  28. identifier = XPath('descendant::dc:identifier')
  29. title = XPath('descendant::dc:title')
  30. date = XPath('descendant::dc:date')
  31. publisher = XPath('descendant::dc:publisher')
  32. subject = XPath('descendant::dc:subject')
  33. description = XPath('descendant::dc:description')
  34. language = XPath('descendant::dc:language')
  35.  
  36. def report(verbose):
  37.     if verbose:
  38.         import traceback
  39.         traceback.print_exc()
  40.     
  41.  
  42.  
  43. class Query(object):
  44.     BASE_URL = 'http://books.google.com/books/feeds/volumes?'
  45.     
  46.     def __init__(self, title = None, author = None, publisher = None, isbn = None, max_results = 20, min_viewability = 'none', start_index = 1):
  47.         q = ''
  48.         if isbn is not None:
  49.             q += 'isbn:' + isbn
  50.         else:
  51.             
  52.             def build_term(prefix, parts):
  53.                 return (' '.join,)((lambda .0: for x in .0:
  54. 'in' + prefix + ':' + x)(parts))
  55.  
  56.             if title is not None:
  57.                 q += build_term('title', title.split())
  58.             
  59.             if author is not None:
  60.                 None += q if q else '' + build_term('author', author.split())
  61.             
  62.             if publisher is not None:
  63.                 None += q if q else '' + build_term('publisher', publisher.split())
  64.             
  65.         if isinstance(q, unicode):
  66.             q = q.encode('utf-8')
  67.         
  68.         self.url = self.BASE_URL + urlencode({
  69.             'q': q,
  70.             'max-results': max_results,
  71.             'start-index': start_index,
  72.             'min-viewability': min_viewability })
  73.  
  74.     
  75.     def __call__(self, browser, verbose):
  76.         if verbose:
  77.             print 'Query:', self.url
  78.         
  79.         feed = etree.fromstring(browser.open(self.url).read())
  80.         total = int(total_results(feed)[0].text)
  81.         start = int(start_index(feed)[0].text)
  82.         entries = entry(feed)
  83.         new_start = start + len(entries)
  84.         if new_start > total:
  85.             new_start = 0
  86.         
  87.         return (entries, new_start)
  88.  
  89.  
  90.  
  91. class ResultList(list):
  92.     
  93.     def get_description(self, entry, verbose):
  94.         
  95.         try:
  96.             desc = description(entry)
  97.             if desc:
  98.                 return 'SUMMARY:\n' + desc[0].text
  99.         except:
  100.             report(verbose)
  101.  
  102.  
  103.     
  104.     def get_language(self, entry, verbose):
  105.         
  106.         try:
  107.             l = language(entry)
  108.             if l:
  109.                 return l[0].text
  110.         except:
  111.             report(verbose)
  112.  
  113.  
  114.     
  115.     def get_title(self, entry):
  116.         candidates = [ x.text for x in title(entry) ]
  117.         return ': '.join(candidates)
  118.  
  119.     
  120.     def get_authors(self, entry):
  121.         m = creator(entry)
  122.         if not m:
  123.             m = []
  124.         
  125.         m = [ x.text for x in m ]
  126.         return m
  127.  
  128.     
  129.     def get_author_sort(self, entry, verbose):
  130.         for x in creator(entry):
  131.             for key, val in x.attrib.items():
  132.                 if key.endswith('file-as'):
  133.                     return val
  134.             
  135.         
  136.  
  137.     
  138.     def get_identifiers(self, entry, mi):
  139.         isbns = []
  140.         for x in identifier(entry):
  141.             t = str(x.text).strip()
  142.             if t[:5].upper() in ('ISBN:', 'LCCN:', 'OCLC:'):
  143.                 if t[:5].upper() == 'ISBN:':
  144.                     isbns.append(t[5:])
  145.                 
  146.             t[:5].upper() == 'ISBN:'
  147.         
  148.         if isbns:
  149.             mi.isbn = sorted(isbns, cmp = (lambda x, y: cmp(len(x), len(y))))[-1]
  150.         
  151.  
  152.     
  153.     def get_tags(self, entry, verbose):
  154.         
  155.         try:
  156.             btags = [ x.text for x in subject(entry) ]
  157.             tags = []
  158.             for t in btags:
  159.                 []([ y.strip() for y in t.split('/') ])
  160.             
  161.             tags = list(sorted(list(set(tags))))
  162.         except:
  163.             report(verbose)
  164.             tags = []
  165.  
  166.         return [ x.replace(',', ';') for x in tags ]
  167.  
  168.     
  169.     def get_publisher(self, entry, verbose):
  170.         
  171.         try:
  172.             pub = publisher(entry)[0].text
  173.         except:
  174.             pub = None
  175.  
  176.         return pub
  177.  
  178.     
  179.     def get_date(self, entry, verbose):
  180.         
  181.         try:
  182.             d = date(entry)
  183.             if d:
  184.                 default = utcnow().replace(day = 15)
  185.                 d = parse_date(d[0].text, assume_utc = True, default = default)
  186.             else:
  187.                 d = None
  188.         except:
  189.             report(verbose)
  190.             d = None
  191.  
  192.         return d
  193.  
  194.     
  195.     def populate(self, entries, browser, verbose = False):
  196.         for x in entries:
  197.             
  198.             try:
  199.                 id_url = entry_id(x)[0].text
  200.                 title = self.get_title(x)
  201.             except:
  202.                 report(verbose)
  203.  
  204.             mi = MetaInformation(title, self.get_authors(x))
  205.             
  206.             try:
  207.                 raw = browser.open(id_url).read()
  208.                 feed = etree.fromstring(raw)
  209.                 x = entry(feed)[0]
  210.             except Exception:
  211.                 e = None
  212.                 if verbose:
  213.                     print 'Failed to get all details for an entry'
  214.                     print e
  215.                 
  216.             except:
  217.                 verbose
  218.  
  219.             mi.author_sort = self.get_author_sort(x, verbose)
  220.             mi.comments = self.get_description(x, verbose)
  221.             self.get_identifiers(x, mi)
  222.             mi.tags = self.get_tags(x, verbose)
  223.             mi.publisher = self.get_publisher(x, verbose)
  224.             mi.pubdate = self.get_date(x, verbose)
  225.             mi.language = self.get_language(x, verbose)
  226.             self.append(mi)
  227.         
  228.  
  229.  
  230.  
  231. def search(title = None, author = None, publisher = None, isbn = None, min_viewability = 'none', verbose = False, max_results = 40):
  232.     br = browser()
  233.     start = 1
  234.     entries = []
  235.     while start > 0 and len(entries) <= max_results:
  236.         (new, start) = Query(title = title, author = author, publisher = publisher, isbn = isbn, min_viewability = min_viewability)(br, verbose)
  237.         if not new:
  238.             break
  239.         
  240.         entries.extend(new)
  241.     entries = entries[:max_results]
  242.     ans = ResultList()
  243.     ans.populate(entries, br, verbose)
  244.     return ans
  245.  
  246.  
  247. def option_parser():
  248.     parser = OptionParser(textwrap.dedent('        %prog [options]\n\n        Fetch book metadata from Google. You must specify one of title, author,\n        publisher or ISBN. If you specify ISBN the others are ignored. Will\n        fetch a maximum of 100 matches, so you should make your query as\n        specific as possible.\n        '))
  249.     parser.add_option('-t', '--title', help = 'Book title')
  250.     parser.add_option('-a', '--author', help = 'Book author(s)')
  251.     parser.add_option('-p', '--publisher', help = 'Book publisher')
  252.     parser.add_option('-i', '--isbn', help = 'Book ISBN')
  253.     parser.add_option('-m', '--max-results', default = 10, help = 'Maximum number of results to fetch')
  254.     parser.add_option('-v', '--verbose', default = 0, action = 'count', help = 'Be more verbose about errors')
  255.     return parser
  256.  
  257.  
  258. def main(args = sys.argv):
  259.     parser = option_parser()
  260.     (opts, args) = parser.parse_args(args)
  261.     
  262.     try:
  263.         results = search(opts.title, opts.author, opts.publisher, opts.isbn, verbose = opts.verbose, max_results = opts.max_results)
  264.     except AssertionError:
  265.         report(True)
  266.         parser.print_help()
  267.         return 1
  268.  
  269.     for result in results:
  270.         print unicode(result).encode(preferred_encoding)
  271.         print 
  272.     
  273.  
  274. if __name__ == '__main__':
  275.     sys.exit(main())
  276.  
  277.