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

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2009, John Schember <john at nachtimwald.com>'
  6. __docformat__ = 'restructuredtext en'
  7. import os
  8. import re
  9. import time
  10. import json
  11. from itertools import cycle
  12. from calibre import prints, isbytestring
  13. from calibre.constants import filesystem_encoding, DEBUG
  14. from calibre.devices.usbms.cli import CLI
  15. from calibre.devices.usbms.device import Device
  16. from calibre.devices.usbms.books import BookList, Book
  17. BASE_TIME = None
  18.  
  19. def debug_print(*args):
  20.     global BASE_TIME
  21.     if BASE_TIME is None:
  22.         BASE_TIME = time.time()
  23.     
  24.     if DEBUG:
  25.         prints('DEBUG: %6.1f' % (time.time() - BASE_TIME), *args)
  26.     
  27.  
  28.  
  29. class USBMS(CLI, Device):
  30.     description = _('Communicate with an eBook reader.')
  31.     author = _('John Schember')
  32.     supported_platforms = [
  33.         'windows',
  34.         'osx',
  35.         'linux']
  36.     booklist_class = BookList
  37.     book_class = Book
  38.     FORMATS = []
  39.     CAN_SET_METADATA = False
  40.     METADATA_CACHE = 'metadata.calibre'
  41.     
  42.     def get_device_information(self, end_session = True):
  43.         self.report_progress(1, _('Get device information...'))
  44.         return (self.get_gui_name(), '', '', '')
  45.  
  46.     
  47.     def books(self, oncard = None, end_session = True):
  48.         path_to_ext = path_to_ext
  49.         import calibre.ebooks.metadata.meta
  50.         debug_print('USBMS: Fetching list of books from device. oncard=', oncard)
  51.         dummy_bl = self.booklist_class(None, None, None)
  52.         if oncard == 'carda' and not (self._card_a_prefix):
  53.             self.report_progress(1, _('Getting list of books on device...'))
  54.             return dummy_bl
  55.         if oncard == 'cardb' and not (self._card_b_prefix):
  56.             self.report_progress(1, _('Getting list of books on device...'))
  57.             return dummy_bl
  58.         if oncard and oncard != 'carda' and oncard != 'cardb':
  59.             self.report_progress(1, _('Getting list of books on device...'))
  60.             return dummy_bl
  61.         if oncard == 'carda':
  62.             pass
  63.         elif oncard == 'cardb':
  64.             pass
  65.         
  66.         prefix = self._main_prefix
  67.         if oncard == 'carda':
  68.             pass
  69.         elif oncard == 'cardb':
  70.             pass
  71.         
  72.         ebook_dirs = self.get_main_ebook_dir()
  73.         debug_print('USBMS: dirs are:', prefix, ebook_dirs)
  74.         bl = self.booklist_class(oncard, prefix, self.settings)
  75.         need_sync = self.parse_metadata_cache(bl, prefix, self.METADATA_CACHE)
  76.         bl_cache = { }
  77.         for idx, b in enumerate(bl):
  78.             bl_cache[b.lpath] = idx
  79.         
  80.         
  81.         def update_booklist(filename, path, prefix):
  82.             changed = False
  83.             if path_to_ext(filename) in self.FORMATS:
  84.                 
  85.                 try:
  86.                     lpath = os.path.join(path, filename).partition(self.normalize_path(prefix))[2]
  87.                     if lpath.startswith(os.sep):
  88.                         lpath = lpath[len(os.sep):]
  89.                     
  90.                     lpath = lpath.replace('\\', '/')
  91.                     idx = bl_cache.get(lpath, None)
  92.                     if idx is not None:
  93.                         bl_cache[lpath] = None
  94.                         if self.update_metadata_item(bl[idx]):
  95.                             changed = True
  96.                         
  97.                     elif bl.add_book(self.book_from_path(prefix, lpath), replace_metadata = False):
  98.                         changed = True
  99.                 import traceback
  100.                 traceback.print_exc()
  101.  
  102.             
  103.             return changed
  104.  
  105.         if isinstance(ebook_dirs, basestring):
  106.             ebook_dirs = [
  107.                 ebook_dirs]
  108.         
  109.         for ebook_dir in ebook_dirs:
  110.             ebook_dir = self.path_to_unicode(ebook_dir)
  111.             ebook_dir = None(self.normalize_path if ebook_dir else prefix)
  112.             if not os.path.exists(ebook_dir):
  113.                 continue
  114.             
  115.             if self.SUPPORTS_SUB_DIRS:
  116.                 flist = []
  117.                 for path, dirs, files in os.walk(ebook_dir):
  118.                     for filename in files:
  119.                         if filename != self.METADATA_CACHE:
  120.                             flist.append({
  121.                                 'filename': self.path_to_unicode(filename),
  122.                                 'path': self.path_to_unicode(path) })
  123.                             continue
  124.                     
  125.                 
  126.                 for i, f in enumerate(flist):
  127.                     self.report_progress(i / float(len(flist)), _('Getting list of books on device...'))
  128.                     changed = update_booklist(f['filename'], f['path'], prefix)
  129.                     if changed:
  130.                         need_sync = True
  131.                         continue
  132.                 
  133.             paths = os.listdir(ebook_dir)
  134.             for i, filename in enumerate(paths):
  135.                 self.report_progress((i + 1) / float(len(paths)), _('Getting list of books on device...'))
  136.                 changed = update_booklist(self.path_to_unicode(filename), ebook_dir, prefix)
  137.                 if changed:
  138.                     need_sync = True
  139.                     continue
  140.             
  141.         
  142.         for idx in sorted(bl_cache.itervalues(), reverse = True):
  143.             if idx is not None:
  144.                 need_sync = True
  145.                 del bl[idx]
  146.                 continue
  147.         
  148.         debug_print('USBMS: count found in cache: %d, count of files in metadata: %d, need_sync: %s' % (len(bl_cache), len(bl), need_sync))
  149.         if need_sync:
  150.             if oncard == 'cardb':
  151.                 self.sync_booklists((None, None, bl))
  152.             elif oncard == 'carda':
  153.                 self.sync_booklists((None, bl, None))
  154.             else:
  155.                 self.sync_booklists((bl, None, None))
  156.         
  157.         self.report_progress(1, _('Getting list of books on device...'))
  158.         debug_print('USBMS: Finished fetching list of books from device. oncard=', oncard)
  159.         return bl
  160.  
  161.     
  162.     def upload_books(self, files, names, on_card = None, end_session = True, metadata = None):
  163.         debug_print('USBMS: uploading %d books' % len(files))
  164.         path = self._sanity_check(on_card, files)
  165.         paths = []
  166.         names = iter(names)
  167.         metadata = iter(metadata)
  168.         for i, infile in enumerate(files):
  169.             mdata = metadata.next()
  170.             fname = names.next()
  171.             filepath = self.normalize_path(self.create_upload_path(path, mdata, fname))
  172.             paths.append(filepath)
  173.             if not hasattr(infile, 'read'):
  174.                 infile = self.normalize_path(infile)
  175.             
  176.             self.put_file(infile, filepath, replace_file = True)
  177.             
  178.             try:
  179.                 self.upload_cover(os.path.dirname(filepath), os.path.splitext(os.path.basename(filepath))[0], mdata)
  180.             except:
  181.                 import traceback
  182.                 traceback.print_exc()
  183.  
  184.             self.report_progress((i + 1) / float(len(files)), _('Transferring books to device...'))
  185.         
  186.         self.report_progress(1, _('Transferring books to device...'))
  187.         debug_print('USBMS: finished uploading %d books' % len(files))
  188.         return zip(paths, cycle([
  189.             on_card]))
  190.  
  191.     
  192.     def upload_cover(self, path, filename, metadata):
  193.         pass
  194.  
  195.     
  196.     def add_books_to_metadata(self, locations, metadata, booklists):
  197.         debug_print('USBMS: adding metadata for %d books' % len(metadata))
  198.         metadata = iter(metadata)
  199.         for i, location in enumerate(locations):
  200.             self.report_progress((i + 1) / float(len(locations)), _('Adding books to device metadata listing...'))
  201.             info = metadata.next()
  202.             if location[1] == 'cardb':
  203.                 pass
  204.             elif location[1] == 'carda':
  205.                 pass
  206.             
  207.             blist = 0
  208.             path = self.normalize_path(location[0])
  209.             if self._main_prefix:
  210.                 prefix = None if path.startswith(self.normalize_path(self._main_prefix)) else None
  211.             
  212.             if not prefix and self._card_a_prefix:
  213.                 prefix = None if path.startswith(self.normalize_path(self._card_a_prefix)) else None
  214.             
  215.             if not prefix and self._card_b_prefix:
  216.                 prefix = None if path.startswith(self.normalize_path(self._card_b_prefix)) else None
  217.             
  218.             if prefix is None:
  219.                 prints('in add_books_to_metadata. Prefix is None!', path, self._main_prefix)
  220.                 continue
  221.             
  222.             lpath = path.partition(prefix)[2]
  223.             if lpath.startswith('/') or lpath.startswith('\\'):
  224.                 lpath = lpath[1:]
  225.             
  226.             book = self.book_class(prefix, lpath, other = info)
  227.             if book.size is None:
  228.                 book.size = os.stat(self.normalize_path(path)).st_size
  229.             
  230.             book._new_book = True
  231.             booklists[blist].add_book(book, replace_metadata = True)
  232.         
  233.         self.report_progress(1, _('Adding books to device metadata listing...'))
  234.         debug_print('USBMS: finished adding metadata')
  235.  
  236.     
  237.     def delete_books(self, paths, end_session = True):
  238.         debug_print('USBMS: deleting %d books' % len(paths))
  239.         for i, path in enumerate(paths):
  240.             self.report_progress((i + 1) / float(len(paths)), _('Removing books from device...'))
  241.             path = self.normalize_path(path)
  242.             if os.path.exists(path):
  243.                 os.unlink(path)
  244.                 filepath = os.path.splitext(path)[0]
  245.                 for ext in self.DELETE_EXTS:
  246.                     if os.path.exists(filepath + ext):
  247.                         os.unlink(filepath + ext)
  248.                     
  249.                     if os.path.exists(path + ext):
  250.                         os.unlink(path + ext)
  251.                         continue
  252.                 
  253.                 if self.SUPPORTS_SUB_DIRS:
  254.                     
  255.                     try:
  256.                         os.removedirs(os.path.dirname(path))
  257.  
  258.                 
  259.             self.SUPPORTS_SUB_DIRS
  260.         
  261.         self.report_progress(1, _('Removing books from device...'))
  262.         debug_print('USBMS: finished deleting %d books' % len(paths))
  263.  
  264.     
  265.     def remove_books_from_metadata(self, paths, booklists):
  266.         debug_print('USBMS: removing metadata for %d books' % len(paths))
  267.         for i, path in enumerate(paths):
  268.             self.report_progress((i + 1) / float(len(paths)), _('Removing books from device metadata listing...'))
  269.             for bl in booklists:
  270.                 for book in bl:
  271.                     if path.endswith(book.path):
  272.                         bl.remove_book(book)
  273.                         continue
  274.                 
  275.             
  276.         
  277.         self.report_progress(1, _('Removing books from device metadata listing...'))
  278.         debug_print('USBMS: finished removing metadata for %d books' % len(paths))
  279.  
  280.     
  281.     def sync_booklists(self, booklists, end_session = True):
  282.         debug_print('USBMS: starting sync_booklists')
  283.         if not os.path.exists(self.normalize_path(self._main_prefix)):
  284.             os.makedirs(self.normalize_path(self._main_prefix))
  285.         
  286.         
  287.         def write_prefix(prefix, listid):
  288.             pass
  289.  
  290.         write_prefix(self._main_prefix, 0)
  291.         write_prefix(self._card_a_prefix, 1)
  292.         write_prefix(self._card_b_prefix, 2)
  293.         for blist in booklists:
  294.             if blist is not None:
  295.                 for book in blist:
  296.                     book._new_book = False
  297.                 
  298.             (None, None)
  299.         
  300.         self.report_progress(1, _('Sending metadata to device...'))
  301.         debug_print('USBMS: finished sync_booklists')
  302.  
  303.     
  304.     def build_template_regexp(cls):
  305.         
  306.         def replfunc(match):
  307.             if match.group(1) in ('title', 'series', 'series_index', 'isbn'):
  308.                 return '(?P<' + match.group(1) + '>.+?)'
  309.             if match.group(1) in ('authors', 'author_sort'):
  310.                 return '(?P<author>.+?)'
  311.             return '(.+?)'
  312.  
  313.         template = cls.save_template().rpartition('/')[2]
  314.         return re.compile(re.sub('{([^}]*)}', replfunc, template) + '([_\\d]*$)')
  315.  
  316.     build_template_regexp = classmethod(build_template_regexp)
  317.     
  318.     def path_to_unicode(cls, path):
  319.         if isbytestring(path):
  320.             path = path.decode(filesystem_encoding)
  321.         
  322.         return path
  323.  
  324.     path_to_unicode = classmethod(path_to_unicode)
  325.     
  326.     def normalize_path(cls, path):
  327.         if path is None:
  328.             return None
  329.         if os.sep == '\\':
  330.             path = path.replace('/', '\\')
  331.         else:
  332.             path = path.replace('\\', '/')
  333.         return cls.path_to_unicode(path)
  334.  
  335.     normalize_path = classmethod(normalize_path)
  336.     
  337.     def parse_metadata_cache(cls, bl, prefix, name):
  338.         js = []
  339.         need_sync = False
  340.         cache_file = cls.normalize_path(os.path.join(prefix, name))
  341.         if os.access(cache_file, os.R_OK):
  342.             
  343.             try:
  344.                 
  345.                 try:
  346.                     f = _[1]
  347.                     js = json.load(f, encoding = 'utf-8')
  348.                 finally:
  349.                     pass
  350.  
  351.                 for item in js:
  352.                     book = cls.book_class(prefix, item.get('lpath', None))
  353.                     for key in item.keys():
  354.                         setattr(book, key, item[key])
  355.                     
  356.                     bl.append(book)
  357.             import traceback
  358.             traceback.print_exc()
  359.             bl = []
  360.             need_sync = True
  361.  
  362.         else:
  363.             need_sync = True
  364.         return need_sync
  365.  
  366.     parse_metadata_cache = classmethod(parse_metadata_cache)
  367.     
  368.     def update_metadata_item(cls, book):
  369.         changed = False
  370.         size = os.stat(cls.normalize_path(book.path)).st_size
  371.         if size != book.size:
  372.             changed = True
  373.             mi = cls.metadata_from_path(book.path)
  374.             book.smart_update(mi)
  375.             book.size = size
  376.         
  377.         return changed
  378.  
  379.     update_metadata_item = classmethod(update_metadata_item)
  380.     
  381.     def metadata_from_path(cls, path):
  382.         return cls.metadata_from_formats([
  383.             path])
  384.  
  385.     metadata_from_path = classmethod(metadata_from_path)
  386.     
  387.     def metadata_from_formats(cls, fmts):
  388.         metadata_from_formats = metadata_from_formats
  389.         import calibre.ebooks.metadata.meta
  390.         quick_metadata = quick_metadata
  391.         import calibre.customize.ui
  392.         quick_metadata.__enter__()
  393.         
  394.         try:
  395.             return metadata_from_formats(fmts, force_read_metadata = True, pattern = cls.build_template_regexp())
  396.         finally:
  397.             pass
  398.  
  399.  
  400.     metadata_from_formats = classmethod(metadata_from_formats)
  401.     
  402.     def book_from_path(cls, prefix, lpath):
  403.         MetaInformation = MetaInformation
  404.         import calibre.ebooks.metadata
  405.         if cls.settings().read_metadata or cls.MUST_READ_METADATA:
  406.             mi = cls.metadata_from_path(cls.normalize_path(os.path.join(prefix, lpath)))
  407.         else:
  408.             metadata_from_filename = metadata_from_filename
  409.             import calibre.ebooks.metadata.meta
  410.             mi = metadata_from_filename(cls.normalize_path(os.path.basename(lpath)), cls.build_template_regexp())
  411.         if mi is None:
  412.             mi = MetaInformation(os.path.splitext(os.path.basename(lpath))[0], [
  413.                 _('Unknown')])
  414.         
  415.         size = os.stat(cls.normalize_path(os.path.join(prefix, lpath))).st_size
  416.         book = cls.book_class(prefix, lpath, other = mi, size = size)
  417.         return book
  418.  
  419.     book_from_path = classmethod(book_from_path)
  420.  
  421.