|
1 # -*- coding: UTF-8 -*- |
|
2 # Copyright (c) 2010 - 2012, Pascal Volk |
|
3 # See COPYING for distribution information. |
|
4 """ |
|
5 VirtualMailManager.cli.config |
|
6 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
7 |
|
8 Adds some interactive stuff to the Config class. |
|
9 """ |
|
10 |
|
11 from ConfigParser import RawConfigParser |
|
12 from shutil import copy2 |
|
13 |
|
14 from VirtualMailManager import ENCODING |
|
15 from VirtualMailManager.config import Config, ConfigValueError, LazyConfig |
|
16 from VirtualMailManager.errors import ConfigError, VMMError |
|
17 from VirtualMailManager.cli import w_err, w_std |
|
18 from VirtualMailManager.constants import CONF_ERROR, VMM_TOO_MANY_FAILURES |
|
19 |
|
20 _ = lambda msg: msg |
|
21 |
|
22 |
|
23 class CliConfig(Config): |
|
24 """Adds the interactive ``configure`` method to the `Config` class |
|
25 and overwrites `LazyConfig.set(), in order to update a single option |
|
26 in the configuration file with a single command line command. |
|
27 """ |
|
28 |
|
29 def configure(self, sections): |
|
30 """Interactive method for configuring all options of the given |
|
31 iterable ``sections`` object.""" |
|
32 input_fmt = _(u'Enter new value for option %(option)s ' |
|
33 u'[%(current_value)s]: ') |
|
34 failures = 0 |
|
35 |
|
36 w_std(_(u'Using configuration file: %s\n') % self._cfg_filename) |
|
37 for section in sections: |
|
38 w_std(_(u"* Configuration section: '%s'") % section) |
|
39 for opt, val in self.items(section): |
|
40 failures = 0 |
|
41 while True: |
|
42 newval = raw_input(input_fmt.encode(ENCODING, 'replace') % |
|
43 {'option': opt, 'current_value': val}) |
|
44 if newval and newval != val: |
|
45 try: |
|
46 LazyConfig.set(self, '%s.%s' % (section, opt), |
|
47 newval) |
|
48 break |
|
49 except (ValueError, ConfigValueError, VMMError), err: |
|
50 w_err(0, _(u'Warning: %s') % err) |
|
51 failures += 1 |
|
52 if failures > 2: |
|
53 raise ConfigError(_(u'Too many failures - try ' |
|
54 u'again later.'), |
|
55 VMM_TOO_MANY_FAILURES) |
|
56 else: |
|
57 break |
|
58 print |
|
59 if self._modified: |
|
60 self._save_changes() |
|
61 |
|
62 def set(self, option, value): |
|
63 """Set the value of an option. |
|
64 |
|
65 If the new `value` has been set, the configuration file will be |
|
66 immediately updated. |
|
67 |
|
68 Throws a ``ConfigError`` if `value` couldn't be converted to |
|
69 ``LazyConfigOption.cls`` or ``LazyConfigOption.validate`` fails.""" |
|
70 section, option_ = self._get_section_option(option) |
|
71 try: |
|
72 val = self._cfg[section][option_].cls(value) |
|
73 if self._cfg[section][option_].validate: |
|
74 val = self._cfg[section][option_].validate(val) |
|
75 except (ValueError, ConfigValueError), err: |
|
76 raise ConfigError(str(err), CONF_ERROR) |
|
77 # Do not write default values also skip identical values |
|
78 if not self._cfg[section][option_].default is None: |
|
79 old_val = self.dget(option) |
|
80 else: |
|
81 old_val = self.pget(option) |
|
82 if val == old_val: |
|
83 return |
|
84 if not RawConfigParser.has_section(self, section): |
|
85 self.add_section(section) |
|
86 RawConfigParser.set(self, section, option_, val) |
|
87 self._save_changes() |
|
88 |
|
89 def _save_changes(self): |
|
90 """Writes changes to the configuration file.""" |
|
91 copy2(self._cfg_filename, self._cfg_filename + '.bak') |
|
92 self._cfg_file = open(self._cfg_filename, 'w') |
|
93 self.write(self._cfg_file) |
|
94 self._cfg_file.close() |
|
95 |
|
96 del _ |