--- a/VirtualMailManager/ext/Postconf.py Fri Jul 23 19:07:30 2010 +0000
+++ b/VirtualMailManager/ext/Postconf.py Sun Jul 25 03:31:32 2010 +0000
@@ -1,84 +1,127 @@
# -*- coding: UTF-8 -*-
# Copyright (c) 2008 - 2010, Pascal Volk
# See COPYING for distribution information.
+"""
+ VirtualMailManager.ext.Postconf
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-"""A small - r/o - wrapper class for Postfix' postconf."""
+ Wrapper class for Postfix's postconf.
+ Postconf instances can be used to read actual values of configuration
+ parameters or edit the value of a configuration parameter.
+
+ postconf.read(parameter) -> value
+ postconf.edit(parameter, value)
+"""
import re
from subprocess import Popen, PIPE
-import VirtualMailManager.constants.ERROR as ERR
from VirtualMailManager.errors import VMMError
+from VirtualMailManager.constants.ERROR import VMM_ERROR
-RE_PC_PARAMS = """^\w+$"""
-RE_PC_VARIABLES = r"""\$\b\w+\b"""
+_ = lambda msg: msg
+
class Postconf(object):
- __slots__ = ('__bin', '__val', '__varFinder')
+ """Wrapper class for Postfix's postconf."""
+ __slots__ = ('_bin', '_val')
+ _parameter_re = re.compile(r'^\w+$')
+ _variables_re = re.compile(r'\$\b\w+\b')
+
def __init__(self, postconf_bin):
"""Creates a new Postconf instance.
- Keyword arguments:
- postconf_bin -- absolute path to the Postfix postconf binary (str)
+ Argument:
+
+ `postconf_bin` : str
+ absolute path to the Postfix postconf binary.
"""
- self.__bin = postconf_bin
- self.__val = ''
- self.__varFinder = re.compile(RE_PC_VARIABLES)
+ self._bin = postconf_bin
+ self._val = ''
+
+ def edit(self, parameter, value):
+ """Set the `parameter`'s value to `value`.
+
+ Arguments:
+
+ `parameter` : str
+ the name of a Postfix configuration parameter
+ `value` : str
+ the parameter's new value.
+ """
+ self._check_parameter(parameter)
+ stdout, stderr = Popen((self._bin, '-e', parameter + '=' + str(value)),
+ stderr=PIPE).communicate()
+ if stderr:
+ raise VMMError(stderr.strip(), VMM_ERROR)
def read(self, parameter, expand_vars=True):
"""Returns the parameters value.
If expand_vars is True (default), all variables in the value will be
expanded:
- e.g. mydestination -> mail.example.com, localhost.example.com, localhost
+ e.g. mydestination: mail.example.com, localhost.example.com, localhost
Otherwise the value may contain one or more variables.
- e.g. mydestination -> $myhostname, localhost.$mydomain, localhost
+ e.g. mydestination: $myhostname, localhost.$mydomain, localhost
+
+ Arguments:
- Keyword arguments:
- parameter -- the name of a Postfix configuration parameter (str)
- expand_vars -- default True (bool)
+ `parameter` : str
+ the name of a Postfix configuration parameter.
+ `expand_vars` : bool
+ indicates if variables should be expanded or not, default True
"""
- if not re.match(RE_PC_PARAMS, parameter):
+ self._check_parameter(parameter)
+ self._val = self._read(parameter)
+ if expand_vars:
+ self._expand_vars()
+ return self._val
+
+ def _check_parameter(self, parameter):
+ """Check that the `parameter` looks like a configuration parameter.
+ If not, a VMMError will be raised."""
+ if not self.__class__._parameter_re.match(parameter):
raise VMMError(_(u"The value '%s' doesn't look like a valid "
u"postfix configuration parameter name.") %
- parameter, ERR.VMM_ERROR)
- self.__val = self.__read(parameter)
- if expand_vars:
- self.__expandVars()
- return self.__val
+ parameter, VMM_ERROR)
- def __expandVars(self):
+ def _expand_vars(self):
+ """Expand the $variables in self._val to their values."""
while True:
- pvars = set(self.__varFinder.findall(self.__val))
- pvars_len = len(pvars)
- if pvars_len < 1:
+ pvars = set(self.__class__._variables_re.findall(self._val))
+ if not pvars:
break
- if pvars_len > 1:
- self.__expandMultiVars(self.__readMulti(pvars))
+ if len(pvars) > 1:
+ self._expand_multi_vars(self._read_multi(pvars))
continue
pvars = pvars.pop()
- self.__val = self.__val.replace(pvars, self.__read(pvars[1:]))
+ self._val = self._val.replace(pvars, self._read(pvars[1:]))
- def __expandMultiVars(self, old_new):
- for old, new in old_new.items():
- self.__val = self.__val.replace('$'+old, new)
+ def _expand_multi_vars(self, old_new):
+ """Replace all $vars in self._val with their values."""
+ for old, new in old_new.iteritems():
+ self._val = self._val.replace('$' + old, new)
- def __read(self, parameter):
- out, err = Popen([self.__bin, '-h', parameter], stdout=PIPE,
- stderr=PIPE).communicate()
- if len(err):
- raise VMMError(err.strip(), ERR.VMM_ERROR)
- return out.strip()
+ def _read(self, parameter):
+ """Ask postconf for the value of a single configuration parameter."""
+ stdout, stderr = Popen([self._bin, '-h', parameter], stdout=PIPE,
+ stderr=PIPE).communicate()
+ if stderr:
+ raise VMMError(stderr.strip(), VMM_ERROR)
+ return stdout.strip()
- def __readMulti(self, parameters):
- cmd = [self.__bin]
+ def _read_multi(self, parameters):
+ """Ask postconf for multiple configuration parameters. Returns a dict
+ parameter: value items."""
+ cmd = [self._bin]
cmd.extend(parameter[1:] for parameter in parameters)
- out, err = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
- if len(err):
- raise VMMError(err.strip(), ERR.VMM_ERROR)
+ stdout, stderr = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()
+ if stderr:
+ raise VMMError(stderr.strip(), VMM_ERROR)
par_val = {}
- for line in out.splitlines():
+ for line in stdout.splitlines():
par, val = line.split(' = ')
par_val[par] = val
return par_val
+del _