VirtualMailManager/Config.py
branchv0.6.x
changeset 200 983cf98d5881
parent 188 cf1b5f22dbd2
child 201 dbb0f7ed7858
equal deleted inserted replaced
199:0684790fff7c 200:983cf98d5881
     1 # -*- coding: UTF-8 -*-
     1 # -*- coding: UTF-8 -*-
     2 # Copyright (c) 2007 - 2010, Pascal Volk
     2 # Copyright (c) 2007 - 2010, Pascal Volk
     3 # See COPYING for distribution information.
     3 # See COPYING for distribution information.
     4 
     4 
     5 """vmm's configuration module for simplified configuration access.
     5 """
       
     6     VirtualMailManager.Config
       
     7 
       
     8     VMM's configuration module for simplified configuration access.
     6 
     9 
     7 This module defines a few classes:
    10 This module defines a few classes:
     8 
    11 
     9 ``LazyConfig``
    12 ``LazyConfig``
    10     This class provides the following additonal methods
    13     This class provides the following additonal methods
   110     def get_boolean(self, section, option):
   113     def get_boolean(self, section, option):
   111         # if the setting was not written to the configuration file, it may
   114         # if the setting was not written to the configuration file, it may
   112         # be still a boolean value - lets see
   115         # be still a boolean value - lets see
   113         if self._modified:
   116         if self._modified:
   114            tmp = self.get(section, option)
   117            tmp = self.get(section, option)
   115            if isinstance(tmp, bool):
   118            assert isinstance(tmp, bool), 'Oops, not a boolean: %r' % tmp
   116                return tmp
   119            return tmp
   117         return self.getboolean(section, option)
   120         return self.getboolean(section, option)
   118 
   121 
   119     def _get_section_option(self, section_option):
   122     def _get_section_option(self, section_option):
   120         """splits ``section_option`` (section\ **.**\ option) in two parts
   123         """splits ``section_option`` (section\ **.**\ option) in two parts
   121         and returns them as list ``[section, option]``, if:
   124         and returns them as list ``[section, option]``, if:
   129             * `BadOptionError`
   132             * `BadOptionError`
   130             * `NoSectionError`
   133             * `NoSectionError`
   131             * `NoOptionError`
   134             * `NoOptionError`
   132         """
   135         """
   133         sect_opt = section_option.lower().split('.')
   136         sect_opt = section_option.lower().split('.')
       
   137         # TODO: cache it
   134         if len(sect_opt) != 2:# do we need a regexp to check the format?
   138         if len(sect_opt) != 2:# do we need a regexp to check the format?
   135             raise BadOptionError(
   139             raise BadOptionError(
   136                         _(u'Bad format: ā€œ%sā€ - expected: section.option') %
   140                         _(u'Bad format: ā€œ%sā€ - expected: section.option') %
   137                         get_unicode(section_option))
   141                         get_unicode(section_option))
   138         if not sect_opt[0] in self._cfg:
   142         if not sect_opt[0] in self._cfg:
   176         """
   180         """
   177         section, option = self._get_section_option(option)
   181         section, option = self._get_section_option(option)
   178         try:
   182         try:
   179             return self._cfg[section][option].getter(section, option)
   183             return self._cfg[section][option].getter(section, option)
   180         except (NoSectionError, NoOptionError):
   184         except (NoSectionError, NoOptionError):
   181             if not self._cfg[section][option].default is None:
   185             if not self._cfg[section][option].default is None:# may be False
   182                 return self._cfg[section][option].default
   186                 return self._cfg[section][option].default
   183             else:
   187             else:
   184                 raise NoDefaultError(section, option)
   188                 raise NoDefaultError(section, option)
   185 
   189 
   186     def pget(self, option):
   190     def pget(self, option):
   193 
   197 
   194         Throws a ``ValueError`` if `value` couldn't be converted to
   198         Throws a ``ValueError`` if `value` couldn't be converted to
   195         ``LazyConfigOption.cls``"""
   199         ``LazyConfigOption.cls``"""
   196         section, option = self._get_section_option(option)
   200         section, option = self._get_section_option(option)
   197         val = self._cfg[section][option].cls(value)
   201         val = self._cfg[section][option].cls(value)
   198         if not self._cfg[section][option].validate is None:
   202         if self._cfg[section][option].validate:
   199             val = self._cfg[section][option].validate(val)
   203             val = self._cfg[section][option].validate(val)
   200         if not RawConfigParser.has_section(self, section):
   204         if not RawConfigParser.has_section(self, section):
   201             self.add_section(section)
   205             self.add_section(section)
   202         RawConfigParser.set(self, section, option, val)
   206         RawConfigParser.set(self, section, option, val)
   203         self._modified = True
   207         self._modified = True
   221 
   225 
   222    ``LazyConfigOption`` instances are required by `LazyConfig` instances,
   226    ``LazyConfigOption`` instances are required by `LazyConfig` instances,
   223    and instances of classes derived from ``LazyConfig``, like the
   227    and instances of classes derived from ``LazyConfig``, like the
   224    `Config` class.
   228    `Config` class.
   225     """
   229     """
   226     __slots__ = ('cls', 'default', 'getter', 'validate')
   230     __slots__ = ('__cls', '__default', '__getter', '__validate')
   227 
   231 
   228     def __init__(self, cls, default, getter, validate=None):
   232     def __init__(self, cls, default, getter, validate=None):
   229         """Creates a new ``LazyConfigOption`` instance.
   233         """Creates a new ``LazyConfigOption`` instance.
   230 
   234 
   231         Arguments:
   235         Arguments:
   240             get a option's value, e.g. `self.getint`.
   244             get a option's value, e.g. `self.getint`.
   241         ``validate`` : NoneType or a callable
   245         ``validate`` : NoneType or a callable
   242             None or any method, that takes one argument, in order to check
   246             None or any method, that takes one argument, in order to check
   243             the value, when `LazyConfig.set()` is called.
   247             the value, when `LazyConfig.set()` is called.
   244         """
   248         """
   245         self.cls = cls
   249         self.__cls = cls
       
   250         self.__default = default
       
   251         if not callable(getter):
       
   252             raise TypeError('getter has to be a callable, got a %r' %
       
   253                             getter.__class__.__name__)
       
   254         self.__getter = getter
       
   255         if validate and not callable(validate):
       
   256             raise TypeError('validate has to be callable or None, got a %r' %
       
   257                             validate.__class__.__name__)
       
   258         self.__validate = validate
       
   259 
       
   260     @property
       
   261     def cls(self):
   246         """The class of the option's value e.g. `str`, `unicode` or `bool`"""
   262         """The class of the option's value e.g. `str`, `unicode` or `bool`"""
   247         self.default = default
   263         return self.__cls
       
   264 
       
   265     @property
       
   266     def default(self):
   248         """The option's default value, may be ``None``"""
   267         """The option's default value, may be ``None``"""
   249         if callable(getter):
   268         return self.__default
   250             self.getter = getter
   269 
   251             """The getter method to get the option's value"""
   270     @property
   252         else:
   271     def getter(self):
   253             raise TypeError('getter has to be a callable, got a %r'\
   272         """The getter method or function to get the option's value"""
   254                             % getter.__class__.__name__)
   273         return self.__getter
   255         if validate is None or callable(validate):
   274 
   256             self.validate = validate
   275     @property
   257             """A method to validate the value"""
   276     def validate(self):
   258         else:
   277         """A method or function to validate the value"""
   259             raise TypeError('validate has to be callable or None, got a %r'\
   278         return self.__validate
   260                             % validate.__class__.__name__)
       
   261 
   279 
   262 
   280 
   263 class Config(LazyConfig):
   281 class Config(LazyConfig):
   264     """This class is for reading vmm's configuration file."""
   282     """This class is for reading vmm's configuration file."""
   265 
   283 
   333             self._cfgFile = open(self._cfgFileName, 'r')
   351             self._cfgFile = open(self._cfgFileName, 'r')
   334             self.readfp(self._cfgFile)
   352             self.readfp(self._cfgFile)
   335         except (MissingSectionHeaderError, ParsingError), e:
   353         except (MissingSectionHeaderError, ParsingError), e:
   336             raise VMMConfigException(str(e), CONF_ERROR)
   354             raise VMMConfigException(str(e), CONF_ERROR)
   337         finally:
   355         finally:
   338             if not self._cfgFile is None and not self._cfgFile.closed:
   356             if self._cfgFile and not self._cfgFile.closed:
   339                 self._cfgFile.close()
   357                 self._cfgFile.close()
   340 
   358 
   341     def check(self):
   359     def check(self):
   342         """Performs a configuration check.
   360         """Performs a configuration check.
   343 
   361 
   386             for option, value in self._cfg[section].iteritems():
   404             for option, value in self._cfg[section].iteritems():
   387                 if (value.default is None and
   405                 if (value.default is None and
   388                     not RawConfigParser.has_option(self, section, option)):
   406                     not RawConfigParser.has_option(self, section, option)):
   389                         missing.append(option)
   407                         missing.append(option)
   390                         errors = True
   408                         errors = True
   391             if len(missing):
   409             if missing:
   392                 self.__missing[section] = missing
   410                 self.__missing[section] = missing
   393         return not errors
   411         return not errors