This list is closed, nobody may subscribe to it.
| 2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
(18) |
Feb
(43) |
Mar
(11) |
Apr
(50) |
May
(10) |
Jun
|
Jul
(39) |
Aug
(30) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2011 |
Jan
(14) |
Feb
(43) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(4) |
Oct
(12) |
Nov
(45) |
Dec
(3) |
| 2012 |
Jan
|
Feb
|
Mar
(2) |
Apr
(65) |
May
(2) |
Jun
(19) |
Jul
(6) |
Aug
(19) |
Sep
(23) |
Oct
(11) |
Nov
(21) |
Dec
(16) |
| 2013 |
Jan
(21) |
Feb
(2) |
Mar
(2) |
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
(2) |
Sep
|
Oct
|
Nov
|
Dec
|
| 2014 |
Jan
(4) |
Feb
(34) |
Mar
(10) |
Apr
|
May
|
Jun
(10) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
|
1
(3) |
2
(1) |
3
|
4
(1) |
5
(2) |
6
(3) |
|
7
(3) |
8
(1) |
9
(2) |
10
(3) |
11
(2) |
12
(3) |
13
(2) |
|
14
|
15
|
16
|
17
|
18
|
19
|
20
(1) |
|
21
|
22
(5) |
23
|
24
(3) |
25
(1) |
26
(1) |
27
(5) |
|
28
(1) |
|
|
|
|
|
|
|
From: <nev...@us...> - 2010-02-28 20:51:50
|
details: http://hg.localdomain.org/vmm/rev/d0c16e70a9fb changeset: 222:d0c16e70a9fb user: Pascal Volk date: Sun Feb 28 20:51:34 2010 +0000 description: VMM/Domain: get_gid() return 0 instead of raising an Exception, if the domain wasn't found in the database. diffstat: VirtualMailManager/Alias.py | 7 +++++-- VirtualMailManager/Domain.py | 9 ++++----- VirtualMailManager/Handler.py | 13 +++---------- VirtualMailManager/Relocated.py | 5 ++++- 4 files changed, 16 insertions(+), 18 deletions(-) diffs (93 lines): diff -r 371ae0b4443d -r d0c16e70a9fb VirtualMailManager/Alias.py --- a/VirtualMailManager/Alias.py Sat Feb 27 21:36:55 2010 +0000 +++ b/VirtualMailManager/Alias.py Sun Feb 28 20:51:34 2010 +0000 @@ -12,8 +12,8 @@ from VirtualMailManager.EmailAddress import EmailAddress from VirtualMailManager.errors import AliasError as AErr from VirtualMailManager.pycompat import all -from VirtualMailManager.constants.ERROR import ALIAS_ADDR_DEST_IDENTICAL, \ - ALIAS_EXCEEDS_EXPANSION_LIMIT, ALIAS_EXISTS, NO_SUCH_ALIAS +from VirtualMailManager.constants.ERROR import \ + ALIAS_EXCEEDS_EXPANSION_LIMIT, NO_SUCH_ALIAS, NO_SUCH_DOMAIN _ = lambda msg: msg @@ -28,6 +28,9 @@ self._addr = address self._dbh = dbh self._gid = get_gid(self._dbh, self._addr.domainname) + if not self._gid: + raise AErr(_(u"The domain %r doesn't exist.") % + self._addr.domainname, NO_SUCH_DOMAIN) self._dests = [] self.__load_dests() diff -r 371ae0b4443d -r d0c16e70a9fb VirtualMailManager/Domain.py --- a/VirtualMailManager/Domain.py Sat Feb 27 21:36:55 2010 +0000 +++ b/VirtualMailManager/Domain.py Sun Feb 28 20:51:34 2010 +0000 @@ -313,9 +313,10 @@ return order, domdict def get_gid(dbh, domainname): - """Returns the *GID* of the domain *domainname*. + """Returns the group id of the domain *domainname*. - Raises an `DomainError` if the domain does not exist. + If the domain couldn't be found in the database 0 will be returned. + """ domainname = check_domainname(domainname) dbc = dbh.cursor() @@ -324,6 +325,4 @@ dbc.close() if gid: return gid[0] - else: - raise DomErr(_(u"The domain “%s” doesn't exist.") % domainname, - NO_SUCH_DOMAIN) + return 0 diff -r 371ae0b4443d -r d0c16e70a9fb VirtualMailManager/Handler.py --- a/VirtualMailManager/Handler.py Sat Feb 27 21:36:55 2010 +0000 +++ b/VirtualMailManager/Handler.py Sun Feb 28 20:51:34 2010 +0000 @@ -547,16 +547,9 @@ self.__warnings.append(_('Ignored destination addresses:')) self.__warnings.extend((' * %s' % w for w in warnings)) for destination in destinations: - try: - gid = get_gid(self._dbh, destination.domainname) - except DomainError, e: - if e.code == ERR.NO_SUCH_DOMAIN: - continue - else: - raise - if gid > 0 and \ - (not Handler.accountExists(self._dbh, destination) and - not Handler.aliasExists(self._dbh, destination)): + gid = get_gid(self._dbh, destination.domainname) + if gid and (not Handler.accountExists(self._dbh, destination) and + not Handler.aliasExists(self._dbh, destination)): self.__warnings.append( _(u"The destination account/alias %r doesn't exist.") % str(destination)) diff -r 371ae0b4443d -r d0c16e70a9fb VirtualMailManager/Relocated.py --- a/VirtualMailManager/Relocated.py Sat Feb 27 21:36:55 2010 +0000 +++ b/VirtualMailManager/Relocated.py Sun Feb 28 20:51:34 2010 +0000 @@ -11,7 +11,7 @@ from VirtualMailManager.Domain import get_gid from VirtualMailManager.EmailAddress import EmailAddress from VirtualMailManager.errors import RelocatedError as RErr -from VirtualMailManager.constants.ERROR import \ +from VirtualMailManager.constants.ERROR import NO_SUCH_DOMAIN, \ NO_SUCH_RELOCATED, RELOCATED_ADDR_DEST_IDENTICAL, RELOCATED_EXISTS @@ -34,6 +34,9 @@ self._addr = address self._dbh = dbh self._gid = get_gid(self._dbh, self._addr.domainname) + if not self._gid: + raise RErr(_(u"The domain %r doesn't exist.") % + self._addr.domainname, NO_SUCH_DOMAIN) self._dest = None self.__load() |
|
From: <nev...@us...> - 2010-02-27 21:37:31
|
details: http://hg.localdomain.org/vmm/rev/371ae0b4443d changeset: 221:371ae0b4443d user: Pascal Volk date: Sat Feb 27 21:36:55 2010 +0000 description: VMM/Alias: renamed Alias.add_destination() to add_destinations(). Now it's possible to add one ore more destinations to the alias with a single method call. VMM/Handler: adjusted Handler.aliasAdd() to the API changes of the Alias class. Also use get_gid from the Domain module to get the gid of a domain. We don't need complete Domain object, only the gid. Handler.getWarnings(): no longer return the __warnings list. Return a copy instead and empty the Handler.__warnings list. diffstat: VirtualMailManager/Alias.py | 61 ++++++++++++++++++++++++++---------------- VirtualMailManager/Handler.py | 48 +++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 38 deletions(-) diffs (185 lines): diff -r 8b8d632f0ef3 -r 371ae0b4443d VirtualMailManager/Alias.py --- a/VirtualMailManager/Alias.py Sat Feb 27 20:58:49 2010 +0000 +++ b/VirtualMailManager/Alias.py Sat Feb 27 21:36:55 2010 +0000 @@ -11,6 +11,7 @@ from VirtualMailManager.Domain import get_gid from VirtualMailManager.EmailAddress import EmailAddress from VirtualMailManager.errors import AliasError as AErr +from VirtualMailManager.pycompat import all from VirtualMailManager.constants.ERROR import ALIAS_ADDR_DEST_IDENTICAL, \ ALIAS_EXCEEDS_EXPANSION_LIMIT, ALIAS_EXISTS, NO_SUCH_ALIAS @@ -44,27 +45,27 @@ dest_add(EmailAddress(dest[0])) dbc.close() - def __check_expansion(self, limit): + def __check_expansion(self, count_new, limit): """Checks the current expansion limit of the alias.""" dcount = len(self._dests) failed = False - if dcount == limit: + if dcount == limit or dcount + count_new > limit: failed = True errmsg = _( -u"""Can't add new destination to alias %(address)r. +u"""Can't add %(count_new)i new destination(s) to alias %(address)r. Currently this alias expands into %(count)i/%(limit)i recipients. -One more destination will render this alias unusable. +%(count_new)i additional destination(s) will render this alias unusable. Hint: Increase Postfix' virtual_alias_expansion_limit""") elif dcount > limit: failed = True errmsg = _( -u"""Can't add new destination to alias %(address)r. +u"""Can't add %(count_new)i new destination(s) to alias %(address)r. This alias already exceeds it's expansion limit (%(count)i/%(limit)i). So its unusable, all messages addressed to this alias will be bounced. Hint: Delete some destination addresses.""") if failed: raise AErr(errmsg % {'address': str(self._addr), 'count': dcount, - 'limit': limit}, + 'limit': limit, 'count_new': count_new}, ALIAS_EXCEEDS_EXPANSION_LIMIT) def __delete(self, destination=None): @@ -89,25 +90,39 @@ """Returns the number of destinations of the alias.""" return len(self._dests) - def add_destination(self, destination, expansion_limit): - """Adds the ``destination`` `EmailAddress` to the alias.""" - assert isinstance(destination, EmailAddress) - if self._addr == destination: - raise AErr(_(u"Address and destination are identical."), - ALIAS_ADDR_DEST_IDENTICAL) - if destination in self._dests: - raise AErr(_( - u'The alias %(a)r has already the destination %(d)r.') % - {'a': str(self._addr), 'd': str(destination)}, - ALIAS_EXISTS) - self.__check_expansion(expansion_limit) + def add_destinations(self, destinations, expansion_limit, warnings=None): + """Adds the `EmailAddress`es from *destinations* list to the + destinations of the alias. + + Destinations, that are already assigned to the alias, will be + removed from *destinations*. When done, this method will return + a set with all destinations, that was saved in the database. + """ + destinations = set(destinations) + assert destinations and \ + all(isinstance(dest, EmailAddress) for dest in destinations) + if not warnings is None: + assert isinstance(warnings, list) + if self._addr in destinations: + destinations.remove(self._addr) + if not warnings is None: + warnings.append(self._addr) + duplicates = destinations.intersection(set(self._dests)) + if duplicates: + destinations.difference_update(set(self._dests)) + if not warnings is None: + warnings.extend(duplicates) + if not destinations: + return destinations + self.__check_expansion(len(destinations), expansion_limit) dbc = self._dbh.cursor() - dbc.execute('INSERT INTO alias (gid, address, destination) \ -VALUES (%s, %s, %s)', - self._gid, self._addr.localpart, str(destination)) + dbc.executemany("INSERT INTO alias VALUES (%d, '%s', %%s)" % + (self._gid, self._addr.localpart), + (str(destination) for destination in destinations)) self._dbh.commit() dbc.close() - self._dests.append(destination) + self._dests.extend(destinations) + return destinations def del_destination(self, destination): """Deletes the specified ``destination`` address from the alias.""" @@ -131,7 +146,7 @@ return iter(self._dests) def delete(self): - """Deletes the alias with all it's destinations.""" + """Deletes the alias with all its destinations.""" if not self._dests: raise AErr(_(u"The alias %r doesn't exist.") % str(self._addr), NO_SUCH_ALIAS) diff -r 8b8d632f0ef3 -r 371ae0b4443d VirtualMailManager/Handler.py --- a/VirtualMailManager/Handler.py Sat Feb 27 20:58:49 2010 +0000 +++ b/VirtualMailManager/Handler.py Sat Feb 27 21:36:55 2010 +0000 @@ -26,9 +26,9 @@ from VirtualMailManager.Alias import Alias from VirtualMailManager.AliasDomain import AliasDomain from VirtualMailManager.Config import Config as Cfg -from VirtualMailManager.Domain import Domain +from VirtualMailManager.Domain import Domain, get_gid from VirtualMailManager.EmailAddress import EmailAddress -from VirtualMailManager.errors import VMMError, AliasError +from VirtualMailManager.errors import VMMError, AliasError, DomainError from VirtualMailManager.Relocated import Relocated from VirtualMailManager.ext.Postconf import Postconf @@ -394,8 +394,13 @@ return bool(len(self.__warnings)) def getWarnings(self): - """Returns a list with all available warnings.""" - return self.__warnings + """Returns a list with all available warnings and resets all + warnings. + + """ + ret_val = self.__warnings[:] + del self.__warnings[:] + return ret_val def cfgDget(self, option): return self._Cfg.dget(option) @@ -529,19 +534,32 @@ self._Cfg.dget('account.sieve')) self.__mailDirMake(acc.getDir('domain'), acc.getUID(), acc.getGID()) - def aliasAdd(self, aliasaddress, targetaddress): + def aliasAdd(self, aliasaddress, *targetaddresses): """Creates a new `Alias` entry for the given *aliasaddress* with - the given *targetaddress*.""" + the given *targetaddresses*.""" alias = self.__getAlias(aliasaddress) - destination = EmailAddress(targetaddress) - alias.add_destination(destination, - long(self._postconf.read('virtual_alias_expansion_limit'))) - gid = self.__getDomain(destination.domainname).getID() - if gid > 0 and (not Handler.accountExists(self._dbh, destination) and - not Handler.aliasExists(self._dbh, destination)): - self.__warnings.append( - _(u"The destination account/alias “%s” doesn't exist.") % - destination) + destinations = [EmailAddress(address) for address in targetaddresses] + warnings = [] + destinations = alias.add_destinations(destinations, + long(self._postconf.read('virtual_alias_expansion_limit')), + warnings) + if warnings: + self.__warnings.append(_('Ignored destination addresses:')) + self.__warnings.extend((' * %s' % w for w in warnings)) + for destination in destinations: + try: + gid = get_gid(self._dbh, destination.domainname) + except DomainError, e: + if e.code == ERR.NO_SUCH_DOMAIN: + continue + else: + raise + if gid > 0 and \ + (not Handler.accountExists(self._dbh, destination) and + not Handler.aliasExists(self._dbh, destination)): + self.__warnings.append( + _(u"The destination account/alias %r doesn't exist.") % + str(destination)) def userDelete(self, emailaddress, force=None): if force not in [None, 'delalias']: |
|
From: <nev...@us...> - 2010-02-27 20:59:07
|
details: http://hg.localdomain.org/vmm/rev/8b8d632f0ef3 changeset: 220:8b8d632f0ef3 user: Pascal Volk date: Sat Feb 27 20:58:49 2010 +0000 description: doc: Added the alias documentation. diffstat: doc/source/index.rst | 1 + doc/source/vmm_alias.rst | 87 ++++++++++++++++++++++++++++++++++++++ doc/source/vmm_constants_error.rst | 4 + doc/source/vmm_relocated.rst | 2 +- 4 files changed, 93 insertions(+), 1 deletions(-) diffs (135 lines): diff -r 0b6ce895e1dc -r 8b8d632f0ef3 doc/source/index.rst --- a/doc/source/index.rst Sat Feb 27 10:51:04 2010 +0000 +++ b/doc/source/index.rst Sat Feb 27 20:58:49 2010 +0000 @@ -15,6 +15,7 @@ vmm.rst vmm_config.rst vmm_emailaddress.rst + vmm_alias.rst vmm_relocated.rst vmm_errors.rst vmm_constants_error.rst diff -r 0b6ce895e1dc -r 8b8d632f0ef3 doc/source/vmm_alias.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/source/vmm_alias.rst Sat Feb 27 20:58:49 2010 +0000 @@ -0,0 +1,87 @@ +:mod:`VirtualMailManager.Alias` --- Handling of alias e-mail addresses +====================================================================== + +.. module:: VirtualMailManager.Alias + :synopsis: Handling of alias e-mail addresses + +.. moduleauthor:: Pascal Volk <nev...@us...> + +.. toctree:: + :maxdepth: 2 + + +This module provides the :class:`Alias` class. The data are read from/stored +in the ``alias`` table. This table is used by Postfix to rewrite recipient +addresses. + + +Alias +--------- +.. class:: Alias(dbh, address) + + Creates a new *Alias* instance. Alias instances provides the :func:`__len__` + method. So the existence of an alias in the database can be tested with a + simple if condition. + + :param dbh: a database connection + :type dbh: :class:`pyPgSQL.PgSQL.Connection` + :param address: the alias e-mail address. + :type address: :class:`VirtualMailManager.EmailAddress.EmailAddress` + + .. method:: add_destinations(destinations, expansion_limit [, warnings=None]) + + Adds the *destinations* to the destinations of the alias. This method + returns a ``set`` of all addresses which successfully were stored into the + database. + + If one of the e-mail addresses in *destinations* is the same as the alias + address, it will be silently discarded. Destination addresses, that are + already assigned to the alias, will be also ignored. + + When the optional *warnings* list is given, all ignored addresses will be + appended to it. + + :param destinations: The destination addresses of the alias + :type destinations: :obj:`list` of + :class:`VirtualMailManager.EmailAddress.EmailAddress` instances + :param expansion_limit: The maximal number of destinations (see also: + `virtual_alias_expansion_limit + <http://www.postfix.org/postconf.5.html#virtual_alias_expansion_limit>`_) + :type expansion_limit: :obj:`int` + :param warnings: A optional list, to record all ignored addresses + :type warnings: :obj:`list` + :rtype: :obj:`set` + :raise VirtualMailManager.errors.AliasError: if the additional + *destinations* will exceed the *expansion_limit* or if the alias + already exceeds its *expansion_limit*. + + .. seealso:: :mod:`VirtualMailManager.ext.postconf` -- to read actual + values of Postfix configuration parameters. + + + .. method:: del_destination(destination) + + Deletes the given *destination* address from the alias. + + :param destination: a destination address of the alias + :type destination: :class:`VirtualMailManager.EmailAddress.EmailAddress` + :rtype: :obj:`None` + :raise VirtualMailManager.errors.AliasError: if the destination wasn't + assigned to the alias or the alias doesn't exist. + + + .. method:: delete() + + Deletes the alias with all its destinations. + + :rtype: :obj:`None` + :raise VirtualMailManager.errors.AliasError: if the alias doesn't exist. + + + .. method:: get_destinations() + + Returns an iterator for all destinations (``EmailAddress`` instances) of + the alias. + + :rtype: :obj:`listiterator` + :raise VirtualMailManager.errors.AliasError: if the alias doesn't exist. diff -r 0b6ce895e1dc -r 8b8d632f0ef3 doc/source/vmm_constants_error.rst --- a/doc/source/vmm_constants_error.rst Sat Feb 27 10:51:04 2010 +0000 +++ b/doc/source/vmm_constants_error.rst Sat Feb 27 20:58:49 2010 +0000 @@ -43,6 +43,8 @@ The alias address and its destination are the same + obsolete? + .. data:: ALIAS_EXCEEDS_EXPANSION_LIMIT The Alias has reached or exceeds its expansion limit @@ -51,6 +53,8 @@ Alias with the given destination exists already + obsolete? + .. data:: ALIAS_MISSING_DEST obsolete? diff -r 0b6ce895e1dc -r 8b8d632f0ef3 doc/source/vmm_relocated.rst --- a/doc/source/vmm_relocated.rst Sat Feb 27 10:51:04 2010 +0000 +++ b/doc/source/vmm_relocated.rst Sat Feb 27 20:58:49 2010 +0000 @@ -26,7 +26,7 @@ order to delete the relocated user from the database. :param dbh: a database connection - :type dbh: :class:`PgSQL.Connection` + :type dbh: :class:`pyPgSQL.PgSQL.Connection` :param address: the e-mail address of the relocated user. :type address: :class:`VirtualMailManager.EmailAddress.EmailAddress` |
|
From: <nev...@us...> - 2010-02-27 10:51:22
|
details: http://hg.localdomain.org/vmm/rev/0b6ce895e1dc changeset: 219:0b6ce895e1dc user: Pascal Volk date: Sat Feb 27 10:51:04 2010 +0000 description: VMM/pycompat: added to the repository. Provides all() for Py24. diffstat: VirtualMailManager/pycompat.py | 23 +++++++++++++++++++++++ 1 files changed, 23 insertions(+), 0 deletions(-) diffs (27 lines): diff -r 84094c7fa28b -r 0b6ce895e1dc VirtualMailManager/pycompat.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualMailManager/pycompat.py Sat Feb 27 10:51:04 2010 +0000 @@ -0,0 +1,23 @@ +# -*- coding: UTF-8 -*- +# Copyright (c) 2010, Pascal Volk +# See COPYING for distribution information. + +""" + VirtualMailManager.pycompat + + VirtualMailManager's compatibility stuff for Python 2.4 +""" + +# http://docs.python.org/library/functions.html#all +try: + all = all +except NameError: + def all(iterable): + """Return True if all elements of the *iterable* are true + (or if the iterable is empty). + + """ + for element in iterable: + if not element: + return False + return True |
|
From: <nev...@us...> - 2010-02-27 09:28:50
|
details: http://hg.localdomain.org/vmm/rev/84094c7fa28b changeset: 218:84094c7fa28b user: Pascal Volk date: Sat Feb 27 09:28:33 2010 +0000 description: VMM/EmailAddress: implemented EmailAddress.__hash__(). So we can have a set() of EmailAddress instances. diffstat: VirtualMailManager/EmailAddress.py | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diffs (13 lines): diff -r eecd05e31517 -r 84094c7fa28b VirtualMailManager/EmailAddress.py --- a/VirtualMailManager/EmailAddress.py Sat Feb 27 06:24:20 2010 +0000 +++ b/VirtualMailManager/EmailAddress.py Sat Feb 27 09:28:33 2010 +0000 @@ -50,6 +50,9 @@ self._domainname != other.domainname return NotImplemented + def __hash__(self): + return hash((self._localpart.lower(), self._domainname.lower())) + def __repr__(self): return "EmailAddress('%s@%s')" % (self._localpart, self._domainname) |
|
From: <nev...@us...> - 2010-02-27 06:24:45
|
details: http://hg.localdomain.org/vmm/rev/eecd05e31517 changeset: 217:eecd05e31517 user: Pascal Volk date: Sat Feb 27 06:24:20 2010 +0000 description: VMM/cli: small optimizations in the functions w_std() and w_err() diffstat: VirtualMailManager/cli/__init__.py | 24 +++++++++++++----------- 1 files changed, 13 insertions(+), 11 deletions(-) diffs (39 lines): diff -r 0c8c053b451c -r eecd05e31517 VirtualMailManager/cli/__init__.py --- a/VirtualMailManager/cli/__init__.py Fri Feb 26 02:35:25 2010 +0000 +++ b/VirtualMailManager/cli/__init__.py Sat Feb 27 06:24:20 2010 +0000 @@ -23,22 +23,24 @@ def w_std(*args): - """Writes each arg of `args`, encoded in the current ENCODING, to stdout - and appends a newline.""" - for arg in args: - _std_write(arg.encode(ENCODING, 'replace')) - _std_write('\n') + """Writes a line for each arg of *args*, encoded in the current + ENCODING, to stdout. + + """ + _std_write('\n'.join(arg.encode(ENCODING, 'replace') for arg in args)) + _std_write('\n') def w_err(code, *args): - """Writes each arg of `args`, encoded in the current ENCODING, to stderr - and appends a newline. + """Writes a line for each arg of *args*, encoded in the current + ENCODING, to stderr. This function additional interrupts the program execution and uses - `code` system exit status.""" - for arg in args: - _err_write(arg.encode(ENCODING, 'replace')) - _err_write('\n') + *code* as the system exit status. + + """ + _err_write('\n'.join(arg.encode(ENCODING, 'replace') for arg in args)) + _err_write('\n') os.sys.exit(code) |
|
From: <nev...@us...> - 2010-02-26 02:35:45
|
details: http://hg.localdomain.org/vmm/rev/0c8c053b451c changeset: 216:0c8c053b451c user: Pascal Volk date: Fri Feb 26 02:35:25 2010 +0000 description: Moved VirtualMailManager/Exceptions to VirtualMailManager/errors. Renamed VMM*Exception classes to *Error. No longer add the attribute 'message' to VMMError if it doesn't exist, like in Python 2.4. It has been deprecated as of Python 2.6. Also removed the methods code() and msg(), the values are now accessible via the attributes 'code' and 'msg'. diffstat: VirtualMailManager/Account.py | 29 ++++---- VirtualMailManager/Alias.py | 36 +++++----- VirtualMailManager/AliasDomain.py | 31 ++++---- VirtualMailManager/Config.py | 14 ++- VirtualMailManager/Domain.py | 36 +++++----- VirtualMailManager/EmailAddress.py | 18 ++-- VirtualMailManager/Exceptions.py | 83 ------------------------- VirtualMailManager/Handler.py | 63 +++++++++--------- VirtualMailManager/MailLocation.py | 2 +- VirtualMailManager/Relocated.py | 18 ++-- VirtualMailManager/Transport.py | 8 +- VirtualMailManager/__init__.py | 38 +++++----- VirtualMailManager/cli/Config.py | 6 +- VirtualMailManager/cli/Handler.py | 8 +- VirtualMailManager/errors.py | 75 ++++++++++++++++++++++ VirtualMailManager/ext/Postconf.py | 8 +- doc/source/index.rst | 2 +- doc/source/vmm.rst | 11 +- doc/source/vmm_config.rst | 12 +- doc/source/vmm_constants_error.rst | 2 +- doc/source/vmm_emailaddress.rst | 4 +- doc/source/vmm_errors.rst | 122 +++++++++++++++++++++++++++++++++++++ doc/source/vmm_exceptions.rst | 117 ----------------------------------- doc/source/vmm_relocated.rst | 13 +-- 24 files changed, 376 insertions(+), 380 deletions(-) diffs (truncated from 1538 to 300 lines): diff -r 33f727efa7c4 -r 0c8c053b451c VirtualMailManager/Account.py --- a/VirtualMailManager/Account.py Thu Feb 25 17:56:08 2010 +0000 +++ b/VirtualMailManager/Account.py Fri Feb 26 02:35:25 2010 +0000 @@ -7,14 +7,14 @@ import VirtualMailManager.constants.ERROR as ERR from VirtualMailManager.Domain import Domain from VirtualMailManager.EmailAddress import EmailAddress -from VirtualMailManager.Exceptions import VMMAccountException as AccE +from VirtualMailManager.errors import AccountError as AccE from VirtualMailManager.MailLocation import MailLocation from VirtualMailManager.Transport import Transport -import VirtualMailManager as VMM class Account(object): """Class to manage e-mail accounts.""" __slots__ = ('_addr','_base','_gid','_mid','_passwd','_tid','_uid','_dbh') + def __init__(self, dbh, address, password=None): self._dbh = dbh self._base = None @@ -29,24 +29,23 @@ self._passwd = password self._setAddr() self._exists() - if self._uid < 1 and VMM.VirtualMailManager.aliasExists(self._dbh, - self._addr): + from VirtualMailManager.Handler import Handler + if self._uid < 1 and Handler.aliasExists(self._dbh, self._addr): # TP: Hm, what quotation marks should be used? # If you are unsure have a look at: # http://en.wikipedia.org/wiki/Quotation_mark,_non-English_usage - raise AccE(_(u"There is already an alias with the address “%s”.") %\ - self._addr, ERR.ALIAS_EXISTS) - if self._uid < 1 and VMM.VirtualMailManager.relocatedExists(self._dbh, - self._addr): + raise AccE(_(u"There is already an alias with the address “%s”.") % + self._addr, ERR.ALIAS_EXISTS) + if self._uid < 1 and Handler.relocatedExists(self._dbh, self._addr): raise AccE( - _(u"There is already a relocated user with the address “%s”.") %\ - self._addr, ERR.RELOCATED_EXISTS) + _(u"There is already a relocated user with the address “%s”.") % + self._addr, ERR.RELOCATED_EXISTS) def _exists(self): dbc = self._dbh.cursor() - dbc.execute("SELECT uid, mid, tid FROM users \ -WHERE gid=%s AND local_part=%s", - self._gid, self._addr._localpart) + dbc.execute( + "SELECT uid, mid, tid FROM users WHERE gid=%s AND local_part=%s", + self._gid, self._addr._localpart) result = dbc.fetchone() dbc.close() if result is not None: @@ -59,8 +58,8 @@ dom = Domain(self._dbh, self._addr._domainname) self._gid = dom.getID() if self._gid == 0: - raise AccE(_(u"The domain “%s” doesn't exist.") %\ - self._addr._domainname, ERR.NO_SUCH_DOMAIN) + raise AccE(_(u"The domain “%s” doesn't exist.") % + self._addr._domainname, ERR.NO_SUCH_DOMAIN) self._base = dom.getDir() self._tid = dom.getTransportID() diff -r 33f727efa7c4 -r 0c8c053b451c VirtualMailManager/Alias.py --- a/VirtualMailManager/Alias.py Thu Feb 25 17:56:08 2010 +0000 +++ b/VirtualMailManager/Alias.py Fri Feb 26 02:35:25 2010 +0000 @@ -10,7 +10,7 @@ from VirtualMailManager.Domain import get_gid from VirtualMailManager.EmailAddress import EmailAddress -from VirtualMailManager.Exceptions import VMMAliasException as VMMAE +from VirtualMailManager.errors import AliasError as AErr from VirtualMailManager.constants.ERROR import ALIAS_ADDR_DEST_IDENTICAL, \ ALIAS_EXCEEDS_EXPANSION_LIMIT, ALIAS_EXISTS, NO_SUCH_ALIAS @@ -63,9 +63,9 @@ So its unusable, all messages addressed to this alias will be bounced. Hint: Delete some destination addresses.""") if failed: - raise VMMAE(errmsg % {'address': str(self._addr), 'count': dcount, - 'limit': limit}, - ALIAS_EXCEEDS_EXPANSION_LIMIT) + raise AErr(errmsg % {'address': str(self._addr), 'count': dcount, + 'limit': limit}, + ALIAS_EXCEEDS_EXPANSION_LIMIT) def __delete(self, destination=None): """Deletes a destination from the alias, if ``destination`` is @@ -93,13 +93,13 @@ """Adds the ``destination`` `EmailAddress` to the alias.""" assert isinstance(destination, EmailAddress) if self._addr == destination: - raise VMMAE(_(u"Address and destination are identical."), - ALIAS_ADDR_DEST_IDENTICAL) + raise AErr(_(u"Address and destination are identical."), + ALIAS_ADDR_DEST_IDENTICAL) if destination in self._dests: - raise VMMAE(_( + raise AErr(_( u'The alias %(a)r has already the destination %(d)r.') % - {'a': str(self._addr), 'd': str(destination)}, - ALIAS_EXISTS) + {'a': str(self._addr), 'd': str(destination)}, + ALIAS_EXISTS) self.__check_expansion(expansion_limit) dbc = self._dbh.cursor() dbc.execute('INSERT INTO alias (gid, address, destination) \ @@ -113,28 +113,28 @@ """Deletes the specified ``destination`` address from the alias.""" assert isinstance(destination, EmailAddress) if not self._dests: - raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr), - NO_SUCH_ALIAS) + raise AErr(_(u"The alias %r doesn't exist.") % str(self._addr), + NO_SUCH_ALIAS) if not destination in self._dests: - raise VMMAE(_(u"The address %(d)r isn't a destination of \ + raise AErr(_(u"The address %(d)r isn't a destination of \ the alias %(a)r.") % - {'a': str(self._addr), 'd': str(destination)}, - NO_SUCH_ALIAS) + {'a': str(self._addr), 'd': str(destination)}, + NO_SUCH_ALIAS) self.__delete(destination) self._dests.remove(destination) def get_destinations(self): """Returns an iterator for all destinations of the alias.""" if not self._dests: - raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr), - NO_SUCH_ALIAS) + raise AErr(_(u"The alias %r doesn't exist.") % str(self._addr), + NO_SUCH_ALIAS) return iter(self._dests) def delete(self): """Deletes the alias with all it's destinations.""" if not self._dests: - raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr), - NO_SUCH_ALIAS) + raise AErr(_(u"The alias %r doesn't exist.") % str(self._addr), + NO_SUCH_ALIAS) self.__delete() del self._dests[:] diff -r 33f727efa7c4 -r 0c8c053b451c VirtualMailManager/AliasDomain.py --- a/VirtualMailManager/AliasDomain.py Thu Feb 25 17:56:08 2010 +0000 +++ b/VirtualMailManager/AliasDomain.py Fri Feb 26 02:35:25 2010 +0000 @@ -6,7 +6,7 @@ import VirtualMailManager.constants.ERROR as ERR from VirtualMailManager import check_domainname -from VirtualMailManager.Exceptions import VMMAliasDomainException as VADE +from VirtualMailManager.errors import AliasDomainError as ADE class AliasDomain(object): """Class to manage e-mail alias domains.""" @@ -27,18 +27,18 @@ if alias is not None: self.__gid, primary = alias if primary: - raise VADE(_(u"The domain “%s” is a primary domain.") % + raise ADE(_(u"The domain “%s” is a primary domain.") % self.__name, ERR.ALIASDOMAIN_ISDOMAIN) def save(self): if self.__gid > 0: - raise VADE(_(u'The alias domain “%s” already exists.') %self.__name, + raise ADE(_(u'The alias domain “%s” already exists.') %self.__name, ERR.ALIASDOMAIN_EXISTS) if self._domain is None: - raise VADE(_(u'No destination domain specified for alias domain.'), + raise ADE(_(u'No destination domain specified for alias domain.'), ERR.ALIASDOMAIN_NO_DOMDEST) if self._domain._id < 1: - raise VADE (_(u"The target domain “%s” doesn't exist.") % + raise ADE (_(u"The target domain “%s” doesn't exist.") % self._domain._name, ERR.NO_SUCH_DOMAIN) dbc = self._dbh.cursor() dbc.execute('INSERT INTO domain_name (domainname, gid, is_primary)\ @@ -56,25 +56,25 @@ if domain is not None: return {'alias': self.__name, 'domain': domain[0]} else:# an almost unlikely case, isn't it? - raise VADE( + raise ADE( _(u'There is no primary domain for the alias domain “%s”.')\ % self.__name, ERR.NO_SUCH_DOMAIN) else: - raise VADE(_(u"The alias domain “%s” doesn't exist.") % - self.__name, ERR.NO_SUCH_ALIASDOMAIN) + raise ADE(_(u"The alias domain “%s” doesn't exist.") % self.__name, + ERR.NO_SUCH_ALIASDOMAIN) def switch(self): if self._domain is None: - raise VADE(_(u'No destination domain specified for alias domain.'), + raise ADE(_(u'No destination domain specified for alias domain.'), ERR.ALIASDOMAIN_NO_DOMDEST) if self._domain._id < 1: - raise VADE (_(u"The target domain “%s” doesn't exist.") % + raise ADE (_(u"The target domain “%s” doesn't exist.") % self._domain._name, ERR.NO_SUCH_DOMAIN) if self.__gid < 1: - raise VADE(_(u"The alias domain “%s” doesn't exist.") % - self.__name, ERR.NO_SUCH_ALIASDOMAIN) + raise ADE(_(u"The alias domain “%s” doesn't exist.") % self.__name, + ERR.NO_SUCH_ALIASDOMAIN) if self.__gid == self._domain._id: - raise VADE(_(u"The alias domain “%(alias)s” is already assigned to\ + raise ADE(_(u"The alias domain “%(alias)s” is already assigned to\ the domain “%(domain)s”.") % {'alias': self.__name, 'domain': self._domain._name}, ERR.ALIASDOMAIN_EXISTS) @@ -93,7 +93,6 @@ if dbc.rowcount > 0: self._dbh.commit() else: - raise VADE( - _(u"The alias domain “%s” doesn't exist.") % self.__name, - ERR.NO_SUCH_ALIASDOMAIN) + raise ADE(_(u"The alias domain “%s” doesn't exist.") % self.__name, + ERR.NO_SUCH_ALIASDOMAIN) diff -r 33f727efa7c4 -r 0c8c053b451c VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Thu Feb 25 17:56:08 2010 +0000 +++ b/VirtualMailManager/Config.py Fri Feb 26 02:35:25 2010 +0000 @@ -16,7 +16,7 @@ from VirtualMailManager import exec_ok, get_unicode, is_dir from VirtualMailManager.constants.ERROR import CONF_ERROR -from VirtualMailManager.Exceptions import VMMConfigException +from VirtualMailManager.errors import ConfigError _ = lambda msg: msg @@ -188,6 +188,8 @@ `LazyConfigOption.cls`. """ + # pylint: disable-msg=W0221 + # @pylint: _L A Z Y_ section, option = self._get_section_option(option) val = self._cfg[section][option].cls(value) if self._cfg[section][option].validate: @@ -206,6 +208,8 @@ configuration option. """ + # pylint: disable-msg=W0221 + # @pylint: _L A Z Y_ try: self._get_section_option(option) return True @@ -349,7 +353,7 @@ def load(self): """Loads the configuration, read only. - Raises a VMMConfigException if the configuration syntax is + Raises a ConfigError if the configuration syntax is invalid. """ @@ -357,7 +361,7 @@ self._cfg_file = open(self._cfg_filename, 'r') self.readfp(self._cfg_file) except (MissingSectionHeaderError, ParsingError), err: - raise VMMConfigException(str(err), CONF_ERROR) + raise ConfigError(str(err), CONF_ERROR) finally: if self._cfg_file and not self._cfg_file.closed: self._cfg_file.close() @@ -365,7 +369,7 @@ def check(self): """Performs a configuration check. - Raises a VMMConfigException if the check fails. + Raises a ConfigError if the check fails. """ # TODO: There are only two settings w/o defaults. @@ -379,7 +383,7 @@ errmsg.write(_(u'* Section: %s\n') % section) for option in options: errmsg.write((u' %s\n') % option) - raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) + raise ConfigError(errmsg.getvalue(), CONF_ERROR) def known_scheme(self, scheme): """Converts `scheme` to upper case and checks if is known by diff -r 33f727efa7c4 -r 0c8c053b451c VirtualMailManager/Domain.py --- a/VirtualMailManager/Domain.py Thu Feb 25 17:56:08 2010 +0000 +++ b/VirtualMailManager/Domain.py Fri Feb 26 02:35:25 2010 +0000 @@ -10,7 +10,7 @@ from VirtualMailManager.constants.ERROR import \ ACCOUNT_AND_ALIAS_PRESENT, ACCOUNT_PRESENT, ALIAS_PRESENT, \ DOMAIN_ALIAS_EXISTS, DOMAIN_EXISTS, NO_SUCH_DOMAIN |
|
From: <nev...@us...> - 2010-02-25 17:56:30
|
details: http://hg.localdomain.org/vmm/rev/33f727efa7c4 changeset: 215:33f727efa7c4 user: Pascal Volk date: Thu Feb 25 17:56:08 2010 +0000 description: PEP-8-ified the work of the last days. Renamed methods in class Alias: addDestination() -> add_destination() delDestination() -> del_destination() getDestinations() -> get_destinations() Renamed methods in class Relocated: setDestination() -> set_destination() getInfo() -> get_info() Renamed VMM/constants/VERSION.py -> VMM/constants/version.py Adjusted relevant parts of the documentation. diffstat: VirtualMailManager/Alias.py | 14 +- VirtualMailManager/Config.py | 193 ++++++++++++++++++------------- VirtualMailManager/EmailAddress.py | 2 +- VirtualMailManager/Handler.py | 10 +- VirtualMailManager/Relocated.py | 14 +- VirtualMailManager/__init__.py | 37 +++-- VirtualMailManager/cli/Config.py | 10 +- VirtualMailManager/cli/__init__.py | 8 +- VirtualMailManager/constants/VERSION.py | 11 - VirtualMailManager/constants/version.py | 17 ++ doc/source/vmm.rst | 12 - doc/source/vmm_config.rst | 8 +- doc/source/vmm_relocated.rst | 8 +- 13 files changed, 189 insertions(+), 155 deletions(-) diffs (truncated from 803 to 300 lines): diff -r 84e6e898e6c5 -r 33f727efa7c4 VirtualMailManager/Alias.py --- a/VirtualMailManager/Alias.py Wed Feb 24 05:48:15 2010 +0000 +++ b/VirtualMailManager/Alias.py Thu Feb 25 17:56:08 2010 +0000 @@ -68,9 +68,11 @@ ALIAS_EXCEEDS_EXPANSION_LIMIT) def __delete(self, destination=None): - """Deletes a destination from the alias, if ``destination`` is not - ``None``. If ``destination`` is None, the alias with all it's - destination addresses will be deleted.""" + """Deletes a destination from the alias, if ``destination`` is + not ``None``. If ``destination`` is None, the alias with all + it's destination addresses will be deleted. + + """ dbc = self._dbh.cursor() if not destination: dbc.execute("DELETE FROM alias WHERE gid=%s AND address=%s", @@ -87,7 +89,7 @@ """Returns the number of destinations of the alias.""" return len(self._dests) - def addDestination(self, destination, expansion_limit): + def add_destination(self, destination, expansion_limit): """Adds the ``destination`` `EmailAddress` to the alias.""" assert isinstance(destination, EmailAddress) if self._addr == destination: @@ -107,7 +109,7 @@ dbc.close() self._dests.append(destination) - def delDestination(self, destination): + def del_destination(self, destination): """Deletes the specified ``destination`` address from the alias.""" assert isinstance(destination, EmailAddress) if not self._dests: @@ -121,7 +123,7 @@ self.__delete(destination) self._dests.remove(destination) - def getDestinations(self): + def get_destinations(self): """Returns an iterator for all destinations of the alias.""" if not self._dests: raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr), diff -r 84e6e898e6c5 -r 33f727efa7c4 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Wed Feb 24 05:48:15 2010 +0000 +++ b/VirtualMailManager/Config.py Thu Feb 25 17:56:08 2010 +0000 @@ -19,6 +19,9 @@ from VirtualMailManager.Exceptions import VMMConfigException +_ = lambda msg: msg + + class BadOptionError(Error): """Raised when a option isn't in the format 'section.option'.""" pass @@ -50,20 +53,21 @@ `LazyConfig._cfg['sectionname']['optionname'].default`, if the option is not configured in a ini-like configuration file. - `set()` differs from `RawConfigParser`'s `set()` method. `set()` takes - the `section` and `option` arguments combined to a single string in the - form "section.option". + `set()` differs from `RawConfigParser`'s `set()` method. `set()` + takes the `section` and `option` arguments combined to a single + string in the form "section.option". + """ def __init__(self): RawConfigParser.__init__(self) self._modified = False + # sample _cfg dict. Create your own in your derived class. self._cfg = { 'sectionname': { - 'optionname': LazyConfigOption(int, 1, self.getint) + 'optionname': LazyConfigOption(int, 1, self.getint), } } - """sample _cfg dictionary. Create your own in your derived class.""" def bool_new(self, value): """Converts the string `value` into a `bool` and returns it. @@ -82,35 +86,38 @@ get_unicode(value)) def getboolean(self, section, option): - """Returns the boolean value of the option, in the given section. + """Returns the boolean value of the option, in the given + section. For a boolean True, the value must be set to '1', 'on', 'yes', 'true' or True. For a boolean False, the value must set to '0', 'off', 'no', 'false' or False. - If the option has another value assigned this method will raise a - ValueError. + If the option has another value assigned this method will raise + a ValueError. + """ # if the setting was modified it may be still a boolean value lets see tmp = self.get(section, option) if isinstance(tmp, bool): return tmp if not tmp.lower() in self._boolean_states: - raise ValueError, 'Not a boolean: %s' % tmp + raise ValueError('Not a boolean: %s' % tmp) return self._boolean_states[tmp.lower()] def _get_section_option(self, section_option): - """splits ``section_option`` (section\ **.**\ option) in two parts - and returns them as list ``[section, option]``, if: + """splits ``section_option`` (section.option) in two parts and + returns them as list ``[section, option]``, if: - * it likes the format of ``section_option`` - * the ``section`` is known - * the ``option`` is known + * it likes the format of ``section_option`` + * the ``section`` is known + * the ``option`` is known Else one of the following exceptions will be thrown: - * `BadOptionError` - * `NoSectionError` - * `NoOptionError` + * `BadOptionError` + * `NoSectionError` + * `NoOptionError` + """ sect_opt = section_option.lower().split('.') # TODO: cache it @@ -125,22 +132,24 @@ return sect_opt def items(self, section): - """returns an iterable that returns key, value ``tuples`` from the - given ``section``.""" + """returns an iterable that returns key, value ``tuples`` from + the given ``section``. + + """ if section in self._sections:# check if the section was parsed - d2 = self._sections[section] + sect = self._sections[section] elif not section in self._cfg: raise NoSectionError(section) else: return ((k, self._cfg[section][k].default) \ for k in self._cfg[section].iterkeys()) # still here? Get defaults and merge defaults with configured setting - d = dict((k, self._cfg[section][k].default) \ - for k in self._cfg[section].iterkeys()) - d.update(d2) - if '__name__' in d: - del d['__name__'] - return d.iteritems() + defaults = dict((k, self._cfg[section][k].default) \ + for k in self._cfg[section].iterkeys()) + defaults.update(sect) + if '__name__' in defaults: + del defaults['__name__'] + return defaults.iteritems() def dget(self, option): """Returns the value of the `option`. @@ -152,11 +161,11 @@ Arguments: `option` : string - the configuration option in the form - "``section``\ **.**\ ``option``" + the configuration option in the form "section.option" Throws a `NoDefaultError`, if no default value was passed to `LazyConfigOption.__init__()` for the `option`. + """ section, option = self._get_section_option(option) try: @@ -176,7 +185,9 @@ """Set the `value` of the `option`. Throws a `ValueError` if `value` couldn't be converted using - `LazyConfigOption.cls`""" + `LazyConfigOption.cls`. + + """ section, option = self._get_section_option(option) val = self._cfg[section][option].cls(value) if self._cfg[section][option].validate: @@ -191,8 +202,10 @@ return section.lower() in self._cfg def has_option(self, option): - """Checks if the option (section.option) is a known configuration - option.""" + """Checks if the option (section.option) is a known + configuration option. + + """ try: self._get_section_option(option) return True @@ -210,6 +223,7 @@ `LazyConfigOption` instances are required by `LazyConfig` instances, and instances of classes derived from `LazyConfig`, like the `Config` class. + """ __slots__ = ('__cls', '__default', '__getter', '__validate') @@ -221,14 +235,15 @@ `cls` : type The class/type of the option's value `default` - Default value of the option. Use ``None`` if the option should not - have a default value. + Default value of the option. Use ``None`` if the option should + not have a default value. `getter` : callable - A method's name of `RawConfigParser` and derived classes, to get a - option's value, e.g. `self.getint`. + A method's name of `RawConfigParser` and derived classes, to + get a option's value, e.g. `self.getint`. `validate` : NoneType or a callable - None or any method, that takes one argument, in order to check the - value, when `LazyConfig.set()` is called. + None or any method, that takes one argument, in order to + check the value, when `LazyConfig.set()` is called. + """ self.__cls = cls if not default is None:# enforce the type of the default value @@ -246,7 +261,10 @@ @property def cls(self): - """The class of the option's value e.g. `str`, `unicode` or `bool`""" + """The class of the option's value e.g. `str`, `unicode` or + `bool`. + + """ return self.__cls @property @@ -275,10 +293,11 @@ `filename` : str path to the configuration file + """ LazyConfig.__init__(self) - self._cfgFileName = filename - self._cfgFile = None + self._cfg_filename = filename + self._cfg_file = None self.__missing = {} LCO = LazyConfigOption @@ -286,75 +305,76 @@ self._cfg = { 'account': { 'delete_directory': LCO(bool_t, False, self.getboolean), - 'directory_mode': LCO(int, 448, self.getint), - 'disk_usage': LCO(bool_t, False, self.getboolean), - 'password_length': LCO(int, 8, self.getint), - 'random_password': LCO(bool_t, False, self.getboolean), - 'imap' : LCO(bool_t, True, self.getboolean), - 'pop3' : LCO(bool_t, True, self.getboolean), - 'sieve': LCO(bool_t, True, self.getboolean), - 'smtp' : LCO(bool_t, True, self.getboolean), + 'directory_mode': LCO(int, 448, self.getint), + 'disk_usage': LCO(bool_t, False, self.getboolean), + 'password_length': LCO(int, 8, self.getint), + 'random_password': LCO(bool_t, False, self.getboolean), + 'imap': LCO(bool_t, True, self.getboolean), + 'pop3': LCO(bool_t, True, self.getboolean), + 'sieve': LCO(bool_t, True, self.getboolean), + 'smtp': LCO(bool_t, True, self.getboolean), }, 'bin': { - 'dovecotpw': LCO(str, '/usr/sbin/dovecotpw', self.get, exec_ok), - 'du': LCO(str, '/usr/bin/du', self.get, exec_ok), - 'postconf': LCO(str, '/usr/sbin/postconf', self.get, exec_ok), + 'dovecotpw': LCO(str, '/usr/sbin/dovecotpw', self.get, + exec_ok), + 'du': LCO(str, '/usr/bin/du', self.get, exec_ok), + 'postconf': LCO(str, '/usr/sbin/postconf', self.get, exec_ok), }, 'database': { 'host': LCO(str, 'localhost', self.get), - 'name': LCO(str, 'mailsys', self.get), - 'pass': LCO(str, None, self.get), - 'user': LCO(str, None, self.get), + 'name': LCO(str, 'mailsys', self.get), |
|
From: <nev...@us...> - 2010-02-24 05:48:29
|
details: http://hg.localdomain.org/vmm/rev/84e6e898e6c5 changeset: 214:84e6e898e6c5 user: Pascal Volk date: Wed Feb 24 05:48:15 2010 +0000 description: VMM/Exceptions: use the inherited CTor in all VMM*Exception classes. diffstat: VirtualMailManager/Exceptions.py | 56 ++++++++++++++++++++++----------------- 1 files changed, 31 insertions(+), 25 deletions(-) diffs (103 lines): diff -r 1a9fee6b93bc -r 84e6e898e6c5 VirtualMailManager/Exceptions.py --- a/VirtualMailManager/Exceptions.py Wed Feb 24 05:04:30 2010 +0000 +++ b/VirtualMailManager/Exceptions.py Wed Feb 24 05:48:15 2010 +0000 @@ -2,10 +2,16 @@ # Copyright (c) 2007 - 2010, Pascal Volk # See COPYING for distribution information. -"""Exception classes for Virtual Mail Manager""" +""" + VirtualMailManager.Exceptions + + VMM's Exception classes +""" + class VMMException(Exception): - """Exception class for VirtualMailManager exceptions""" + """Exception base class for VirtualMailManager exceptions""" + def __init__(self, msg, code): Exception.__init__(self, msg) self._code = int(code) @@ -21,57 +27,57 @@ """Returns the numeric exception error code.""" return self._code + class VMMConfigException(VMMException): - """Exception class for Configurtion exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + """Exception class for configuration exceptions""" + pass + class VMMPermException(VMMException): """Exception class for permissions exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMNotRootException(VMMException): """Exception class for non-root exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMDomainException(VMMException): """Exception class for Domain exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMAliasDomainException(VMMException): """Exception class for AliasDomain exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMAccountException(VMMException): """Exception class for Account exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMAliasException(VMMException): """Exception class for Alias exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMEmailAddressException(VMMException): """Exception class for EmailAddress exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMMailLocationException(VMMException): """Exception class for MailLocation exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMRelocatedException(VMMException): """Exception class for Relocated exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass + class VMMTransportException(VMMException): """Exception class for Transport exceptions""" - def __init__(self, msg, code): - VMMException.__init__(self, msg, code) + pass |
|
From: <nev...@us...> - 2010-02-24 05:04:45
|
details: http://hg.localdomain.org/vmm/rev/1a9fee6b93bc changeset: 213:1a9fee6b93bc user: Pascal Volk date: Wed Feb 24 05:04:30 2010 +0000 description: VMM:/{Alias,EmailAddress,Relocated}: use assertions for argument checks. diffstat: VirtualMailManager/Alias.py | 9 +++------ VirtualMailManager/EmailAddress.py | 4 +--- VirtualMailManager/Relocated.py | 6 ++---- 3 files changed, 6 insertions(+), 13 deletions(-) diffs (70 lines): diff -r 77ac6f572855 -r 1a9fee6b93bc VirtualMailManager/Alias.py --- a/VirtualMailManager/Alias.py Wed Feb 24 04:01:48 2010 +0000 +++ b/VirtualMailManager/Alias.py Wed Feb 24 05:04:30 2010 +0000 @@ -23,8 +23,7 @@ __slots__ = ('_addr', '_dests', '_gid', '_dbh') def __init__(self, dbh, address): - if not isinstance(address, EmailAddress): - raise TypeError("Argument 'address' is not an EmailAddress") + assert isinstance(address, EmailAddress) self._addr = address self._dbh = dbh self._gid = get_gid(self._dbh, self._addr.domainname) @@ -90,8 +89,7 @@ def addDestination(self, destination, expansion_limit): """Adds the ``destination`` `EmailAddress` to the alias.""" - if not isinstance(destination, EmailAddress): - raise TypeError("Argument 'destination' is not an EmailAddress") + assert isinstance(destination, EmailAddress) if self._addr == destination: raise VMMAE(_(u"Address and destination are identical."), ALIAS_ADDR_DEST_IDENTICAL) @@ -111,8 +109,7 @@ def delDestination(self, destination): """Deletes the specified ``destination`` address from the alias.""" - if not isinstance(destination, EmailAddress): - raise TypeError("Argument 'destination' is not an EmailAddress") + assert isinstance(destination, EmailAddress) if not self._dests: raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr), NO_SUCH_ALIAS) diff -r 77ac6f572855 -r 1a9fee6b93bc VirtualMailManager/EmailAddress.py --- a/VirtualMailManager/EmailAddress.py Wed Feb 24 04:01:48 2010 +0000 +++ b/VirtualMailManager/EmailAddress.py Wed Feb 24 05:04:30 2010 +0000 @@ -23,9 +23,7 @@ def __init__(self, address): """Creates a new instance from the string/unicode ``address``.""" - if not isinstance(address, basestring): - raise TypeError('address is not a str/unicode object: %r' % - address) + assert isinstance(address, basestring) self._localpart = None self._domainname = None self._chk_address(address) diff -r 77ac6f572855 -r 1a9fee6b93bc VirtualMailManager/Relocated.py --- a/VirtualMailManager/Relocated.py Wed Feb 24 04:01:48 2010 +0000 +++ b/VirtualMailManager/Relocated.py Wed Feb 24 05:04:30 2010 +0000 @@ -28,8 +28,7 @@ Use `setDestination()` to set/update the new address, where the user has moved to.""" - if not isinstance(address, EmailAddress): - raise TypeError("Argument 'address' is not an EmailAddress") + assert isinstance(address, EmailAddress) self._addr = address self._dbh = dbh self._gid = get_gid(self._dbh, self._addr.domainname) @@ -52,8 +51,7 @@ def setDestination(self, destination): """Sets/updates the new address of the relocated user.""" update = False - if not isinstance(destination, EmailAddress): - raise TypeError("Argument 'destination' is not an EmailAddress") + assert isinstance(destination, EmailAddress) if self._addr == destination: raise VMMRE(_(u'Address and destination are identical.'), RELOCATED_ADDR_DEST_IDENTICAL) |
|
From: <nev...@us...> - 2010-02-24 04:03:31
|
details: http://hg.localdomain.org/vmm/rev/77ac6f572855 changeset: 212:77ac6f572855 user: Pascal Volk date: Wed Feb 24 04:01:48 2010 +0000 description: doc: extended documentation. diffstat: doc/source/conf.py | 4 +- doc/source/index.rst | 4 + doc/source/vmm.rst | 48 ++++---- doc/source/vmm_constants_error.rst | 213 +++++++++++++++++++++++++++++++++++++ doc/source/vmm_emailaddress.rst | 61 ++++++++++ doc/source/vmm_exceptions.rst | 118 ++++++++++++++++++++ doc/source/vmm_relocated.rst | 61 ++++++++++ 7 files changed, 484 insertions(+), 25 deletions(-) diffs (truncated from 557 to 300 lines): diff -r 0b129678cfe1 -r 77ac6f572855 doc/source/conf.py --- a/doc/source/conf.py Mon Feb 22 10:44:13 2010 +0000 +++ b/doc/source/conf.py Wed Feb 24 04:01:48 2010 +0000 @@ -22,7 +22,7 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.intersphinx'] +extensions = ['sphinx.ext.intersphinx', 'sphinx.ext.todo'] # Add any paths that contain templates here, relative to this directory. templates_path = ['.templates'] @@ -197,3 +197,5 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'http://docs.python.org/': None} + +todo_include_todos = True diff -r 0b129678cfe1 -r 77ac6f572855 doc/source/index.rst --- a/doc/source/index.rst Mon Feb 22 10:44:13 2010 +0000 +++ b/doc/source/index.rst Wed Feb 24 04:01:48 2010 +0000 @@ -14,6 +14,10 @@ vmm.rst vmm_config.rst + vmm_emailaddress.rst + vmm_relocated.rst + vmm_exceptions.rst + vmm_constants_error.rst Indices and tables ================== diff -r 0b129678cfe1 -r 77ac6f572855 doc/source/vmm.rst --- a/doc/source/vmm.rst Mon Feb 22 10:44:13 2010 +0000 +++ b/doc/source/vmm.rst Wed Feb 24 04:01:48 2010 +0000 @@ -118,28 +118,28 @@ Examples -------- - >>> from VirtualMailManager import * - >>> ace2idna('xn--pypal-4ve.tld') - u'p\u0430ypal.tld' - >>> idn2ascii(u'öko.de') - 'xn--ko-eka.de' - >>> check_domainname(u'pаypal.tld') - 'xn--pypal-4ve.tld' - >>> check_localpart('john.doe') - 'john.doe' - >>> exec_ok('usr/bin/vim') - Traceback (most recent call last): - File "<stdin>", line 1, in <module> - File "./VirtualMailManager/__init__.py", line 93, in exec_ok - NO_SUCH_BINARY) - VirtualMailManager.Exceptions.VMMException: 'usr/bin/vim' is not a file - >>> exec_ok('/usr/bin/vim') - '/usr/bin/vim' - >>> expand_path('.') - '/home/user/hg/vmm' - >>> get_unicode('hello world') - u'hello world' - >>> is_dir('~/hg') - '/home/user/hg' - >>> + >>> from VirtualMailManager import * + >>> ace2idna('xn--pypal-4ve.tld') + u'p\u0430ypal.tld' + >>> idn2ascii(u'öko.de') + 'xn--ko-eka.de' + >>> check_domainname(u'pаypal.tld') + 'xn--pypal-4ve.tld' + >>> check_localpart('john.doe') + 'john.doe' + >>> exec_ok('usr/bin/vim') + Traceback (most recent call last): + File "<stdin>", line 1, in <module> + File "./VirtualMailManager/__init__.py", line 93, in exec_ok + NO_SUCH_BINARY) + VirtualMailManager.Exceptions.VMMException: 'usr/bin/vim' is not a file + >>> exec_ok('/usr/bin/vim') + '/usr/bin/vim' + >>> expand_path('.') + '/home/user/hg/vmm' + >>> get_unicode('hello world') + u'hello world' + >>> is_dir('~/hg') + '/home/user/hg' + >>> diff -r 0b129678cfe1 -r 77ac6f572855 doc/source/vmm_constants_error.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/source/vmm_constants_error.rst Wed Feb 24 04:01:48 2010 +0000 @@ -0,0 +1,213 @@ +:mod:`VirtualMailManager.constants.ERROR` --- Error codes +========================================================= + +.. module:: VirtualMailManager.constants.ERROR + :synopsis: VirtualMailManager's error codes + +.. moduleauthor:: Pascal Volk <nev...@us...> + +.. toctree:: + :maxdepth: 2 + +Error codes, used by all :mod:`VirtualMailManager.Exceptions`. + +.. data:: ACCOUNT_AND_ALIAS_PRESENT + + Can't delete the Domain - there are accounts and aliases assigned + +.. data:: ACCOUNT_EXISTS + + The Account exists already + +.. data:: ACCOUNT_PRESENT + + Can't delete the Domain - there are accounts + +.. data:: ALIASDOMAIN_EXISTS + + Can't save/switch the destination of the AliasDomain - old and new destination + are the same. + +.. data:: ALIASDOMAIN_ISDOMAIN + + Can't create AliasDomain - there is already a Domain with the given name + + .. todo:: Move the related check to the Handler class + +.. data:: ALIASDOMAIN_NO_DOMDEST + + Can't save/switch the destination of an AliasDomain if the destination was + omitted + +.. data:: ALIAS_ADDR_DEST_IDENTICAL + + The alias address and its destination are the same + +.. data:: ALIAS_EXCEEDS_EXPANSION_LIMIT + + The Alias has reached or exceeds its expansion limit + +.. data:: ALIAS_EXISTS + + Alias with the given destination exists already + +.. data:: ALIAS_MISSING_DEST + + obsolete? + +.. data:: ALIAS_PRESENT + + Can't delete Domain or Account - there are aliases assigned + +.. data:: CONF_ERROR + + Syntax error in the configuration file or missing settings w/o a default value + +.. data:: CONF_NOFILE + + The configuration file couldn't be found + +.. data:: CONF_NOPERM + + The user's permissions are insufficient + +.. data:: CONF_WRONGPERM + + Configuration file has the wrong access mode + +.. data:: DATABASE_ERROR + + A database error occurred + +.. data:: DOMAINDIR_GROUP_MISMATCH + + Domain directory is owned by the wrong group + +.. data:: DOMAIN_ALIAS_EXISTS + + Can't create Domain - there is already an AliasDomain with the same name + + .. todo:: Move the related check to the Handler class + +.. data:: DOMAIN_EXISTS + + The Domain is already available in the database + +.. data:: DOMAIN_INVALID + + The domain name is invalid + +.. data:: DOMAIN_NO_NAME + + Missing the domain name + +.. data:: DOMAIN_TOO_LONG + + The length of domain is > 255 + +.. data:: FOUND_DOTS_IN_PATH + + Can't delete directory with ``.`` or ``..`` in path + + .. todo:: check if we can solve this issue with expand_path() + +.. data:: INVALID_ADDRESS + + The specified value doesn't look like a e-mail address + +.. data:: INVALID_AGUMENT + + The given argument is invalid + +.. data:: INVALID_OPTION + + The given option is invalid + +.. data:: INVALID_SECTION + + The section is not a known configuration section + +.. data:: LOCALPART_INVALID + + The local-part of an e-mail address was omitted or is invalid + +.. data:: LOCALPART_TOO_LONG + + The local-part (w/o a extension) is too long (> 64) + +.. data:: MAILDIR_PERM_MISMATCH + + The Maildir is owned by the wrong user/group + +.. data:: MAILLOCATION_INIT + + Can't create a new MailLocation instance + +.. data:: NOT_EXECUTABLE + + The binary is not executable + +.. data:: NO_SUCH_ACCOUNT + + No Account with the given e-mail address + +.. data:: NO_SUCH_ALIAS + + No Alias with the given e-mail address + +.. data:: NO_SUCH_ALIASDOMAIN + + The given domain is not an AliasDomain + +.. data:: NO_SUCH_BINARY + + Can't find the file at the specified location + +.. data:: NO_SUCH_DIRECTORY + + There is no directory with the given path + +.. data:: NO_SUCH_DOMAIN + + No Domain with the given name + +.. data:: NO_SUCH_RELOCATED + + There is no Relocated user with the given e-mail address + +.. data:: RELOCATED_ADDR_DEST_IDENTICAL + + The e-mail address of the Relocated user an its destination are the same + +.. data:: RELOCATED_EXISTS + + Can't create Account or Alias, there is already a Relocated user with the + given e-mail address + +.. data:: RELOCATED_MISSING_DEST + + obsolete? + +.. data:: TRANSPORT_INIT + + Can't initialize a new Transport instance + +.. data:: UNKNOWN_MAILLOCATION_ID + + There is no MailLocation entry with the given ID + +.. data:: UNKNOWN_SERVICE + + The specified service is unknown + +.. data:: UNKNOWN_TRANSPORT_ID + + There is no Transport entry with the given ID + +.. data:: VMM_ERROR + |
|
From: <nev...@us...> - 2010-02-22 10:44:26
|
details: http://hg.localdomain.org/vmm/rev/0b129678cfe1 changeset: 211:0b129678cfe1 user: Pascal Volk date: Mon Feb 22 10:44:13 2010 +0000 description: VMM/Config: LazyConfig.getboolean(), convert the value in our getboolean. So RawConfigParser hasn't to do the whole get() stuff again. diffstat: VirtualMailManager/Config.py | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diffs (14 lines): diff -r 3ddb735ec9d2 -r 0b129678cfe1 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Mon Feb 22 10:25:48 2010 +0000 +++ b/VirtualMailManager/Config.py Mon Feb 22 10:44:13 2010 +0000 @@ -94,7 +94,9 @@ tmp = self.get(section, option) if isinstance(tmp, bool): return tmp - return RawConfigParser.getboolean(self, section, option) + if not tmp.lower() in self._boolean_states: + raise ValueError, 'Not a boolean: %s' % tmp + return self._boolean_states[tmp.lower()] def _get_section_option(self, section_option): """splits ``section_option`` (section\ **.**\ option) in two parts |
|
From: <nev...@us...> - 2010-02-22 10:26:04
|
details: http://hg.localdomain.org/vmm/rev/3ddb735ec9d2 changeset: 210:3ddb735ec9d2 user: Pascal Volk date: Mon Feb 22 10:25:48 2010 +0000 description: Added 'doc/build' to the ignored files. diffstat: .hgignore | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diffs (8 lines): diff -r c705a9e38962 -r 3ddb735ec9d2 .hgignore --- a/.hgignore Mon Feb 22 10:20:46 2010 +0000 +++ b/.hgignore Mon Feb 22 10:25:48 2010 +0000 @@ -5,3 +5,4 @@ *.py? .*.swp .swp +doc/build |
|
From: <nev...@us...> - 2010-02-22 10:21:04
|
details: http://hg.localdomain.org/vmm/rev/c705a9e38962 changeset: 209:c705a9e38962 user: Pascal Volk date: Mon Feb 22 10:20:46 2010 +0000 description: VMM{/Config}: reduced docstrings. Added doc to the repository. diffstat: VirtualMailManager/Config.py | 112 ++++++---------- VirtualMailManager/__init__.py | 26 ++- doc/Makefile | 89 +++++++++++++ doc/source/conf.py | 199 +++++++++++++++++++++++++++++ doc/source/index.rst | 24 +++ doc/source/vmm.rst | 145 +++++++++++++++++++++ doc/source/vmm_config.rst | 275 +++++++++++++++++++++++++++++++++++++++++ 7 files changed, 788 insertions(+), 82 deletions(-) diffs (truncated from 1028 to 300 lines): diff -r efa1327b721f -r c705a9e38962 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Mon Feb 22 04:26:52 2010 +0000 +++ b/VirtualMailManager/Config.py Mon Feb 22 10:20:46 2010 +0000 @@ -6,33 +6,6 @@ VirtualMailManager.Config VMM's configuration module for simplified configuration access. - -This module defines a few classes: - -``LazyConfig`` - This class provides the following additonal methods - - * `LazyConfig.pget()` - polymorphic getter which returns the value with the appropriate - type. - * `LazyConfig.dget()` - like *pget()*, but checks additonal for default values in - `LazyConfig._cfg`. - * `LazyConfig.set()` - like `RawConfigParser.set()`, but converts the new value to the - appropriate type/class and optional validates the new value. - * `LazyConfig.bool_new()` - converts data from raw_input into boolean values. - * `LazyConfig.get_boolean()` - like `RawConfigParser.getboolean()`, but doesn't fail on real - `bool` values. - -``Config`` - The Config class used by vmm. - -``LazyConfigOption`` - The class for the configuration objects in the ``Config`` class' - ``_cfg`` dictionary. """ @@ -69,19 +42,17 @@ There are two additional getters: - `LazyConfig.pget()` - The polymorphic getter, which returns a option's value with the - appropriate type. - `LazyConfig.dget()` - Like `LazyConfig.pget()`, but returns the option's default, from - `LazyConfig._cfg['sectionname']['optionname'].default`, if the - option is not configured in a ini-like configuration file. + `pget()` + The polymorphic getter, which returns a option's value with the + appropriate type. + `dget()` + Like `LazyConfig.pget()`, but returns the option's default, from + `LazyConfig._cfg['sectionname']['optionname'].default`, if the + option is not configured in a ini-like configuration file. - - `LazyConfig.set()` differs from ``RawConfigParser``'s ``set()`` method. - ``LazyConfig.set()`` takes the ``section`` and ``option`` arguments - combined to a single string in the form - "``section``\ **.**\ ``option``". + `set()` differs from `RawConfigParser`'s `set()` method. `set()` takes + the `section` and `option` arguments combined to a single string in the + form "section.option". """ def __init__(self): @@ -97,10 +68,10 @@ def bool_new(self, value): """Converts the string `value` into a `bool` and returns it. - | '1', 'on', 'yes' and 'true' will become ``True`` - | '0', 'off', 'no' and 'false' will become ``False`` + | '1', 'on', 'yes' and 'true' will become `True` + | '0', 'off', 'no' and 'false' will become `False` - Throws a `ConfigValueError` for all other values, except ``bool``\ s. + Throws a `ConfigValueError` for all other values, except bools. """ if isinstance(value, bool): return value @@ -200,10 +171,10 @@ return self._cfg[section][option].getter(section, option) def set(self, option, value): - """Set the value of an option. + """Set the `value` of the `option`. - Throws a ``ValueError`` if `value` couldn't be converted to - ``LazyConfigOption.cls``""" + Throws a `ValueError` if `value` couldn't be converted using + `LazyConfigOption.cls`""" section, option = self._get_section_option(option) val = self._cfg[section][option].cls(value) if self._cfg[section][option].validate: @@ -214,12 +185,12 @@ self._modified = True def has_section(self, section): - """Checks if ``section`` is a known configuration section.""" + """Checks if `section` is a known configuration section.""" return section.lower() in self._cfg def has_option(self, option): - """Checks if the option (section\ **.**\ option) is a known - configuration option.""" + """Checks if the option (section.option) is a known configuration + option.""" try: self._get_section_option(option) return True @@ -234,28 +205,28 @@ class LazyConfigOption(object): """A simple container class for configuration settings. - ``LazyConfigOption`` instances are required by `LazyConfig` instances, - and instances of classes derived from ``LazyConfig``, like the - `Config` class. + `LazyConfigOption` instances are required by `LazyConfig` instances, + and instances of classes derived from `LazyConfig`, like the + `Config` class. """ __slots__ = ('__cls', '__default', '__getter', '__validate') def __init__(self, cls, default, getter, validate=None): - """Creates a new ``LazyConfigOption`` instance. + """Creates a new `LazyConfigOption` instance. Arguments: - ``cls`` : type - The class/type of the option's value - ``default`` - Default value of the option. Use ``None`` if the option should - not have a default value. - ``getter`` : callable - A method's name of `RawConfigParser` and derived classes, to - get a option's value, e.g. `self.getint`. - ``validate`` : NoneType or a callable - None or any method, that takes one argument, in order to check - the value, when `LazyConfig.set()` is called. + `cls` : type + The class/type of the option's value + `default` + Default value of the option. Use ``None`` if the option should not + have a default value. + `getter` : callable + A method's name of `RawConfigParser` and derived classes, to get a + option's value, e.g. `self.getint`. + `validate` : NoneType or a callable + None or any method, that takes one argument, in order to check the + value, when `LazyConfig.set()` is called. """ self.__cls = cls if not default is None:# enforce the type of the default value @@ -278,7 +249,7 @@ @property def default(self): - """The option's default value, may be ``None``""" + """The option's default value, may be `None`""" return self.__default @property @@ -300,8 +271,8 @@ Arguments: - ``filename`` - path to the configuration file + `filename` : str + path to the configuration file """ LazyConfig.__init__(self) self._cfgFileName = filename @@ -389,7 +360,7 @@ raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) def known_scheme(self, scheme): - """Converts ``scheme`` to upper case and checks if is known by + """Converts `scheme` to upper case and checks if is known by Dovecot (listed in VirtualMailManager.SCHEMES). Throws a `ConfigValueError` if the scheme is not listed in @@ -399,15 +370,14 @@ # TODO: VMM.SCHEMES def unicode(self, section, option): - """Returns the value of the ``option`` from ``section``, converted - to Unicode. - """ + """Returns the value of the `option` from `section`, converted to + Unicode.""" return get_unicode(self.get(section, option)) def __chkCfg(self): """Checks all section's options for settings w/o a default value. - Returns ``True`` if everything is fine, else ``False``.""" + Returns `True` if everything is fine, else `False`.""" errors = False for section in self._cfg.iterkeys(): missing = [] diff -r efa1327b721f -r c705a9e38962 VirtualMailManager/__init__.py --- a/VirtualMailManager/__init__.py Mon Feb 22 04:26:52 2010 +0000 +++ b/VirtualMailManager/__init__.py Mon Feb 22 10:20:46 2010 +0000 @@ -1,8 +1,12 @@ # -*- coding: UTF-8 -*- # Copyright (c) 2007 - 2010, Pascal Volk # See COPYING for distribution information. -# package initialization code -# + +""" + VirtualMailManager + + VirtualMailManager package initialization code +""" import gettext import os @@ -23,7 +27,7 @@ 'os', 're', 'locale', # version information from VERSION '__author__', '__date__', '__version__', - # error codes + # defined stuff 'ENCODING', 'ace2idna', 'check_domainname', 'check_localpart', 'exec_ok', 'expand_path', 'get_unicode', 'idn2ascii', 'is_dir', ] @@ -66,29 +70,29 @@ def is_dir(path): - """Checks if ``path`` is a directory. + """Checks if `path` is a directory. - Throws a `VMMException` if ``path`` is not a directory. + Throws a `VMMException` if `path` is not a directory. """ path = expand_path(path) if not os.path.isdir(path): - raise VMMException(_(u'“%s” is not a directory') % + raise VMMException(_(u"'%s' is not a directory") % get_unicode(path), NO_SUCH_DIRECTORY) return path def exec_ok(binary): - """Checks if the ``binary`` exists and if it is executable. + """Checks if the `binary` exists and if it is executable. - Throws a `VMMException` if the ``binary`` isn't a file or is not + Throws a `VMMException` if the `binary` isn't a file or is not executable. """ binary = expand_path(binary) if not os.path.isfile(binary): - raise VMMException(_(u'“%s” is not a file') % get_unicode(binary), + raise VMMException(_(u"'%s' is not a file") % get_unicode(binary), NO_SUCH_BINARY) if not os.access(binary, os.X_OK): - raise VMMException(_(u'File is not executable: “%s”') % + raise VMMException(_(u"File is not executable: '%s'") % get_unicode(binary), NOT_EXECUTABLE) return binary @@ -122,7 +126,7 @@ def check_localpart(localpart): - """Returns the validated local-part *localpart*. + """Returns the validated local-part `localpart`. Throws a `VMMException` if the local-part is too long or contains invalid characters. diff -r efa1327b721f -r c705a9e38962 doc/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/Makefile Mon Feb 22 10:20:46 2010 +0000 @@ -0,0 +1,89 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" |
|
From: <nev...@us...> - 2010-02-22 04:27:07
|
details: http://hg.localdomain.org/vmm/rev/efa1327b721f changeset: 208:efa1327b721f user: Pascal Volk date: Mon Feb 22 04:26:52 2010 +0000 description: VMM: removed unneeded/duplicated regular expression definitions diffstat: VirtualMailManager/EmailAddress.py | 1 - VirtualMailManager/Handler.py | 1 - VirtualMailManager/__init__.py | 1 - 3 files changed, 0 insertions(+), 3 deletions(-) diffs (33 lines): diff -r 95be8f62bc0c -r efa1327b721f VirtualMailManager/EmailAddress.py --- a/VirtualMailManager/EmailAddress.py Mon Feb 22 03:14:12 2010 +0000 +++ b/VirtualMailManager/EmailAddress.py Mon Feb 22 04:26:52 2010 +0000 @@ -14,7 +14,6 @@ from VirtualMailManager.Exceptions import VMMEmailAddressException as VMMEAE -RE_LOCALPART = """[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]""" _ = lambda msg: msg diff -r 95be8f62bc0c -r efa1327b721f VirtualMailManager/Handler.py --- a/VirtualMailManager/Handler.py Mon Feb 22 03:14:12 2010 +0000 +++ b/VirtualMailManager/Handler.py Mon Feb 22 04:26:52 2010 +0000 @@ -35,7 +35,6 @@ SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' RE_DOMAIN_SRCH = """^[a-z0-9-\.]+$""" -RE_LOCALPART = """[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]""" RE_MBOX_NAMES = """^[\x20-\x25\x27-\x7E]*$""" diff -r 95be8f62bc0c -r efa1327b721f VirtualMailManager/__init__.py --- a/VirtualMailManager/__init__.py Mon Feb 22 03:14:12 2010 +0000 +++ b/VirtualMailManager/__init__.py Mon Feb 22 04:26:52 2010 +0000 @@ -37,7 +37,6 @@ locale.setlocale(locale.LC_ALL, 'C') ENCODING = locale.nl_langinfo(locale.CODESET) -RE_ASCII_CHARS = r"^[\x20-\x7E]*$" RE_DOMAIN = r"^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$" RE_LOCALPART = r"[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]" |
|
From: <nev...@us...> - 2010-02-22 03:14:31
|
details: http://hg.localdomain.org/vmm/rev/95be8f62bc0c changeset: 207:95be8f62bc0c user: Pascal Volk date: Mon Feb 22 03:14:12 2010 +0000 description: VMM/Config: moved Config.sections() to class LazyConfig. No longer import the ENCODING from VirtualMailManager, it's no longer required in the Config module. diffstat: VirtualMailManager/Config.py | 12 ++++++------ 1 files changed, 6 insertions(+), 6 deletions(-) diffs (43 lines): diff -r da07dd944ad1 -r 95be8f62bc0c VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Sat Feb 20 17:20:52 2010 +0000 +++ b/VirtualMailManager/Config.py Mon Feb 22 03:14:12 2010 +0000 @@ -41,7 +41,7 @@ ParsingError, RawConfigParser from cStringIO import StringIO# TODO: move interactive stff to cli -from VirtualMailManager import ENCODING, exec_ok, get_unicode, is_dir +from VirtualMailManager import exec_ok, get_unicode, is_dir from VirtualMailManager.constants.ERROR import CONF_ERROR from VirtualMailManager.Exceptions import VMMConfigException @@ -226,6 +226,10 @@ except(BadOptionError, NoSectionError, NoOptionError): return False + def sections(self): + """Returns an iterator object for all configuration sections.""" + return self._cfg.iterkeys() + class LazyConfigOption(object): """A simple container class for configuration settings. @@ -384,10 +388,6 @@ errmsg.write((u' %s\n') % option) raise VMMConfigException(errmsg.getvalue(), CONF_ERROR) - def sections(self): - """Returns an iterator object for all configuration sections.""" - return self._cfg.iterkeys() - def known_scheme(self, scheme): """Converts ``scheme`` to upper case and checks if is known by Dovecot (listed in VirtualMailManager.SCHEMES). @@ -405,7 +405,7 @@ return get_unicode(self.get(section, option)) def __chkCfg(self): - """Checks all section's options for settings w/o default values. + """Checks all section's options for settings w/o a default value. Returns ``True`` if everything is fine, else ``False``.""" errors = False |
|
From: <nev...@us...> - 2010-02-20 17:21:28
|
details: http://hg.localdomain.org/vmm/rev/da07dd944ad1 changeset: 206:da07dd944ad1 user: Pascal Volk date: Sat Feb 20 17:20:52 2010 +0000 description: VMM/Config: renamed LazyConfig's get_boolean() to getboolean(). VMM/cli/Config: import required ConfigParser.RawConfigParser. diffstat: VirtualMailManager/Config.py | 40 +++++++++++++++++++++++----------------- VirtualMailManager/cli/Config.py | 1 + 2 files changed, 24 insertions(+), 17 deletions(-) diffs (79 lines): diff -r bc9726c9ad85 -r da07dd944ad1 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Sat Feb 13 04:20:09 2010 +0000 +++ b/VirtualMailManager/Config.py Sat Feb 20 17:20:52 2010 +0000 @@ -110,14 +110,20 @@ raise ConfigValueError(_(u"Not a boolean: '%s'") % get_unicode(value)) - def get_boolean(self, section, option): - # if the setting was not written to the configuration file, it may - # be still a boolean value - lets see - if self._modified: - tmp = self.get(section, option) - assert isinstance(tmp, bool), 'Oops, not a boolean: %r' % tmp + def getboolean(self, section, option): + """Returns the boolean value of the option, in the given section. + + For a boolean True, the value must be set to '1', 'on', 'yes', + 'true' or True. For a boolean False, the value must set to '0', + 'off', 'no', 'false' or False. + If the option has another value assigned this method will raise a + ValueError. + """ + # if the setting was modified it may be still a boolean value lets see + tmp = self.get(section, option) + if isinstance(tmp, bool): return tmp - return self.getboolean(section, option) + return RawConfigParser.getboolean(self, section, option) def _get_section_option(self, section_option): """splits ``section_option`` (section\ **.**\ option) in two parts @@ -302,15 +308,15 @@ bool_t = self.bool_new self._cfg = { 'account': { - 'delete_directory': LCO(bool_t, False, self.get_boolean), + 'delete_directory': LCO(bool_t, False, self.getboolean), 'directory_mode': LCO(int, 448, self.getint), - 'disk_usage': LCO(bool_t, False, self.get_boolean), + 'disk_usage': LCO(bool_t, False, self.getboolean), 'password_length': LCO(int, 8, self.getint), - 'random_password': LCO(bool_t, False, self.get_boolean), - 'imap' : LCO(bool_t, True, self.get_boolean), - 'pop3' : LCO(bool_t, True, self.get_boolean), - 'sieve': LCO(bool_t, True, self.get_boolean), - 'smtp' : LCO(bool_t, True, self.get_boolean), + 'random_password': LCO(bool_t, False, self.getboolean), + 'imap' : LCO(bool_t, True, self.getboolean), + 'pop3' : LCO(bool_t, True, self.getboolean), + 'sieve': LCO(bool_t, True, self.getboolean), + 'smtp' : LCO(bool_t, True, self.getboolean), }, 'bin': { 'dovecotpw': LCO(str, '/usr/sbin/dovecotpw', self.get, exec_ok), @@ -324,10 +330,10 @@ 'user': LCO(str, None, self.get), }, 'domain': { - 'auto_postmaster': LCO(bool_t, True, self.get_boolean), - 'delete_directory': LCO(bool_t, False, self.get_boolean), + 'auto_postmaster': LCO(bool_t, True, self.getboolean), + 'delete_directory': LCO(bool_t, False, self.getboolean), 'directory_mode': LCO(int, 504, self.getint), - 'force_deletion': LCO(bool_t, False, self.get_boolean), + 'force_deletion': LCO(bool_t, False, self.getboolean), }, 'maildir': { 'folders': LCO(str, 'Drafts:Sent:Templates:Trash', self.get), diff -r bc9726c9ad85 -r da07dd944ad1 VirtualMailManager/cli/Config.py --- a/VirtualMailManager/cli/Config.py Sat Feb 13 04:20:09 2010 +0000 +++ b/VirtualMailManager/cli/Config.py Sat Feb 20 17:20:52 2010 +0000 @@ -8,6 +8,7 @@ Adds some interactive stuff to the Config class. """ +from ConfigParser import RawConfigParser from shutil import copy2 from VirtualMailManager import ENCODING |
|
From: <nev...@us...> - 2010-02-13 04:20:35
|
details: http://hg.localdomain.org/vmm/rev/bc9726c9ad85 changeset: 205:bc9726c9ad85 user: Pascal Volk date: Sat Feb 13 04:20:09 2010 +0000 description: VMM/cli: added __init__.py to the repository. diffstat: VirtualMailManager/cli/__init__.py | 105 +++++++++++++++++++++++++++++++++++++ 1 files changed, 105 insertions(+), 0 deletions(-) diffs (109 lines): diff -r 83938336c518 -r bc9726c9ad85 VirtualMailManager/cli/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualMailManager/cli/__init__.py Sat Feb 13 04:20:09 2010 +0000 @@ -0,0 +1,105 @@ +# -*- coding: UTF-8 -*- +# Copyright (c) 2010, Pascal Volk +# See COPYING for distribution information. + +""" + VirtualMailManager.cli + + VirtualMailManager's command line interface. +""" + +from cStringIO import StringIO +from getpass import getpass +from textwrap import TextWrapper + +import VirtualMailManager + + +__all__ = ('get_winsize', 'read_pass', 'string_io', 'w_err', 'w_std') + +os = VirtualMailManager.os +_std_write = os.sys.stdout.write +_err_write = os.sys.stderr.write + + +def w_std(*args): + """Writes each arg of `args`, encoded in the current ENCODING, to stdout + and appends a newline.""" + for arg in args: + _std_write(arg.encode(VirtualMailManager.ENCODING, 'replace')) + _std_write('\n') + + +def w_err(code, *args): + """Writes each arg of `args`, encoded in the current ENCODING, to stderr + and appends a newline. + + This function additional interrupts the program execution and uses + `code` system exit status.""" + for arg in args: + _err_write(arg.encode(VirtualMailManager.ENCODING, 'replace')) + _err_write('\n') + os.sys.exit(code) + + +def get_winsize(): + """Returns a tuple of integers ``(ws_row, ws_col)`` with the height and + width of the terminal.""" + fd = None + for dev in (os.sys.stdout, os.sys.stderr, os.sys.stdin): + if hasattr(dev, 'fileno') and os.isatty(dev.fileno()): + fd = dev.fileno() + break + if fd is None:# everything seems to be redirected + # fall back to environment or assume some common defaults + ws_row, ws_col = 24, 80 + try: + ws_col = int(os.environ.get('COLUMNS', 80)) + ws_row = int(os.environ.get('LINES', 24)) + except ValueError: + pass + return ws_row, ws_col + + from array import array + from fcntl import ioctl + from termios import TIOCGWINSZ + + #"struct winsize" with the ``unsigned short int``s ws_{row,col,{x,y}pixel} + ws = array('H', (0, 0, 0, 0)) + ioctl(fd, TIOCGWINSZ, ws, True) + ws_row, ws_col = ws[:2] + return ws_row, ws_col + + +def read_pass(): + """Interactive 'password chat', returns the password in plain format. + + Throws a VMMException after the third failure. + """ + # TP: Please preserve the trailing space. + readp_msg0 = _(u'Enter new password: ').encode(ENCODING, 'replace') + # TP: Please preserve the trailing space. + readp_msg1 = _(u'Retype new password: ').encode(ENCODING, 'replace') + mismatched = True + failures = 0 + while mismatched: + if failures > 2: + raise VMMException(_(u'Too many failures - try again later.'), + ERR.VMM_TOO_MANY_FAILURES) + clear0 = getpass(prompt=readp_msg0) + clear1 = getpass(prompt=readp_msg1) + if clear0 != clear1: + failures += 1 + w_std(_(u'Sorry, passwords do not match')) + continue + if not clear0: + failures += 1 + w_std(_(u'Sorry, empty passwords are not permitted')) + continue + mismatched = False + return clear0 + + +def string_io(): + """Returns a new `cStringIO.StringIO` instance.""" + return StringIO() |
|
From: <nev...@us...> - 2010-02-13 03:21:03
|
details: http://hg.localdomain.org/vmm/rev/83938336c518 changeset: 204:83938336c518 user: Pascal Volk date: Sat Feb 13 03:20:42 2010 +0000 description: VMM/{,cli/}Config: fixed imports. Small code cleanups and cosmetic. diffstat: VirtualMailManager/Config.py | 21 +++++++++++---------- VirtualMailManager/cli/Config.py | 21 +++++++++++++-------- 2 files changed, 24 insertions(+), 18 deletions(-) diffs (145 lines): diff -r 4d601240b7db -r 83938336c518 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Fri Feb 12 09:10:54 2010 +0000 +++ b/VirtualMailManager/Config.py Sat Feb 13 03:20:42 2010 +0000 @@ -36,7 +36,6 @@ """ -from shutil import copy2 from ConfigParser import \ Error, MissingSectionHeaderError, NoOptionError, NoSectionError, \ ParsingError, RawConfigParser @@ -61,8 +60,8 @@ """Raised when the requested option has no default value.""" def __init__(self, section, option): - Error.__init__(self, 'Option %r in section %r has no default value' %( - option, section)) + Error.__init__(self, 'Option %r in section %r has no default value' % + (option, section)) class LazyConfig(RawConfigParser): @@ -84,6 +83,7 @@ combined to a single string in the form "``section``\ **.**\ ``option``". """ + def __init__(self): RawConfigParser.__init__(self) self._modified = False @@ -107,16 +107,16 @@ if value.lower() in self._boolean_states: return self._boolean_states[value.lower()] else: - raise ConfigValueError(_(u'Not a boolean: “%s”') % + raise ConfigValueError(_(u"Not a boolean: '%s'") % get_unicode(value)) def get_boolean(self, section, option): # if the setting was not written to the configuration file, it may # be still a boolean value - lets see if self._modified: - tmp = self.get(section, option) - assert isinstance(tmp, bool), 'Oops, not a boolean: %r' % tmp - return tmp + tmp = self.get(section, option) + assert isinstance(tmp, bool), 'Oops, not a boolean: %r' % tmp + return tmp return self.getboolean(section, option) def _get_section_option(self, section_option): @@ -137,8 +137,8 @@ # TODO: cache it if len(sect_opt) != 2:# do we need a regexp to check the format? raise BadOptionError( - _(u'Bad format: “%s” - expected: section.option') % - get_unicode(section_option)) + _(u"Bad format: '%s' - expected: section.option") % + get_unicode(section_option)) if not sect_opt[0] in self._cfg: raise NoSectionError(sect_opt[0]) if not sect_opt[1] in self._cfg[sect_opt[0]]: @@ -159,7 +159,8 @@ d = dict((k, self._cfg[section][k].default) \ for k in self._cfg[section].iterkeys()) d.update(d2) - if '__name__' in d: del d['__name__'] + if '__name__' in d: + del d['__name__'] return d.iteritems() def dget(self, option): diff -r 4d601240b7db -r 83938336c518 VirtualMailManager/cli/Config.py --- a/VirtualMailManager/cli/Config.py Fri Feb 12 09:10:54 2010 +0000 +++ b/VirtualMailManager/cli/Config.py Sat Feb 13 03:20:42 2010 +0000 @@ -8,16 +8,21 @@ Adds some interactive stuff to the Config class. """ +from shutil import copy2 + from VirtualMailManager import ENCODING -from VirtualMailManager.Config import Config +from VirtualMailManager.Config import Config, ConfigValueError, LazyConfig +from VirtualMailManager.Exceptions import VMMConfigException from VirtualMailManager.cli import w_std from VirtualMailManager.constants.ERROR import VMM_TOO_MANY_FAILURES + class CliConfig(Config): """Adds the interactive ``configure`` method to the `Config` class and overwrites `LazyConfig.set(), in order to update a single option in the configuration file with a single command line command. """ + def configure(self, sections): """Interactive method for configuring all options of the given iterable ``sections`` object.""" @@ -27,15 +32,15 @@ w_std(_(u'Using configuration file: %s\n') % self._cfgFileName) for s in sections: - w_std(_(u'* Configuration section: “%s”') % s ) + w_std(_(u'* Configuration section: %r') % s) for opt, val in self.items(s): failures = 0 while True: - newval = raw_input(input_fmt.encode(ENCODING,'replace') %{ - 'option': opt, 'current_value': val}) + newval = raw_input(input_fmt.encode(ENCODING, 'replace') % + {'option': opt, 'current_value': val}) if newval and newval != val: try: - LazyConfig.set('%s.%s' % (s, opt), newval) + LazyConfig.set(self, '%s.%s' % (s, opt), newval) break except (ValueError, ConfigValueError), e: w_std(_(u'Warning: %s') % e) @@ -43,7 +48,7 @@ if failures > 2: raise VMMConfigException( _(u'Too many failures - try again later.'), - VMM_TOO_MANY_FAILURES) + VMM_TOO_MANY_FAILURES) else: break print @@ -60,7 +65,7 @@ ``LazyConfigOption.cls``""" section, option_ = self._get_section_option(option) val = self._cfg[section][option_].cls(value) - if not self._cfg[section][option_].validate is None: + if self._cfg[section][option_].validate: val = self._cfg[section][option_].validate(val) # Do not write default values also skip identical values if not self._cfg[section][option_].default is None: @@ -76,7 +81,7 @@ def __saveChanges(self): """Writes changes to the configuration file.""" - copy2(self._cfgFileName, self._cfgFileName+'.bak') + copy2(self._cfgFileName, self._cfgFileName + '.bak') self._cfgFile = open(self._cfgFileName, 'w') self.write(self._cfgFile) self._cfgFile.close() |
|
From: <nev...@us...> - 2010-02-12 09:11:10
|
details: http://hg.localdomain.org/vmm/rev/4d601240b7db changeset: 203:4d601240b7db user: Pascal Volk date: Fri Feb 12 09:10:54 2010 +0000 description: VMM/Alias: small code cleanups and cosmetic. diffstat: VirtualMailManager/Alias.py | 62 +++++++++++++++++++++----------------------- 1 files changed, 30 insertions(+), 32 deletions(-) diffs (123 lines): diff -r 43e7c8b440da -r 4d601240b7db VirtualMailManager/Alias.py --- a/VirtualMailManager/Alias.py Fri Feb 12 04:26:30 2010 +0000 +++ b/VirtualMailManager/Alias.py Fri Feb 12 09:10:54 2010 +0000 @@ -23,10 +23,9 @@ __slots__ = ('_addr', '_dests', '_gid', '_dbh') def __init__(self, dbh, address): - if isinstance(address, EmailAddress): - self._addr = address - else: + if not isinstance(address, EmailAddress): raise TypeError("Argument 'address' is not an EmailAddress") + self._addr = address self._dbh = dbh self._gid = get_gid(self._dbh, self._addr.domainname) self._dests = [] @@ -53,19 +52,19 @@ if dcount == limit: failed = True errmsg = _( -u"""Can't add new destination to alias “%(address)s”. +u"""Can't add new destination to alias %(address)r. Currently this alias expands into %(count)i/%(limit)i recipients. One more destination will render this alias unusable. Hint: Increase Postfix' virtual_alias_expansion_limit""") elif dcount > limit: failed = True errmsg = _( -u"""Can't add new destination to alias “%(address)s”. +u"""Can't add new destination to alias %(address)r. This alias already exceeds it's expansion limit (%(count)i/%(limit)i). So its unusable, all messages addressed to this alias will be bounced. Hint: Delete some destination addresses.""") if failed: - raise VMMAE(errmsg % {'address': self._addr, 'count': dcount, + raise VMMAE(errmsg % {'address': str(self._addr), 'count': dcount, 'limit': limit}, ALIAS_EXCEEDS_EXPANSION_LIMIT) @@ -74,7 +73,7 @@ ``None``. If ``destination`` is None, the alias with all it's destination addresses will be deleted.""" dbc = self._dbh.cursor() - if destination is None: + if not destination: dbc.execute("DELETE FROM alias WHERE gid=%s AND address=%s", self._gid, self._addr.localpart) else: @@ -96,50 +95,49 @@ if self._addr == destination: raise VMMAE(_(u"Address and destination are identical."), ALIAS_ADDR_DEST_IDENTICAL) - if not destination in self._dests: - self.__check_expansion(expansion_limit) - dbc = self._dbh.cursor() - dbc.execute('INSERT INTO alias (gid, address, destination) \ + if destination in self._dests: + raise VMMAE(_( + u'The alias %(a)r has already the destination %(d)r.') % + {'a': str(self._addr), 'd': str(destination)}, + ALIAS_EXISTS) + self.__check_expansion(expansion_limit) + dbc = self._dbh.cursor() + dbc.execute('INSERT INTO alias (gid, address, destination) \ VALUES (%s, %s, %s)', - self._gid, self._addr.localpart, str(destination)) - self._dbh.commit() - dbc.close() - self._dests.append(destination) - else: - raise VMMAE(_( - u'The alias “%(a)s” has already the destination “%(d)s”.') % - {'a': self._addr, 'd': destination}, ALIAS_EXISTS) + self._gid, self._addr.localpart, str(destination)) + self._dbh.commit() + dbc.close() + self._dests.append(destination) def delDestination(self, destination): """Deletes the specified ``destination`` address from the alias.""" if not isinstance(destination, EmailAddress): raise TypeError("Argument 'destination' is not an EmailAddress") if not self._dests: - raise VMMAE(_(u"The alias “%s” doesn't exist.") % self._addr, + raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr), NO_SUCH_ALIAS) if not destination in self._dests: - raise VMMAE(_(u"The address “%(d)s” isn't a destination of \ -the alias “%(a)s”.") % - {'a': self._addr, 'd': destination}, NO_SUCH_ALIAS) + raise VMMAE(_(u"The address %(d)r isn't a destination of \ +the alias %(a)r.") % + {'a': str(self._addr), 'd': str(destination)}, + NO_SUCH_ALIAS) self.__delete(destination) self._dests.remove(destination) def getDestinations(self): """Returns an iterator for all destinations of the alias.""" - if self._dests: - return iter(self._dests) - else: - raise VMMAE(_(u"The alias “%s” doesn't exist.") % self._addr, + if not self._dests: + raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr), NO_SUCH_ALIAS) + return iter(self._dests) def delete(self): """Deletes the alias with all it's destinations.""" - if self._dests: - self.__delete() - del self._dests[:] - else: - raise VMMAE(_(u"The alias “%s” doesn't exist.") % self._addr, + if not self._dests: + raise VMMAE(_(u"The alias %r doesn't exist.") % str(self._addr), NO_SUCH_ALIAS) + self.__delete() + del self._dests[:] del _ |
|
From: <nev...@us...> - 2010-02-12 04:26:44
|
details: http://hg.localdomain.org/vmm/rev/43e7c8b440da changeset: 202:43e7c8b440da user: Pascal Volk date: Fri Feb 12 04:26:30 2010 +0000 description: VMM/Relocated: small code cleanups and cosmetic. diffstat: VirtualMailManager/Relocated.py | 38 +++++++++++++++++--------------------- 1 files changed, 17 insertions(+), 21 deletions(-) diffs (71 lines): diff -r dbb0f7ed7858 -r 43e7c8b440da VirtualMailManager/Relocated.py --- a/VirtualMailManager/Relocated.py Fri Feb 12 04:15:18 2010 +0000 +++ b/VirtualMailManager/Relocated.py Fri Feb 12 04:26:30 2010 +0000 @@ -28,10 +28,9 @@ Use `setDestination()` to set/update the new address, where the user has moved to.""" - if isinstance(address, EmailAddress): - self._addr = address - else: + if not isinstance(address, EmailAddress): raise TypeError("Argument 'address' is not an EmailAddress") + self._addr = address self._dbh = dbh self._gid = get_gid(self._dbh, self._addr.domainname) self._dest = None @@ -53,22 +52,20 @@ def setDestination(self, destination): """Sets/updates the new address of the relocated user.""" update = False - if isinstance(destination, EmailAddress): - if self._addr == destination: - raise VMMRE(_(u'Address and destination are identical.'), - RELOCATED_ADDR_DEST_IDENTICAL) - if self._dest: - if self._dest == destination: - raise VMMRE( - _(u'The relocated user “%s” already exists.') % - self._addr, RELOCATED_EXISTS) - else: - self._dest = destination - update = True + if not isinstance(destination, EmailAddress): + raise TypeError("Argument 'destination' is not an EmailAddress") + if self._addr == destination: + raise VMMRE(_(u'Address and destination are identical.'), + RELOCATED_ADDR_DEST_IDENTICAL) + if self._dest: + if self._dest == destination: + raise VMMRE(_(u'The relocated user %r already exists.') % + self._addr, RELOCATED_EXISTS) else: self._dest = destination + update = True else: - raise TypeError("Argument 'destination' is not an EmailAddress") + self._dest = destination dbc = self._dbh.cursor() if not update: @@ -83,16 +80,15 @@ def getInfo(self): """Returns the address to which mails should be sent.""" - if self._dest: - return self._dest - else: - raise VMMRE(_(u"The relocated user “%s” doesn't exist.") % + if not self._dest: + raise VMMRE(_(u"The relocated user %r doesn't exist.") % self._addr, NO_SUCH_RELOCATED) + return self._dest def delete(self): """Deletes the relocated entry from the database.""" if not self._dest: - raise VMMRE(_(u"The relocated user “%s” doesn't exist.") % + raise VMMRE(_(u"The relocated user %r doesn't exist.") % self._addr, NO_SUCH_RELOCATED) dbc = self._dbh.cursor() dbc.execute("DELETE FROM relocated WHERE gid = %s AND address = %s", |
|
From: <nev...@us...> - 2010-02-12 04:15:36
|
details: http://hg.localdomain.org/vmm/rev/dbb0f7ed7858 changeset: 201:dbb0f7ed7858 user: Pascal Volk date: Fri Feb 12 04:15:18 2010 +0000 description: VMM/Config: LazyConfigOption.__init__() cast 'default' to 'cls'. If the default value is not None, make sure it has the proper type. diffstat: VirtualMailManager/Config.py | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diffs (15 lines): diff -r 983cf98d5881 -r dbb0f7ed7858 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Thu Feb 11 07:20:49 2010 +0000 +++ b/VirtualMailManager/Config.py Fri Feb 12 04:15:18 2010 +0000 @@ -247,7 +247,10 @@ the value, when `LazyConfig.set()` is called. """ self.__cls = cls - self.__default = default + if not default is None:# enforce the type of the default value + self.__default = self.__cls(default) + else: + self.__default = default if not callable(getter): raise TypeError('getter has to be a callable, got a %r' % getter.__class__.__name__) |
|
From: <nev...@us...> - 2010-02-11 07:21:05
|
details: http://hg.localdomain.org/vmm/rev/983cf98d5881 changeset: 200:983cf98d5881 user: Pascal Volk date: Thu Feb 11 07:20:49 2010 +0000 description: VMM/Config: attributes of class LazyConfigOption are read-only now. Some small code cleanups. diffstat: VirtualMailManager/Config.py | 62 ++++++++++++++++++++++++++++--------------- 1 files changed, 40 insertions(+), 22 deletions(-) diffs (129 lines): diff -r 0684790fff7c -r 983cf98d5881 VirtualMailManager/Config.py --- a/VirtualMailManager/Config.py Thu Feb 11 03:08:11 2010 +0000 +++ b/VirtualMailManager/Config.py Thu Feb 11 07:20:49 2010 +0000 @@ -2,7 +2,10 @@ # Copyright (c) 2007 - 2010, Pascal Volk # See COPYING for distribution information. -"""vmm's configuration module for simplified configuration access. +""" + VirtualMailManager.Config + + VMM's configuration module for simplified configuration access. This module defines a few classes: @@ -112,8 +115,8 @@ # be still a boolean value - lets see if self._modified: tmp = self.get(section, option) - if isinstance(tmp, bool): - return tmp + assert isinstance(tmp, bool), 'Oops, not a boolean: %r' % tmp + return tmp return self.getboolean(section, option) def _get_section_option(self, section_option): @@ -131,6 +134,7 @@ * `NoOptionError` """ sect_opt = section_option.lower().split('.') + # TODO: cache it if len(sect_opt) != 2:# do we need a regexp to check the format? raise BadOptionError( _(u'Bad format: “%s” - expected: section.option') % @@ -178,7 +182,7 @@ try: return self._cfg[section][option].getter(section, option) except (NoSectionError, NoOptionError): - if not self._cfg[section][option].default is None: + if not self._cfg[section][option].default is None:# may be False return self._cfg[section][option].default else: raise NoDefaultError(section, option) @@ -195,7 +199,7 @@ ``LazyConfigOption.cls``""" section, option = self._get_section_option(option) val = self._cfg[section][option].cls(value) - if not self._cfg[section][option].validate is None: + if self._cfg[section][option].validate: val = self._cfg[section][option].validate(val) if not RawConfigParser.has_section(self, section): self.add_section(section) @@ -223,7 +227,7 @@ and instances of classes derived from ``LazyConfig``, like the `Config` class. """ - __slots__ = ('cls', 'default', 'getter', 'validate') + __slots__ = ('__cls', '__default', '__getter', '__validate') def __init__(self, cls, default, getter, validate=None): """Creates a new ``LazyConfigOption`` instance. @@ -242,22 +246,36 @@ None or any method, that takes one argument, in order to check the value, when `LazyConfig.set()` is called. """ - self.cls = cls + self.__cls = cls + self.__default = default + if not callable(getter): + raise TypeError('getter has to be a callable, got a %r' % + getter.__class__.__name__) + self.__getter = getter + if validate and not callable(validate): + raise TypeError('validate has to be callable or None, got a %r' % + validate.__class__.__name__) + self.__validate = validate + + @property + def cls(self): """The class of the option's value e.g. `str`, `unicode` or `bool`""" - self.default = default + return self.__cls + + @property + def default(self): """The option's default value, may be ``None``""" - if callable(getter): - self.getter = getter - """The getter method to get the option's value""" - else: - raise TypeError('getter has to be a callable, got a %r'\ - % getter.__class__.__name__) - if validate is None or callable(validate): - self.validate = validate - """A method to validate the value""" - else: - raise TypeError('validate has to be callable or None, got a %r'\ - % validate.__class__.__name__) + return self.__default + + @property + def getter(self): + """The getter method or function to get the option's value""" + return self.__getter + + @property + def validate(self): + """A method or function to validate the value""" + return self.__validate class Config(LazyConfig): @@ -335,7 +353,7 @@ except (MissingSectionHeaderError, ParsingError), e: raise VMMConfigException(str(e), CONF_ERROR) finally: - if not self._cfgFile is None and not self._cfgFile.closed: + if self._cfgFile and not self._cfgFile.closed: self._cfgFile.close() def check(self): @@ -388,6 +406,6 @@ not RawConfigParser.has_option(self, section, option)): missing.append(option) errors = True - if len(missing): + if missing: self.__missing[section] = missing return not errors |
|
From: <nev...@us...> - 2010-02-11 03:08:28
|
details: http://hg.localdomain.org/vmm/rev/0684790fff7c changeset: 199:0684790fff7c user: Pascal Volk date: Thu Feb 11 03:08:11 2010 +0000 description: VMM: renamed function chk_domainname() -> check_domainname(). Moved EmailAddress.check_localpart() -> VirtualMailManager.check_localpart(). Some small code cleanups in class EmailAddress. diffstat: VirtualMailManager/AliasDomain.py | 4 +- VirtualMailManager/Domain.py | 8 ++-- VirtualMailManager/EmailAddress.py | 59 ++++++++++++------------------------- VirtualMailManager/__init__.py | 60 +++++++++++++++++++++++++++++-------- 4 files changed, 71 insertions(+), 60 deletions(-) diffs (279 lines): diff -r 02d467e4fbab -r 0684790fff7c VirtualMailManager/AliasDomain.py --- a/VirtualMailManager/AliasDomain.py Wed Feb 10 08:55:51 2010 +0000 +++ b/VirtualMailManager/AliasDomain.py Thu Feb 11 03:08:11 2010 +0000 @@ -5,7 +5,7 @@ """Virtual Mail Manager's AliasDomain class to manage alias domains.""" import VirtualMailManager.constants.ERROR as ERR -from VirtualMailManager import chk_domainname +from VirtualMailManager import check_domainname from VirtualMailManager.Exceptions import VMMAliasDomainException as VADE class AliasDomain(object): @@ -13,7 +13,7 @@ __slots__ = ('__gid', '__name', '_domain', '_dbh') def __init__(self, dbh, domainname, targetDomain=None): self._dbh = dbh - self.__name = chk_domainname(domainname) + self.__name = check_domainname(domainname) self.__gid = 0 self._domain = targetDomain self._exists() diff -r 02d467e4fbab -r 0684790fff7c VirtualMailManager/Domain.py --- a/VirtualMailManager/Domain.py Wed Feb 10 08:55:51 2010 +0000 +++ b/VirtualMailManager/Domain.py Thu Feb 11 03:08:11 2010 +0000 @@ -6,7 +6,7 @@ from random import choice -from VirtualMailManager import chk_domainname +from VirtualMailManager import check_domainname from VirtualMailManager.constants.ERROR import \ ACCOUNT_AND_ALIAS_PRESENT, ACCOUNT_PRESENT, ALIAS_PRESENT, \ DOMAIN_ALIAS_EXISTS, DOMAIN_EXISTS, NO_SUCH_DOMAIN @@ -29,7 +29,7 @@ transport -- default vmm.cfg/misc/transport (str) """ self._dbh = dbh - self._name = chk_domainname(domainname) + self._name = check_domainname(domainname) self._basedir = basedir if transport is not None: self._transport = Transport(self._dbh, transport=transport) @@ -281,7 +281,7 @@ def search(dbh, pattern=None, like=False): if pattern is not None and like is False: - pattern = chk_domainname(pattern) + pattern = check_domainname(pattern) sql = 'SELECT gid, domainname, is_primary FROM domain_name' if pattern is None: pass @@ -317,7 +317,7 @@ Raises an `VMMDomainException` if the domain does not exist. """ - domainname = chk_domainname(domainname) + domainname = check_domainname(domainname) dbc = dbh.cursor() dbc.execute('SELECT gid FROM domain_name WHERE domainname=%s', domainname) gid = dbc.fetchone() diff -r 02d467e4fbab -r 0684790fff7c VirtualMailManager/EmailAddress.py --- a/VirtualMailManager/EmailAddress.py Wed Feb 10 08:55:51 2010 +0000 +++ b/VirtualMailManager/EmailAddress.py Thu Feb 11 03:08:11 2010 +0000 @@ -8,15 +8,14 @@ Virtual Mail Manager's EmailAddress class to handle e-mail addresses. """ -import re - -from VirtualMailManager import chk_domainname +from VirtualMailManager import check_domainname, check_localpart from VirtualMailManager.constants.ERROR import \ - DOMAIN_NO_NAME, INVALID_ADDRESS, LOCALPART_INVALID, LOCALPART_TOO_LONG + DOMAIN_NO_NAME, INVALID_ADDRESS, LOCALPART_INVALID from VirtualMailManager.Exceptions import VMMEmailAddressException as VMMEAE RE_LOCALPART = """[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]""" +_ = lambda msg: msg class EmailAddress(object): @@ -58,48 +57,28 @@ return "EmailAddress('%s@%s')" % (self._localpart, self._domainname) def __str__(self): - return "%s@%s" % (self._localpart, self._domainname) + return '%s@%s' % (self._localpart, self._domainname) def _chk_address(self, address): """Checks if the string ``address`` could be used for an e-mail - address.""" + address. If so, it will assign the corresponding values to the + attributes `_localpart` and `_domainname`.""" parts = address.split('@') p_len = len(parts) - if p_len is 2: - self._localpart = check_localpart(parts[0]) - if len(parts[1]) > 0: - self._domainname = chk_domainname(parts[1]) - else: - raise VMMEAE(_(u"Missing domain name after “%s@”.") % - self._localpart, DOMAIN_NO_NAME) - elif p_len < 2: - raise VMMEAE(_(u"Missing '@' sign in e-mail address “%s”.") % - address, INVALID_ADDRESS) + if p_len < 2: + raise VMMEAE(_(u"Missing the '@' sign in address %r") % address, + INVALID_ADDRESS) elif p_len > 2: - raise VMMEAE(_(u"Too many '@' signs in e-mail address “%s”.") % - address, INVALID_ADDRESS) + raise VMMEAE(_(u"Too many '@' signs in address %r") % address, + INVALID_ADDRESS) + if not parts[0]: + raise VMMEAE(_(u"Missing local-part in address %r") % address, + LOCALPART_INVALID) + if not parts[1]: + raise VMMEAE(_(u"Missing domain name in address %r") % address, + DOMAIN_NO_NAME) + self._localpart = check_localpart(parts[0]) + self._domainname = check_domainname(parts[1]) -_ = lambda msg: msg - - -def check_localpart(localpart): - """Validates the local-part of an e-mail address. - - Argument: - localpart -- local-part of the e-mail address that should be validated - """ - if len(localpart) < 1: - raise VMMEAE(_(u'No local-part specified.'), LOCALPART_INVALID) - if len(localpart) > 64: - raise VMMEAE(_(u'The local-part “%s” is too long') % localpart, - LOCALPART_TOO_LONG) - invalid_chars = set(re.findall(RE_LOCALPART, localpart)) - if invalid_chars: - i_chrs = u''.join((u'“%s” ' % c for c in invalid_chars)) - raise VMMEAE(_(u"The local-part “%(l_part)s” contains invalid\ - characters: %(i_chrs)s") % {'l_part': localpart, 'i_chrs': i_chrs}, - LOCALPART_INVALID) - return localpart - del _ diff -r 02d467e4fbab -r 0684790fff7c VirtualMailManager/__init__.py --- a/VirtualMailManager/__init__.py Wed Feb 10 08:55:51 2010 +0000 +++ b/VirtualMailManager/__init__.py Thu Feb 11 03:08:11 2010 +0000 @@ -12,8 +12,8 @@ from encodings.idna import ToASCII, ToUnicode from VirtualMailManager.constants.ERROR import \ - DOMAIN_INVALID, DOMAIN_TOO_LONG, NOT_EXECUTABLE, NO_SUCH_BINARY, \ - NO_SUCH_DIRECTORY + DOMAIN_INVALID, DOMAIN_TOO_LONG, LOCALPART_INVALID, LOCALPART_TOO_LONG, \ + NOT_EXECUTABLE, NO_SUCH_BINARY, NO_SUCH_DIRECTORY from VirtualMailManager.constants.VERSION import * from VirtualMailManager.Exceptions import VMMException @@ -24,8 +24,8 @@ # version information from VERSION '__author__', '__date__', '__version__', # error codes - 'ENCODING', 'ace2idna', 'chk_domainname', 'exec_ok', 'expand_path', - 'get_unicode', 'idn2ascii', 'is_dir', + 'ENCODING', 'ace2idna', 'check_domainname', 'check_localpart', 'exec_ok', + 'expand_path', 'get_unicode', 'idn2ascii', 'is_dir', ] @@ -37,18 +37,26 @@ locale.setlocale(locale.LC_ALL, 'C') ENCODING = locale.nl_langinfo(locale.CODESET) -RE_ASCII_CHARS = """^[\x20-\x7E]*$""" -RE_DOMAIN = """^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$""" +RE_ASCII_CHARS = r"^[\x20-\x7E]*$" +RE_DOMAIN = r"^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$" +RE_LOCALPART = r"[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]" + + +# there may be many domain and e-mail address checks +re_obj_domain = re.compile(RE_DOMAIN) +re_obj_localpart = re.compile(RE_LOCALPART) gettext.install('vmm', '/usr/local/share/locale', unicode=1) + def get_unicode(string): """Converts `string` to `unicode`, if necessary.""" if isinstance(string, unicode): return string return unicode(string, ENCODING, 'replace') + def expand_path(path): """Expands paths, starting with ``.`` or ``~``, to an absolute path.""" if path.startswith('.'): @@ -57,6 +65,7 @@ return os.path.expanduser(path) return path + def is_dir(path): """Checks if ``path`` is a directory. @@ -64,10 +73,11 @@ """ path = expand_path(path) if not os.path.isdir(path): - raise VMMException(_(u'“%s” is not a directory') % get_unicode(path), - NO_SUCH_DIRECTORY) + raise VMMException(_(u'“%s” is not a directory') % + get_unicode(path), NO_SUCH_DIRECTORY) return path + def exec_ok(binary): """Checks if the ``binary`` exists and if it is executable. @@ -83,27 +93,49 @@ get_unicode(binary), NOT_EXECUTABLE) return binary + def idn2ascii(domainname): """Converts the idn domain name `domainname` into punycode.""" return '.'.join([ToASCII(lbl) for lbl in domainname.split('.') if lbl]) + def ace2idna(domainname): """Converts the domain name `domainname` from ACE according to IDNA.""" return u'.'.join([ToUnicode(lbl) for lbl in domainname.split('.') if lbl]) -def chk_domainname(domainname): + +def check_domainname(domainname): """Returns the validated domain name `domainname`. It also converts the name of the domain from IDN to ASCII, if necessary. - Throws an VMMException, if the domain name is too long or doesn't look + Throws an `VMMException`, if the domain name is too long or doesn't look like a valid domain name (label.label.label). """ - if not re.match(RE_ASCII_CHARS, domainname): + if not re_obj_domain.match(domainname): domainname = idn2ascii(domainname) if len(domainname) > 255: - raise VMMException(_(u'The domain name is too long.'), DOMAIN_TOO_LONG) - if not re.match(RE_DOMAIN, domainname): - raise VMMException(_(u'The domain name “%s” is invalid.') % domainname, + raise VMMException(_(u'The domain name is too long'), DOMAIN_TOO_LONG) + if not re_obj_domain.match(domainname): + raise VMMException(_(u'The domain name %r is invalid') % domainname, DOMAIN_INVALID) return domainname + + +def check_localpart(localpart): + """Returns the validated local-part *localpart*. + + Throws a `VMMException` if the local-part is too long or contains + invalid characters. + """ + if len(localpart) > 64: + raise VMMException(_(u'The local-part %r is too long') % localpart, + LOCALPART_TOO_LONG) + invalid_chars = set(re_obj_localpart.findall(localpart)) + if invalid_chars: + i_chars = u''.join((u'"%s" ' % c for c in invalid_chars)) + raise VMMException(_(u"The local-part %(l_part)r contains invalid \ +characters: %(i_chars)s") % + {'l_part': localpart, 'i_chars': i_chars}, + LOCALPART_INVALID) + return localpart |
|
From: <nev...@us...> - 2010-02-10 08:56:06
|
details: http://hg.localdomain.org/vmm/rev/02d467e4fbab changeset: 198:02d467e4fbab user: Pascal Volk date: Wed Feb 10 08:55:51 2010 +0000 description: VMM/Domain: added function get_gid() to the Domain module. We don't need to load all the domain related information from the database, when we need only the GID of a domain. For example in the Alias or Relocated classes. diffstat: VirtualMailManager/Alias.py | 15 +++------------ VirtualMailManager/Domain.py | 16 ++++++++++++++++ VirtualMailManager/Relocated.py | 15 +++------------ 3 files changed, 22 insertions(+), 24 deletions(-) diffs (107 lines): diff -r d2712e8c724e -r 02d467e4fbab VirtualMailManager/Alias.py --- a/VirtualMailManager/Alias.py Wed Feb 10 07:38:19 2010 +0000 +++ b/VirtualMailManager/Alias.py Wed Feb 10 08:55:51 2010 +0000 @@ -8,11 +8,11 @@ Virtual Mail Manager's Alias class to manage e-mail aliases. """ -from VirtualMailManager.Domain import Domain +from VirtualMailManager.Domain import get_gid from VirtualMailManager.EmailAddress import EmailAddress from VirtualMailManager.Exceptions import VMMAliasException as VMMAE from VirtualMailManager.constants.ERROR import ALIAS_ADDR_DEST_IDENTICAL, \ - ALIAS_EXCEEDS_EXPANSION_LIMIT, ALIAS_EXISTS, NO_SUCH_ALIAS, NO_SUCH_DOMAIN + ALIAS_EXCEEDS_EXPANSION_LIMIT, ALIAS_EXISTS, NO_SUCH_ALIAS _ = lambda msg: msg @@ -28,20 +28,11 @@ else: raise TypeError("Argument 'address' is not an EmailAddress") self._dbh = dbh - self._gid = 0 + self._gid = get_gid(self._dbh, self._addr.domainname) self._dests = [] - self.__set_gid() self.__load_dests() - def __set_gid(self): - """Sets the alias' _gid based on its _addr.domainname.""" - dom = Domain(self._dbh, self._addr.domainname) - self._gid = dom.getID() - if self._gid == 0: - raise VMMAE(_(u"The domain “%s” doesn't exist.") % - self._addr.domainname, NO_SUCH_DOMAIN) - def __load_dests(self): """Loads all known destination addresses into the _dests list.""" dbc = self._dbh.cursor() diff -r d2712e8c724e -r 02d467e4fbab VirtualMailManager/Domain.py --- a/VirtualMailManager/Domain.py Wed Feb 10 07:38:19 2010 +0000 +++ b/VirtualMailManager/Domain.py Wed Feb 10 08:55:51 2010 +0000 @@ -278,6 +278,7 @@ aliasdomains = [aname[0] for aname in anames] return aliasdomains + def search(dbh, pattern=None, like=False): if pattern is not None and like is False: pattern = chk_domainname(pattern) @@ -311,3 +312,18 @@ del doms return order, domdict +def get_gid(dbh, domainname): + """Returns the *GID* of the domain *domainname*. + + Raises an `VMMDomainException` if the domain does not exist. + """ + domainname = chk_domainname(domainname) + dbc = dbh.cursor() + dbc.execute('SELECT gid FROM domain_name WHERE domainname=%s', domainname) + gid = dbc.fetchone() + dbc.close() + if gid: + return gid[0] + else: + raise VMMDE(_(u"The domain “%s” doesn't exist.") % domainname, + NO_SUCH_DOMAIN) diff -r d2712e8c724e -r 02d467e4fbab VirtualMailManager/Relocated.py --- a/VirtualMailManager/Relocated.py Wed Feb 10 07:38:19 2010 +0000 +++ b/VirtualMailManager/Relocated.py Wed Feb 10 08:55:51 2010 +0000 @@ -8,10 +8,10 @@ Virtual Mail Manager's Relocated class to handle relocated users. """ -from VirtualMailManager.Domain import Domain +from VirtualMailManager.Domain import get_gid from VirtualMailManager.EmailAddress import EmailAddress from VirtualMailManager.Exceptions import VMMRelocatedException as VMMRE -from VirtualMailManager.constants.ERROR import NO_SUCH_DOMAIN, \ +from VirtualMailManager.constants.ERROR import \ NO_SUCH_RELOCATED, RELOCATED_ADDR_DEST_IDENTICAL, RELOCATED_EXISTS @@ -33,20 +33,11 @@ else: raise TypeError("Argument 'address' is not an EmailAddress") self._dbh = dbh - self._gid = 0 + self._gid = get_gid(self._dbh, self._addr.domainname) self._dest = None - self.__set_gid() self.__load() - def __set_gid(self): - """Sets the `_gid` attribute, based on the `_addr.domainname`.""" - dom = Domain(self._dbh, self._addr.domainname) - self._gid = dom.getID() - if self._gid == 0: - raise VMMRE(_(u"The domain “%s” doesn't exist.") % - self._addr.domainname, NO_SUCH_DOMAIN) - def __load(self): """Loads the destination address from the database into the `_dest` attribute.""" |