VirtualMailManager/Config.py
branchv0.6.x
changeset 303 8dd3a107fd92
parent 301 e1d3f027dd64
child 304 df0f7b22540c
equal deleted inserted replaced
302:32b4a39b5640 303:8dd3a107fd92
    58       option is not configured in a ini-like configuration file.
    58       option is not configured in a ini-like configuration file.
    59 
    59 
    60     `set()` differs from `RawConfigParser`'s `set()` method. `set()`
    60     `set()` differs from `RawConfigParser`'s `set()` method. `set()`
    61     takes the `section` and `option` arguments combined to a single
    61     takes the `section` and `option` arguments combined to a single
    62     string in the form "section.option".
    62     string in the form "section.option".
    63 
       
    64     """
    63     """
    65 
    64 
    66     def __init__(self):
    65     def __init__(self):
    67         RawConfigParser.__init__(self)
    66         RawConfigParser.__init__(self)
    68         self._modified = False
    67         self._modified = False
    96         For a boolean True, the value must be set to '1', 'on', 'yes',
    95         For a boolean True, the value must be set to '1', 'on', 'yes',
    97         'true' or True. For a boolean False, the value must set to '0',
    96         'true' or True. For a boolean False, the value must set to '0',
    98         'off', 'no', 'false' or False.
    97         'off', 'no', 'false' or False.
    99         If the option has another value assigned this method will raise
    98         If the option has another value assigned this method will raise
   100         a ValueError.
    99         a ValueError.
   101 
       
   102         """
   100         """
   103         # if the setting was modified it may be still a boolean value lets see
   101         # if the setting was modified it may be still a boolean value lets see
   104         tmp = self.get(section, option)
   102         tmp = self.get(section, option)
   105         if isinstance(tmp, bool):
   103         if isinstance(tmp, bool):
   106             return tmp
   104             return tmp
   119         Else one of the following exceptions will be thrown:
   117         Else one of the following exceptions will be thrown:
   120 
   118 
   121           * `BadOptionError`
   119           * `BadOptionError`
   122           * `NoSectionError`
   120           * `NoSectionError`
   123           * `NoOptionError`
   121           * `NoOptionError`
   124 
       
   125         """
   122         """
   126         sect_opt = section_option.lower().split('.')
   123         sect_opt = section_option.lower().split('.')
   127         # TODO: cache it
   124         # TODO: cache it
   128         if len(sect_opt) != 2:  # do we need a regexp to check the format?
   125         if len(sect_opt) != 2:  # do we need a regexp to check the format?
   129             raise BadOptionError(_(u"Bad format: '%s' - expected: "
   126             raise BadOptionError(_(u"Bad format: '%s' - expected: "
   136         return sect_opt
   133         return sect_opt
   137 
   134 
   138     def items(self, section):
   135     def items(self, section):
   139         """returns an iterable that returns key, value ``tuples`` from
   136         """returns an iterable that returns key, value ``tuples`` from
   140         the given ``section``.
   137         the given ``section``.
   141 
       
   142         """
   138         """
   143         if section in self._sections:  # check if the section was parsed
   139         if section in self._sections:  # check if the section was parsed
   144             sect = self._sections[section]
   140             sect = self._sections[section]
   145         elif not section in self._cfg:
   141         elif not section in self._cfg:
   146             raise NoSectionError(section)
   142             raise NoSectionError(section)
   167         `option` : string
   163         `option` : string
   168             the configuration option in the form "section.option"
   164             the configuration option in the form "section.option"
   169 
   165 
   170         Throws a `NoDefaultError`, if no default value was passed to
   166         Throws a `NoDefaultError`, if no default value was passed to
   171         `LazyConfigOption.__init__()` for the `option`.
   167         `LazyConfigOption.__init__()` for the `option`.
   172 
       
   173         """
   168         """
   174         section, option = self._get_section_option(option)
   169         section, option = self._get_section_option(option)
   175         try:
   170         try:
   176             return self._cfg[section][option].getter(section, option)
   171             return self._cfg[section][option].getter(section, option)
   177         except (NoSectionError, NoOptionError):
   172         except (NoSectionError, NoOptionError):
   188     def set(self, option, value):
   183     def set(self, option, value):
   189         """Set the `value` of the `option`.
   184         """Set the `value` of the `option`.
   190 
   185 
   191         Throws a `ValueError` if `value` couldn't be converted using
   186         Throws a `ValueError` if `value` couldn't be converted using
   192         `LazyConfigOption.cls`.
   187         `LazyConfigOption.cls`.
   193 
   188         """
   194         """
   189         # pylint: disable=W0221
   195         # pylint: disable-msg=W0221
       
   196         # @pylint: _L A Z Y_
   190         # @pylint: _L A Z Y_
   197         section, option = self._get_section_option(option)
   191         section, option = self._get_section_option(option)
   198         val = self._cfg[section][option].cls(value)
   192         val = self._cfg[section][option].cls(value)
   199         if self._cfg[section][option].validate:
   193         if self._cfg[section][option].validate:
   200             val = self._cfg[section][option].validate(val)
   194             val = self._cfg[section][option].validate(val)
   208         return section.lower() in self._cfg
   202         return section.lower() in self._cfg
   209 
   203 
   210     def has_option(self, option):
   204     def has_option(self, option):
   211         """Checks if the option (section.option) is a known
   205         """Checks if the option (section.option) is a known
   212         configuration option.
   206         configuration option.
   213 
   207         """
   214         """
   208         # pylint: disable=W0221
   215         # pylint: disable-msg=W0221
       
   216         # @pylint: _L A Z Y_
   209         # @pylint: _L A Z Y_
   217         try:
   210         try:
   218             self._get_section_option(option)
   211             self._get_section_option(option)
   219             return True
   212             return True
   220         except(BadOptionError, NoSectionError, NoOptionError):
   213         except(BadOptionError, NoSectionError, NoOptionError):
   229     """A simple container class for configuration settings.
   222     """A simple container class for configuration settings.
   230 
   223 
   231     `LazyConfigOption` instances are required by `LazyConfig` instances,
   224     `LazyConfigOption` instances are required by `LazyConfig` instances,
   232     and instances of classes derived from `LazyConfig`, like the
   225     and instances of classes derived from `LazyConfig`, like the
   233     `Config` class.
   226     `Config` class.
   234 
       
   235     """
   227     """
   236     __slots__ = ('__cls', '__default', '__getter', '__validate')
   228     __slots__ = ('__cls', '__default', '__getter', '__validate')
   237 
   229 
   238     def __init__(self, cls, default, getter, validate=None):
   230     def __init__(self, cls, default, getter, validate=None):
   239         """Creates a new `LazyConfigOption` instance.
   231         """Creates a new `LazyConfigOption` instance.
   249           A method's name of `RawConfigParser` and derived classes, to
   241           A method's name of `RawConfigParser` and derived classes, to
   250           get a option's value, e.g. `self.getint`.
   242           get a option's value, e.g. `self.getint`.
   251         `validate` : NoneType or a callable
   243         `validate` : NoneType or a callable
   252           None or any method, that takes one argument, in order to
   244           None or any method, that takes one argument, in order to
   253           check the value, when `LazyConfig.set()` is called.
   245           check the value, when `LazyConfig.set()` is called.
   254 
       
   255         """
   246         """
   256         self.__cls = cls
   247         self.__cls = cls
   257         if not default is None:  # enforce the type of the default value
   248         if not default is None:  # enforce the type of the default value
   258             self.__default = self.__cls(default)
   249             self.__default = self.__cls(default)
   259         else:
   250         else:
   267                             validate.__class__.__name__)
   258                             validate.__class__.__name__)
   268         self.__validate = validate
   259         self.__validate = validate
   269 
   260 
   270     @property
   261     @property
   271     def cls(self):
   262     def cls(self):
   272         """The class of the option's value e.g. `str`, `unicode` or
   263         """The class of the option's value e.g. `str`, `unicode` or `bool`."""
   273         `bool`.
       
   274 
       
   275         """
       
   276         return self.__cls
   264         return self.__cls
   277 
   265 
   278     @property
   266     @property
   279     def default(self):
   267     def default(self):
   280         """The option's default value, may be `None`"""
   268         """The option's default value, may be `None`"""
   299 
   287 
   300         Arguments:
   288         Arguments:
   301 
   289 
   302         `filename` : str
   290         `filename` : str
   303           path to the configuration file
   291           path to the configuration file
   304 
       
   305         """
   292         """
   306         LazyConfig.__init__(self)
   293         LazyConfig.__init__(self)
   307         self._cfg_filename = filename
   294         self._cfg_filename = filename
   308         self._cfg_file = None
   295         self._cfg_file = None
   309         self.__missing = {}
   296         self.__missing = {}
   339                 'delete_directory': LCO(bool_t, False, self.getboolean),
   326                 'delete_directory': LCO(bool_t, False, self.getboolean),
   340                 'directory_mode': LCO(int, 504, self.getint),
   327                 'directory_mode': LCO(int, 504, self.getint),
   341                 'force_deletion': LCO(bool_t, False, self.getboolean),
   328                 'force_deletion': LCO(bool_t, False, self.getboolean),
   342             },
   329             },
   343             'mailbox': {
   330             'mailbox': {
   344                 'folders': LCO(str, 'Drafts:Sent:Templates:Trash', self.get),
   331                 'folders': LCO(str, 'Drafts:Sent:Templates:Trash',
       
   332                                self.unicode),
   345                 'format': LCO(str, 'maildir', self.get, check_mailbox_format),
   333                 'format': LCO(str, 'maildir', self.get, check_mailbox_format),
   346                 'root': LCO(str, 'Maildir', self.get),
   334                 'root': LCO(str, 'Maildir', self.unicode),
   347             },
   335             },
   348             'misc': {
   336             'misc': {
   349                 'base_directory': LCO(str, '/srv/mail', self.get, is_dir),
   337                 'base_directory': LCO(str, '/srv/mail', self.get, is_dir),
   350                 'crypt_blowfish_rounds': LCO(int, 5, self.getint),
   338                 'crypt_blowfish_rounds': LCO(int, 5, self.getint),
   351                 'crypt_sha256_rounds': LCO(int, 5000, self.getint),
   339                 'crypt_sha256_rounds': LCO(int, 5000, self.getint),
   361     def load(self):
   349     def load(self):
   362         """Loads the configuration, read only.
   350         """Loads the configuration, read only.
   363 
   351 
   364         Raises a ConfigError if the configuration syntax is
   352         Raises a ConfigError if the configuration syntax is
   365         invalid.
   353         invalid.
   366 
       
   367         """
   354         """
   368         try:
   355         try:
   369             self._cfg_file = open(self._cfg_filename, 'r')
   356             self._cfg_file = open(self._cfg_filename, 'r')
   370             self.readfp(self._cfg_file)
   357             self.readfp(self._cfg_file)
   371         except (MissingSectionHeaderError, ParsingError), err:
   358         except (MissingSectionHeaderError, ParsingError), err:
   408     def __chk_cfg(self):
   395     def __chk_cfg(self):
   409         """Checks all section's options for settings w/o a default
   396         """Checks all section's options for settings w/o a default
   410         value.
   397         value.
   411 
   398 
   412         Returns `True` if everything is fine, else `False`.
   399         Returns `True` if everything is fine, else `False`.
   413 
       
   414         """
   400         """
   415         errors = False
   401         errors = False
   416         for section in self._cfg.iterkeys():
   402         for section in self._cfg.iterkeys():
   417             missing = []
   403             missing = []
   418             for option, value in self._cfg[section].iteritems():
   404             for option, value in self._cfg[section].iteritems():