4 |
4 |
5 """ |
5 """ |
6 VirtualMailManager.Config |
6 VirtualMailManager.Config |
7 |
7 |
8 VMM's configuration module for simplified configuration access. |
8 VMM's configuration module for simplified configuration access. |
9 |
|
10 This module defines a few classes: |
|
11 |
|
12 ``LazyConfig`` |
|
13 This class provides the following additonal methods |
|
14 |
|
15 * `LazyConfig.pget()` |
|
16 polymorphic getter which returns the value with the appropriate |
|
17 type. |
|
18 * `LazyConfig.dget()` |
|
19 like *pget()*, but checks additonal for default values in |
|
20 `LazyConfig._cfg`. |
|
21 * `LazyConfig.set()` |
|
22 like `RawConfigParser.set()`, but converts the new value to the |
|
23 appropriate type/class and optional validates the new value. |
|
24 * `LazyConfig.bool_new()` |
|
25 converts data from raw_input into boolean values. |
|
26 * `LazyConfig.get_boolean()` |
|
27 like `RawConfigParser.getboolean()`, but doesn't fail on real |
|
28 `bool` values. |
|
29 |
|
30 ``Config`` |
|
31 The Config class used by vmm. |
|
32 |
|
33 ``LazyConfigOption`` |
|
34 The class for the configuration objects in the ``Config`` class' |
|
35 ``_cfg`` dictionary. |
|
36 """ |
9 """ |
37 |
10 |
38 |
11 |
39 from ConfigParser import \ |
12 from ConfigParser import \ |
40 Error, MissingSectionHeaderError, NoOptionError, NoSectionError, \ |
13 Error, MissingSectionHeaderError, NoOptionError, NoSectionError, \ |
67 class LazyConfig(RawConfigParser): |
40 class LazyConfig(RawConfigParser): |
68 """The **lazy** derivate of the `RawConfigParser`. |
41 """The **lazy** derivate of the `RawConfigParser`. |
69 |
42 |
70 There are two additional getters: |
43 There are two additional getters: |
71 |
44 |
72 `LazyConfig.pget()` |
45 `pget()` |
73 The polymorphic getter, which returns a option's value with the |
46 The polymorphic getter, which returns a option's value with the |
74 appropriate type. |
47 appropriate type. |
75 `LazyConfig.dget()` |
48 `dget()` |
76 Like `LazyConfig.pget()`, but returns the option's default, from |
49 Like `LazyConfig.pget()`, but returns the option's default, from |
77 `LazyConfig._cfg['sectionname']['optionname'].default`, if the |
50 `LazyConfig._cfg['sectionname']['optionname'].default`, if the |
78 option is not configured in a ini-like configuration file. |
51 option is not configured in a ini-like configuration file. |
79 |
52 |
80 |
53 `set()` differs from `RawConfigParser`'s `set()` method. `set()` takes |
81 `LazyConfig.set()` differs from ``RawConfigParser``'s ``set()`` method. |
54 the `section` and `option` arguments combined to a single string in the |
82 ``LazyConfig.set()`` takes the ``section`` and ``option`` arguments |
55 form "section.option". |
83 combined to a single string in the form |
|
84 "``section``\ **.**\ ``option``". |
|
85 """ |
56 """ |
86 |
57 |
87 def __init__(self): |
58 def __init__(self): |
88 RawConfigParser.__init__(self) |
59 RawConfigParser.__init__(self) |
89 self._modified = False |
60 self._modified = False |
95 """sample _cfg dictionary. Create your own in your derived class.""" |
66 """sample _cfg dictionary. Create your own in your derived class.""" |
96 |
67 |
97 def bool_new(self, value): |
68 def bool_new(self, value): |
98 """Converts the string `value` into a `bool` and returns it. |
69 """Converts the string `value` into a `bool` and returns it. |
99 |
70 |
100 | '1', 'on', 'yes' and 'true' will become ``True`` |
71 | '1', 'on', 'yes' and 'true' will become `True` |
101 | '0', 'off', 'no' and 'false' will become ``False`` |
72 | '0', 'off', 'no' and 'false' will become `False` |
102 |
73 |
103 Throws a `ConfigValueError` for all other values, except ``bool``\ s. |
74 Throws a `ConfigValueError` for all other values, except bools. |
104 """ |
75 """ |
105 if isinstance(value, bool): |
76 if isinstance(value, bool): |
106 return value |
77 return value |
107 if value.lower() in self._boolean_states: |
78 if value.lower() in self._boolean_states: |
108 return self._boolean_states[value.lower()] |
79 return self._boolean_states[value.lower()] |
198 """Returns the value of the `option`.""" |
169 """Returns the value of the `option`.""" |
199 section, option = self._get_section_option(option) |
170 section, option = self._get_section_option(option) |
200 return self._cfg[section][option].getter(section, option) |
171 return self._cfg[section][option].getter(section, option) |
201 |
172 |
202 def set(self, option, value): |
173 def set(self, option, value): |
203 """Set the value of an option. |
174 """Set the `value` of the `option`. |
204 |
175 |
205 Throws a ``ValueError`` if `value` couldn't be converted to |
176 Throws a `ValueError` if `value` couldn't be converted using |
206 ``LazyConfigOption.cls``""" |
177 `LazyConfigOption.cls`""" |
207 section, option = self._get_section_option(option) |
178 section, option = self._get_section_option(option) |
208 val = self._cfg[section][option].cls(value) |
179 val = self._cfg[section][option].cls(value) |
209 if self._cfg[section][option].validate: |
180 if self._cfg[section][option].validate: |
210 val = self._cfg[section][option].validate(val) |
181 val = self._cfg[section][option].validate(val) |
211 if not RawConfigParser.has_section(self, section): |
182 if not RawConfigParser.has_section(self, section): |
212 self.add_section(section) |
183 self.add_section(section) |
213 RawConfigParser.set(self, section, option, val) |
184 RawConfigParser.set(self, section, option, val) |
214 self._modified = True |
185 self._modified = True |
215 |
186 |
216 def has_section(self, section): |
187 def has_section(self, section): |
217 """Checks if ``section`` is a known configuration section.""" |
188 """Checks if `section` is a known configuration section.""" |
218 return section.lower() in self._cfg |
189 return section.lower() in self._cfg |
219 |
190 |
220 def has_option(self, option): |
191 def has_option(self, option): |
221 """Checks if the option (section\ **.**\ option) is a known |
192 """Checks if the option (section.option) is a known configuration |
222 configuration option.""" |
193 option.""" |
223 try: |
194 try: |
224 self._get_section_option(option) |
195 self._get_section_option(option) |
225 return True |
196 return True |
226 except(BadOptionError, NoSectionError, NoOptionError): |
197 except(BadOptionError, NoSectionError, NoOptionError): |
227 return False |
198 return False |
232 |
203 |
233 |
204 |
234 class LazyConfigOption(object): |
205 class LazyConfigOption(object): |
235 """A simple container class for configuration settings. |
206 """A simple container class for configuration settings. |
236 |
207 |
237 ``LazyConfigOption`` instances are required by `LazyConfig` instances, |
208 `LazyConfigOption` instances are required by `LazyConfig` instances, |
238 and instances of classes derived from ``LazyConfig``, like the |
209 and instances of classes derived from `LazyConfig`, like the |
239 `Config` class. |
210 `Config` class. |
240 """ |
211 """ |
241 __slots__ = ('__cls', '__default', '__getter', '__validate') |
212 __slots__ = ('__cls', '__default', '__getter', '__validate') |
242 |
213 |
243 def __init__(self, cls, default, getter, validate=None): |
214 def __init__(self, cls, default, getter, validate=None): |
244 """Creates a new ``LazyConfigOption`` instance. |
215 """Creates a new `LazyConfigOption` instance. |
245 |
216 |
246 Arguments: |
217 Arguments: |
247 |
218 |
248 ``cls`` : type |
219 `cls` : type |
249 The class/type of the option's value |
220 The class/type of the option's value |
250 ``default`` |
221 `default` |
251 Default value of the option. Use ``None`` if the option should |
222 Default value of the option. Use ``None`` if the option should not |
252 not have a default value. |
223 have a default value. |
253 ``getter`` : callable |
224 `getter` : callable |
254 A method's name of `RawConfigParser` and derived classes, to |
225 A method's name of `RawConfigParser` and derived classes, to get a |
255 get a option's value, e.g. `self.getint`. |
226 option's value, e.g. `self.getint`. |
256 ``validate`` : NoneType or a callable |
227 `validate` : NoneType or a callable |
257 None or any method, that takes one argument, in order to check |
228 None or any method, that takes one argument, in order to check the |
258 the value, when `LazyConfig.set()` is called. |
229 value, when `LazyConfig.set()` is called. |
259 """ |
230 """ |
260 self.__cls = cls |
231 self.__cls = cls |
261 if not default is None:# enforce the type of the default value |
232 if not default is None:# enforce the type of the default value |
262 self.__default = self.__cls(default) |
233 self.__default = self.__cls(default) |
263 else: |
234 else: |
387 for option in options: |
358 for option in options: |
388 errmsg.write((u' %s\n') % option) |
359 errmsg.write((u' %s\n') % option) |
389 raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) |
360 raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) |
390 |
361 |
391 def known_scheme(self, scheme): |
362 def known_scheme(self, scheme): |
392 """Converts ``scheme`` to upper case and checks if is known by |
363 """Converts `scheme` to upper case and checks if is known by |
393 Dovecot (listed in VirtualMailManager.SCHEMES). |
364 Dovecot (listed in VirtualMailManager.SCHEMES). |
394 |
365 |
395 Throws a `ConfigValueError` if the scheme is not listed in |
366 Throws a `ConfigValueError` if the scheme is not listed in |
396 VirtualMailManager.SCHEMES. |
367 VirtualMailManager.SCHEMES. |
397 """ |
368 """ |
398 scheme = scheme.upper() |
369 scheme = scheme.upper() |
399 # TODO: VMM.SCHEMES |
370 # TODO: VMM.SCHEMES |
400 |
371 |
401 def unicode(self, section, option): |
372 def unicode(self, section, option): |
402 """Returns the value of the ``option`` from ``section``, converted |
373 """Returns the value of the `option` from `section`, converted to |
403 to Unicode. |
374 Unicode.""" |
404 """ |
|
405 return get_unicode(self.get(section, option)) |
375 return get_unicode(self.get(section, option)) |
406 |
376 |
407 def __chkCfg(self): |
377 def __chkCfg(self): |
408 """Checks all section's options for settings w/o a default value. |
378 """Checks all section's options for settings w/o a default value. |
409 |
379 |
410 Returns ``True`` if everything is fine, else ``False``.""" |
380 Returns `True` if everything is fine, else `False`.""" |
411 errors = False |
381 errors = False |
412 for section in self._cfg.iterkeys(): |
382 for section in self._cfg.iterkeys(): |
413 missing = [] |
383 missing = [] |
414 for option, value in self._cfg[section].iteritems(): |
384 for option, value in self._cfg[section].iteritems(): |
415 if (value.default is None and |
385 if (value.default is None and |