32 ``_cfg`` dictionary. |
32 ``_cfg`` dictionary. |
33 """ |
33 """ |
34 |
34 |
35 |
35 |
36 from shutil import copy2 |
36 from shutil import copy2 |
37 from ConfigParser import (Error, MissingSectionHeaderError, NoOptionError, |
37 from ConfigParser import \ |
38 NoSectionError, ParsingError, RawConfigParser) |
38 Error, MissingSectionHeaderError, NoOptionError, NoSectionError, \ |
|
39 ParsingError, RawConfigParser |
39 from cStringIO import StringIO# TODO: move interactive stff to cli |
40 from cStringIO import StringIO# TODO: move interactive stff to cli |
40 |
41 |
41 import VirtualMailManager.constants.ERROR as ERR |
|
42 |
|
43 from VirtualMailManager import ENCODING, exec_ok, get_unicode, is_dir |
42 from VirtualMailManager import ENCODING, exec_ok, get_unicode, is_dir |
44 from VirtualMailManager.cli import w_std# move to cli |
43 from VirtualMailManager.constants.ERROR import CONF_ERROR |
45 from VirtualMailManager.Exceptions import VMMConfigException |
44 from VirtualMailManager.Exceptions import VMMConfigException |
46 |
45 |
47 |
46 |
48 class BadOptionError(Error): |
47 class BadOptionError(Error): |
49 """Raised when a option isn't in the format 'section.option'.""" |
48 """Raised when a option isn't in the format 'section.option'.""" |
103 if isinstance(value, bool): |
102 if isinstance(value, bool): |
104 return value |
103 return value |
105 if value.lower() in self._boolean_states: |
104 if value.lower() in self._boolean_states: |
106 return self._boolean_states[value.lower()] |
105 return self._boolean_states[value.lower()] |
107 else: |
106 else: |
108 raise ConfigValueError(_(u'Not a boolean: “%s”') % \ |
107 raise ConfigValueError(_(u'Not a boolean: “%s”') % |
109 get_unicode(value)) |
108 get_unicode(value)) |
110 |
109 |
111 def get_boolean(self, section, option): |
110 def get_boolean(self, section, option): |
112 # if the setting was not written to the configuration file, it may |
111 # if the setting was not written to the configuration file, it may |
113 # be still a boolean value - lets see |
112 # be still a boolean value - lets see |
115 tmp = self.get(section, option) |
114 tmp = self.get(section, option) |
116 if isinstance(tmp, bool): |
115 if isinstance(tmp, bool): |
117 return tmp |
116 return tmp |
118 return self.getboolean(section, option) |
117 return self.getboolean(section, option) |
119 |
118 |
120 def __get_section_option(self, section_option): |
119 def _get_section_option(self, section_option): |
121 """splits ``section_option`` (section\ **.**\ option) in two parts |
120 """splits ``section_option`` (section\ **.**\ option) in two parts |
122 and returns them as list ``[section, option]``, if: |
121 and returns them as list ``[section, option]``, if: |
123 |
122 |
124 * it likes the format of ``section_option`` |
123 * it likes the format of ``section_option`` |
125 * the ``section`` is known |
124 * the ``section`` is known |
132 * `NoOptionError` |
131 * `NoOptionError` |
133 """ |
132 """ |
134 sect_opt = section_option.lower().split('.') |
133 sect_opt = section_option.lower().split('.') |
135 if len(sect_opt) != 2:# do we need a regexp to check the format? |
134 if len(sect_opt) != 2:# do we need a regexp to check the format? |
136 raise BadOptionError( |
135 raise BadOptionError( |
137 _(u'Bad format: “%s” - expected: section.option') % \ |
136 _(u'Bad format: “%s” - expected: section.option') % |
138 get_unicode(section_option)) |
137 get_unicode(section_option)) |
139 if not sect_opt[0] in self._cfg: |
138 if not sect_opt[0] in self._cfg: |
140 raise NoSectionError(sect_opt[0]) |
139 raise NoSectionError(sect_opt[0]) |
141 if not sect_opt[1] in self._cfg[sect_opt[0]]: |
140 if not sect_opt[1] in self._cfg[sect_opt[0]]: |
142 raise NoOptionError(sect_opt[1], sect_opt[0]) |
141 raise NoOptionError(sect_opt[1], sect_opt[0]) |
173 "``section``\ **.**\ ``option``" |
172 "``section``\ **.**\ ``option``" |
174 |
173 |
175 Throws a `NoDefaultError`, if no default value was passed to |
174 Throws a `NoDefaultError`, if no default value was passed to |
176 `LazyConfigOption.__init__()` for the `option`. |
175 `LazyConfigOption.__init__()` for the `option`. |
177 """ |
176 """ |
178 section, option = self.__get_section_option(option) |
177 section, option = self._get_section_option(option) |
179 try: |
178 try: |
180 return self._cfg[section][option].getter(section, option) |
179 return self._cfg[section][option].getter(section, option) |
181 except (NoSectionError, NoOptionError): |
180 except (NoSectionError, NoOptionError): |
182 if not self._cfg[section][option].default is None: |
181 if not self._cfg[section][option].default is None: |
183 return self._cfg[section][option].default |
182 return self._cfg[section][option].default |
184 else: |
183 else: |
185 raise NoDefaultError(section, option) |
184 raise NoDefaultError(section, option) |
186 |
185 |
187 def pget(self, option): |
186 def pget(self, option): |
188 """Returns the value of the `option`.""" |
187 """Returns the value of the `option`.""" |
189 section, option = self.__get_section_option(option) |
188 section, option = self._get_section_option(option) |
190 return self._cfg[section][option].getter(section, option) |
189 return self._cfg[section][option].getter(section, option) |
191 |
190 |
192 def set(self, option, value): |
191 def set(self, option, value): |
193 """Set the value of an option. |
192 """Set the value of an option. |
194 |
193 |
195 Throws a ``ValueError`` if `value` couldn't be converted to |
194 Throws a ``ValueError`` if `value` couldn't be converted to |
196 ``LazyConfigOption.cls``""" |
195 ``LazyConfigOption.cls``""" |
197 section, option = self.__get_section_option(option) |
196 section, option = self._get_section_option(option) |
198 val = self._cfg[section][option].cls(value) |
197 val = self._cfg[section][option].cls(value) |
199 if not self._cfg[section][option].validate is None: |
198 if not self._cfg[section][option].validate is None: |
200 val = self._cfg[section][option].validate(val) |
199 val = self._cfg[section][option].validate(val) |
201 if not RawConfigParser.has_section(self, section): |
200 if not RawConfigParser.has_section(self, section): |
202 self.add_section(section) |
201 self.add_section(section) |
209 |
208 |
210 def has_option(self, option): |
209 def has_option(self, option): |
211 """Checks if the option (section\ **.**\ option) is a known |
210 """Checks if the option (section\ **.**\ option) is a known |
212 configuration option.""" |
211 configuration option.""" |
213 try: |
212 try: |
214 self.__get_section_option(option) |
213 self._get_section_option(option) |
215 return True |
214 return True |
216 except(BadOptionError, NoSectionError, NoOptionError): |
215 except(BadOptionError, NoSectionError, NoOptionError): |
217 return False |
216 return False |
218 |
217 |
219 |
218 |
326 """Loads the configuration, read only. |
325 """Loads the configuration, read only. |
327 |
326 |
328 Raises a VMMConfigException if the configuration syntax is invalid. |
327 Raises a VMMConfigException if the configuration syntax is invalid. |
329 """ |
328 """ |
330 try: |
329 try: |
331 self.__cfgFile = open(self.__cfgFileName, 'r') |
330 self._cfgFile = open(self._cfgFileName, 'r') |
332 self.readfp(self.__cfgFile) |
331 self.readfp(self._cfgFile) |
333 except (MissingSectionHeaderError, ParsingError), e: |
332 except (MissingSectionHeaderError, ParsingError), e: |
334 raise VMMConfigException(str(e), ERR.CONF_ERROR) |
333 raise VMMConfigException(str(e), CONF_ERROR) |
335 finally: |
334 finally: |
336 if not self.__cfgFile is None and not self.__cfgFile.closed: |
335 if not self._cfgFile is None and not self._cfgFile.closed: |
337 self.__cfgFile.close() |
336 self._cfgFile.close() |
338 |
337 |
339 def check(self): |
338 def check(self): |
340 """Performs a configuration check. |
339 """Performs a configuration check. |
341 |
340 |
342 Raises a VMMConfigException if the check fails. |
341 Raises a VMMConfigException if the check fails. |
344 # TODO: There are only two settings w/o defaults. |
343 # TODO: There are only two settings w/o defaults. |
345 # So there is no need for cStringIO |
344 # So there is no need for cStringIO |
346 if not self.__chkCfg(): |
345 if not self.__chkCfg(): |
347 errmsg = StringIO() |
346 errmsg = StringIO() |
348 errmsg.write(_(u'Missing options, which have no default value.\n')) |
347 errmsg.write(_(u'Missing options, which have no default value.\n')) |
349 errmsg.write(_(u'Using configuration file: %s\n') %\ |
348 errmsg.write(_(u'Using configuration file: %s\n') % |
350 self.__cfgFileName) |
349 self._cfgFileName) |
351 for section, options in self.__missing.iteritems(): |
350 for section, options in self.__missing.iteritems(): |
352 errmsg.write(_(u'* Section: %s\n') % section) |
351 errmsg.write(_(u'* Section: %s\n') % section) |
353 for option in options: |
352 for option in options: |
354 errmsg.write((u' %s\n') % option) |
353 errmsg.write((u' %s\n') % option) |
355 raise VMMConfigException(errmsg.getvalue(), ERR.CONF_ERROR) |
354 raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) |
356 |
355 |
357 def getsections(self): |
356 def sections(self): |
358 """Returns an iterator object for all configuration sections.""" |
357 """Returns an iterator object for all configuration sections.""" |
359 return self._cfg.iterkeys() |
358 return self._cfg.iterkeys() |
360 |
359 |
361 def known_scheme(self, scheme): |
360 def known_scheme(self, scheme): |
362 """Converts ``scheme`` to upper case and checks if is known by |
361 """Converts ``scheme`` to upper case and checks if is known by |
371 def unicode(self, section, option): |
370 def unicode(self, section, option): |
372 """Returns the value of the ``option`` from ``section``, converted |
371 """Returns the value of the ``option`` from ``section``, converted |
373 to Unicode. |
372 to Unicode. |
374 """ |
373 """ |
375 return get_unicode(self.get(section, option)) |
374 return get_unicode(self.get(section, option)) |
376 |
|
377 def configure(self, sections): |
|
378 """Interactive method for configuring all options in the given sections |
|
379 |
|
380 Arguments: |
|
381 sections -- list of strings with section names |
|
382 """ |
|
383 # TODO: Derivate CliConfig from Config an move the interactive |
|
384 # stuff to CliConfig |
|
385 input_fmt = _(u'Enter new value for option %(option)s \ |
|
386 [%(current_value)s]: ') |
|
387 failures = 0 |
|
388 |
|
389 w_std(_(u'Using configuration file: %s\n') % self.__cfgFileName) |
|
390 for s in sections: |
|
391 w_std(_(u'* Configuration section: “%s”') % s ) |
|
392 for opt, val in self.items(s): |
|
393 failures = 0 |
|
394 while True: |
|
395 newval = raw_input(input_fmt.encode(ENCODING,'replace') %{ |
|
396 'option': opt, 'current_value': val}) |
|
397 if newval and newval != val: |
|
398 try: |
|
399 self.set('%s.%s' % (s, opt), newval) |
|
400 break |
|
401 except (ValueError, ConfigValueError), e: |
|
402 w_std(_(u'Warning: %s') % e) |
|
403 failures += 1 |
|
404 if failures > 2: |
|
405 raise VMMConfigException( |
|
406 _(u'Too many failures - try again later.'), |
|
407 ERR.VMM_TOO_MANY_FAILURES) |
|
408 else: |
|
409 break |
|
410 print |
|
411 if self._modified: |
|
412 self.__saveChanges() |
|
413 |
|
414 def __saveChanges(self): |
|
415 """Writes changes to the configuration file.""" |
|
416 # TODO: Move interactive stuff to CliConfig |
|
417 copy2(self.__cfgFileName, self.__cfgFileName+'.bak') |
|
418 self.__cfgFile = open(self.__cfgFileName, 'w') |
|
419 self.write(self.__cfgFile) |
|
420 self.__cfgFile.close() |
|
421 |
375 |
422 def __chkCfg(self): |
376 def __chkCfg(self): |
423 """Checks all section's options for settings w/o default values. |
377 """Checks all section's options for settings w/o default values. |
424 |
378 |
425 Returns ``True`` if everything is fine, else ``False``.""" |
379 Returns ``True`` if everything is fine, else ``False``.""" |
426 errors = False |
380 errors = False |
427 for section in self._cfg.iterkeys(): |
381 for section in self._cfg.iterkeys(): |
428 missing = [] |
382 missing = [] |
429 for option, value in self._cfg[section].iteritems(): |
383 for option, value in self._cfg[section].iteritems(): |
430 if (value.default is None |
384 if (value.default is None and |
431 and not RawConfigParser.has_option(self, section, option)): |
385 not RawConfigParser.has_option(self, section, option)): |
432 missing.append(option) |
386 missing.append(option) |
433 errors = True |
387 errors = True |
434 if len(missing): |
388 if len(missing): |
435 self.__missing[section] = missing |
389 self.__missing[section] = missing |
436 return not errors |
390 return not errors |
437 |
|