# HG changeset patch # User Pascal Volk # Date 1265422315 0 # Node ID 38b9a985974971e99a318a994dbe24f90e82221d # Parent 18757fd45e603fb42334b21c9c26613e875cea78 VMM/{,cli/Cli}Config: Moved interactive stuff to new CliConfig class. Renamed Config.getsections() to Config.sections(). Small cosmetics. diff -r 18757fd45e60 -r 38b9a9859749 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Fri Feb 05 20:16:44 2010 +0000 +++ b/VirtualMailManager/Config.py Sat Feb 06 02:11:55 2010 +0000 @@ -34,14 +34,13 @@ from shutil import copy2 -from ConfigParser import (Error, MissingSectionHeaderError, NoOptionError, - NoSectionError, ParsingError, RawConfigParser) +from ConfigParser import \ + Error, MissingSectionHeaderError, NoOptionError, NoSectionError, \ + ParsingError, RawConfigParser from cStringIO import StringIO# TODO: move interactive stff to cli -import VirtualMailManager.constants.ERROR as ERR - from VirtualMailManager import ENCODING, exec_ok, get_unicode, is_dir -from VirtualMailManager.cli import w_std# move to cli +from VirtualMailManager.constants.ERROR import CONF_ERROR from VirtualMailManager.Exceptions import VMMConfigException @@ -105,7 +104,7 @@ if value.lower() in self._boolean_states: return self._boolean_states[value.lower()] else: - raise ConfigValueError(_(u'Not a boolean: “%s”') % \ + raise ConfigValueError(_(u'Not a boolean: “%s”') % get_unicode(value)) def get_boolean(self, section, option): @@ -117,7 +116,7 @@ return tmp return self.getboolean(section, option) - def __get_section_option(self, section_option): + def _get_section_option(self, section_option): """splits ``section_option`` (section\ **.**\ option) in two parts and returns them as list ``[section, option]``, if: @@ -134,7 +133,7 @@ sect_opt = section_option.lower().split('.') if len(sect_opt) != 2:# do we need a regexp to check the format? raise BadOptionError( - _(u'Bad format: “%s” - expected: section.option') % \ + _(u'Bad format: “%s” - expected: section.option') % get_unicode(section_option)) if not sect_opt[0] in self._cfg: raise NoSectionError(sect_opt[0]) @@ -175,7 +174,7 @@ Throws a `NoDefaultError`, if no default value was passed to `LazyConfigOption.__init__()` for the `option`. """ - section, option = self.__get_section_option(option) + section, option = self._get_section_option(option) try: return self._cfg[section][option].getter(section, option) except (NoSectionError, NoOptionError): @@ -186,7 +185,7 @@ def pget(self, option): """Returns the value of the `option`.""" - section, option = self.__get_section_option(option) + section, option = self._get_section_option(option) return self._cfg[section][option].getter(section, option) def set(self, option, value): @@ -194,7 +193,7 @@ Throws a ``ValueError`` if `value` couldn't be converted to ``LazyConfigOption.cls``""" - section, option = self.__get_section_option(option) + section, option = self._get_section_option(option) val = self._cfg[section][option].cls(value) if not self._cfg[section][option].validate is None: val = self._cfg[section][option].validate(val) @@ -211,7 +210,7 @@ """Checks if the option (section\ **.**\ option) is a known configuration option.""" try: - self.__get_section_option(option) + self._get_section_option(option) return True except(BadOptionError, NoSectionError, NoOptionError): return False @@ -273,8 +272,8 @@ path to the configuration file """ LazyConfig.__init__(self) - self.__cfgFileName = filename - self.__cfgFile = None + self._cfgFileName = filename + self._cfgFile = None self.__missing = {} LCO = LazyConfigOption @@ -328,13 +327,13 @@ Raises a VMMConfigException if the configuration syntax is invalid. """ try: - self.__cfgFile = open(self.__cfgFileName, 'r') - self.readfp(self.__cfgFile) + self._cfgFile = open(self._cfgFileName, 'r') + self.readfp(self._cfgFile) except (MissingSectionHeaderError, ParsingError), e: - raise VMMConfigException(str(e), ERR.CONF_ERROR) + raise VMMConfigException(str(e), CONF_ERROR) finally: - if not self.__cfgFile is None and not self.__cfgFile.closed: - self.__cfgFile.close() + if not self._cfgFile is None and not self._cfgFile.closed: + self._cfgFile.close() def check(self): """Performs a configuration check. @@ -346,15 +345,15 @@ if not self.__chkCfg(): errmsg = StringIO() errmsg.write(_(u'Missing options, which have no default value.\n')) - errmsg.write(_(u'Using configuration file: %s\n') %\ - self.__cfgFileName) + errmsg.write(_(u'Using configuration file: %s\n') % + self._cfgFileName) for section, options in self.__missing.iteritems(): errmsg.write(_(u'* Section: %s\n') % section) for option in options: errmsg.write((u' %s\n') % option) - raise VMMConfigException(errmsg.getvalue(), ERR.CONF_ERROR) + raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) - def getsections(self): + def sections(self): """Returns an iterator object for all configuration sections.""" return self._cfg.iterkeys() @@ -374,51 +373,6 @@ """ return get_unicode(self.get(section, option)) - def configure(self, sections): - """Interactive method for configuring all options in the given sections - - Arguments: - sections -- list of strings with section names - """ - # TODO: Derivate CliConfig from Config an move the interactive - # stuff to CliConfig - input_fmt = _(u'Enter new value for option %(option)s \ -[%(current_value)s]: ') - failures = 0 - - w_std(_(u'Using configuration file: %s\n') % self.__cfgFileName) - for s in sections: - w_std(_(u'* Configuration section: “%s”') % s ) - for opt, val in self.items(s): - failures = 0 - while True: - newval = raw_input(input_fmt.encode(ENCODING,'replace') %{ - 'option': opt, 'current_value': val}) - if newval and newval != val: - try: - self.set('%s.%s' % (s, opt), newval) - break - except (ValueError, ConfigValueError), e: - w_std(_(u'Warning: %s') % e) - failures += 1 - if failures > 2: - raise VMMConfigException( - _(u'Too many failures - try again later.'), - ERR.VMM_TOO_MANY_FAILURES) - else: - break - print - if self._modified: - self.__saveChanges() - - def __saveChanges(self): - """Writes changes to the configuration file.""" - # TODO: Move interactive stuff to CliConfig - copy2(self.__cfgFileName, self.__cfgFileName+'.bak') - self.__cfgFile = open(self.__cfgFileName, 'w') - self.write(self.__cfgFile) - self.__cfgFile.close() - def __chkCfg(self): """Checks all section's options for settings w/o default values. @@ -427,11 +381,10 @@ for section in self._cfg.iterkeys(): missing = [] for option, value in self._cfg[section].iteritems(): - if (value.default is None - and not RawConfigParser.has_option(self, section, option)): - missing.append(option) - errors = True + if (value.default is None and + not RawConfigParser.has_option(self, section, option)): + missing.append(option) + errors = True if len(missing): self.__missing[section] = missing return not errors - diff -r 18757fd45e60 -r 38b9a9859749 VirtualMailManager/Handler.py --- a/VirtualMailManager/Handler.py Fri Feb 05 20:16:44 2010 +0000 +++ b/VirtualMailManager/Handler.py Sat Feb 06 02:11:55 2010 +0000 @@ -80,12 +80,12 @@ self.__findCfgFile() fstat = os.stat(self.__cfgFileName) fmode = int(oct(fstat.st_mode & 0777)) - if fmode % 100 and fstat.st_uid != fstat.st_gid \ - or fmode % 10 and fstat.st_uid == fstat.st_gid: - raise VMMPermException(_( - u'fix permissions (%(perms)s) for “%(file)s”\n\ + if fmode % 100 and fstat.st_uid != fstat.st_gid or \ + fmode % 10 and fstat.st_uid == fstat.st_gid: + raise VMMPermException(_( + u'fix permissions (%(perms)s) for “%(file)s”\n\ `chmod 0600 %(file)s` would be great.') % {'file': - self.__cfgFileName, 'perms': fmode}, ERR.CONF_WRONGPERM) + self.__cfgFileName, 'perms': fmode}, ERR.CONF_WRONGPERM) else: return True @@ -154,14 +154,14 @@ def aliasExists(dbh, address): sql = "SELECT DISTINCT gid FROM alias WHERE gid = (SELECT gid FROM\ - domain_name WHERE domainname = '%s') AND address = '%s'" %\ + domain_name WHERE domainname = '%s') AND address = '%s'" % (address._domainname, address._localpart) return Handler._exists(dbh, sql) aliasExists = staticmethod(aliasExists) def relocatedExists(dbh, address): sql = "SELECT gid FROM relocated WHERE gid = (SELECT gid FROM\ - domain_name WHERE domainname = '%s') AND address = '%s'" %\ + domain_name WHERE domainname = '%s') AND address = '%s'" % (address._domainname, address._localpart) return Handler._exists(dbh, sql) relocatedExists = staticmethod(relocatedExists) @@ -404,7 +404,7 @@ section -- the section to configure (default None): """ if section is None: - self.__Cfg.configure(self.__Cfg.getsections()) + self.__Cfg.configure(self.__Cfg.sections()) elif self.__Cfg.has_section(section): self.__Cfg.configure([section]) else: @@ -545,12 +545,11 @@ alias = self.__getAlias(aliasaddress, targetaddress) alias.save(long(self._postconf.read('virtual_alias_expansion_limit'))) gid = self.__getDomain(alias._dest._domainname).getID() - if gid > 0 and not Handler.accountExists(self.__dbh, - alias._dest) and not Handler.aliasExists(self.__dbh, - alias._dest): + if gid > 0 and (not Handler.accountExists(self.__dbh, alias._dest) and + not Handler.aliasExists(self.__dbh, alias._dest)): self.__warnings.append( - _(u"The destination account/alias “%s” doesn't exist.")%\ - alias._dest) + _(u"The destination account/alias “%s” doesn't exist.") % + alias._dest) def userDelete(self, emailaddress, force=None): if force not in [None, 'delalias']: diff -r 18757fd45e60 -r 38b9a9859749 VirtualMailManager/__init__.py --- a/VirtualMailManager/__init__.py Fri Feb 05 20:16:44 2010 +0000 +++ b/VirtualMailManager/__init__.py Sat Feb 06 02:11:55 2010 +0000 @@ -76,7 +76,7 @@ raise VMMException(_(u'“%s” is not a file') % get_unicode(binary), NO_SUCH_BINARY) if not os.access(binary, os.X_OK): - raise VMMException(_(u'File is not executable: “%s”') % \ + raise VMMException(_(u'File is not executable: “%s”') % get_unicode(binary), NOT_EXECUTABLE) return binary diff -r 18757fd45e60 -r 38b9a9859749 VirtualMailManager/cli/CliConfig.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualMailManager/cli/CliConfig.py Sat Feb 06 02:11:55 2010 +0000 @@ -0,0 +1,82 @@ +# -*- coding: UTF-8 -*- +# Copyright (c) 2010, Pascal Volk +# See COPYING for distribution information. + +""" + VirtualMailManager.cli.CliConfig + + Adds some interactive stuff to the Config class. +""" + +from VirtualMailManager import ENCODING +from VirtualMailManager.Config import Config +from VirtualMailManager.cli import w_std +from VirtualMailManager.constants.ERROR import VMM_TOO_MANY_FAILURES + +class CliConfig(Config): + """Adds the interactive ``configure`` method to the `Config` class + and overwrites `LazyConfig.set(), in order to update a single option + in the configuration file with a single command line command. + """ + def configure(self, sections): + """Interactive method for configuring all options of the given + iterable ``sections`` object.""" + input_fmt = _(u'Enter new value for option %(option)s \ +[%(current_value)s]: ') + failures = 0 + + w_std(_(u'Using configuration file: %s\n') % self._cfgFileName) + for s in sections: + w_std(_(u'* Configuration section: “%s”') % s ) + for opt, val in self.items(s): + failures = 0 + while True: + newval = raw_input(input_fmt.encode(ENCODING,'replace') %{ + 'option': opt, 'current_value': val}) + if newval and newval != val: + try: + LazyConfig.set('%s.%s' % (s, opt), newval) + break + except (ValueError, ConfigValueError), e: + w_std(_(u'Warning: %s') % e) + failures += 1 + if failures > 2: + raise VMMConfigException( + _(u'Too many failures - try again later.'), + VMM_TOO_MANY_FAILURES) + else: + break + print + if self._modified: + self.__saveChanges() + + def set(self, option, value): + """Set the value of an option. + + If the new `value` has been set, the configuration file will be + immediately updated. + + Throws a ``ValueError`` if `value` couldn't be converted to + ``LazyConfigOption.cls``""" + section, option_ = self._get_section_option(option) + val = self._cfg[section][option_].cls(value) + if not self._cfg[section][option_].validate is None: + val = self._cfg[section][option_].validate(val) + # Do not write default values also skip identical values + if not self._cfg[section][option_].default is None: + old_val = self.dget(option) + else: + old_val = self.pget(option) + if val == old_val: + return + if not RawConfigParser.has_section(self, section): + self.add_section(section) + RawConfigParser.set(self, section, option_, val) + self.__saveChanges() + + def __saveChanges(self): + """Writes changes to the configuration file.""" + copy2(self._cfgFileName, self._cfgFileName+'.bak') + self._cfgFile = open(self._cfgFileName, 'w') + self.write(self._cfgFile) + self._cfgFile.close()