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

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. from __future__ import with_statement
  5. __license__ = 'GPL v3'
  6. __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
  7. __docformat__ = 'restructuredtext en'
  8. import os
  9. import traceback
  10. import cStringIO
  11. import re
  12. from calibre.constants import DEBUG
  13. from calibre.utils.config import Config, StringConfig, tweaks
  14. from calibre.utils.formatter import TemplateFormatter
  15. from calibre.utils.filenames import shorten_components_to, supports_long_names, ascii_filename, sanitize_file_name
  16. from calibre.ebooks.metadata.opf2 import metadata_to_opf
  17. from calibre.ebooks.metadata.meta import set_metadata
  18. from calibre.constants import preferred_encoding, filesystem_encoding
  19. from calibre.ebooks.metadata import fmt_sidx
  20. from calibre.ebooks.metadata import title_sort
  21. from calibre import strftime, prints
  22. plugboard_any_device_value = 'any device'
  23. plugboard_any_format_value = 'any format'
  24. plugboard_save_to_disk_value = 'save_to_disk'
  25. DEFAULT_TEMPLATE = '{author_sort}/{title}/{title} - {authors}'
  26. DEFAULT_SEND_TEMPLATE = '{author_sort}/{title} - {authors}'
  27. FORMAT_ARG_DESCS = dict(title = _('The title'), authors = _('The authors'), author_sort = _('The author sort string. To use only the first letter of the name use {author_sort[0]}'), tags = _('The tags'), series = _('The series'), series_index = _('The series number. To get leading zeros use {series_index:0>3s} or {series_index:>3s} for leading spaces'), rating = _('The rating'), isbn = _('The ISBN'), publisher = _('The publisher'), timestamp = _('The date'), pubdate = _('The published date'), id = _('The calibre internal id'))
  28. FORMAT_ARGS = { }
  29. for x in FORMAT_ARG_DESCS:
  30.     FORMAT_ARGS[x] = ''
  31.  
  32.  
  33. def config(defaults = None):
  34.     if defaults is None:
  35.         c = Config('save_to_disk', _('Options to control saving to disk'))
  36.     else:
  37.         c = StringConfig(defaults)
  38.     x = c.add_opt
  39.     x('update_metadata', default = True, help = _('Normally, calibre will update the metadata in the saved files from what is in the calibre library. Makes saving to disk slower.'))
  40.     x('write_opf', default = True, help = _('Normally, calibre will write the metadata into a separate OPF file along with the actual e-book files.'))
  41.     x('save_cover', default = True, help = _('Normally, calibre will save the cover in a separate file along with the actual e-book file(s).'))
  42.     x('formats', default = 'all', help = _('Comma separated list of formats to save for each book. By default all available formats are saved.'))
  43.     x('template', default = DEFAULT_TEMPLATE, help = _('The template to control the filename and directory structure of the saved files. Default is "%s" which will save books into a per-author subdirectory with filenames containing title and author. Available controls are: {%s}') % (DEFAULT_TEMPLATE, ', '.join(FORMAT_ARGS)))
  44.     x('send_template', default = DEFAULT_SEND_TEMPLATE, help = _('The template to control the filename and directory structure of files sent to the device. Default is "%s" which will save books into a per-author directory with filenames containing title and author. Available controls are: {%s}') % (DEFAULT_SEND_TEMPLATE, ', '.join(FORMAT_ARGS)))
  45.     x('asciiize', default = True, help = _('Normally, calibre will convert all non English characters into English equivalents for the file names. WARNING: If you turn this off, you may experience errors when saving, depending on how well the filesystem you are saving to supports unicode.'))
  46.     x('timefmt', default = '%b, %Y', help = _('The format in which to display dates. %d - day, %b - month, %Y - year. Default is: %b, %Y'))
  47.     x('send_timefmt', default = '%b, %Y', help = _('The format in which to display dates. %d - day, %b - month, %Y - year. Default is: %b, %Y'))
  48.     x('to_lowercase', default = False, help = _('Convert paths to lowercase.'))
  49.     x('replace_whitespace', default = False, help = _('Replace whitespace with underscores.'))
  50.     return c
  51.  
  52.  
  53. def preprocess_template(template):
  54.     template = template.replace('//', '/')
  55.     template = template.replace('{author}', '{authors}')
  56.     template = template.replace('{tag}', '{tags}')
  57.     if not isinstance(template, unicode):
  58.         template = template.decode(preferred_encoding, 'replace')
  59.     
  60.     return template
  61.  
  62.  
  63. class SafeFormat(TemplateFormatter):
  64.     
  65.     def get_value(self, key, args, kwargs):
  66.         
  67.         try:
  68.             key = key.lower()
  69.             
  70.             try:
  71.                 b = self.book.get_user_metadata(key, False)
  72.             except:
  73.                 if DEBUG:
  74.                     traceback.print_exc()
  75.                 
  76.                 b = None
  77.  
  78.             if b is not None and b['datatype'] == 'composite':
  79.                 if key in self.composite_values:
  80.                     return self.composite_values[key]
  81.                 self.composite_values[key] = 'RECURSIVE_COMPOSITE FIELD (S2D) ' + key
  82.                 self.composite_values[key] = self.vformat(b['display']['composite_template'], [], kwargs)
  83.                 return self.composite_values[key]
  84.             if key in kwargs:
  85.                 val = kwargs[key]
  86.                 return val.replace('/', '_').replace('\\', '_')
  87.             return ''
  88.         except:
  89.             if DEBUG:
  90.                 traceback.print_exc()
  91.             
  92.             return key
  93.  
  94.  
  95.  
  96.  
  97. def get_components(template, mi, id, timefmt = '%b %Y', length = 250, sanitize_func = ascii_filename, replace_whitespace = False, to_lowercase = False):
  98.     library_order = tweaks['save_template_title_series_sorting'] == 'library_order'
  99.     tsfmt = None if library_order else (lambda x: x)
  100.     format_args = FORMAT_ARGS.copy()
  101.     format_args.update(mi.all_non_none_fields())
  102.     if mi.title:
  103.         format_args['title'] = tsfmt(mi.title)
  104.     
  105.     if mi.authors:
  106.         format_args['authors'] = mi.format_authors()
  107.         format_args['author'] = format_args['authors']
  108.     
  109.     if mi.tags:
  110.         format_args['tags'] = mi.format_tags()
  111.         if format_args['tags'].startswith('/'):
  112.             format_args['tags'] = format_args['tags'][1:]
  113.         
  114.     
  115.     if mi.series:
  116.         format_args['series'] = tsfmt(mi.series)
  117.         if mi.series_index is not None:
  118.             format_args['series_index'] = mi.format_series_index()
  119.         
  120.     else:
  121.         template = re.sub('\\{series_index[^}]*?\\}', '', template)
  122.     if mi.rating is not None:
  123.         format_args['rating'] = mi.format_rating()
  124.     
  125.     if hasattr(mi.timestamp, 'timetuple'):
  126.         format_args['timestamp'] = strftime(timefmt, mi.timestamp.timetuple())
  127.     
  128.     if hasattr(mi.pubdate, 'timetuple'):
  129.         format_args['pubdate'] = strftime(timefmt, mi.pubdate.timetuple())
  130.     
  131.     format_args['id'] = str(id)
  132.     custom_metadata = mi.get_all_user_metadata(make_copy = False)
  133.     for key in custom_metadata:
  134.         if key in format_args:
  135.             cm = custom_metadata[key]
  136.             if cm['datatype'] == 'series':
  137.                 format_args[key] = tsfmt(format_args[key])
  138.                 if key + '_index' in format_args:
  139.                     format_args[key + '_index'] = fmt_sidx(format_args[key + '_index'])
  140.                 
  141.             elif cm['datatype'] == 'datetime':
  142.                 format_args[key] = strftime(timefmt, format_args[key].timetuple())
  143.             elif cm['datatype'] == 'bool':
  144.                 format_args[key] = None if format_args[key] else _('no')
  145.             elif cm['datatype'] in ('int', 'float'):
  146.                 if format_args[key] != 0:
  147.                     format_args[key] = unicode(format_args[key])
  148.                 else:
  149.                     format_args[key] = ''
  150.             
  151.         cm['datatype'] == 'series'
  152.     
  153.     components = SafeFormat().safe_format(template, format_args, 'G_C-EXCEPTION!', mi)
  154.     components = _[1]
  155.     components = _[2]
  156.     components = [ _[3] if isinstance(x, unicode) else x for x in components ]
  157.     return shorten_components_to(length, components)
  158.  
  159.  
  160. def save_book_to_disk(id, db, root, opts, length):
  161.     mi = db.get_metadata(id, index_is_id = True)
  162.     available_formats = db.formats(id, index_is_id = True)
  163.     formats = set(available_formats).intersection(set(asked_formats))
  164.     if not formats:
  165.         return (True, id, mi.title)
  166.     components = formats(get_components, opts.template, mi, id, opts.timefmt, length if opts.asciiize else sanitize_file_name, to_lowercase = opts.to_lowercase, replace_whitespace = opts.replace_whitespace)
  167.     base_path = os.path.join(root, *components)
  168.     base_name = os.path.basename(base_path)
  169.     dirpath = os.path.dirname(base_path)
  170.     
  171.     try:
  172.         os.makedirs(dirpath)
  173.     except BaseException:
  174.         [] if opts.formats == 'all' else []
  175.         [] if opts.formats == 'all' else []
  176.         if not os.path.exists(dirpath):
  177.             raise 
  178.         os.path.exists(dirpath)
  179.     except:
  180.         [] if opts.formats == 'all' else []
  181.  
  182.     cdata = db.cover(id, index_is_id = True)
  183.     if opts.save_cover:
  184.         if cdata is not None:
  185.             
  186.             try:
  187.                 f = _[3]
  188.                 f.write(cdata)
  189.             finally:
  190.                 pass
  191.  
  192.             mi.cover = base_name + '.jpg'
  193.         else:
  194.             mi.cover = None
  195.     
  196.     if cdata is not None:
  197.         mi.cover_data = ('jpg', cdata)
  198.     
  199.     mi.cover = None
  200.     written = False
  201.     for fmt in formats:
  202.         dev_name = plugboard_save_to_disk_value
  203.         plugboards = db.prefs.get('plugboards', { })
  204.         cpb = None
  205.         if fmt in plugboards:
  206.             cpb = plugboards[fmt]
  207.             if dev_name in cpb:
  208.                 cpb = cpb[dev_name]
  209.             else:
  210.                 cpb = None
  211.         
  212.         if cpb is None and plugboard_any_format_value in plugboards:
  213.             cpb = plugboards[plugboard_any_format_value]
  214.             if dev_name in cpb:
  215.                 cpb = cpb[dev_name]
  216.             else:
  217.                 cpb = None
  218.         
  219.         if cpb is not None:
  220.             prints('Save-to-disk using plugboard:', fmt, cpb)
  221.         
  222.         data = db.format(id, fmt, index_is_id = True)
  223.         if data is None:
  224.             continue
  225.         else:
  226.             written = True
  227.         if opts.update_metadata:
  228.             stream = cStringIO.StringIO()
  229.             stream.write(data)
  230.             stream.seek(0)
  231.             
  232.             try:
  233.                 if cpb:
  234.                     newmi = mi.deepcopy_metadata()
  235.                     newmi.template_to_attribute(mi, cpb)
  236.                 else:
  237.                     newmi = mi
  238.                 set_metadata(stream, newmi, fmt)
  239.             except:
  240.                 if DEBUG:
  241.                     traceback.print_exc()
  242.                 
  243.  
  244.             stream.seek(0)
  245.             data = stream.read()
  246.         
  247.         fmt_path = base_path + '.' + str(fmt)
  248.         
  249.         try:
  250.             f = _[5]
  251.             f.write(data)
  252.         finally:
  253.             pass
  254.  
  255.     
  256.     return (not written, id, mi.title)
  257.  
  258.  
  259. def save_to_disk(db, ids, root, opts = None, callback = None):
  260.     if opts is None:
  261.         opts = config().parse()
  262.     
  263.     if isinstance(root, unicode):
  264.         root = root.encode(filesystem_encoding)
  265.     
  266.     root = os.path.abspath(root)
  267.     opts.template = preprocess_template(opts.template)
  268.     length = None if supports_long_names(root) else 250
  269.     length -= len(root)
  270.     if length < 5:
  271.         raise ValueError('%r is too long.' % root)
  272.     length < 5
  273.     failures = []
  274.     for x in ids:
  275.         tb = ''
  276.         
  277.         try:
  278.             (failed, id, title) = save_book_to_disk(x, db, root, opts, length)
  279.             tb = _('Requested formats not available')
  280.         except:
  281.             failed = True
  282.             id = x
  283.             title = db.title(x, index_is_id = True)
  284.             tb = traceback.format_exc()
  285.  
  286.         if failed:
  287.             failures.append((id, title, tb))
  288.         
  289.         if callable(callback):
  290.             if not callback(int(id), title, failed, tb):
  291.                 break
  292.             
  293.         callback(int(id), title, failed, tb)
  294.     
  295.     return failures
  296.  
  297.