# HG changeset patch # User Pascal Volk # Date 1357430987 0 # Node ID 2bc11dada2965c633c2a40fbcd47239aa9c0a332 # Parent 995203a101e1e3f2c4aa800024ae5a72498cc414# Parent d24f094d1cb5438385b7c7594061690add16d3a3 merged changes from default(d24f094d1cb5) diff -r d24f094d1cb5 -r 2bc11dada296 VirtualMailManager/__init__.py --- a/VirtualMailManager/__init__.py Sat Jan 05 23:49:42 2013 +0000 +++ b/VirtualMailManager/__init__.py Sun Jan 06 00:09:47 2013 +0000 @@ -32,4 +32,4 @@ locale.setlocale(locale.LC_ALL, 'C') ENCODING = locale.nl_langinfo(locale.CODESET) -gettext.install('vmm', '/usr/local/share/locale', unicode=1) +gettext.install('vmm', '/usr/local/share/locale') diff -r d24f094d1cb5 -r 2bc11dada296 VirtualMailManager/account.py --- a/VirtualMailManager/account.py Sat Jan 05 23:49:42 2013 +0000 +++ b/VirtualMailManager/account.py Sun Jan 06 00:09:47 2013 +0000 @@ -57,7 +57,7 @@ # 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 AErr(_(u"The domain '%s' does not exist.") % + raise AErr(_("The domain '%s' does not exist.") % self._addr.domainname, NO_SUCH_DOMAIN) self._uid = 0 self._mail = None @@ -69,7 +69,7 @@ self._new = True self._load() - def __nonzero__(self): + def __bool__(self): """Returns `True` if the Account is known, `False` if it's new.""" return not self._new @@ -86,11 +86,7 @@ self._uid, _mid, _qid, _ssid, _tid, _note = result def load_helper(ctor, own, field, dbresult): - # Py25: cur = None if own is None else getattr(own, field) - if own is None: - cur = None - else: - cur = getattr(own, field) + cur = None if own is None else getattr(own, field) if cur != dbresult: kwargs = {field: dbresult} if dbresult is None: @@ -120,8 +116,8 @@ information in the database. """ if maillocation.dovecot_version > cfg_dget('misc.dovecot_version'): - raise AErr(_(u"The mailbox format '%(mbfmt)s' requires Dovecot " - u">= v%(version)s.") % { + raise AErr(_("The mailbox format '%(mbfmt)s' requires Dovecot " + ">= v%(version)s.") % { 'mbfmt': maillocation.mbformat, 'version': version_str(maillocation.dovecot_version)}, INVALID_MAIL_LOCATION) @@ -137,7 +133,7 @@ `column` : basestring Name of the table column. Currently: qid, ssid and tid - `value` : long + `value` : int The referenced key """ if column not in ('qid', 'ssid', 'tid'): @@ -163,7 +159,7 @@ """Raise an AccountError if the Account is new - not yet saved in the database.""" if self._new: - raise AErr(_(u"The account '%s' does not exist.") % self._addr, + raise AErr(_("The account '%s' does not exist.") % self._addr, NO_SUCH_ACCOUNT) @property @@ -219,10 +215,10 @@ The password for the new Account. """ if not self._new: - raise AErr(_(u"The account '%s' already exists.") % self._addr, + raise AErr(_("The account '%s' already exists.") % self._addr, ACCOUNT_EXISTS) - if not isinstance(password, basestring) or not password: - raise AErr(_(u"Could not accept password: '%s'") % password, + if not isinstance(password, str) or not password: + raise AErr(_("Could not accept password: '%s'") % password, ACCOUNT_MISSING_PASSWORD) self._passwd = password @@ -234,36 +230,29 @@ `note` : basestring or None The note, or None to remove """ - assert note is None or isinstance(note, basestring) + assert note is None or isinstance(note, str) self._note = note def save(self): """Save the new Account in the database.""" if not self._new: - raise AErr(_(u"The account '%s' already exists.") % self._addr, + raise AErr(_("The account '%s' already exists.") % self._addr, ACCOUNT_EXISTS) if not self._passwd: - raise AErr(_(u"No password set for account: '%s'") % self._addr, + raise AErr(_("No password set for account: '%s'") % self._addr, ACCOUNT_MISSING_PASSWORD) self._prepare(MailLocation(self._dbh, mbfmt=cfg_dget('mailbox.format'), directory=cfg_dget('mailbox.root'))) dbc = self._dbh.cursor() - qid = ssid = tid = None - if self._qlimit: - qid = self._qlimit.qid - if self._services: - ssid = self._services.ssid - if self._transport: - tid = self._transport.tid dbc.execute('INSERT INTO users (local_part, passwd, uid, gid, mid, ' 'qid, ssid, tid, note) ' 'VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)', (self._addr.localpart, pwhash(self._passwd, user=self._addr), self._uid, - self._domain.gid, self._mail.mid, qid, ssid, tid, -# self._qlimit.qid if self._qlimit else None, -# self._services.ssid if self._services else None, -# self._transport.tid if self._transport else None, + self._domain.gid, self._mail.mid, + self._qlimit.qid if self._qlimit else None, + self._services.ssid if self._services else None, + self._transport.tid if self._transport else None, self._note)) self._dbh.commit() dbc.close() @@ -282,7 +271,7 @@ The new value of the attribute. """ if field not in ('name', 'password', 'note'): - raise AErr(_(u"Unknown field: '%s'") % field, INVALID_ARGUMENT) + raise AErr(_("Unknown field: '%s'") % field, INVALID_ARGUMENT) self._chk_state() dbc = self._dbh.cursor() if field == 'password': @@ -304,8 +293,8 @@ the new quota limit of the domain. """ if cfg_dget('misc.dovecot_version') < 0x10102f00: - raise VMMError(_(u'PostgreSQL-based dictionary quota requires ' - u'Dovecot >= v1.1.2.'), VMM_ERROR) + raise VMMError(_('PostgreSQL-based dictionary quota requires ' + 'Dovecot >= v1.1.2.'), VMM_ERROR) self._chk_state() if quotalimit == self._qlimit: return @@ -364,7 +353,7 @@ fmt = format_domain_default ret = {} - for service, state in services.iteritems(): + for service, state in services.items(): # TP: A service (e.g. pop3 or imap) may be enabled/usable or # disabled/unusable for a user. ret[service] = fmt((_('disabled'), _('enabled'))[state]) @@ -387,7 +376,7 @@ info = dbc.fetchone() dbc.close() if info: - info = dict(zip(('name', 'uq_bytes', 'uq_messages'), info)) + info = dict(list(zip(('name', 'uq_bytes', 'uq_messages'), info))) info.update(self._get_info_serviceset()) info['address'] = self._addr info['gid'] = self._domain.gid @@ -406,7 +395,7 @@ info['uid'] = self._uid return info # nearly impossible‽ - raise AErr(_(u"Could not fetch information for account: '%s'") % + raise AErr(_("Could not fetch information for account: '%s'") % self._addr, NO_SUCH_ACCOUNT) def get_aliases(self): @@ -450,8 +439,8 @@ a_count = self._count_aliases() if a_count > 0: dbc.close() - raise AErr(_(u"There are %(count)d aliases with the " - u"destination address '%(address)s'.") % + raise AErr(_("There are %(count)d aliases with the " + "destination address '%(address)s'.") % {'count': a_count, 'address': self._addr}, ALIAS_PRESENT) dbc.execute('DELETE FROM users WHERE uid = %s', (self._uid,)) @@ -471,17 +460,17 @@ Argument: - `uid` : long + `uid` : int The Account unique ID. `dbh` : pyPgSQL.PgSQL.Connection a database connection for the database access. """ try: - uid = long(uid) + uid = int(uid) except ValueError: - raise AErr(_(u'UID must be an int/long.'), INVALID_ARGUMENT) + raise AErr(_('UID must be an integer.'), INVALID_ARGUMENT) if uid < 1: - raise AErr(_(u'UID must be greater than 0.'), INVALID_ARGUMENT) + raise AErr(_('UID must be greater than 0.'), INVALID_ARGUMENT) dbc = dbh.cursor() dbc.execute("SELECT local_part||'@'|| domain_name.domainname AS address, " "uid, users.gid, note FROM users LEFT JOIN domain_name ON " @@ -490,9 +479,9 @@ info = dbc.fetchone() dbc.close() if not info: - raise AErr(_(u"There is no account with the UID: '%d'") % uid, + raise AErr(_("There is no account with the UID: '%d'") % uid, NO_SUCH_ACCOUNT) - info = dict(zip(('address', 'uid', 'gid', 'note'), info)) + info = dict(list(zip(('address', 'uid', 'gid', 'note'), info))) return info del _, cfg_dget diff -r d24f094d1cb5 -r 2bc11dada296 VirtualMailManager/alias.py --- a/VirtualMailManager/alias.py Sat Jan 05 23:49:42 2013 +0000 +++ b/VirtualMailManager/alias.py Sun Jan 06 00:09:47 2013 +0000 @@ -13,7 +13,6 @@ EmailAddress, DestinationEmailAddress as DestAddr from VirtualMailManager.errors import AliasError as AErr from VirtualMailManager.ext.postconf import Postconf -from VirtualMailManager.pycompat import all from VirtualMailManager.constants import \ ALIAS_EXCEEDS_EXPANSION_LIMIT, NO_SUCH_ALIAS, NO_SUCH_DOMAIN @@ -32,7 +31,7 @@ self._dbh = dbh self._gid = get_gid(self._dbh, self._addr.domainname) if not self._gid: - raise AErr(_(u"The domain '%s' does not exist.") % + raise AErr(_("The domain '%s' does not exist.") % self._addr.domainname, NO_SUCH_DOMAIN) self._dests = [] @@ -52,20 +51,20 @@ def _check_expansion(self, count_new): """Checks the current expansion limit of the alias.""" postconf = Postconf(cfg_dget('bin.postconf')) - limit = long(postconf.read('virtual_alias_expansion_limit')) + limit = int(postconf.read('virtual_alias_expansion_limit')) dcount = len(self._dests) failed = False if dcount == limit or dcount + count_new > limit: failed = True errmsg = _( -u"""Cannot add %(count_new)i new destination(s) to alias '%(address)s'. +"""Cannot add %(count_new)i new destination(s) to alias '%(address)s'. Currently this alias expands into %(count)i/%(limit)i recipients. %(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"""Cannot add %(count_new)i new destination(s) to alias '%(address)s'. +"""Cannot add %(count_new)i new destination(s) to alias '%(address)s'. This alias already exceeds its expansion limit (%(count)i/%(limit)i). So its unusable, all messages addressed to this alias will be bounced. Hint: Delete some destination addresses.""") @@ -152,7 +151,7 @@ if not warnings is None: warnings.append(self._addr) if not self._dests: - raise AErr(_(u"The alias '%s' does not exist.") % self._addr, + raise AErr(_("The alias '%s' does not exist.") % self._addr, NO_SUCH_ALIAS) unknown = destinations.difference(set(self._dests)) if unknown: @@ -160,8 +159,8 @@ if not warnings is None: warnings.extend(unknown) if not destinations: - raise AErr(_(u"No suitable destinations left to remove from alias " - u"'%s'.") % self._addr, NO_SUCH_ALIAS) + raise AErr(_("No suitable destinations left to remove from alias " + "'%s'.") % self._addr, NO_SUCH_ALIAS) self._delete(destinations) for destination in destinations: self._dests.remove(destination) @@ -169,14 +168,14 @@ def get_destinations(self): """Returns an iterator for all destinations of the alias.""" if not self._dests: - raise AErr(_(u"The alias '%s' does not exist.") % self._addr, + raise AErr(_("The alias '%s' does not exist.") % self._addr, NO_SUCH_ALIAS) return iter(self._dests) def delete(self): """Deletes the alias with all its destinations.""" if not self._dests: - raise AErr(_(u"The alias '%s' does not exist.") % self._addr, + raise AErr(_("The alias '%s' does not exist.") % self._addr, NO_SUCH_ALIAS) self._delete() del self._dests[:] diff -r d24f094d1cb5 -r 2bc11dada296 VirtualMailManager/aliasdomain.py --- a/VirtualMailManager/aliasdomain.py Sat Jan 05 23:49:42 2013 +0000 +++ b/VirtualMailManager/aliasdomain.py Sun Jan 06 00:09:47 2013 +0000 @@ -47,7 +47,7 @@ dbc.close() if result: if result[1]: - raise ADErr(_(u"The domain '%s' is a primary domain.") % + raise ADErr(_("The domain '%s' is a primary domain.") % self._name, ALIASDOMAIN_ISDOMAIN) self._gid = result[0] @@ -66,13 +66,13 @@ def save(self): """Stores information about the new AliasDomain in the database.""" if self._gid > 0: - raise ADErr(_(u"The alias domain '%s' already exists.") % + raise ADErr(_("The alias domain '%s' already exists.") % self._name, ALIASDOMAIN_EXISTS) if not self._domain: - raise ADErr(_(u'No destination domain set for the alias domain.'), + raise ADErr(_('No destination domain set for the alias domain.'), ALIASDOMAIN_NO_DOMDEST) if self._domain.gid < 1: - raise ADErr(_(u"The target domain '%s' does not exist.") % + raise ADErr(_("The target domain '%s' does not exist.") % self._domain.name, NO_SUCH_DOMAIN) dbc = self._dbh.cursor() dbc.execute('INSERT INTO domain_name (domainname, gid, is_primary) ' @@ -85,7 +85,7 @@ """Returns a dict (keys: "alias" and "domain") with the names of the AliasDomain and its primary domain.""" if self._gid < 1: - raise ADErr(_(u"The alias domain '%s' does not exist.") % + raise ADErr(_("The alias domain '%s' does not exist.") % self._name, NO_SUCH_ALIASDOMAIN) dbc = self._dbh.cursor() dbc.execute('SELECT domainname FROM domain_name WHERE gid = %s AND ' @@ -95,25 +95,25 @@ if domain: return {'alias': self._name, 'domain': domain[0]} else: # an almost unlikely case, isn't it? - raise ADErr(_(u'There is no primary domain for the alias domain ' - u"'%s'.") % self._name, NO_SUCH_DOMAIN) + raise ADErr(_('There is no primary domain for the alias domain ' + "'%s'.") % self._name, NO_SUCH_DOMAIN) def switch(self): """Switch the destination of the AliasDomain to the new destination, set with the method `set_destination()`. """ if not self._domain: - raise ADErr(_(u'No destination domain set for the alias domain.'), + raise ADErr(_('No destination domain set for the alias domain.'), ALIASDOMAIN_NO_DOMDEST) if self._domain.gid < 1: - raise ADErr(_(u"The target domain '%s' does not exist.") % + raise ADErr(_("The target domain '%s' does not exist.") % self._domain.name, NO_SUCH_DOMAIN) if self._gid < 1: - raise ADErr(_(u"The alias domain '%s' does not exist.") % + raise ADErr(_("The alias domain '%s' does not exist.") % self._name, NO_SUCH_ALIASDOMAIN) if self._gid == self._domain.gid: - raise ADErr(_(u"The alias domain '%(alias)s' is already assigned " - u"to the domain '%(domain)s'.") % + raise ADErr(_("The alias domain '%(alias)s' is already assigned " + "to the domain '%(domain)s'.") % {'alias': self._name, 'domain': self._domain.name}, ALIASDOMAIN_EXISTS) dbc = self._dbh.cursor() @@ -130,7 +130,7 @@ Raises an AliasDomainError if the AliasDomain doesn't exist. """ if self._gid < 1: - raise ADErr(_(u"The alias domain '%s' does not exist.") % + raise ADErr(_("The alias domain '%s' does not exist.") % self._name, NO_SUCH_ALIASDOMAIN) dbc = self._dbh.cursor() dbc.execute('DELETE FROM domain_name WHERE domainname = %s AND NOT ' diff -r d24f094d1cb5 -r 2bc11dada296 VirtualMailManager/catchall.py --- a/VirtualMailManager/catchall.py Sat Jan 05 23:49:42 2013 +0000 +++ b/VirtualMailManager/catchall.py Sun Jan 06 00:09:47 2013 +0000 @@ -23,7 +23,6 @@ EmailAddress, DestinationEmailAddress as DestAddr from VirtualMailManager.errors import AliasError as AErr from VirtualMailManager.ext.postconf import Postconf -from VirtualMailManager.pycompat import all from VirtualMailManager.constants import \ ALIAS_EXCEEDS_EXPANSION_LIMIT, NO_SUCH_ALIAS, NO_SUCH_DOMAIN @@ -41,7 +40,7 @@ self._dbh = dbh self._gid = get_gid(self._dbh, self.domain) if not self._gid: - raise AErr(_(u"The domain '%s' does not exist.") % + raise AErr(_("The domain '%s' does not exist.") % self.domain, NO_SUCH_DOMAIN) self._dests = [] @@ -60,13 +59,13 @@ def _check_expansion(self, count_new): """Checks the current expansion limit of the alias.""" postconf = Postconf(cfg_dget('bin.postconf')) - limit = long(postconf.read('virtual_alias_expansion_limit')) + limit = int(postconf.read('virtual_alias_expansion_limit')) dcount = len(self._dests) failed = False if dcount == limit or dcount + count_new > limit: failed = True errmsg = _( -u"""Cannot add %(count_new)i new destination(s) to catch-all alias for +"""Cannot add %(count_new)i new destination(s) to catch-all alias for domain '%(domain)s'. Currently this alias expands into %(count)i/%(limit)i recipients. %(count_new)i additional destination(s) will render this alias unusable. @@ -74,7 +73,7 @@ elif dcount > limit: failed = True errmsg = _( -u"""Cannot add %(count_new)i new destination(s) to catch-all alias for domain +"""Cannot add %(count_new)i new destination(s) to catch-all alias for domain '%(domain)s'. This alias already exceeds its expansion limit \ (%(count)i/%(limit)i). So its unusable, all messages addressed to this alias will be bounced. @@ -148,16 +147,16 @@ if not warnings is None: assert isinstance(warnings, list) if not self._dests: - raise AErr(_(u"There are no catch-all aliases defined for " - u"domain '%s'.") % self._domain, NO_SUCH_ALIAS) + raise AErr(_("There are no catch-all aliases defined for " + "domain '%s'.") % self._domain, NO_SUCH_ALIAS) unknown = destinations.difference(set(self._dests)) if unknown: destinations.intersection_update(set(self._dests)) if not warnings is None: warnings.extend(unknown) if not destinations: - raise AErr(_(u"No suitable destinations left to remove from the " - u"catch-all alias of domain '%s'.") % self._domain, + raise AErr(_("No suitable destinations left to remove from the " + "catch-all alias of domain '%s'.") % self._domain, NO_SUCH_ALIAS) self._delete(destinations) for destination in destinations: @@ -166,15 +165,15 @@ def get_destinations(self): """Returns an iterator for all destinations of the catchall alias.""" if not self._dests: - raise AErr(_(u"There are no catch-all aliases defined for " - u"domain '%s'.") % self._domain, NO_SUCH_ALIAS) + raise AErr(_("There are no catch-all aliases defined for " + "domain '%s'.") % self._domain, NO_SUCH_ALIAS) return iter(self._dests) def delete(self): """Deletes all catchall destinations for the domain.""" if not self._dests: - raise AErr(_(u"There are no catch-all aliases defined for " - u"domain '%s'.") % self._domain, NO_SUCH_ALIAS) + raise AErr(_("There are no catch-all aliases defined for " + "domain '%s'.") % self._domain, NO_SUCH_ALIAS) self._delete() del self._dests[:] diff -r d24f094d1cb5 -r 2bc11dada296 VirtualMailManager/cli/__init__.py --- a/VirtualMailManager/cli/__init__.py Sat Jan 05 23:49:42 2013 +0000 +++ b/VirtualMailManager/cli/__init__.py Sun Jan 06 00:09:47 2013 +0000 @@ -19,19 +19,20 @@ from VirtualMailManager.errors import VMMError -__all__ = ('prog', 'get_winsize', 'read_pass', 'w_err', 'w_std') +__all__ = ('get_winsize', 'read_pass', 'w_err', 'w_std') _ = lambda msg: msg _std_write = os.sys.stdout.write _err_write = os.sys.stderr.write -prog = os.path.basename(os.sys.argv[0]) def w_std(*args): """Writes a line for each arg of *args*, encoded in the current ENCODING, to stdout. """ - _std_write('\n'.join(a.encode(ENCODING, 'replace') for a in args) + '\n') + _std_write('\n'.join(arg.encode(ENCODING, 'replace').decode(ENCODING, + 'replace') + for arg in args) + '\n') def w_err(code, *args): @@ -40,7 +41,9 @@ This function optionally interrupts the program execution if *code* does not equal to 0. *code* will be used as the system exit status. """ - _err_write('\n'.join(a.encode(ENCODING, 'replace') for a in args) + '\n') + _err_write('\n'.join(arg.encode(ENCODING, 'replace').decode(ENCODING, + 'replace') + for arg in args) + '\n') if code: os.sys.exit(code) @@ -75,24 +78,24 @@ Throws a VMMError after the third failure. """ # TP: Please preserve the trailing space. - readp_msg0 = _(u'Enter new password: ').encode(ENCODING, 'replace') + readp_msg0 = _('Enter new password: ') # TP: Please preserve the trailing space. - readp_msg1 = _(u'Retype new password: ').encode(ENCODING, 'replace') + readp_msg1 = _('Retype new password: ') mismatched = True failures = 0 while mismatched: if failures > 2: - raise VMMError(_(u'Too many failures - try again later.'), + raise VMMError(_('Too many failures - try again later.'), VMM_TOO_MANY_FAILURES) clear0 = getpass(prompt=readp_msg0) clear1 = getpass(prompt=readp_msg1) if clear0 != clear1: failures += 1 - w_err(0, _(u'Sorry, passwords do not match.')) + w_err(0, _('Sorry, passwords do not match.')) continue if not clear0: failures += 1 - w_err(0, _(u'Sorry, empty passwords are not permitted.')) + w_err(0, _('Sorry, empty passwords are not permitted.')) continue mismatched = False return clear0 diff -r d24f094d1cb5 -r 2bc11dada296 VirtualMailManager/cli/clihelp.py --- a/VirtualMailManager/cli/clihelp.py Sat Jan 05 23:49:42 2013 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,261 +0,0 @@ -# -*- coding: UTF-8 -*- -# Copyright (c) 2012 - 2013, Pascal Volk -# See COPYING for distribution information. -""" - VirtualMailManager.cli.vmmhelp - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Virtual Mail Manager's command line help. -""" - -_ = lambda msg: msg - -help_msgs = { -# TP: There are some words enclosed within angle brackets '<'word'>'. They -# are used to indicate replaceable arguments. Please do not translate them. -# -# The descriptions of subcommands may contain the both keywords 'domain' -# and 'force', enclosed within single quotes. Please keep them as they are. -# - # TP: description of subcommand configget - 'configget': (_(u"""This subcommand is used to display the actual value -of the given configuration