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 |