home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / calibre-0.7.26.msi / file_1453 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-10-31  |  33.3 KB  |  908 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__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
  7. __docformat__ = 'restructuredtext en'
  8. import os
  9. import re
  10. import cPickle
  11. import textwrap
  12. import traceback
  13. import plistlib
  14. import json
  15. import base64
  16. import datetime
  17. from copy import deepcopy
  18. from functools import partial
  19. from optparse import OptionParser as _OptionParser
  20. from optparse import IndentedHelpFormatter
  21. from collections import defaultdict
  22. from calibre.constants import terminal_controller, config_dir, CONFIG_DIR_MODE, __appname__, __version__, __author__
  23. from calibre.utils.lock import LockError, ExclusiveFile
  24. plugin_dir = os.path.join(config_dir, 'plugins')
  25.  
  26. def make_config_dir():
  27.     if not os.path.exists(plugin_dir):
  28.         os.makedirs(plugin_dir, mode = CONFIG_DIR_MODE)
  29.     
  30.  
  31.  
  32. def check_config_write_access():
  33.     if os.access(config_dir, os.W_OK):
  34.         pass
  35.     return os.access(config_dir, os.X_OK)
  36.  
  37.  
  38. class CustomHelpFormatter(IndentedHelpFormatter):
  39.     
  40.     def format_usage(self, usage):
  41.         return _('%sUsage%s: %s\n') % (terminal_controller.BLUE, terminal_controller.NORMAL, usage)
  42.  
  43.     
  44.     def format_heading(self, heading):
  45.         return '%*s%s%s%s:\n' % (self.current_indent, terminal_controller.BLUE, '', heading, terminal_controller.NORMAL)
  46.  
  47.     
  48.     def format_option(self, option):
  49.         result = []
  50.         opts = self.option_strings[option]
  51.         opt_width = self.help_position - self.current_indent - 2
  52.         if len(opts) > opt_width:
  53.             opts = '%*s%s\n' % (self.current_indent, '', terminal_controller.GREEN + opts + terminal_controller.NORMAL)
  54.             indent_first = self.help_position
  55.         else:
  56.             opts = '%*s%-*s  ' % (self.current_indent, '', opt_width + len(terminal_controller.GREEN + terminal_controller.NORMAL), terminal_controller.GREEN + opts + terminal_controller.NORMAL)
  57.             indent_first = 0
  58.         result.append(opts)
  59.         if option.help:
  60.             help_text = self.expand_default(option).split('\n')
  61.             help_lines = []
  62.             for line in help_text:
  63.                 help_lines.extend(textwrap.wrap(line, self.help_width))
  64.             
  65.             result.append('%*s%s\n' % (indent_first, '', help_lines[0]))
  66.             []([ '%*s%s\n' % (self.help_position, '', line) for line in help_lines[1:] ])
  67.         elif opts[-1] != '\n':
  68.             result.append('\n')
  69.         
  70.         return ''.join(result) + '\n'
  71.  
  72.  
  73.  
  74. class OptionParser(_OptionParser):
  75.     
  76.     def __init__(self, usage = '%prog [options] filename', version = '%%prog (%s %s)' % (__appname__, __version__), epilog = None, gui_mode = False, conflict_handler = 'resolve', **kwds):
  77.         usage = textwrap.dedent(usage)
  78.         if epilog is None:
  79.             epilog = _('Created by ') + terminal_controller.RED + __author__ + terminal_controller.NORMAL
  80.         
  81.         usage += '\n\n' + _('Whenever you pass arguments to %prog that have spaces in them, enclose the arguments in quotation marks.')
  82.         _OptionParser.__init__(self, usage = usage, version = version, epilog = epilog, formatter = CustomHelpFormatter(), conflict_handler = conflict_handler, **kwds)
  83.         self.gui_mode = gui_mode
  84.  
  85.     
  86.     def error(self, msg):
  87.         if self.gui_mode:
  88.             raise Exception(msg)
  89.         self.gui_mode
  90.         _OptionParser.error(self, msg)
  91.  
  92.     
  93.     def merge(self, parser):
  94.         opts = list(parser.option_list)
  95.         groups = list(parser.option_groups)
  96.         
  97.         def merge_options(options, container):
  98.             for opt in deepcopy(options):
  99.                 if not self.has_option(opt.get_opt_string()):
  100.                     container.add_option(opt)
  101.                     continue
  102.             
  103.  
  104.         merge_options(opts, self)
  105.         for group in groups:
  106.             g = self.add_option_group(group.title)
  107.             merge_options(group.option_list, g)
  108.         
  109.  
  110.     
  111.     def subsume(self, group_name, msg = ''):
  112.         opts = _[1]
  113.         self.option_groups = []
  114.         subgroup = self.add_option_group(group_name, msg)
  115.         for opt in opts:
  116.             self.remove_option(opt.get_opt_string())
  117.             subgroup.add_option(opt)
  118.         
  119.  
  120.     
  121.     def options_iter(self):
  122.         for opt in self.option_list:
  123.             if str(opt).strip():
  124.                 yield opt
  125.                 continue
  126.         
  127.         for gr in self.option_groups:
  128.             for opt in gr.option_list:
  129.                 if str(opt).strip():
  130.                     yield opt
  131.                     continue
  132.             
  133.         
  134.  
  135.     
  136.     def option_by_dest(self, dest):
  137.         for opt in self.options_iter():
  138.             if opt.dest == dest:
  139.                 return opt
  140.         
  141.  
  142.     
  143.     def merge_options(self, lower, upper):
  144.         for dest in lower.__dict__.keys():
  145.             if not upper.__dict__.has_key(dest):
  146.                 continue
  147.             
  148.             opt = self.option_by_dest(dest)
  149.             if lower.__dict__[dest] != opt.default and upper.__dict__[dest] == opt.default:
  150.                 upper.__dict__[dest] = lower.__dict__[dest]
  151.                 continue
  152.         
  153.  
  154.  
  155.  
  156. class Option(object):
  157.     
  158.     def __init__(self, name, switches = [], help = '', type = None, choices = None, check = None, group = None, default = None, action = None, metavar = None):
  159.         if choices:
  160.             type = 'choice'
  161.         
  162.         self.name = name
  163.         self.switches = switches
  164.         self.help = None if help else None
  165.         self.type = type
  166.         if self.type is None and action is None and choices is None:
  167.             if isinstance(default, float):
  168.                 self.type = 'float'
  169.             elif isinstance(default, int) and not isinstance(default, bool):
  170.                 self.type = 'int'
  171.             
  172.         
  173.         self.choices = choices
  174.         self.check = check
  175.         self.group = group
  176.         self.default = default
  177.         self.action = action
  178.         self.metavar = metavar
  179.  
  180.     
  181.     def __eq__(self, other):
  182.         return self.name == getattr(other, 'name', other)
  183.  
  184.     
  185.     def __repr__(self):
  186.         return 'Option: ' + self.name
  187.  
  188.     
  189.     def __str__(self):
  190.         return repr(self)
  191.  
  192.  
  193.  
  194. class OptionValues(object):
  195.     
  196.     def copy(self):
  197.         return deepcopy(self)
  198.  
  199.  
  200.  
  201. class OptionSet(object):
  202.     OVERRIDE_PAT = re.compile('#{3,100} Override Options #{15}(.*?)#{3,100} End Override #{3,100}', re.DOTALL | re.IGNORECASE)
  203.     
  204.     def __init__(self, description = ''):
  205.         self.description = description
  206.         self.defaults = { }
  207.         self.preferences = []
  208.         self.group_list = []
  209.         self.groups = { }
  210.         self.set_buffer = { }
  211.  
  212.     
  213.     def has_option(self, name_or_option_object):
  214.         if name_or_option_object in self.preferences:
  215.             return True
  216.         for p in self.preferences:
  217.             if p.name == name_or_option_object:
  218.                 return True
  219.         
  220.         return False
  221.  
  222.     
  223.     def get_option(self, name_or_option_object):
  224.         idx = self.preferences.index(name_or_option_object)
  225.         if idx > -1:
  226.             return self.preferences[idx]
  227.         for p in self.preferences:
  228.             if p.name == name_or_option_object:
  229.                 return p
  230.         
  231.  
  232.     
  233.     def add_group(self, name, description = ''):
  234.         if name in self.group_list:
  235.             raise ValueError('A group by the name %s already exists in this set' % name)
  236.         name in self.group_list
  237.         self.groups[name] = description
  238.         self.group_list.append(name)
  239.         return partial(self.add_opt, group = name)
  240.  
  241.     
  242.     def update(self, other):
  243.         for name in other.groups.keys():
  244.             self.groups[name] = other.groups[name]
  245.             if name not in self.group_list:
  246.                 self.group_list.append(name)
  247.                 continue
  248.         
  249.         for pref in other.preferences:
  250.             if pref in self.preferences:
  251.                 self.preferences.remove(pref)
  252.             
  253.             self.preferences.append(pref)
  254.         
  255.  
  256.     
  257.     def smart_update(self, opts1, opts2):
  258.         for pref in self.preferences:
  259.             new = getattr(opts2, pref.name, pref.default)
  260.             if new != pref.default:
  261.                 setattr(opts1, pref.name, new)
  262.                 continue
  263.         
  264.  
  265.     
  266.     def remove_opt(self, name):
  267.         if name in self.preferences:
  268.             self.preferences.remove(name)
  269.         
  270.  
  271.     
  272.     def add_opt(self, name, switches = [], help = None, type = None, choices = None, group = None, default = None, action = None, metavar = None):
  273.         pref = Option(name, switches = switches, help = help, type = type, choices = choices, group = group, default = default, action = action, metavar = None)
  274.         if group is not None and group not in self.groups.keys():
  275.             raise ValueError('Group %s has not been added to this section' % group)
  276.         group not in self.groups.keys()
  277.         if pref in self.preferences:
  278.             raise ValueError('An option with the name %s already exists in this set.' % name)
  279.         pref in self.preferences
  280.         self.preferences.append(pref)
  281.         self.defaults[name] = default
  282.  
  283.     
  284.     def option_parser(self, user_defaults = None, usage = '', gui_mode = False):
  285.         parser = OptionParser(usage, gui_mode = gui_mode)
  286.         groups = (defaultdict,)((lambda : parser))
  287.         for group, desc in self.groups.items():
  288.             groups[group] = parser.add_option_group(group.upper(), desc)
  289.         
  290.         for pref in self.preferences:
  291.             if not pref.switches:
  292.                 continue
  293.             
  294.             g = groups[pref.group]
  295.             action = pref.action
  296.             if action is None:
  297.                 action = 'store'
  298.                 if pref.default is True or pref.default is False:
  299.                     action = None + 'store_' if pref.default else 'true'
  300.                 
  301.             
  302.             args = dict(dest = pref.name, help = pref.help, metavar = pref.metavar, type = pref.type, choices = pref.choices, default = getattr(user_defaults, pref.name, pref.default), action = action)
  303.             g.add_option(*pref.switches, **args)
  304.         
  305.         return parser
  306.  
  307.     
  308.     def get_override_section(self, src):
  309.         match = self.OVERRIDE_PAT.search(src)
  310.         if match:
  311.             return match.group()
  312.         return ''
  313.  
  314.     
  315.     def parse_string(self, src):
  316.         options = {
  317.             'cPickle': cPickle }
  318.         if src is not None:
  319.             
  320.             try:
  321.                 if not isinstance(src, unicode):
  322.                     src = src.decode('utf-8')
  323.                 
  324.                 exec src in options
  325.             print 'Failed to parse options string:'
  326.             print repr(src)
  327.             traceback.print_exc()
  328.  
  329.         
  330.         opts = OptionValues()
  331.         for pref in self.preferences:
  332.             val = options.get(pref.name, pref.default)
  333.             formatter = __builtins__.get(pref.type, None)
  334.             if callable(formatter):
  335.                 val = formatter(val)
  336.             
  337.             setattr(opts, pref.name, val)
  338.         
  339.         return opts
  340.  
  341.     
  342.     def render_group(self, name, desc, opts):
  343.         prefs = _[1]
  344.         lines = [
  345.             [] % '### Begin group: %s' if name else 'DEFAULT']
  346.         if desc:
  347.             lines += map((lambda x: '# ' + x), desc.split('\n'))
  348.         
  349.         lines.append(' ')
  350.         for pref in prefs:
  351.             lines.append('# ' + pref.name.replace('_', ' '))
  352.             if pref.help:
  353.                 lines += map((lambda x: '# ' + x), pref.help.split('\n'))
  354.             
  355.             lines.append('%s = %s' % (pref.name, self.serialize_opt(getattr(opts, pref.name, pref.default))))
  356.             lines.append(' ')
  357.         
  358.         return '\n'.join(lines)
  359.  
  360.     
  361.     def serialize_opt(self, val):
  362.         if val is val:
  363.             pass
  364.         elif val is True and val is False and val is None or isinstance(val, (int, float, long, basestring)):
  365.             return repr(val)
  366.         QString = QString
  367.         import PyQt4.QtCore
  368.         if isinstance(val, QString):
  369.             return repr(unicode(val))
  370.         pickle = cPickle.dumps(val, -1)
  371.         return 'cPickle.loads(%s)' % repr(pickle)
  372.  
  373.     
  374.     def serialize(self, opts):
  375.         src = '# %s\n\n' % self.description.replace('\n', '\n# ')
  376.         groups = [ self.render_group(name, self.groups.get(name, ''), opts) for name in [
  377.             None] + self.group_list ]
  378.         return src + '\n\n'.join(groups)
  379.  
  380.  
  381.  
  382. class ConfigInterface(object):
  383.     
  384.     def __init__(self, description):
  385.         self.option_set = OptionSet(description = description)
  386.         self.add_opt = self.option_set.add_opt
  387.         self.add_group = self.option_set.add_group
  388.         self.remove_opt = self.remove = self.option_set.remove_opt
  389.         self.parse_string = self.option_set.parse_string
  390.         self.get_option = self.option_set.get_option
  391.         self.preferences = self.option_set.preferences
  392.  
  393.     
  394.     def update(self, other):
  395.         self.option_set.update(other.option_set)
  396.  
  397.     
  398.     def option_parser(self, usage = '', gui_mode = False):
  399.         return self.option_set.option_parser(user_defaults = self.parse(), usage = usage, gui_mode = gui_mode)
  400.  
  401.     
  402.     def smart_update(self, opts1, opts2):
  403.         self.option_set.smart_update(opts1, opts2)
  404.  
  405.  
  406.  
  407. class Config(ConfigInterface):
  408.     
  409.     def __init__(self, basename, description = ''):
  410.         ConfigInterface.__init__(self, description)
  411.         self.config_file_path = os.path.join(config_dir, basename + '.py')
  412.  
  413.     
  414.     def parse(self):
  415.         src = ''
  416.         if os.path.exists(self.config_file_path):
  417.             
  418.             try:
  419.                 
  420.                 try:
  421.                     f = _[1]
  422.                     
  423.                     try:
  424.                         src = f.read().decode('utf-8')
  425.                     except ValueError:
  426.                         ExclusiveFile(self.config_file_path).__exit__
  427.                         ExclusiveFile(self.config_file_path).__exit__
  428.                         ExclusiveFile(self.config_file_path)
  429.                         print 'Failed to parse', self.config_file_path
  430.                         traceback.print_exc()
  431.                     except:
  432.                         ExclusiveFile(self.config_file_path).__exit__
  433.  
  434.                 finally:
  435.                     pass
  436.  
  437.             except LockError:
  438.                 raise IOError('Could not lock config file: %s' % self.config_file_path)
  439.             except:
  440.                 None<EXCEPTION MATCH>LockError
  441.             
  442.  
  443.         None<EXCEPTION MATCH>LockError
  444.         return self.option_set.parse_string(src)
  445.  
  446.     
  447.     def as_string(self):
  448.         if not os.path.exists(self.config_file_path):
  449.             return ''
  450.         
  451.         try:
  452.             
  453.             try:
  454.                 f = _[1]
  455.                 return f.read().decode('utf-8')
  456.             finally:
  457.                 pass
  458.  
  459.         except LockError:
  460.             os.path.exists(self.config_file_path)
  461.             os.path.exists(self.config_file_path)
  462.             raise IOError('Could not lock config file: %s' % self.config_file_path)
  463.         except:
  464.             os.path.exists(self.config_file_path)
  465.  
  466.  
  467.     
  468.     def set(self, name, val):
  469.         if not self.option_set.has_option(name):
  470.             raise ValueError('The option %s is not defined.' % name)
  471.         self.option_set.has_option(name)
  472.         
  473.         try:
  474.             if not os.path.exists(config_dir):
  475.                 make_config_dir()
  476.             
  477.             
  478.             try:
  479.                 f = _[1]
  480.                 src = f.read()
  481.                 opts = self.option_set.parse_string(src)
  482.                 setattr(opts, name, val)
  483.                 footer = self.option_set.get_override_section(src)
  484.                 src = self.option_set.serialize(opts) + '\n\n' + footer + '\n'
  485.                 f.seek(0)
  486.                 f.truncate()
  487.                 f.write(src)
  488.             finally:
  489.                 pass
  490.  
  491.         except LockError:
  492.             raise IOError('Could not lock config file: %s' % self.config_file_path)
  493.  
  494.  
  495.  
  496.  
  497. class StringConfig(ConfigInterface):
  498.     
  499.     def __init__(self, src, description = ''):
  500.         ConfigInterface.__init__(self, description)
  501.         self.src = src
  502.  
  503.     
  504.     def parse(self):
  505.         return self.option_set.parse_string(self.src)
  506.  
  507.     
  508.     def set(self, name, val):
  509.         if not self.option_set.has_option(name):
  510.             raise ValueError('The option %s is not defined.' % name)
  511.         self.option_set.has_option(name)
  512.         opts = self.option_set.parse_string(self.src)
  513.         setattr(opts, name, val)
  514.         footer = self.option_set.get_override_section(self.src)
  515.         self.src = self.option_set.serialize(opts) + '\n\n' + footer + '\n'
  516.  
  517.  
  518.  
  519. class ConfigProxy(object):
  520.     
  521.     def __init__(self, config):
  522.         self._ConfigProxy__config = config
  523.         self._ConfigProxy__opts = None
  524.  
  525.     
  526.     def defaults(self):
  527.         return self._ConfigProxy__config.option_set.defaults
  528.  
  529.     defaults = property(defaults)
  530.     
  531.     def refresh(self):
  532.         self._ConfigProxy__opts = self._ConfigProxy__config.parse()
  533.  
  534.     
  535.     def __getitem__(self, key):
  536.         return self.get(key)
  537.  
  538.     
  539.     def __setitem__(self, key, val):
  540.         return self.set(key, val)
  541.  
  542.     
  543.     def get(self, key):
  544.         if self._ConfigProxy__opts is None:
  545.             self.refresh()
  546.         
  547.         return getattr(self._ConfigProxy__opts, key)
  548.  
  549.     
  550.     def set(self, key, val):
  551.         if self._ConfigProxy__opts is None:
  552.             self.refresh()
  553.         
  554.         setattr(self._ConfigProxy__opts, key, val)
  555.         return self._ConfigProxy__config.set(key, val)
  556.  
  557.     
  558.     def help(self, key):
  559.         return self._ConfigProxy__config.get_option(key).help
  560.  
  561.  
  562.  
  563. class DynamicConfig(dict):
  564.     
  565.     def __init__(self, name = 'dynamic'):
  566.         dict.__init__(self, { })
  567.         self.name = name
  568.         self.defaults = { }
  569.         self.file_path = os.path.join(config_dir, name + '.pickle')
  570.         self.refresh()
  571.  
  572.     
  573.     def refresh(self):
  574.         d = { }
  575.         self.clear()
  576.         self.update(d)
  577.  
  578.     
  579.     def __getitem__(self, key):
  580.         
  581.         try:
  582.             return dict.__getitem__(self, key)
  583.         except KeyError:
  584.             return self.defaults.get(key, None)
  585.  
  586.  
  587.     
  588.     def get(self, key, default = None):
  589.         
  590.         try:
  591.             return dict.__getitem__(self, key)
  592.         except KeyError:
  593.             return self.defaults.get(key, default)
  594.  
  595.  
  596.     
  597.     def __setitem__(self, key, val):
  598.         dict.__setitem__(self, key, val)
  599.         self.commit()
  600.  
  601.     
  602.     def set(self, key, val):
  603.         self.__setitem__(key, val)
  604.  
  605.     
  606.     def commit(self):
  607.         pass
  608.  
  609.  
  610. dynamic = DynamicConfig()
  611.  
  612. class XMLConfig(dict):
  613.     EXTENSION = '.plist'
  614.     
  615.     def __init__(self, rel_path_to_cf_file):
  616.         dict.__init__(self)
  617.         self.defaults = { }
  618.         self.file_path = os.path.join(config_dir, *rel_path_to_cf_file.split('/'))
  619.         self.file_path = os.path.abspath(self.file_path)
  620.         if not self.file_path.endswith(self.EXTENSION):
  621.             self.file_path += self.EXTENSION
  622.         
  623.         self.refresh()
  624.  
  625.     
  626.     def raw_to_object(self, raw):
  627.         return plistlib.readPlistFromString(raw)
  628.  
  629.     
  630.     def to_raw(self):
  631.         return plistlib.writePlistToString(self)
  632.  
  633.     
  634.     def refresh(self):
  635.         d = { }
  636.         self.clear()
  637.         self.update(d)
  638.  
  639.     
  640.     def __getitem__(self, key):
  641.         
  642.         try:
  643.             ans = dict.__getitem__(self, key)
  644.             if isinstance(ans, plistlib.Data):
  645.                 ans = ans.data
  646.             
  647.             return ans
  648.         except KeyError:
  649.             return self.defaults.get(key, None)
  650.  
  651.  
  652.     
  653.     def get(self, key, default = None):
  654.         
  655.         try:
  656.             ans = dict.__getitem__(self, key)
  657.             if isinstance(ans, plistlib.Data):
  658.                 ans = ans.data
  659.             
  660.             return ans
  661.         except KeyError:
  662.             return self.defaults.get(key, default)
  663.  
  664.  
  665.     
  666.     def __setitem__(self, key, val):
  667.         if isinstance(val, (bytes, str)):
  668.             val = plistlib.Data(val)
  669.         
  670.         dict.__setitem__(self, key, val)
  671.         self.commit()
  672.  
  673.     
  674.     def set(self, key, val):
  675.         self.__setitem__(key, val)
  676.  
  677.     
  678.     def __delitem__(self, key):
  679.         if dict.has_key(self, key):
  680.             dict.__delitem__(self, key)
  681.             self.commit()
  682.         
  683.  
  684.     
  685.     def commit(self):
  686.         pass
  687.  
  688.  
  689.  
  690. def to_json(obj):
  691.     if isinstance(obj, bytearray):
  692.         return {
  693.             '__class__': 'bytearray',
  694.             '__value__': base64.standard_b64encode(bytes(obj)) }
  695.     if isinstance(obj, datetime.datetime):
  696.         isoformat = isoformat
  697.         import calibre.utils.date
  698.         return {
  699.             '__class__': 'datetime.datetime',
  700.             '__value__': isoformat(obj, as_utc = True) }
  701.     raise TypeError(repr(obj) + ' is not JSON serializable')
  702.  
  703.  
  704. def from_json(obj):
  705.     return obj
  706.  
  707.  
  708. class JSONConfig(XMLConfig):
  709.     EXTENSION = '.json'
  710.     
  711.     def raw_to_object(self, raw):
  712.         return json.loads(raw.decode('utf-8'), object_hook = from_json)
  713.  
  714.     
  715.     def to_raw(self):
  716.         return json.dumps(self, indent = 2, default = to_json)
  717.  
  718.     
  719.     def __getitem__(self, key):
  720.         
  721.         try:
  722.             return dict.__getitem__(self, key)
  723.         except KeyError:
  724.             return self.defaults[key]
  725.  
  726.  
  727.     
  728.     def get(self, key, default = None):
  729.         
  730.         try:
  731.             return dict.__getitem__(self, key)
  732.         except KeyError:
  733.             return self.defaults.get(key, default)
  734.  
  735.  
  736.     
  737.     def __setitem__(self, key, val):
  738.         dict.__setitem__(self, key, val)
  739.         self.commit()
  740.  
  741.  
  742.  
  743. def _prefs():
  744.     c = Config('global', 'calibre wide preferences')
  745.     c.add_opt('database_path', default = os.path.expanduser('~/library1.db'), help = _('Path to the database in which books are stored'))
  746.     c.add_opt('filename_pattern', default = u'(?P<title>.+) - (?P<author>[^_]+)', help = _('Pattern to guess metadata from filenames'))
  747.     c.add_opt('isbndb_com_key', default = '', help = _('Access key for isbndb.com'))
  748.     c.add_opt('network_timeout', default = 5, help = _('Default timeout for network operations (seconds)'))
  749.     c.add_opt('library_path', default = None, help = _('Path to directory in which your library of books is stored'))
  750.     c.add_opt('language', default = None, help = _('The language in which to display the user interface'))
  751.     c.add_opt('output_format', default = 'EPUB', help = _('The default output format for ebook conversions.'))
  752.     c.add_opt('input_format_order', default = [
  753.         'EPUB',
  754.         'MOBI',
  755.         'LIT',
  756.         'PRC',
  757.         'FB2',
  758.         'HTML',
  759.         'HTM',
  760.         'XHTM',
  761.         'SHTML',
  762.         'XHTML',
  763.         'ZIP',
  764.         'ODT',
  765.         'RTF',
  766.         'PDF',
  767.         'TXT'], help = _('Ordered list of formats to prefer for input.'))
  768.     c.add_opt('read_file_metadata', default = True, help = _('Read metadata from files'))
  769.     c.add_opt('worker_process_priority', default = 'normal', help = _('The priority of worker processes'))
  770.     c.add_opt('swap_author_names', default = False, help = _('Swap author first and last names when reading metadata'))
  771.     c.add_opt('add_formats_to_existing', default = False, help = _('Add new formats to existing book records'))
  772.     c.add_opt('installation_uuid', default = None, help = 'Installation UUID')
  773.     c.add_opt('new_book_tags', default = [], help = _('Tags to apply to books added to the library'))
  774.     c.add_opt('saved_searches', default = { }, help = _('List of named saved searches'))
  775.     c.add_opt('user_categories', default = { }, help = _('User-created tag browser categories'))
  776.     c.add_opt('manage_device_metadata', default = 'manual', help = _('How and when calibre updates metadata on the device.'))
  777.     c.add_opt('migrated', default = False, help = "For Internal use. Don't modify.")
  778.     return c
  779.  
  780. prefs = ConfigProxy(_prefs())
  781. if prefs['installation_uuid'] is None:
  782.     import uuid
  783.     prefs['installation_uuid'] = str(uuid.uuid4())
  784.  
  785.  
  786. def read_raw_tweaks():
  787.     make_config_dir()
  788.     default_tweaks = P('default_tweaks.py', data = True, allow_user_override = False)
  789.     tweaks_file = os.path.join(config_dir, 'tweaks.py')
  790.     
  791.     try:
  792.         f = _[2]
  793.         return (default_tweaks, f.read())
  794.     finally:
  795.         pass
  796.  
  797.  
  798.  
  799. def read_tweaks():
  800.     (default_tweaks, tweaks) = read_raw_tweaks()
  801.     l = { }
  802.     g = { }
  803.     
  804.     try:
  805.         exec tweaks in g, l
  806.     except:
  807.         print 'Failed to load custom tweaks file'
  808.         traceback.print_exc()
  809.  
  810.     dl = { }
  811.     dg = { }
  812.     exec default_tweaks in dg, dl
  813.     dl.update(l)
  814.     return dl
  815.  
  816.  
  817. def write_tweaks(raw):
  818.     make_config_dir()
  819.     tweaks_file = os.path.join(config_dir, 'tweaks.py')
  820.     
  821.     try:
  822.         f = _[1]
  823.         f.write(raw)
  824.     finally:
  825.         pass
  826.  
  827.  
  828. tweaks = read_tweaks()
  829.  
  830. def migrate():
  831.     if hasattr(os, 'geteuid') and os.geteuid() == 0:
  832.         return None
  833.     p = prefs
  834.     if p.get('migrated'):
  835.         return None
  836.     QSettings = QSettings
  837.     QVariant = QVariant
  838.     import PyQt4.QtCore
  839.     
  840.     class Settings('Settings', (QSettings,)):
  841.         
  842.         def __init__(self, name = ('calibre2',)):
  843.             QSettings.__init__(self, QSettings.IniFormat, QSettings.UserScope, 'kovidgoyal.net', name)
  844.  
  845.         
  846.         def get(self, key, default = (None,)):
  847.             
  848.             try:
  849.                 key = str(key)
  850.                 if not self.contains(key):
  851.                     return default
  852.                 val = str(self.value(key, QVariant()).toByteArray())
  853.                 if not val:
  854.                     return None
  855.                 return cPickle.loads(val)
  856.             except:
  857.                 return default
  858.  
  859.  
  860.  
  861.     s = Settings()
  862.     migrated = set([])
  863.     all_keys = set(map(unicode, s.allKeys()))
  864.     config = config
  865.     dynamic = dynamic
  866.     import calibre.gui2
  867.     
  868.     def _migrate(key, safe = None, from_qvariant = os.geteuid() == 0, p = (None, None, config)):
  869.         
  870.         try:
  871.             if key not in all_keys:
  872.                 return None
  873.             if safe is None:
  874.                 safe = re.sub('[^0-9a-zA-Z]', '_', key)
  875.             
  876.             val = s.get(key)
  877.             if from_qvariant is not None:
  878.                 val = getattr(s.value(key), from_qvariant)()
  879.             
  880.             p.set(safe, val)
  881.         except:
  882.             pass
  883.         finally:
  884.             migrated.add(key)
  885.  
  886.  
  887.     _migrate('database path', p = prefs)
  888.     _migrate('filename pattern', p = prefs)
  889.     _migrate('network timeout', p = prefs)
  890.     _migrate('isbndb.com key', p = prefs)
  891.     _migrate('frequently used directories')
  892.     _migrate('send to device by default')
  893.     _migrate('save to disk single format')
  894.     _migrate('confirm delete')
  895.     _migrate('show text in toolbar')
  896.     _migrate('new version notification')
  897.     _migrate('use roman numerals for series number')
  898.     _migrate('cover flow queue length')
  899.     _migrate('LRF conversion defaults')
  900.     _migrate('LRF ebook viewer options')
  901.     for key in all_keys - migrated:
  902.         if key.endswith(': un') or key.endswith(': pw'):
  903.             _migrate(key, p = dynamic)
  904.             continue
  905.     
  906.     p.set('migrated', True)
  907.  
  908.