diff options
| author | Barry Warsaw | 2008-10-06 22:07:04 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2008-10-06 22:07:04 -0400 |
| commit | c7340d712c640fa5992518a7cf16272f634abccc (patch) | |
| tree | 99057710fbc7b92eaa1720daea4c3a6cd5929cf3 | |
| parent | 6f4351721559e8b7b577d3a01216fec88121ed11 (diff) | |
| parent | f0c9fad6372a645981b5c72fe02a6ad62f35790f (diff) | |
| download | mailman-c7340d712c640fa5992518a7cf16272f634abccc.tar.gz mailman-c7340d712c640fa5992518a7cf16272f634abccc.tar.zst mailman-c7340d712c640fa5992518a7cf16272f634abccc.zip | |
130 files changed, 434 insertions, 808 deletions
diff --git a/mailman/Archiver/Archiver.py b/mailman/Archiver/Archiver.py index 23757b427..313bd9a0a 100644 --- a/mailman/Archiver/Archiver.py +++ b/mailman/Archiver/Archiver.py @@ -34,7 +34,6 @@ from string import Template from mailman import Mailbox from mailman import Utils -from mailman.SafeDict import SafeDict from mailman.configuration import config from mailman.i18n import _ @@ -161,9 +160,9 @@ class Archiver: raise def ExternalArchive(self, ar, txt): - d = SafeDict({'listname': self.fqdn_listname, - 'hostname': self.host_name, - }) + cmd = Template(ar).safe_substitute( + listname=self.fqdn_listname, + hostname=self.host_name) cmd = ar % d extarch = os.popen(cmd, 'w') extarch.write(txt) diff --git a/mailman/Archiver/HyperArch.py b/mailman/Archiver/HyperArch.py index a376279cb..48e6d5835 100644 --- a/mailman/Archiver/HyperArch.py +++ b/mailman/Archiver/HyperArch.py @@ -42,14 +42,13 @@ from email.Charset import Charset from email.Errors import HeaderParseError from email.Header import decode_header, make_header from locknix.lockfile import Lock +from string import Template -from mailman import Errors from mailman import Utils from mailman import i18n from mailman.Archiver import HyperDatabase from mailman.Archiver import pipermail from mailman.Mailbox import ArchiverMailbox -from mailman.SafeDict import SafeDict from mailman.configuration import config log = logging.getLogger('mailman.error') @@ -200,15 +199,14 @@ def quick_maketext(templatefile, dict=None, lang=None, mlist=None): text = template if dict is not None: try: - sdict = SafeDict(dict) try: - text = sdict.interpolate(template) + text = Template(template).safe_substitute(**dict) except UnicodeError: # Try again after coercing the template to unicode utemplate = unicode(template, Utils.GetCharSet(lang), 'replace') - text = sdict.interpolate(utemplate) + text = Template(utemplate).safe_substitute(**dict) except (TypeError, ValueError): # The template is really screwed up pass diff --git a/mailman/Archiver/pipermail.py b/mailman/Archiver/pipermail.py index a7c4e3a98..19bc05c3f 100644 --- a/mailman/Archiver/pipermail.py +++ b/mailman/Archiver/pipermail.py @@ -17,8 +17,8 @@ __version__ = '0.11 (Mailman edition)' VERSION = __version__ CACHESIZE = 100 # Number of slots in the cache -from mailman import Errors from mailman.Mailbox import ArchiverMailbox +from mailman.core import errors from mailman.i18n import _ SPACE = ' ' @@ -548,7 +548,7 @@ class T: while counter < start: try: m = mbox.next() - except Errors.DiscardMessage: + except errors.DiscardMessage: continue if m is None: return @@ -557,7 +557,7 @@ class T: try: pos = input.tell() m = mbox.next() - except Errors.DiscardMessage: + except errors.DiscardMessage: continue except Exception: log.error('uncaught archiver exception at filepos: %s', pos) diff --git a/mailman/Defaults.py b/mailman/Defaults.py index 1f862657d..a0aad0b8e 100644 --- a/mailman/Defaults.py +++ b/mailman/Defaults.py @@ -236,8 +236,8 @@ DEFAULT_DIGEST_VOLUME_FREQUENCY = 1 # be a shell command string which will get passed to os.popen(). This string # can contain the following substitution strings: # -# %(listname)s -- gets the internal name of the list -# %(hostname)s -- gets the email hostname for the list +# $listname -- gets the internal name of the list +# $hostname -- gets the email hostname for the list # # being archived will be substituted for this. Please note that os.popen() is # used. diff --git a/mailman/SafeDict.py b/mailman/SafeDict.py deleted file mode 100644 index 31db1df67..000000000 --- a/mailman/SafeDict.py +++ /dev/null @@ -1,55 +0,0 @@ -# Copyright (C) 1998-2008 by the Free Software Foundation, Inc. -# -# This file is part of GNU Mailman. -# -# GNU Mailman is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation, either version 3 of the License, or (at your option) -# any later version. -# -# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. - -from mailman.configuration import config - -"""A `safe' dictionary for string interpolation.""" - -COMMASPACE = ', ' - -# XXX This module should go away. - - - -class SafeDict(dict): - """Dictionary which returns a default value for unknown keys. - - This is used in maketext so that editing templates is a bit more robust. - """ - def __init__(self, d='', charset=None, lang=None): - super(SafeDict, self).__init__(d) - if charset: - self.cset = charset - elif lang: - self.cset = config.languages.get_charset(lang) - else: - self.cset = 'us-ascii' - - def __getitem__(self, key): - try: - return super(SafeDict, self).__getitem__(key) - except KeyError: - if isinstance(key, basestring): - return '%('+key+')s' - else: - return '<Missing key: %s>' % `key` - - def interpolate(self, template): - for k, v in self.items(): - if isinstance(v, str): - self.__setitem__(k, unicode(v, self.cset)) - return template % self diff --git a/mailman/UserDesc.py b/mailman/UserDesc.py deleted file mode 100644 index cb89176ee..000000000 --- a/mailman/UserDesc.py +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (C) 2001-2008 by the Free Software Foundation, Inc. -# -# This file is part of GNU Mailman. -# -# GNU Mailman is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation, either version 3 of the License, or (at your option) -# any later version. -# -# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. - -"""User description class/structure, for ApprovedAddMember and friends.""" - - - -class UserDesc: - def __init__(self, address=None, fullname=None, password=None, - digest=None, lang=None): - if address is not None: - self.address = address - if fullname is not None: - self.fullname = fullname - if password is not None: - self.password = password - if digest is not None: - self.digest = digest - if lang is not None: - self.language = lang - - def __iadd__(self, other): - if getattr(other, 'address', None) is not None: - self.address = other.address - if getattr(other, 'fullname', None) is not None: - self.fullname = other.fullname - if getattr(other, 'password', None) is not None: - self.password = other.password - if getattr(other, 'digest', None) is not None: - self.digest = other.digest - if getattr(other, 'language', None) is not None: - self.language = other.language - return self - - def __repr__(self): - address = getattr(self, 'address', 'n/a') - fullname = getattr(self, 'fullname', 'n/a') - password = getattr(self, 'password', 'n/a') - digest = getattr(self, 'digest', 'n/a') - if digest == 0: - digest = 'no' - elif digest == 1: - digest = 'yes' - language = getattr(self, 'language', 'n/a') - # Make sure fullname and password are encoded if they're strings - if isinstance(fullname, unicode): - fullname = fullname.encode('ascii', 'replace') - if isinstance(password, unicode): - password = password.encode('ascii', 'replace') - return '<UserDesc %s (%s) [%s] [digest? %s] [%s]>' % ( - address, fullname, password, digest, language) diff --git a/mailman/Utils.py b/mailman/Utils.py index 7975cb9d3..b9e34d5cd 100644 --- a/mailman/Utils.py +++ b/mailman/Utils.py @@ -37,13 +37,13 @@ import email.Header import email.Iterators from email.Errors import HeaderParseError -from string import ascii_letters, digits, whitespace +from string import ascii_letters, digits, whitespace, Template import mailman.templates -from mailman import Errors + from mailman import passwords -from mailman.SafeDict import SafeDict from mailman.configuration import config +from mailman.core import errors AT = '@' CR = '\r' @@ -199,15 +199,15 @@ def ValidateEmail(s): """Verify that the an email address isn't grossly evil.""" # Pretty minimal, cheesy check. We could do better... if not s or ' ' in s: - raise Errors.InvalidEmailAddress(repr(s)) + raise errors.InvalidEmailAddress(repr(s)) if _badchars.search(s) or s[0] == '-': - raise Errors.InvalidEmailAddress(repr(s)) + raise errors.InvalidEmailAddress(repr(s)) user, domain_parts = ParseEmail(s) # Local, unqualified addresses are not allowed. if not domain_parts: - raise Errors.InvalidEmailAddress(repr(s)) + raise errors.InvalidEmailAddress(repr(s)) if len(domain_parts) < 2: - raise Errors.InvalidEmailAddress(repr(s)) + raise errors.InvalidEmailAddress(repr(s)) @@ -524,8 +524,7 @@ def findtext(templatefile, dict=None, raw=False, lang=None, mlist=None): text = template if dict is not None: try: - sdict = SafeDict(dict, lang=lang) - text = sdict.interpolate(template) + text = Template(template).safe_substitute(**dict) except (TypeError, ValueError): # The template is really screwed up log.exception('broken template: %s', filename) @@ -564,30 +563,6 @@ def GetRequestURI(fallback=None, escape=True): -# Wait on a dictionary of child pids -def reap(kids, func=None, once=False): - while kids: - if func: - func() - try: - pid, status = os.waitpid(-1, os.WNOHANG) - except OSError, e: - # If the child procs had a bug we might have no children - if e.errno <> errno.ECHILD: - raise - kids.clear() - break - if pid <> 0: - try: - del kids[pid] - except KeyError: - # Huh? How can this happen? - pass - if once: - break - - - def makedirs(path, mode=02775): try: omask = os.umask(0) diff --git a/mailman/app/commands.py b/mailman/app/commands.py index f35ea531e..6ff6fdf0a 100644 --- a/mailman/app/commands.py +++ b/mailman/app/commands.py @@ -23,8 +23,8 @@ __all__ = [ ] -from mailman.app.plugins import get_plugins from mailman.configuration import config +from mailman.core.plugins import get_plugins from mailman.interfaces import IEmailCommand diff --git a/mailman/app/lifecycle.py b/mailman/app/lifecycle.py index 7095c0f9a..b707fdbbd 100644 --- a/mailman/app/lifecycle.py +++ b/mailman/app/lifecycle.py @@ -17,24 +17,26 @@ """Application level list creation.""" +__metaclass__ = type +__all__ = [ + 'create_list', + 'remove_list', + ] + + import os import sys import shutil import logging -from mailman import Errors from mailman import Utils from mailman.Utils import ValidateEmail -from mailman.app.plugins import get_plugin -from mailman.app.styles import style_manager from mailman.configuration import config +from mailman.core import errors +from mailman.core.plugins import get_plugin +from mailman.core.styles import style_manager from mailman.interfaces import MemberRole -__all__ = [ - 'create_list', - 'remove_list', - ] - log = logging.getLogger('mailman.error') @@ -47,7 +49,7 @@ def create_list(fqdn_listname, owners=None): ValidateEmail(fqdn_listname) listname, domain = Utils.split_listname(fqdn_listname) if domain not in config.domains: - raise Errors.BadDomainSpecificationError(domain) + raise errors.BadDomainSpecificationError(domain) mlist = config.db.list_manager.create(fqdn_listname) for style in style_manager.lookup(mlist): # XXX FIXME. When we get rid of the wrapper object, this hack won't diff --git a/mailman/app/membership.py b/mailman/app/membership.py index 481e55a4e..775c5cf59 100644 --- a/mailman/app/membership.py +++ b/mailman/app/membership.py @@ -28,12 +28,12 @@ __all__ = [ from email.utils import formataddr -from mailman import Errors from mailman import Message from mailman import Utils from mailman import i18n from mailman.app.notifications import send_goodbye_message from mailman.configuration import config +from mailman.core import errors from mailman.interfaces import AlreadySubscribedError, DeliveryMode, MemberRole _ = i18n._ @@ -68,7 +68,7 @@ def add_member(mlist, address, realname, password, delivery_mode, language): # confirmations. pattern = Utils.get_pattern(address, mlist.ban_list) if pattern: - raise Errors.MembershipIsBanned(pattern) + raise errors.MembershipIsBanned(pattern) # Do the actual addition. First, see if there's already a user linked # with the given address. user = config.db.user_manager.get_user(address) diff --git a/mailman/app/moderator.py b/mailman/app/moderator.py index 2483d933e..7ef454c03 100644 --- a/mailman/app/moderator.py +++ b/mailman/app/moderator.py @@ -33,7 +33,6 @@ import logging from datetime import datetime from email.utils import formataddr, formatdate, getaddresses, make_msgid -from mailman import Errors from mailman import Message from mailman import Utils from mailman import i18n @@ -41,6 +40,7 @@ from mailman.app.membership import add_member, delete_member from mailman.app.notifications import ( send_admin_subscription_notice, send_welcome_message) from mailman.configuration import config +from mailman.core import errors from mailman.interfaces import Action, DeliveryMode, RequestType from mailman.interfaces.member import AlreadySubscribedError from mailman.queue import Switchboard @@ -310,7 +310,7 @@ def handle_unsubscription(mlist, id, action, comment=None): key, data = requestdb.get_request(id) try: delete_member(mlist, address) - except Errors.NotAMemberError: + except errors.NotAMemberError: # User has already been unsubscribed. pass slog.info('%s: deleted %s', mlist.fqdn_listname, address) diff --git a/mailman/archiving/__init__.py b/mailman/archiving/__init__.py index 203d4d78c..41dff720c 100644 --- a/mailman/archiving/__init__.py +++ b/mailman/archiving/__init__.py @@ -21,8 +21,8 @@ __all__ = [ ] -from mailman.app.plugins import get_plugins from mailman.configuration import config +from mailman.core.plugins import get_plugins def initialize(): diff --git a/mailman/Bouncer.py b/mailman/attic/Bouncer.py index 690525b37..690525b37 100644 --- a/mailman/Bouncer.py +++ b/mailman/attic/Bouncer.py diff --git a/mailman/Deliverer.py b/mailman/attic/Deliverer.py index 5fcc78edc..5fcc78edc 100644 --- a/mailman/Deliverer.py +++ b/mailman/attic/Deliverer.py diff --git a/mailman/Digester.py b/mailman/attic/Digester.py index d27ee62a6..d27ee62a6 100644 --- a/mailman/Digester.py +++ b/mailman/attic/Digester.py diff --git a/mailman/MailList.py b/mailman/attic/MailList.py index 705189751..705189751 100644 --- a/mailman/MailList.py +++ b/mailman/attic/MailList.py diff --git a/mailman/SecurityManager.py b/mailman/attic/SecurityManager.py index 45801d10a..45801d10a 100644 --- a/mailman/SecurityManager.py +++ b/mailman/attic/SecurityManager.py diff --git a/mailman/bin/__init__.py b/mailman/bin/__init__.py index eb7e7b846..4c3fc1673 100644 --- a/mailman/bin/__init__.py +++ b/mailman/bin/__init__.py @@ -20,7 +20,6 @@ __all__ = [ 'arch', 'bounces', 'bumpdigests', - 'change_pw', 'check_perms', 'checkdbs', 'cleanarch', diff --git a/mailman/bin/add_members.py b/mailman/bin/add_members.py index 98e14c5e6..613d2b322 100644 --- a/mailman/bin/add_members.py +++ b/mailman/bin/add_members.py @@ -24,7 +24,7 @@ import codecs from cStringIO import StringIO from email.utils import parseaddr -from mailman import Errors +from mailman import errors from mailman import Message from mailman import Utils from mailman import i18n @@ -122,7 +122,7 @@ def addall(mlist, subscribers, delivery_mode, ack, admin_notify, outfp): config.DEFAULT_SERVER_LANGUAGE, ack, admin_notify) except AlreadySubscribedError: print >> tee, _('Already a member: $subscriber') - except Errors.InvalidEmailAddress: + except errors.InvalidEmailAddress: if not address: print >> tee, _('Bad/Invalid email address: blank line') else: diff --git a/mailman/bin/bumpdigests.py b/mailman/bin/bumpdigests.py index 7cde0d9de..2739a0fe6 100644 --- a/mailman/bin/bumpdigests.py +++ b/mailman/bin/bumpdigests.py @@ -18,7 +18,7 @@ import sys import optparse -from mailman import Errors +from mailman import errors from mailman import MailList from mailman.configuration import config from mailman.i18n import _ @@ -58,7 +58,7 @@ def main(): try: # Be sure the list is locked mlist = MailList.MailList(listname) - except Errors.MMListError, e: + except errors.MMListError, e: parser.print_help() print >> sys.stderr, _('No such list: $listname') sys.exit(1) diff --git a/mailman/bin/change_pw.py b/mailman/bin/change_pw.py deleted file mode 100644 index e67b951d2..000000000 --- a/mailman/bin/change_pw.py +++ /dev/null @@ -1,177 +0,0 @@ -# Copyright (C) 2001-2008 by the Free Software Foundation, Inc. -# -# This file is part of GNU Mailman. -# -# GNU Mailman is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation, either version 3 of the License, or (at your option) -# any later version. -# -# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. - -from __future__ import with_statement - -import sha -import sys -import optparse - -from mailman import Errors -from mailman import MailList -from mailman import Message -from mailman import Utils -from mailman import i18n -from mailman.configuration import config -from mailman.version import MAILMAN_VERSION - -_ = i18n._ -SPACE = ' ' - - - -def parseargs(): - parser = optparse.OptionParser(version=MAILMAN_VERSION, - usage=_("""\ -%%prog [options] - -Change a list's password. - -Prior to Mailman 2.1, list passwords were kept in crypt'd format -- usually. -Some Python installations didn't have the crypt module available, so they'd -fall back to md5. Then suddenly the Python installation might grow a crypt -module and all list passwords would be broken. - -In Mailman 2.1, all list and site passwords are stored in SHA1 hexdigest -form. This breaks list passwords for all existing pre-Mailman 2.1 lists, and -since those passwords aren't stored anywhere in plain text, they cannot be -retrieved and updated. - -Thus, this script generates new passwords for a list, and optionally sends it -to all the owners of the list.""")) - parser.add_option('-a', '--all', - default=False, action='store_true', - help=_('Change the password for all lists')) - parser.add_option('-d', '--domain', - default=[], type='string', action='append', - dest='domains', help=_("""\ -Change the password for all lists in the virtual domain DOMAIN. It is okay -to give multiple -d options.""")) - parser.add_option('-l', '--listname', - default=[], type='string', action='append', - dest='listnames', help=_("""\ -Change the password only for the named list. It is okay to give multiple -l -options.""")) - parser.add_option('-p', '--password', - type='string', metavar='NEWPASSWORD', help=_("""\ -Use the supplied plain text password NEWPASSWORD as the new password for any -lists that are being changed (as specified by the -a, -d, and -l options). If -not given, lists will be assigned a randomly generated new password.""")) - parser.add_option('-q', '--quiet', - default=False, action='store_true', help=_("""\ -Don't notify list owners of the new password. You'll have to have some other -way of letting the list owners know the new password (presumably -out-of-band).""")) - parser.add_option('-C', '--config', - help=_('Alternative configuration file to use')) - opts, args = parser.parse_args() - if args: - parser.print_help() - print >> sys.stderr, _('Unexpected arguments') - sys.exit(1) - if opts.password == '': - parser.print_help() - print >> sys.stderr, _('Empty list passwords are not allowed') - sys.exit(1) - return parser, opts, args - - - -_listcache = {} -_missing = object() - -def openlist(listname): - missing = [] - mlist = _listcache.get(listname, _missing) - if mlist is _missing: - try: - mlist = MailList.MailList(listname, lock=False) - except Errors.MMListError: - print >> sys.stderr, _('No such list: $listname') - return None - _listcache[listname] = mlist - return mlist - - - -def main(): - parser, opts, args = parseargs() - config.load(opts.config) - - # Cull duplicates - domains = set(opts.domains) - listnames = set(config.list_manager.names if opts.all else opts.listnames) - - if domains: - for name in config.list_manager.names: - mlist = openlist(name) - if mlist.host_name in domains: - listnames.add(name) - - if not listnames: - print >> sys.stderr, _('Nothing to do.') - sys.exit(0) - - # Set the password on the lists - if opts.password: - shapassword = sha.new(opts.password).hexdigest() - - for listname in listnames: - mlist = openlist(listname) - mlist.Lock() - try: - if opts.password is None: - randompw = Utils.MakeRandomPassword( - config.ADMIN_PASSWORD_LENGTH) - shapassword = sha.new(randompw).hexdigest() - notifypassword = randompw - else: - notifypassword = opts.password - - mlist.password = shapassword - mlist.Save() - finally: - mlist.Unlock() - - # Notification - print _('New $listname password: $notifypassword') - if not opts.quiet: - with i18n.using_language(mlist.preferred_language): - hostname = mlist.host_name - adminurl = mlist.GetScriptURL('admin', absolute=True) - msg = Message.UserNotification( - mlist.owner[:], mlist.no_reply_address, - _('Your new $listname list password'), - _('''\ -The site administrator at $hostname has changed the password for your -mailing list $listname. It is now - - $notifypassword - -Please be sure to use this for all future list administration. You may want -to log in now to your list and change the password to something more to your -liking. Visit your list admin page at - - $adminurl -'''), - mlist.preferred_language) - msg.send(mlist) - - - -if __name__ == '__main__': - main() diff --git a/mailman/bin/config_list.py b/mailman/bin/config_list.py index 814b9640c..7fb3e73a7 100644 --- a/mailman/bin/config_list.py +++ b/mailman/bin/config_list.py @@ -20,7 +20,7 @@ import sys import time import optparse -from mailman import Errors +from mailman import errors from mailman import MailList from mailman import Utils from mailman import i18n @@ -97,7 +97,7 @@ def do_output(listname, outfile, parser): # Open the specified list unlocked, since we're only reading it. try: mlist = MailList.MailList(listname, lock=False) - except Errors.MMListError: + except errors.MMListError: parser.error(_('No such list: $listname')) # Preamble for the config info. PEP 263 charset and capture time. language = mlist.preferred_language @@ -246,7 +246,7 @@ def do_input(listname, infile, checkonly, verbose, parser): # Open the specified list locked, unless checkonly is set try: mlist = MailList.MailList(listname, lock=not checkonly) - except Errors.MMListError, e: + except errors.MMListError, e: parser.error(_('No such list "$listname"\n$e')) savelist = False guibyprop = getPropertyMap(mlist) @@ -278,7 +278,7 @@ def do_input(listname, infile, checkonly, verbose, parser): validval = gui._getValidValue(mlist, k, wtype, v) except ValueError: print >> sys.stderr, _('Invalid value for property: $k') - except Errors.EmailAddressError: + except errors.EmailAddressError: print >> sys.stderr, _( 'Bad email address for option $k: $v') else: diff --git a/mailman/bin/create_list.py b/mailman/bin/create_list.py index f581184dc..c25ab3283 100644 --- a/mailman/bin/create_list.py +++ b/mailman/bin/create_list.py @@ -19,7 +19,7 @@ from __future__ import with_statement import sys -from mailman import Errors +from mailman import errors from mailman import Message from mailman import Utils from mailman import i18n @@ -100,11 +100,11 @@ def main(): try: mlist = create_list(fqdn_listname, options.options.owners) mlist.preferred_language = options.options.language - except Errors.InvalidEmailAddress: + except errors.InvalidEmailAddress: options.parser.error(_('Illegal list name: $fqdn_listname')) except ListAlreadyExistsError: options.parser.error(_('List already exists: $fqdn_listname')) - except Errors.BadDomainSpecificationError, domain: + except errors.BadDomainSpecificationError, domain: options.parser.error(_('Undefined domain: $domain')) config.db.commit() diff --git a/mailman/bin/disabled.py b/mailman/bin/disabled.py index ae57757f1..31fd0c014 100644 --- a/mailman/bin/disabled.py +++ b/mailman/bin/disabled.py @@ -19,7 +19,7 @@ import time import logging import optparse -from mailman import Errors +from mailman import errors from mailman import MailList from mailman import MemberAdaptor from mailman import Pending @@ -183,7 +183,7 @@ def main(): member, mlist.internal_name()) try: mlist.sendNextNotification(member) - except Errors.NotAMemberError: + except errors.NotAMemberError: # There must have been some problem with the data we have # on this member. Most likely it's that they don't have a # password assigned. Log this and delete the member. diff --git a/mailman/bin/export.py b/mailman/bin/export.py index 1834205e7..e494d5a8d 100644 --- a/mailman/bin/export.py +++ b/mailman/bin/export.py @@ -29,7 +29,7 @@ import optparse from xml.sax.saxutils import escape from mailman import Defaults -from mailman import Errors +from mailman import errors from mailman import MemberAdaptor from mailman.MailList import MailList from mailman.configuration import config @@ -247,7 +247,7 @@ class XMLDumper(object): for listname in sorted(listnames): try: mlist = MailList(listname, lock=False) - except Errors.MMUnknownListError: + except errors.MMUnknownListError: print >> sys.stderr, _('No such list: $listname') continue self._dump_list(mlist) diff --git a/mailman/bin/find_member.py b/mailman/bin/find_member.py index e605767a7..605e243b4 100644 --- a/mailman/bin/find_member.py +++ b/mailman/bin/find_member.py @@ -19,7 +19,7 @@ import re import sys import optparse -from mailman import Errors +from mailman import errors from mailman import MailList from mailman.configuration import config from mailman.i18n import _ @@ -93,7 +93,7 @@ def main(): for listname in listnames: try: mlist = MailList.MailList(listname, lock=False) - except Errors.MMListError: + except errors.MMListError: print _('No such list: $listname') continue if opts.owners: diff --git a/mailman/bin/import.py b/mailman/bin/import.py index 51dffceb9..2617cca99 100644 --- a/mailman/bin/import.py +++ b/mailman/bin/import.py @@ -26,7 +26,7 @@ from xml.dom import minidom from xml.parsers.expat import ExpatError from mailman import Defaults -from mailman import Errors +from mailman import errors from mailman import MemberAdaptor from mailman import Utils from mailman import passwords @@ -202,7 +202,7 @@ def create(all_listdata): print _('Creating mailing list: $fqdn_listname') mlist.Create(fqdn_listname, list_config['owner'][0], list_config['password']) - except Errors.BadDomainSpecificationError: + except errors.BadDomainSpecificationError: print _('List is not in a supported domain: $fqdn_listname') continue # Save the list creation, then unlock and relock the list. This is so diff --git a/mailman/bin/list_members.py b/mailman/bin/list_members.py index 31bc61b0c..a5b047504 100644 --- a/mailman/bin/list_members.py +++ b/mailman/bin/list_members.py @@ -19,7 +19,7 @@ import sys from email.Utils import formataddr -from mailman import Errors +from mailman import errors from mailman import Utils from mailman.configuration import config from mailman.i18n import _ @@ -120,7 +120,7 @@ def isinvalid(addr): try: Utils.ValidateEmail(addr) return False - except Errors.EmailAddressError: + except errors.EmailAddressError: return True diff --git a/mailman/bin/qrunner.py b/mailman/bin/qrunner.py index 33c17f91d..422809fa3 100644 --- a/mailman/bin/qrunner.py +++ b/mailman/bin/qrunner.py @@ -149,9 +149,9 @@ def make_qrunner(name, slice, range, once=False): raise qrclass = getattr(sys.modules[modulename], classname) if once: - # Subclass to hack in the setting of the stop flag in _doperiodic() + # Subclass to hack in the setting of the stop flag in _do_periodic() class Once(qrclass): - def _doperiodic(self): + def _do_periodic(self): self.stop() qrunner = Once(slice, range) else: diff --git a/mailman/bin/remove_list.py b/mailman/bin/remove_list.py index 76db51f2d..b83c56bbf 100644 --- a/mailman/bin/remove_list.py +++ b/mailman/bin/remove_list.py @@ -19,7 +19,6 @@ import os import sys import shutil -from mailman import Errors from mailman import Utils from mailman.app.lifecycle import remove_list from mailman.configuration import config diff --git a/mailman/bin/withlist.py b/mailman/bin/withlist.py index daf009ca3..32bfb1206 100644 --- a/mailman/bin/withlist.py +++ b/mailman/bin/withlist.py @@ -19,7 +19,6 @@ import os import sys import optparse -from mailman import Errors from mailman import interact from mailman.configuration import config from mailman.i18n import _ @@ -105,7 +104,7 @@ As another example, say you wanted to change the password for a particular user on a particular list. You could put the following function in a file called 'changepw.py': - from mailman.Errors import NotAMemberError + from mailman.errors import NotAMemberError def changepw(mlist, addr, newpasswd): try: diff --git a/mailman/configuration.py b/mailman/configuration.py index 1c4612f32..070f82085 100644 --- a/mailman/configuration.py +++ b/mailman/configuration.py @@ -22,8 +22,8 @@ import sys import errno from mailman import Defaults -from mailman import Errors from mailman import version +from mailman.core import errors from mailman.domain import Domain from mailman.languages import LanguageManager @@ -184,11 +184,11 @@ class Configuration(object): """ domain = Domain(*args, **kws) if domain.email_host in self.domains: - raise Errors.BadDomainSpecificationError( + raise errors.BadDomainSpecificationError( 'Duplicate email host: %s' % domain.email_host) # Make sure there's only one mapping for the url_host if domain.url_host in self.domains.values(): - raise Errors.BadDomainSpecificationError( + raise errors.BadDomainSpecificationError( 'Duplicate url host: %s' % domain.url_host) # We'll do the reverse mappings on-demand. There shouldn't be too # many virtual hosts that it will really matter that much. diff --git a/mailman/Cgi/__init__.py b/mailman/core/__init__.py index e69de29bb..e69de29bb 100644 --- a/mailman/Cgi/__init__.py +++ b/mailman/core/__init__.py diff --git a/mailman/app/chains.py b/mailman/core/chains.py index bebbf5bee..bebbf5bee 100644 --- a/mailman/app/chains.py +++ b/mailman/core/chains.py diff --git a/mailman/Errors.py b/mailman/core/errors.py index 91e724195..0704acb4a 100644 --- a/mailman/Errors.py +++ b/mailman/core/errors.py @@ -26,22 +26,6 @@ class MailmanException(Exception): -# Exceptions for problems related to opening a list -class MMListError(MailmanException): pass - -class MMUnknownListError(MMListError): - def __init__(self, listname=None): - self._listname = listname - - def __str__(self): - return self._listname - - -# Membership exceptions -class MMMemberError(MailmanException): pass -class MMBadUserError(MMMemberError): pass -class MMAlreadyAMember(MMMemberError): pass - # "New" style membership exceptions (new w/ MM2.1) class MemberError(MailmanException): pass class NotAMemberError(MemberError): pass @@ -51,27 +35,6 @@ class CantDigestError(MemberError): pass class MustDigestError(MemberError): pass class MembershipIsBanned(MemberError): pass -# Exception hierarchy for various authentication failures, can be -# raised from functions in SecurityManager.py -class MMAuthenticationError(MailmanException): pass -class MMCookieError(MMAuthenticationError): pass -class MMExpiredCookieError(MMCookieError): pass -class MMInvalidCookieError(MMCookieError): pass - -# BAW: these still need to be converted to classes. -MMMustDigestError = "MMMustDigestError" -MMCantDigestError = "MMCantDigestError" -MMNeedApproval = "MMNeedApproval" -MMSubscribeNeedsConfirmation = "MMSubscribeNeedsConfirmation" -MMBadConfirmation = "MMBadConfirmation" -MMAlreadyDigested = "MMAlreadyDigested" -MMAlreadyUndigested = "MMAlreadyUndigested" - -MODERATED_LIST_MSG = "Moderated list" -IMPLICIT_DEST_MSG = "Implicit destination" -SUSPICIOUS_HEADER_MSG = "Suspicious header" -FORBIDDEN_SENDER_MSG = "Forbidden sender" - # New style class based exceptions. All the above errors should eventually be @@ -84,10 +47,6 @@ class MailmanError(MailmanException): class BadDomainSpecificationError(MailmanError): """The specification of a virtual domain is invalid or duplicated.""" -class MMLoopingPost(MailmanError): - """Post already went through this list!""" - pass - # Exception hierarchy for bad email address errors that can be raised from @@ -140,10 +99,6 @@ class SomeRecipientsFailed(HandlerError): self.tempfailures = tempfailures self.permfailures = permfailures -# multiple inheritance for backwards compatibility -class LoopError(DiscardMessage, MMLoopingPost): - """We've seen this message before""" - class RejectMessage(HandlerError): """The message will be bounced back to the sender""" def __init__(self, notice=None): @@ -166,7 +121,7 @@ class SubscriptionError(MailmanError): class HostileSubscriptionError(SubscriptionError): """A cross-subscription attempt was made. - + This exception gets raised when an invitee attempts to use the invitation to cross-subscribe to some other mailing list. """ @@ -177,14 +132,6 @@ class PasswordError(MailmanError): """A password related error.""" -class MMBadPasswordError(PasswordError, MMAuthenticationError): - """A bad password was given.""" - - -class MMPasswordsMustMatch(PasswordError, MMAuthenticationError): - """The given passwords don't match.""" - - class BadPasswordSchemeError(PasswordError): """A bad password scheme was given.""" diff --git a/mailman/app/pipelines.py b/mailman/core/pipelines.py index 949ed9e42..c790901b2 100644 --- a/mailman/app/pipelines.py +++ b/mailman/core/pipelines.py @@ -27,8 +27,8 @@ __all__ = [ from zope.interface import implements from zope.interface.verify import verifyObject -from mailman.app.plugins import get_plugins from mailman.configuration import config +from mailman.core.plugins import get_plugins from mailman.i18n import _ from mailman.interfaces import IHandler, IPipeline diff --git a/mailman/app/plugins.py b/mailman/core/plugins.py index cf22ad377..cf22ad377 100644 --- a/mailman/app/plugins.py +++ b/mailman/core/plugins.py diff --git a/mailman/app/rules.py b/mailman/core/rules.py index b48673690..2c1e4fb3b 100644 --- a/mailman/app/rules.py +++ b/mailman/core/rules.py @@ -17,15 +17,17 @@ """Various rule helpers""" -__all__ = ['initialize'] __metaclass__ = type +__all__ = [ + 'initialize', + ] from zope.interface import implements from zope.interface.verify import verifyObject -from mailman.app.plugins import get_plugins from mailman.configuration import config +from mailman.core.plugins import get_plugins from mailman.interfaces import IRule diff --git a/mailman/app/styles.py b/mailman/core/styles.py index 8f487177e..96104c204 100644 --- a/mailman/app/styles.py +++ b/mailman/core/styles.py @@ -30,8 +30,8 @@ from zope.interface import implements from zope.interface.verify import verifyObject from mailman import Utils -from mailman.app.plugins import get_plugins from mailman.configuration import config +from mailman.core.plugins import get_plugins from mailman.i18n import _ from mailman.interfaces import ( Action, DuplicateStyleError, IStyle, IStyleManager, NewsModeration, diff --git a/mailman/database/listmanager.py b/mailman/database/listmanager.py index 1fb416203..c4cebce4c 100644 --- a/mailman/database/listmanager.py +++ b/mailman/database/listmanager.py @@ -21,7 +21,6 @@ import datetime from zope.interface import implements -from mailman import Errors from mailman.Utils import split_listname, fqdn_listname from mailman.configuration import config from mailman.database.mailinglist import MailingList diff --git a/mailman/docs/bounces.txt b/mailman/docs/bounces.txt index 671e43a22..ff110c509 100644 --- a/mailman/docs/bounces.txt +++ b/mailman/docs/bounces.txt @@ -72,7 +72,7 @@ An error message can be given when the message is bounced, and this will be included in the payload of the text/plain part. The error message must be passed in as an instance of a RejectMessage exception. - >>> from mailman.Errors import RejectMessage + >>> from mailman.core.errors import RejectMessage >>> error = RejectMessage("This wasn't very important after all.") >>> bounce_message(mlist, msg, error) >>> len(switchboard.files) diff --git a/mailman/docs/chains.txt b/mailman/docs/chains.txt index 964ef0edb..1118df687 100644 --- a/mailman/docs/chains.txt +++ b/mailman/docs/chains.txt @@ -36,7 +36,7 @@ The Discard chain simply throws the message away. ... An important message. ... """) - >>> from mailman.app.chains import process + >>> from mailman.core.chains import process # XXX This checks the vette log file because there is no other evidence # that this chain has done anything. @@ -309,7 +309,6 @@ The previously created message is innocuous enough that it should pass through all default rules. This message will end up in the pipeline queue. >>> file_pos = fp.tell() - >>> from mailman.app.chains import process >>> process(mlist, msg, {}) >>> fp.seek(file_pos) >>> print 'LOG:', fp.read() diff --git a/mailman/docs/lifecycle.txt b/mailman/docs/lifecycle.txt index e5b0f726c..69f656208 100644 --- a/mailman/docs/lifecycle.txt +++ b/mailman/docs/lifecycle.txt @@ -57,7 +57,7 @@ Start by registering a test style. ... # Applies to any test list ... if 'test' in mailing_list.fqdn_listname: ... styles.append(self) - >>> from mailman.app.styles import style_manager + >>> from mailman.core.styles import style_manager >>> style_manager.register(TestStyle()) Using the higher level interface for creating a list, applies all matching diff --git a/mailman/docs/pipelines.txt b/mailman/docs/pipelines.txt index c4f8488a1..ab6b99aa3 100644 --- a/mailman/docs/pipelines.txt +++ b/mailman/docs/pipelines.txt @@ -13,7 +13,7 @@ message once it's started. >>> mlist.web_page_url = u'http://lists.example.com/archives/' >>> mlist.pipeline u'built-in' - >>> from mailman.app.pipelines import process + >>> from mailman.core.pipelines import process Processing a message diff --git a/mailman/docs/styles.txt b/mailman/docs/styles.txt index 88bdd9cf5..37b3b20e2 100644 --- a/mailman/docs/styles.txt +++ b/mailman/docs/styles.txt @@ -15,7 +15,7 @@ Let's start with a vanilla mailing list and a default style manager. >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> from mailman.app.styles import style_manager + >>> from mailman.core.styles import style_manager The default style diff --git a/mailman/i18n.py b/mailman/i18n.py index e9c58ad91..186965509 100644 --- a/mailman/i18n.py +++ b/mailman/i18n.py @@ -22,7 +22,6 @@ import string import gettext import mailman.messages -from mailman.SafeDict import SafeDict from mailman.configuration import config _translation = None diff --git a/mailman/initialize.py b/mailman/initialize.py index fd6fd5b26..ea7c294c8 100644 --- a/mailman/initialize.py +++ b/mailman/initialize.py @@ -32,7 +32,7 @@ from zope.interface.verify import verifyObject import mailman.configuration import mailman.loginit -from mailman.app.plugins import get_plugin +from mailman.core.plugins import get_plugin from mailman.interfaces import IDatabase @@ -88,11 +88,11 @@ def initialize_2(debug=False): mailman.configuration.config.db = database # Initialize the rules and chains. Do the imports here so as to avoid # circular imports. - from mailman.archiving import initialize as initialize_archivers - from mailman.app.chains import initialize as initialize_chains - from mailman.app.rules import initialize as initialize_rules - from mailman.app.pipelines import initialize as initialize_pipelines from mailman.app.commands import initialize as initialize_commands + from mailman.archiving import initialize as initialize_archivers + from mailman.core.chains import initialize as initialize_chains + from mailman.core.pipelines import initialize as initialize_pipelines + from mailman.core.rules import initialize as initialize_rules initialize_archivers() initialize_rules() initialize_chains() diff --git a/mailman/interfaces/member.py b/mailman/interfaces/member.py index a5e1caf07..009b18c91 100644 --- a/mailman/interfaces/member.py +++ b/mailman/interfaces/member.py @@ -31,7 +31,7 @@ __all__ = [ from munepy import Enum from zope.interface import Interface, Attribute -from mailman.Errors import SubscriptionError +from mailman.core.errors import SubscriptionError diff --git a/mailman/interfaces/runner.py b/mailman/interfaces/runner.py index d279c5e7a..28b15968c 100644 --- a/mailman/interfaces/runner.py +++ b/mailman/interfaces/runner.py @@ -29,3 +29,82 @@ class IRunner(Interface): def stop(): """Stop the queue runner on the next iteration through the loop.""" + + QDIR = Attribute('The queue directory. Overridden in subclasses.') + + SLEEPTIME = Attribute("""\ + The number of seconds this queue runner will sleep between iterations + through the main loop. If given, overrides + `config.QRUNNER_SLEEP_TIME` + """) + + def _one_iteration(): + """The work done in one iteration of the main loop. + + Can be overridden by subclasses. + + :return: The number of files still left to process. + :rtype: int + """ + + def _process_one_file(msg, msgdata): + """Process one queue file. + + :param msg: The message object. + :type msg: `email.message.Message` + :param msgdata: The message metadata. + :type msgdata: dict + """ + + def _clean_up(): + """Clean up upon exit from the main processing loop. + + Called when the queue runner's main loop is stopped, this should + perform any necessary resource deallocation. + """ + + def _dispose(mlist, msg, msgdata): + """Dispose of a single message destined for a mailing list. + + Called for each message that the queue runner is responsible for, this + is the primary overridable method for processing each message. + Subclasses, must provide implementation for this method. + + :param mlist: The mailing list this message is destined for. + :type mlist: `IMailingList` + :param msg: The message being processed. + :type msg: `email.message.Message` + :param msgdata: The message metadata. + :type msgdata: dict + :return: True if the message should continue to be queue, False if the + message should be deleted automatically. + :rtype: bool + """ + + def _do_periodic(): + """Do some arbitrary periodic processing. + + Called every once in a while both from the queue runner's main loop, + and from the runner's hash slice processing loop. You can do whatever + special periodic processing you want here. + """ + + def _snooze(filecnt): + """Sleep for a little while. + + :param filecnt: The number of messages in the queue the last time + through. Queue runners can decide to continue to do work, or + sleep for a while based on this value. By default, the base queue + runner only snoozes when there was nothing to do last time around. + :type filecnt: int + """ + + def _short_circuit(): + """Should processing be short-circuited? + + :return: True if the file processing loop should exit before it's + finished processing each message in the current slice of hash + space. False tells _one_iteration() to continue processing until + the current snapshot of hash space is exhausted. + :rtype: bool + """ diff --git a/mailman/messages/fr/LC_MESSAGES/mailman.po b/mailman/messages/fr/LC_MESSAGES/mailman.po index 6bccf8d9c..05cd532a4 100644 --- a/mailman/messages/fr/LC_MESSAGES/mailman.po +++ b/mailman/messages/fr/LC_MESSAGES/mailman.po @@ -13850,35 +13850,35 @@ msgstr "" #: templates/en/masthead.txt:1 msgid "" -"Send %(real_name)s mailing list submissions to\n" -"\t%(got_list_email)s\n" +"Send $real_name mailing list submissions to\n" +"\t$got_list_email\n" "\n" "To subscribe or unsubscribe via the World Wide Web, visit\n" -"\t%(got_listinfo_url)s\n" +"\t$got_listinfo_url\n" "or, via email, send a message with subject or body 'help' to\n" -"\t%(got_request_email)s\n" +"\t$got_request_email\n" "\n" "You can reach the person managing the list at\n" -"\t%(got_owner_email)s\n" +"\t$got_owner_email\n" "\n" "When replying, please edit your Subject line so it is more specific than\n" -"\"Re: Contents of %(real_name)s digest...\"" +"\"Re: Contents of $real_name digest...\"" msgstr "" -"Envoyez vos messages pour la liste %(real_name)s à\n" -"\t%(got_list_email)s\n" +"Envoyez vos messages pour la liste $real_name à\n" +"\t$got_list_email\n" "\n" "Pour vous (dés)abonner par le web, consultez\n" -"\t%(got_listinfo_url)s\n" +"\t$got_listinfo_url\n" "\n" "ou, par courriel, envoyez un message avec « help » dans le corps\n" "ou dans le sujet à\n" -"\t%(got_request_email)s\n" +"\t$got_request_email\n" "\n" "Vous pouvez contacter l'administrateur de la liste à l'adresse\n" -"\t%(got_owner_email)s\n" +"\t$got_owner_email\n" "\n" "Si vous répondez, n'oubliez pas de changer l'objet du message afin\n" -"qu'il soit plus spécifique que « Re: Contenu du groupe de %(real_name)s... »" +"qu'il soit plus spécifique que « Re: Contenu du groupe de $real_name... »" #: templates/en/newlist.txt:1 msgid "" diff --git a/mailman/passwords.py b/mailman/passwords.py index b353e7710..65bf8de05 100644 --- a/mailman/passwords.py +++ b/mailman/passwords.py @@ -30,7 +30,7 @@ from base64 import urlsafe_b64decode as decode from base64 import urlsafe_b64encode as encode from munepy import Enum -from mailman import Errors +from mailman.core import errors SALT_LENGTH = 20 # bytes ITERATIONS = 2000 @@ -221,7 +221,7 @@ def make_secret(password, scheme=None): password = password.encode('utf-8') scheme_class = _SCHEMES_BY_ENUM.get(scheme) if not scheme_class: - raise Errors.BadPasswordSchemeError(scheme) + raise errors.BadPasswordSchemeError(scheme) secret = scheme_class.make_secret(password) return '{%s}%s' % (scheme_class.TAG, secret) diff --git a/mailman/pipeline/acknowledge.py b/mailman/pipeline/acknowledge.py index a7e6f2ce8..41fc931ae 100644 --- a/mailman/pipeline/acknowledge.py +++ b/mailman/pipeline/acknowledge.py @@ -26,7 +26,6 @@ __all__ = ['Acknowledge'] from zope.interface import implements -from mailman import Errors from mailman import Message from mailman import Utils from mailman.configuration import config diff --git a/mailman/pipeline/calculate_recipients.py b/mailman/pipeline/calculate_recipients.py index a7e5f1521..f892435cd 100644 --- a/mailman/pipeline/calculate_recipients.py +++ b/mailman/pipeline/calculate_recipients.py @@ -28,10 +28,10 @@ __all__ = ['CalculateRecipients'] from zope.interface import implements -from mailman import Errors from mailman import Message from mailman import Utils from mailman.configuration import config +from mailman.core import errors from mailman.i18n import _ from mailman.interfaces import DeliveryStatus, IHandler @@ -83,7 +83,7 @@ class CalculateRecipients: Your urgent message to the %(realname)s mailing list was not authorized for delivery. The original message as received by Mailman is attached. """) - raise Errors.RejectMessage, Utils.wrap(text) + raise errors.RejectMessage, Utils.wrap(text) # Calculate the regular recipients of the message recips = set(member.address.address for member in mlist.regular_members.members diff --git a/mailman/pipeline/cook_headers.py b/mailman/pipeline/cook_headers.py index 348380078..362c8ecf7 100644 --- a/mailman/pipeline/cook_headers.py +++ b/mailman/pipeline/cook_headers.py @@ -18,20 +18,22 @@ """Cook a message's headers.""" __metaclass__ = type -__all__ = ['CookHeaders'] +__all__ = [ + 'CookHeaders', + ] import re -from email.Charset import Charset -from email.Errors import HeaderParseError -from email.Header import Header, decode_header, make_header -from email.Utils import parseaddr, formataddr, getaddresses +from email.charset import Charset +from email.errors import HeaderParseError +from email.header import Header, decode_header, make_header +from email.utils import parseaddr, formataddr, getaddresses from zope.interface import implements from mailman import Utils -from mailman.app.plugins import get_plugins from mailman.configuration import config +from mailman.core.plugins import get_plugins from mailman.i18n import _ from mailman.interfaces import IHandler, Personalization, ReplyToMunging from mailman.version import VERSION diff --git a/mailman/pipeline/decorate.py b/mailman/pipeline/decorate.py index a9f20f4d8..3e9c6360b 100644 --- a/mailman/pipeline/decorate.py +++ b/mailman/pipeline/decorate.py @@ -28,7 +28,6 @@ from email.MIMEText import MIMEText from string import Template from zope.interface import implements -from mailman import Errors from mailman import Utils from mailman.Message import Message from mailman.configuration import config diff --git a/mailman/pipeline/file_recipients.py b/mailman/pipeline/file_recipients.py index 3ca13b6e1..5f47059d3 100644 --- a/mailman/pipeline/file_recipients.py +++ b/mailman/pipeline/file_recipients.py @@ -28,7 +28,6 @@ import errno from zope.interface import implements -from mailman import Errors from mailman.i18n import _ from mailman.interfaces import IHandler diff --git a/mailman/pipeline/mime_delete.py b/mailman/pipeline/mime_delete.py index bfcdd39a9..9cb34297f 100644 --- a/mailman/pipeline/mime_delete.py +++ b/mailman/pipeline/mime_delete.py @@ -37,14 +37,14 @@ from email.Iterators import typed_subpart_iterator from os.path import splitext from zope.interface import implements -from mailman import Errors from mailman.Message import UserNotification from mailman.Utils import oneline -from mailman.version import VERSION from mailman.configuration import config +from mailman.core import errors from mailman.i18n import _ from mailman.interfaces import IHandler from mailman.queue import Switchboard +from mailman.version import VERSION log = logging.getLogger('mailman.error') @@ -231,7 +231,7 @@ def dispose(mlist, msg, msgdata, why): # filter_action == 0 just discards, see below if mlist.filter_action == 1: # Bounce the message to the original author - raise Errors.RejectMessage, why + raise errors.RejectMessage, why if mlist.filter_action == 2: # Forward it on to the list owner listname = mlist.internal_name() @@ -249,7 +249,7 @@ are receiving the only remaining copy of the discarded message. badq = Switchboard(config.BADQUEUE_DIR) badq.enqueue(msg, msgdata) # Most cases also discard the message - raise Errors.DiscardMessage + raise errors.DiscardMessage def get_file_ext(m): """ diff --git a/mailman/pipeline/moderate.py b/mailman/pipeline/moderate.py index 0463a5e9b..11471dd3a 100644 --- a/mailman/pipeline/moderate.py +++ b/mailman/pipeline/moderate.py @@ -22,10 +22,10 @@ import re from email.MIMEMessage import MIMEMessage from email.MIMEText import MIMEText -from mailman import Errors from mailman import Message from mailman import Utils from mailman.configuration import config +from mailman.core import errors from mailman.i18n import _ @@ -72,11 +72,11 @@ def process(mlist, msg, msgdata): else: # Use the default RejectMessage notice string text = None - raise Errors.RejectMessage, text + raise errors.RejectMessage, text elif mlist.member_moderation_action == 2: # Discard. BAW: Again, it would be nice if we could send a # discard notice to the sender - raise Errors.DiscardMessage + raise errors.DiscardMessage else: assert 0, 'bad member_moderation_action' # Should we do anything explict to mark this message as getting past @@ -135,10 +135,10 @@ def matches_p(sender, nonmembers): def do_reject(mlist): listowner = mlist.GetOwnerEmail() if mlist.nonmember_rejection_notice: - raise Errors.RejectMessage, \ + raise errors.RejectMessage, \ Utils.wrap(_(mlist.nonmember_rejection_notice)) else: - raise Errors.RejectMessage, Utils.wrap(_("""\ + raise errors.RejectMessage, Utils.wrap(_("""\ You are not allowed to post to this mailing list, and your message has been automatically rejected. If you think that your messages are being rejected in error, contact the mailing list owner at %(listowner)s.""")) @@ -164,4 +164,4 @@ def do_discard(mlist, msg): nmsg.attach(MIMEMessage(msg)) nmsg.send(mlist) # Discard this sucker - raise Errors.DiscardMessage + raise errors.DiscardMessage diff --git a/mailman/pipeline/scrubber.py b/mailman/pipeline/scrubber.py index f6187a1cd..8e2b1503e 100644 --- a/mailman/pipeline/scrubber.py +++ b/mailman/pipeline/scrubber.py @@ -39,12 +39,13 @@ from mimetypes import guess_all_extensions from zope.interface import implements from mailman import Utils -from mailman.Errors import DiscardMessage -from mailman.app.plugins import get_plugin from mailman.configuration import config +from mailman.core.errors import DiscardMessage +from mailman.core.plugins import get_plugin from mailman.i18n import _ from mailman.interfaces import IHandler + # Path characters for common platforms pre = re.compile(r'[/\\:]') # All other characters to strip out of Content-Disposition: filenames diff --git a/mailman/pipeline/smtp_direct.py b/mailman/pipeline/smtp_direct.py index 447c61c8b..7d9242417 100644 --- a/mailman/pipeline/smtp_direct.py +++ b/mailman/pipeline/smtp_direct.py @@ -43,9 +43,9 @@ from email.Header import Header from email.Utils import formataddr from zope.interface import implements -from mailman import Errors from mailman import Utils from mailman.configuration import config +from mailman.core import errors from mailman.i18n import _ from mailman.interfaces import IHandler, Personalization @@ -254,7 +254,7 @@ def process(mlist, msg, msgdata): failure_log.info('%s', template.safe_substitute(substitutions)) # Return the results if tempfailures or permfailures: - raise Errors.SomeRecipientsFailed(tempfailures, permfailures) + raise errors.SomeRecipientsFailed(tempfailures, permfailures) diff --git a/mailman/pipeline/to_digest.py b/mailman/pipeline/to_digest.py index d8d4ac669..7c868fe74 100644 --- a/mailman/pipeline/to_digest.py +++ b/mailman/pipeline/to_digest.py @@ -48,16 +48,16 @@ from email.parser import Parser from email.utils import formatdate, getaddresses, make_msgid from zope.interface import implements -from mailman import Errors from mailman import Message from mailman import Utils from mailman import i18n from mailman.Mailbox import Mailbox from mailman.Mailbox import Mailbox from mailman.configuration import config +from mailman.core import errors +from mailman.interfaces import DeliveryMode, DeliveryStatus, IHandler from mailman.pipeline.decorate import decorate from mailman.pipeline.scrubber import process as scrubber -from mailman.interfaces import DeliveryMode, DeliveryStatus, IHandler from mailman.queue import Switchboard @@ -321,7 +321,7 @@ def send_i18n_digests(mlist, mboxfp): # Use Mailman.pipeline.scrubber.process() to get plain text try: msg = scrubber(mlist, msg) - except Errors.DiscardMessage: + except errors.DiscardMessage: print >> plainmsg, _('[Message discarded by content filter]') continue # Honor the default setting diff --git a/mailman/queue/__init__.py b/mailman/queue/__init__.py index 351fa0bd2..290f53978 100644 --- a/mailman/queue/__init__.py +++ b/mailman/queue/__init__.py @@ -69,6 +69,19 @@ class Switchboard: implements(ISwitchboard) def __init__(self, whichq, slice=None, numslices=1, recover=False): + """Create a switchboard object. + + :param whichq: The queue directory. + :type whichq: str + :param slice: The slice number for this switchboard, or None. If not + None, it must be [0..`numslices`). + :type slice: int or None + :param numslices: The total number of slices to split this queue + directory into. It must be a power of 2. + :type numslices: int + :param recover: True if backup files should be recovered. + :type recover: bool + """ self._whichq = whichq # Create the directory if it doesn't yet exist. Utils.makedirs(self._whichq, 0770) @@ -84,9 +97,11 @@ class Switchboard: @property def queue_directory(self): + """See `ISwitchboard`.""" return self._whichq def enqueue(self, _msg, _metadata=None, **_kws): + """See `ISwitchboard`.""" if _metadata is None: _metadata = {} # Calculate the SHA hexdigest of the message to get a unique base @@ -133,6 +148,7 @@ class Switchboard: return filebase def dequeue(self, filebase): + """See `ISwitchboard`.""" # Calculate the filename from the given filebase. filename = os.path.join(self._whichq, filebase + '.pck') backfile = os.path.join(self._whichq, filebase + '.bak') @@ -174,9 +190,11 @@ class Switchboard: @property def files(self): + """See `ISwitchboard`.""" return self.get_files() def get_files(self, extension='.pck'): + """See `ISwitchboard`.""" times = {} lower = self._lower upper = self._upper @@ -199,6 +217,7 @@ class Switchboard: return [times[key] for key in sorted(times)] def recover_backup_files(self): + """See `ISwitchboard`.""" # Move all .bak files in our slice to .pck. It's impossible for both # to exist at the same time, so the move is enough to ensure that our # normal dequeuing process will handle them. @@ -216,7 +235,15 @@ class Runner: SLEEPTIME = None def __init__(self, slice=None, numslices=1): - self._kids = {} + """Create a queue runner. + + :param slice: The slice number for this queue runner. This is passed + directly to the underlying `ISwitchboard` object. + :type slice: int or None + :param numslices: The number of slices for this queue. Must be a + power of 2. + :type numslices: int + """ # Create our own switchboard. Don't use the switchboard cache because # we want to provide slice and numslice arguments. self._switchboard = Switchboard(self.QDIR, slice, numslices, True) @@ -230,54 +257,50 @@ class Runner: return '<%s at %s>' % (self.__class__.__name__, id(self)) def stop(self): + """See `IRunner`.""" self._stop = True def run(self): + """See `IRunner`.""" # Start the main loop for this queue runner. try: - try: - while True: - # Once through the loop that processes all the files in - # the queue directory. - filecnt = self._oneloop() - # Do the periodic work for the subclass. BAW: this - # shouldn't be called here. There should be one more - # _doperiodic() call at the end of the _oneloop() loop. - self._doperiodic() - # If the stop flag is set, we're done. - if self._stop: - break - # Give the runner an opportunity to snooze for a while, - # but pass it the file count so it can decide whether to - # do more work now or not. - self._snooze(filecnt) - except KeyboardInterrupt: - pass + while True: + # Once through the loop that processes all the files in the + # queue directory. + filecnt = self._one_iteration() + # Do the periodic work for the subclass. + self._do_periodic() + # If the stop flag is set, we're done. + if self._stop: + break + # Give the runner an opportunity to snooze for a while, but + # pass it the file count so it can decide whether to do more + # work now or not. + self._snooze(filecnt) + except KeyboardInterrupt: + pass finally: - # We've broken out of our main loop, so we want to reap all the - # subprocesses we've created and do any other necessary cleanups. - self._cleanup() + self._clean_up() - def _oneloop(self): + def _one_iteration(self): + """See `IRunner`.""" me = self.__class__.__name__ dlog.debug('[%s] starting oneloop', me) - # First, list all the files in our queue directory. - # Switchboard.files() is guaranteed to hand us the files in FIFO - # order. Return an integer count of the number of files that were - # available for this qrunner to process. + # List all the files in our queue directory. The switchboard is + # guaranteed to hand us the files in FIFO order. files = self._switchboard.files for filebase in files: dlog.debug('[%s] processing filebase: %s', me, filebase) try: # Ask the switchboard for the message and metadata objects - # associated with this filebase. + # associated with this queue file. msg, msgdata = self._switchboard.dequeue(filebase) except Exception, e: - # This used to just catch email.Errors.MessageParseError, - # but other problems can occur in message parsing, e.g. - # ValueError, and exceptions can occur in unpickling too. - # We don't want the runner to die, so we just log and skip - # this entry, but preserve it for analysis. + # This used to just catch email.Errors.MessageParseError, but + # other problems can occur in message parsing, e.g. + # ValueError, and exceptions can occur in unpickling too. We + # don't want the runner to die, so we just log and skip this + # entry, but preserve it for analysis. self._log(e) elog.error('Skipping and preserving unparseable message: %s', filebase) @@ -286,7 +309,7 @@ class Runner: continue try: dlog.debug('[%s] processing onefile', me) - self._onefile(msg, msgdata) + self._process_one_file(msg, msgdata) dlog.debug('[%s] finishing filebase: %s', me, filebase) self._switchboard.finish(filebase) except Exception, e: @@ -297,7 +320,7 @@ class Runner: # cause the message to be stored in the shunt queue for human # intervention. self._log(e) - # Put a marker in the metadata for unshunting + # Put a marker in the metadata for unshunting. msgdata['whichq'] = self._switchboard.queue_directory # It is possible that shunting can throw an exception, e.g. a # permissions problem or a MemoryError due to a really large @@ -317,12 +340,10 @@ class Runner: self._switchboard.finish(filebase, preserve=True) config.db.abort() # Other work we want to do each time through the loop. - dlog.debug('[%s] reaping', me) - Utils.reap(self._kids, once=True) dlog.debug('[%s] doing periodic', me) - self._doperiodic() + self._do_periodic() dlog.debug('[%s] checking short circuit', me) - if self._shortcircuit(): + if self._short_curcuit(): dlog.debug('[%s] short circuiting', me) break dlog.debug('[%s] commiting', me) @@ -330,43 +351,36 @@ class Runner: dlog.debug('[%s] ending oneloop: %s', me, len(files)) return len(files) - def _onefile(self, msg, msgdata): + def _process_one_file(self, msg, msgdata): + """See `IRunner`.""" # Do some common sanity checking on the message metadata. It's got to # be destined for a particular mailing list. This switchboard is used # to shunt off badly formatted messages. We don't want to just trash # them because they may be fixable with human intervention. Just get - # them out of our site though. + # them out of our sight. # # Find out which mailing list this message is destined for. listname = msgdata.get('listname') mlist = config.db.list_manager.get(listname) - if not mlist: + if mlist is None: elog.error('Dequeuing message destined for missing list: %s', listname) self._shunt.enqueue(msg, msgdata) return - # Now process this message, keeping track of any subprocesses that may - # have been spawned. We'll reap those later. - # - # We also want to set up the language context for this message. The - # context will be the preferred language for the user if a member of - # the list, or the list's preferred language. However, we must take + # Now process this message. We also want to set up the language + # context for this message. The context will be the preferred + # language for the user if the sender is a member of the list, or it + # will be the list's preferred language. However, we must take # special care to reset the defaults, otherwise subsequent messages - # may be translated incorrectly. BAW: I'm not sure I like this - # approach, but I can't think of anything better right now. + # may be translated incorrectly. sender = msg.get_sender() member = mlist.members.get_member(sender) - if member: - lang = member.preferred_language - else: - lang = mlist.preferred_language - with i18n.using_language(lang): - msgdata['lang'] = lang + language = (member.preferred_language + if member is not None + else mlist.preferred_language) + with i18n.using_language(language): + msgdata['lang'] = language keepqueued = self._dispose(mlist, msg, msgdata) - # Keep tabs on any child processes that got spawned. - kids = msgdata.get('_kids') - if kids: - self._kids.update(kids) if keepqueued: self._switchboard.enqueue(msg, msgdata) @@ -376,60 +390,23 @@ class Runner: traceback.print_exc(file=s) elog.error('%s', s.getvalue()) - # - # Subclasses can override these methods. - # - def _cleanup(self): - """Clean up upon exit from the main processing loop. - - Called when the Runner's main loop is stopped, this should perform - any necessary resource deallocation. Its return value is irrelevant. - """ - Utils.reap(self._kids) + def _clean_up(self): + """See `IRunner`.""" def _dispose(self, mlist, msg, msgdata): - """Dispose of a single message destined for a mailing list. - - Called for each message that the Runner is responsible for, this is - the primary overridable method for processing each message. - Subclasses, must provide implementation for this method. - - mlist is the IMailingList instance this message is destined for. - - msg is the Message object representing the message. - - msgdata is a dictionary of message metadata. - """ + """See `IRunner`.""" raise NotImplementedError - def _doperiodic(self): - """Do some processing `every once in a while'. - - Called every once in a while both from the Runner's main loop, and - from the Runner's hash slice processing loop. You can do whatever - special periodic processing you want here, and the return value is - irrelevant. - """ + def _do_periodic(self): + """See `IRunner`.""" pass def _snooze(self, filecnt): - """Sleep for a little while. - - filecnt is the number of messages in the queue the last time through. - Sub-runners can decide to continue to do work, or sleep for a while - based on this value. By default, we only snooze if there was nothing - to do last time around. - """ + """See `IRunner`.""" if filecnt or float(self.SLEEPTIME) <= 0: return time.sleep(float(self.SLEEPTIME)) - def _shortcircuit(self): - """Return a true value if the individual file processing loop should - exit before it's finished processing each message in the current slice - of hash space. A false value tells _oneloop() to continue processing - until the current snapshot of hash space is exhausted. - - You could, for example, implement a throttling algorithm here. - """ + def _short_curcuit(self): + """See `IRunner`.""" return self._stop diff --git a/mailman/queue/archive.py b/mailman/queue/archive.py index 32c49804f..a10ae3e9c 100644 --- a/mailman/queue/archive.py +++ b/mailman/queue/archive.py @@ -32,8 +32,8 @@ from datetime import datetime from email.Utils import parsedate_tz, mktime_tz, formatdate from locknix.lockfile import Lock -from mailman.app.plugins import get_plugins from mailman.configuration import config +from mailman.core.plugins import get_plugins from mailman.queue import Runner diff --git a/mailman/queue/bounce.py b/mailman/queue/bounce.py index cfd86be60..0c5788174 100644 --- a/mailman/queue/bounce.py +++ b/mailman/queue/bounce.py @@ -51,7 +51,7 @@ class BounceMixin: # # today is itself a 3-tuple of (year, month, day) # - # Every once in a while (see _doperiodic()), the bounce runner cracks + # Every once in a while (see _do_periodic()), the bounce runner cracks # open the file, reads all the records and registers all the bounces. # Then it truncates the file and continues on. We don't need to lock # the bounce event file because bounce qrunners are single threaded @@ -123,11 +123,11 @@ class BounceMixin: os.unlink(self._bounce_events_file) self._bouncecnt = 0 - def _cleanup(self): + def _clean_up(self): if self._bouncecnt > 0: self._register_bounces() - def _doperiodic(self): + def _do_periodic(self): now = datetime.datetime.now() if self._nextaction > now or self._bouncecnt == 0: return @@ -218,11 +218,11 @@ class BounceRunner(Runner, BounceMixin): addrs = filter(None, addrs) self._queue_bounces(mlist.fqdn_listname, addrs, msg) - _doperiodic = BounceMixin._doperiodic + _do_periodic = BounceMixin._do_periodic - def _cleanup(self): - BounceMixin._cleanup(self) - Runner._cleanup(self) + def _clean_up(self): + BounceMixin._clean_up(self) + Runner._clean_up(self) diff --git a/mailman/queue/docs/runner.txt b/mailman/queue/docs/runner.txt index e95e20ecd..a9e17370b 100644 --- a/mailman/queue/docs/runner.txt +++ b/mailman/queue/docs/runner.txt @@ -34,7 +34,7 @@ This is about as simple as a qrunner can be. ... self.msgdata = msgdata ... return False ... - ... def _doperiodic(self): + ... def _do_periodic(self): ... self.stop() ... ... def _snooze(self, filecnt): diff --git a/mailman/queue/http.py b/mailman/queue/http.py index bbbef51df..cb6940b29 100644 --- a/mailman/queue/http.py +++ b/mailman/queue/http.py @@ -37,7 +37,7 @@ class HTTPRunner(Runner): def __init__(self, slice=None, numslices=1): pass - def _cleanup(self): + def _clean_up(self): pass diff --git a/mailman/queue/incoming.py b/mailman/queue/incoming.py index 635b1833a..d4decd435 100644 --- a/mailman/queue/incoming.py +++ b/mailman/queue/incoming.py @@ -26,8 +26,8 @@ prepared for delivery. Rejections, discards, and holds are processed immediately. """ -from mailman.app.chains import process from mailman.configuration import config +from mailman.core.chains import process from mailman.queue import Runner diff --git a/mailman/queue/maildir.py b/mailman/queue/maildir.py index 4a6c0f250..71bac67dc 100644 --- a/mailman/queue/maildir.py +++ b/mailman/queue/maildir.py @@ -98,7 +98,7 @@ class MaildirRunner(Runner): self._cur = os.path.join(config.MAILDIR_DIR, 'cur') self._parser = Parser(Message) - def _oneloop(self): + def _one_iteration(self): # Refresh this each time through the list. listnames = list(config.list_manager.names) # Cruise through all the files currently in the new/ directory @@ -185,5 +185,5 @@ class MaildirRunner(Runner): os.rename(dstname, xdstname) log.error('%s', e) - def _cleanup(self): + def _clean_up(self): pass diff --git a/mailman/queue/outgoing.py b/mailman/queue/outgoing.py index 42b2d71db..3ab67eaad 100644 --- a/mailman/queue/outgoing.py +++ b/mailman/queue/outgoing.py @@ -26,14 +26,14 @@ import logging from datetime import datetime -from mailman import Errors from mailman import Message from mailman.configuration import config +from mailman.core import errors from mailman.queue import Runner, Switchboard from mailman.queue.bounce import BounceMixin -# This controls how often _doperiodic() will try to deal with deferred -# permanent failures. It is a count of calls to _doperiodic() +# This controls how often _do_periodic() will try to deal with deferred +# permanent failures. It is a count of calls to _do_periodic() DEAL_WITH_PERMFAILURES_EVERY = 10 log = logging.getLogger('mailman.error') @@ -82,7 +82,7 @@ class OutgoingRunner(Runner, BounceMixin): config.SMTPHOST, port) self._logged = True return True - except Errors.SomeRecipientsFailed, e: + except errors.SomeRecipientsFailed, e: # Handle local rejects of probe messages differently. if msgdata.get('probe_token') and e.permfailures: self._probe_bounce(mlist, msgdata['probe_token']) @@ -123,8 +123,8 @@ class OutgoingRunner(Runner, BounceMixin): # We've successfully completed handling of this message return False - _doperiodic = BounceMixin._doperiodic + _do_periodic = BounceMixin._do_periodic - def _cleanup(self): - BounceMixin._cleanup(self) - Runner._cleanup(self) + def _clean_up(self): + BounceMixin._clean_up(self) + Runner._clean_up(self) diff --git a/mailman/rules/docs/emergency.txt b/mailman/rules/docs/emergency.txt index 56eceaccb..6437ba626 100644 --- a/mailman/rules/docs/emergency.txt +++ b/mailman/rules/docs/emergency.txt @@ -19,7 +19,7 @@ list are held for moderator approval. The emergency rule is matched as part of the built-in chain. The emergency rule matches if the flag is set on the mailing list. - >>> from mailman.app.chains import process + >>> from mailman.core.chains import process >>> mlist.emergency = True >>> process(mlist, msg, {}, 'built-in') diff --git a/mailman/rules/docs/header-matching.txt b/mailman/rules/docs/header-matching.txt index 78554526a..0dd917a71 100644 --- a/mailman/rules/docs/header-matching.txt +++ b/mailman/rules/docs/header-matching.txt @@ -28,7 +28,7 @@ the chain untouched (i.e. no disposition). ... This is a message. ... """) - >>> from mailman.app.chains import process + >>> from mailman.core.chains import process Pass through is seen as nothing being in the log file after processing. diff --git a/mailman/templates/en/adminaddrchgack.txt b/mailman/templates/en/adminaddrchgack.txt index a24dd3d91..1b66a2fcf 100644 --- a/mailman/templates/en/adminaddrchgack.txt +++ b/mailman/templates/en/adminaddrchgack.txt @@ -1,4 +1,4 @@ -Address for member %(name)s has been successfully changed -from %(oldaddr)s to %(newaddr)s for list %(listname)s. +Address for member $name has been successfully changed +from $oldaddr to $newaddr for list $listname. diff --git a/mailman/templates/en/adminsubscribeack.txt b/mailman/templates/en/adminsubscribeack.txt index 5e8ee6cf8..5d5f36417 100644 --- a/mailman/templates/en/adminsubscribeack.txt +++ b/mailman/templates/en/adminsubscribeack.txt @@ -1 +1 @@ -%(member)s has been successfully subscribed to %(listname)s. +$member has been successfully subscribed to $listname. diff --git a/mailman/templates/en/adminunsubscribeack.txt b/mailman/templates/en/adminunsubscribeack.txt index fb87ac87d..a6ed99f59 100644 --- a/mailman/templates/en/adminunsubscribeack.txt +++ b/mailman/templates/en/adminunsubscribeack.txt @@ -1 +1 @@ -%(member)s has been removed from %(listname)s. +$member has been removed from $listname. diff --git a/mailman/templates/en/approve.txt b/mailman/templates/en/approve.txt index dfb0dfb1e..10ab69356 100644 --- a/mailman/templates/en/approve.txt +++ b/mailman/templates/en/approve.txt @@ -1,6 +1,6 @@ -Your request to %(requestaddr)s: +Your request to $requestaddr: - %(cmd)s + $cmd has been forwarded to the person running the list. @@ -12,4 +12,4 @@ your subscription request. Any questions about the list owner's policy should be directed to: - %(adminaddr)s + $adminaddr diff --git a/mailman/templates/en/archidxentry.html b/mailman/templates/en/archidxentry.html index f9bb57aab..1927ae7fe 100644 --- a/mailman/templates/en/archidxentry.html +++ b/mailman/templates/en/archidxentry.html @@ -1,4 +1,4 @@ -<LI><A HREF="%(filename)s">%(subject)s -</A><A NAME="%(sequence)i"> </A> -<I>%(author)s +<LI><A HREF="$filename">$subject +</A><A NAME="$sequence"> </A> +<I>$author </I> diff --git a/mailman/templates/en/archidxfoot.html b/mailman/templates/en/archidxfoot.html index 0b0a42075..6a43546ea 100644 --- a/mailman/templates/en/archidxfoot.html +++ b/mailman/templates/en/archidxfoot.html @@ -1,21 +1,21 @@ </ul> <p> <a name="end"><b>Last message date:</b></a> - <i>%(lastdate)s</i><br> - <b>Archived on:</b> <i>%(archivedate)s</i> + <i>$lastdate</i><br> + <b>Archived on:</b> <i>$archivedate</i> <p> <ul> <li> <b>Messages sorted by:</b> - %(thread_ref)s - %(subject_ref)s - %(author_ref)s - %(date_ref)s - <li><b><a href="%(listinfo)s">More info on this list... + $thread_ref + $subject_ref + $author_ref + $date_ref + <li><b><a href="$listinfo">More info on this list... </a></b></li> </ul> <p> <hr> <i>This archive was generated by - Pipermail %(version)s.</i> + Pipermail $version.</i> </BODY> </HTML> diff --git a/mailman/templates/en/archidxhead.html b/mailman/templates/en/archidxhead.html index 4fdf4731d..70a7558d7 100644 --- a/mailman/templates/en/archidxhead.html +++ b/mailman/templates/en/archidxhead.html @@ -1,24 +1,24 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> - <title>The %(listname)s %(archive)s Archive by %(archtype)s</title> + <title>The $listname $archive Archive by $archtype</title> <META NAME="robots" CONTENT="noindex,follow"> - %(encoding)s + $encoding </HEAD> <BODY BGCOLOR="#ffffff"> <a name="start"></A> - <h1>%(archive)s Archives by %(archtype)s</h1> + <h1>$archive Archives by $archtype</h1> <ul> <li> <b>Messages sorted by:</b> - %(thread_ref)s - %(subject_ref)s - %(author_ref)s - %(date_ref)s + $thread_ref + $subject_ref + $author_ref + $date_ref - <li><b><a href="%(listinfo)s">More info on this list... + <li><b><a href="$listinfo">More info on this list... </a></b></li> </ul> - <p><b>Starting:</b> <i>%(firstdate)s</i><br> - <b>Ending:</b> <i>%(lastdate)s</i><br> - <b>Messages:</b> %(size)s<p> + <p><b>Starting:</b> <i>$firstdate</i><br> + <b>Ending:</b> <i>$lastdate</i><br> + <b>Messages:</b> $size<p> <ul> diff --git a/mailman/templates/en/archtoc.html b/mailman/templates/en/archtoc.html index 6969d5152..4dcaf5a50 100644 --- a/mailman/templates/en/archtoc.html +++ b/mailman/templates/en/archtoc.html @@ -1,20 +1,20 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> - <title>The %(listname)s Archives</title> + <title>The $listname Archives</title> <META NAME="robots" CONTENT="noindex,follow"> - %(meta)s + $meta </HEAD> <BODY BGCOLOR="#ffffff"> - <h1>The %(listname)s Archives </h1> + <h1>The $listname Archives </h1> <p> - You can get <a href="%(listinfo)s">more information about this list</a> - or you can <a href="%(fullarch)s">download the full raw archive</a> - (%(size)s). + You can get <a href="$listinfo">more information about this list</a> + or you can <a href="$fullarch">download the full raw archive</a> + ($size). </p> - %(noarchive_msg)s - %(archive_listing_start)s - %(archive_listing)s - %(archive_listing_end)s + $noarchive_msg + $archive_listing_start + $archive_listing + $archive_listing_end </BODY> </HTML> diff --git a/mailman/templates/en/archtocentry.html b/mailman/templates/en/archtocentry.html index 00cf9c47d..e2a6d2e37 100644 --- a/mailman/templates/en/archtocentry.html +++ b/mailman/templates/en/archtocentry.html @@ -1,12 +1,12 @@ <tr> - <td>%(archivelabel)s:</td> + <td>$archivelabel:</td> <td> - <A href="%(archive)s/thread.html">[ Thread ]</a> - <A href="%(archive)s/subject.html">[ Subject ]</a> - <A href="%(archive)s/author.html">[ Author ]</a> - <A href="%(archive)s/date.html">[ Date ]</a> + <A href="$archive/thread.html">[ Thread ]</a> + <A href="$archive/subject.html">[ Subject ]</a> + <A href="$archive/author.html">[ Author ]</a> + <A href="$archive/date.html">[ Date ]</a> </td> - %(textlink)s + $textlink </tr> diff --git a/mailman/templates/en/archtocnombox.html b/mailman/templates/en/archtocnombox.html index 0b1239ec8..5989aa53d 100644 --- a/mailman/templates/en/archtocnombox.html +++ b/mailman/templates/en/archtocnombox.html @@ -1,18 +1,18 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> - <title>The %(listname)s Archives</title> + <title>The $listname Archives</title> <META NAME="robots" CONTENT="noindex,follow"> - %(meta)s + $meta </HEAD> <BODY BGCOLOR="#ffffff"> - <h1>The %(listname)s Archives </h1> + <h1>The $listname Archives </h1> <p> - You can get <a href="%(listinfo)s">more information about this list</a>. + You can get <a href="$listinfo">more information about this list</a>. </p> - %(noarchive_msg)s - %(archive_listing_start)s - %(archive_listing)s - %(archive_listing_end)s + $noarchive_msg + $archive_listing_start + $archive_listing + $archive_listing_end </BODY> </HTML> diff --git a/mailman/templates/en/article.html b/mailman/templates/en/article.html index 38dbc5543..9ba25fe4e 100644 --- a/mailman/templates/en/article.html +++ b/mailman/templates/en/article.html @@ -1,50 +1,50 @@ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> <HTML> <HEAD> - <TITLE> %(title)s + <TITLE> $title </TITLE> <LINK REL="Index" HREF="index.html" > - <LINK REL="made" HREF="mailto:%(email_url)s?Subject=%(subject_url)s&In-Reply-To=%(in_reply_to_url)s"> + <LINK REL="made" HREF="mailto:${email_url}?Subject=${subject_url}&In-Reply-To=$in_reply_to_url"> <META NAME="robots" CONTENT="index,nofollow"> - %(encoding)s - %(prev)s - %(next)s + $encoding + $prev + $next </HEAD> <BODY BGCOLOR="#ffffff"> - <H1>%(subject_html)s</H1> - <B>%(author_html)s</B> - <A HREF="mailto:%(email_url)s?Subject=%(subject_url)s&In-Reply-To=%(in_reply_to_url)s" - TITLE="%(subject_html)s">%(email_html)s + <H1>$subject_html</H1> + <B>$author_html</B> + <A HREF="mailto:${email_url}?Subject=${subject_url}&In-Reply-To=${in_reply_to_url}" + TITLE="$subject_html">$email_html </A><BR> - <I>%(datestr_html)s</I> + <I>$datestr_html</I> <P><UL> - %(prev_wsubj)s - %(next_wsubj)s + $prev_wsubj + $next_wsubj <LI> <B>Messages sorted by:</B> - <a href="date.html#%(sequence)s">[ date ]</a> - <a href="thread.html#%(sequence)s">[ thread ]</a> - <a href="subject.html#%(sequence)s">[ subject ]</a> - <a href="author.html#%(sequence)s">[ author ]</a> + <a href="date.html#$sequence">[ date ]</a> + <a href="thread.html#$sequence">[ thread ]</a> + <a href="subject.html#$sequence">[ subject ]</a> + <a href="author.html#$sequence">[ author ]</a> </LI> </UL> <HR> <!--beginarticle--> -%(body)s +$body <!--endarticle--> <HR> <P><UL> <!--threads--> - %(prev_wsubj)s - %(next_wsubj)s + $prev_wsubj + $next_wsubj <LI> <B>Messages sorted by:</B> - <a href="date.html#%(sequence)s">[ date ]</a> - <a href="thread.html#%(sequence)s">[ thread ]</a> - <a href="subject.html#%(sequence)s">[ subject ]</a> - <a href="author.html#%(sequence)s">[ author ]</a> + <a href="date.html#$sequence">[ date ]</a> + <a href="thread.html#$sequence">[ thread ]</a> + <a href="subject.html#$sequence">[ subject ]</a> + <a href="author.html#$sequence">[ author ]</a> </LI> </UL> <hr> -<a href="%(listurl)s">More information about the %(listname)s +<a href="$listurl">More information about the $listname mailing list</a><br> </body></html> diff --git a/mailman/templates/en/invite.txt b/mailman/templates/en/invite.txt index 920c84213..337ac2ddc 100644 --- a/mailman/templates/en/invite.txt +++ b/mailman/templates/en/invite.txt @@ -1,20 +1,20 @@ -Your address "%(email)s" has been invited to join the %(listname)s -mailing list at %(hostname)s by the %(listname)s mailing list owner. +Your address "$email" has been invited to join the $listname +mailing list at $hostname by the $listname mailing list owner. You may accept the invitation by simply replying to this message, keeping the Subject: header intact. You can also visit this web page: - %(confirmurl)s + $confirmurl Or you should include the following line -- and only the following -line -- in a message to %(requestaddr)s: +line -- in a message to $requestaddr: - confirm %(cookie)s + confirm $cookie Note that simply sending a `reply' to this message should work from most mail readers. If you want to decline this invitation, please simply disregard this message. If you have any questions, please send them to -%(listowner)s. +$listowner. diff --git a/mailman/templates/en/masthead.txt b/mailman/templates/en/masthead.txt index 30c526ac9..01cd6afec 100644 --- a/mailman/templates/en/masthead.txt +++ b/mailman/templates/en/masthead.txt @@ -1,13 +1,13 @@ -Send %(real_name)s mailing list submissions to - %(got_list_email)s +Send $real_name mailing list submissions to + $got_list_email To subscribe or unsubscribe via the World Wide Web, visit - %(got_listinfo_url)s + $got_listinfo_url or, via email, send a message with subject or body 'help' to - %(got_request_email)s + $got_request_email You can reach the person managing the list at - %(got_owner_email)s + $got_owner_email When replying, please edit your Subject line so it is more specific than -"Re: Contents of %(real_name)s digest..." +"Re: Contents of $real_name digest..." diff --git a/mailman/templates/en/postack.txt b/mailman/templates/en/postack.txt index 7402e4c2a..a2d6e972b 100644 --- a/mailman/templates/en/postack.txt +++ b/mailman/templates/en/postack.txt @@ -1,8 +1,8 @@ Your message entitled - %(subject)s + $subject -was successfully received by the %(listname)s mailing list. +was successfully received by the $listname mailing list. -List info page: %(listinfo_url)s -Your preferences: %(optionsurl)s +List info page: $listinfo_url +Your preferences: $optionsurl diff --git a/mailman/templates/en/postauth.txt b/mailman/templates/en/postauth.txt index 19f1e384a..fce85f52f 100644 --- a/mailman/templates/en/postauth.txt +++ b/mailman/templates/en/postauth.txt @@ -1,13 +1,13 @@ As list administrator, your authorization is requested for the following mailing list posting: - List: %(listname)s - From: %(sender)s - Subject: %(subject)s - Reason: %(reason)s + List: $listname + From: $sender + Subject: $subject + Reason: $reason At your convenience, visit: - %(admindb_url)s + $admindb_url to approve or deny the request. diff --git a/mailman/templates/en/postheld.txt b/mailman/templates/en/postheld.txt index 877bb4050..b2c938acf 100644 --- a/mailman/templates/en/postheld.txt +++ b/mailman/templates/en/postheld.txt @@ -1,15 +1,15 @@ -Your mail to '%(listname)s' with the subject +Your mail to '$listname' with the subject - %(subject)s + $subject Is being held until the list moderator can review it for approval. The reason it is being held: - %(reason)s + $reason Either the message will get posted to the list, or you will receive notification of the moderator's decision. If you would like to cancel this posting, please visit the following URL: - %(confirmurl)s + $confirmurl diff --git a/mailman/templates/en/refuse.txt b/mailman/templates/en/refuse.txt index 9b6d9bb9c..ee8eba9b3 100644 --- a/mailman/templates/en/refuse.txt +++ b/mailman/templates/en/refuse.txt @@ -1,13 +1,13 @@ -Your request to the %(listname)s mailing list +Your request to the $listname mailing list - %(request)s + $request has been rejected by the list moderator. The moderator gave the following reason for rejecting your request: -"%(reason)s" +"$reason" Any questions or comments should be directed to the list administrator at: - %(adminaddr)s + $adminaddr diff --git a/mailman/templates/en/subauth.txt b/mailman/templates/en/subauth.txt index 869be71c7..1b13ebaeb 100644 --- a/mailman/templates/en/subauth.txt +++ b/mailman/templates/en/subauth.txt @@ -1,11 +1,11 @@ Your authorization is required for a mailing list subscription request approval: - For: %(username)s - List: %(listname)s + For: $username + List: $listname At your convenience, visit: - %(admindb_url)s + $admindb_url to process the request. diff --git a/mailman/templates/en/subscribeack.txt b/mailman/templates/en/subscribeack.txt index 03f56c022..b39783737 100644 --- a/mailman/templates/en/subscribeack.txt +++ b/mailman/templates/en/subscribeack.txt @@ -1,22 +1,22 @@ -Welcome to the "%(real_name)s" mailing list! -%(welcome)s +Welcome to the "$real_name" mailing list! +$welcome To post to this list, send your email to: - %(posting_address)s + $posting_address General information about the mailing list is at: - %(listinfo_url)s + $listinfo_url If you ever want to unsubscribe or change your options (eg, switch to or from digest mode, change your password, etc.), visit your subscription page at: - %(optionsurl)s + $optionsurl You can also make such adjustments via email by sending a message to: - %(request_address)s + $request_address with the word 'help' in the subject or body (don't include the quotes), and you will get back a message with instructions. You will need your password to diff --git a/mailman/templates/en/unsubauth.txt b/mailman/templates/en/unsubauth.txt index 40bc3d5e6..5975a2ce8 100644 --- a/mailman/templates/en/unsubauth.txt +++ b/mailman/templates/en/unsubauth.txt @@ -1,11 +1,11 @@ Your authorization is required for a mailing list unsubscription request approval: - By: %(address)s - From: %(listname)s + By: $address + From: $listname At your convenience, visit: - %(admindb_url)s + $admindb_url to process the request. diff --git a/mailman/testing/helpers.py b/mailman/testing/helpers.py index dd241ddba..5bd019ab7 100644 --- a/mailman/testing/helpers.py +++ b/mailman/testing/helpers.py @@ -63,7 +63,7 @@ def make_testable_runner(runner_class): class EmptyingRunner(runner_class): """Stop processing when the queue is empty.""" - def _doperiodic(self): + def _do_periodic(self): """Stop when the queue is empty.""" self._stop = (len(self._switchboard.files) == 0) diff --git a/mailman/tests/test_documentation.py b/mailman/tests/test_documentation.py index ff3dd8378..cf53be245 100644 --- a/mailman/tests/test_documentation.py +++ b/mailman/tests/test_documentation.py @@ -27,8 +27,8 @@ from email import message_from_string import mailman from mailman.Message import Message -from mailman.app.styles import style_manager from mailman.configuration import config +from mailman.core.styles import style_manager from mailman.testing.helpers import SMTPServer diff --git a/mailman/tests/test_membership.py b/mailman/tests/test_membership.py index dca7e020b..792681472 100644 --- a/mailman/tests/test_membership.py +++ b/mailman/tests/test_membership.py @@ -23,9 +23,8 @@ import unittest from mailman import Utils from mailman import passwords -from mailman.Errors import NotAMemberError -from mailman.UserDesc import UserDesc from mailman.configuration import config +from mailman.core.errors import NotAMemberError diff --git a/mailman/tests/test_passwords.py b/mailman/tests/test_passwords.py index 3c539c77b..7c9b9671e 100644 --- a/mailman/tests/test_passwords.py +++ b/mailman/tests/test_passwords.py @@ -19,8 +19,8 @@ import unittest -from mailman import Errors from mailman import passwords +from mailman.core import errors @@ -73,19 +73,19 @@ class TestBogusPasswords(TestPasswordsBase): scheme = -1 def test_passwords(self): - self.assertRaises(Errors.BadPasswordSchemeError, + self.assertRaises(errors.BadPasswordSchemeError, passwords.make_secret, self.pw8a, self.scheme) def test_unicode_passwords(self): - self.assertRaises(Errors.BadPasswordSchemeError, + self.assertRaises(errors.BadPasswordSchemeError, passwords.make_secret, self.pwua, self.scheme) def test_passwords_with_funky_chars(self): - self.assertRaises(Errors.BadPasswordSchemeError, + self.assertRaises(errors.BadPasswordSchemeError, passwords.make_secret, self.pw8b, self.scheme) def test_unicode_passwords_with_funky_chars(self): - self.assertRaises(Errors.BadPasswordSchemeError, + self.assertRaises(errors.BadPasswordSchemeError, passwords.make_secret, self.pwub, self.scheme) diff --git a/mailman/tests/test_safedict.py b/mailman/tests/test_safedict.py deleted file mode 100644 index 12abbdb97..000000000 --- a/mailman/tests/test_safedict.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (C) 2001-2008 by the Free Software Foundation, Inc. -# -# This file is part of GNU Mailman. -# -# GNU Mailman is free software: you can redistribute it and/or modify it under -# the terms of the GNU General Public License as published by the Free -# Software Foundation, either version 3 of the License, or (at your option) -# any later version. -# -# GNU Mailman is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. - -"""Unit tests for the SafeDict module.""" - -import email -import unittest - -from mailman import SafeDict - - - -class TestSafeDict(unittest.TestCase): - def test_okay(self): - sd = SafeDict.SafeDict({'foo': 'bar'}) - si = '%(foo)s' % sd - self.assertEqual(si, 'bar') - - def test_key_error(self): - sd = SafeDict.SafeDict({'foo': 'bar'}) - si = '%(baz)s' % sd - self.assertEqual(si, '%(baz)s') - - def test_key_error_not_string(self): - key = () - sd = SafeDict.SafeDict({}) - self.assertEqual(sd[key], '<Missing key: ()>') - - - -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestSafeDict)) - return suite diff --git a/mailman/tests/test_security_mgr.py b/mailman/tests/test_security_mgr.py index 2b5cd20c3..3dde9dd2a 100644 --- a/mailman/tests/test_security_mgr.py +++ b/mailman/tests/test_security_mgr.py @@ -27,7 +27,6 @@ import unittest # Don't use cStringIO because we're going to inherit from StringIO import StringIO -from mailman import Errors from mailman import Utils from mailman import passwords from mailman.configuration import config diff --git a/mailman/Cgi/Auth.py b/mailman/web/Cgi/Auth.py index 996aa21c5..996aa21c5 100644 --- a/mailman/Cgi/Auth.py +++ b/mailman/web/Cgi/Auth.py diff --git a/mailman/web/Cgi/__init__.py b/mailman/web/Cgi/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/mailman/web/Cgi/__init__.py diff --git a/mailman/Cgi/admin.py b/mailman/web/Cgi/admin.py index ca90805a7..ca90805a7 100644 --- a/mailman/Cgi/admin.py +++ b/mailman/web/Cgi/admin.py diff --git a/mailman/Cgi/admindb.py b/mailman/web/Cgi/admindb.py index 3934c7d42..3934c7d42 100644 --- a/mailman/Cgi/admindb.py +++ b/mailman/web/Cgi/admindb.py diff --git a/mailman/Cgi/confirm.py b/mailman/web/Cgi/confirm.py index b9c87f788..b9c87f788 100644 --- a/mailman/Cgi/confirm.py +++ b/mailman/web/Cgi/confirm.py diff --git a/mailman/Cgi/create.py b/mailman/web/Cgi/create.py index 3caf9fcc0..3caf9fcc0 100644 --- a/mailman/Cgi/create.py +++ b/mailman/web/Cgi/create.py diff --git a/mailman/Cgi/edithtml.py b/mailman/web/Cgi/edithtml.py index e06fb7956..e06fb7956 100644 --- a/mailman/Cgi/edithtml.py +++ b/mailman/web/Cgi/edithtml.py diff --git a/mailman/Cgi/listinfo.py b/mailman/web/Cgi/listinfo.py index 656801a90..656801a90 100644 --- a/mailman/Cgi/listinfo.py +++ b/mailman/web/Cgi/listinfo.py diff --git a/mailman/Cgi/options.py b/mailman/web/Cgi/options.py index 3b9331fd1..3b9331fd1 100644 --- a/mailman/Cgi/options.py +++ b/mailman/web/Cgi/options.py diff --git a/mailman/Cgi/private.py b/mailman/web/Cgi/private.py index 3199fb842..3199fb842 100644 --- a/mailman/Cgi/private.py +++ b/mailman/web/Cgi/private.py diff --git a/mailman/Cgi/rmlist.py b/mailman/web/Cgi/rmlist.py index 21d54a4a4..21d54a4a4 100644 --- a/mailman/Cgi/rmlist.py +++ b/mailman/web/Cgi/rmlist.py diff --git a/mailman/Cgi/roster.py b/mailman/web/Cgi/roster.py index 697786af1..697786af1 100644 --- a/mailman/Cgi/roster.py +++ b/mailman/web/Cgi/roster.py diff --git a/mailman/Cgi/subscribe.py b/mailman/web/Cgi/subscribe.py index 78fae7230..78fae7230 100644 --- a/mailman/Cgi/subscribe.py +++ b/mailman/web/Cgi/subscribe.py diff --git a/mailman/Cgi/wsgi_app.py b/mailman/web/Cgi/wsgi_app.py index 08a92fdf9..08a92fdf9 100644 --- a/mailman/Cgi/wsgi_app.py +++ b/mailman/web/Cgi/wsgi_app.py diff --git a/mailman/Gui/Archive.py b/mailman/web/Gui/Archive.py index 5929f097b..5929f097b 100644 --- a/mailman/Gui/Archive.py +++ b/mailman/web/Gui/Archive.py diff --git a/mailman/Gui/Autoresponse.py b/mailman/web/Gui/Autoresponse.py index 04cefa0d9..04cefa0d9 100644 --- a/mailman/Gui/Autoresponse.py +++ b/mailman/web/Gui/Autoresponse.py diff --git a/mailman/Gui/Bounce.py b/mailman/web/Gui/Bounce.py index 0ea128205..0ea128205 100644 --- a/mailman/Gui/Bounce.py +++ b/mailman/web/Gui/Bounce.py diff --git a/mailman/Gui/ContentFilter.py b/mailman/web/Gui/ContentFilter.py index d7f26321b..d7f26321b 100644 --- a/mailman/Gui/ContentFilter.py +++ b/mailman/web/Gui/ContentFilter.py diff --git a/mailman/Gui/Digest.py b/mailman/web/Gui/Digest.py index 278fa808d..278fa808d 100644 --- a/mailman/Gui/Digest.py +++ b/mailman/web/Gui/Digest.py diff --git a/mailman/Gui/GUIBase.py b/mailman/web/Gui/GUIBase.py index c521d940e..c521d940e 100644 --- a/mailman/Gui/GUIBase.py +++ b/mailman/web/Gui/GUIBase.py diff --git a/mailman/Gui/General.py b/mailman/web/Gui/General.py index 1d0424de9..1d0424de9 100644 --- a/mailman/Gui/General.py +++ b/mailman/web/Gui/General.py diff --git a/mailman/Gui/Language.py b/mailman/web/Gui/Language.py index 71065d93d..71065d93d 100644 --- a/mailman/Gui/Language.py +++ b/mailman/web/Gui/Language.py diff --git a/mailman/Gui/Membership.py b/mailman/web/Gui/Membership.py index 6dd751807..6dd751807 100644 --- a/mailman/Gui/Membership.py +++ b/mailman/web/Gui/Membership.py diff --git a/mailman/Gui/NonDigest.py b/mailman/web/Gui/NonDigest.py index 6ed0e4612..6ed0e4612 100644 --- a/mailman/Gui/NonDigest.py +++ b/mailman/web/Gui/NonDigest.py diff --git a/mailman/Gui/Passwords.py b/mailman/web/Gui/Passwords.py index 234859bc1..234859bc1 100644 --- a/mailman/Gui/Passwords.py +++ b/mailman/web/Gui/Passwords.py diff --git a/mailman/Gui/Privacy.py b/mailman/web/Gui/Privacy.py index ccc8a2e29..ccc8a2e29 100644 --- a/mailman/Gui/Privacy.py +++ b/mailman/web/Gui/Privacy.py diff --git a/mailman/Gui/Topics.py b/mailman/web/Gui/Topics.py index 501c21329..501c21329 100644 --- a/mailman/Gui/Topics.py +++ b/mailman/web/Gui/Topics.py diff --git a/mailman/Gui/Usenet.py b/mailman/web/Gui/Usenet.py index 713114e1b..713114e1b 100644 --- a/mailman/Gui/Usenet.py +++ b/mailman/web/Gui/Usenet.py diff --git a/mailman/Gui/__init__.py b/mailman/web/Gui/__init__.py index f88274a6e..f88274a6e 100644 --- a/mailman/Gui/__init__.py +++ b/mailman/web/Gui/__init__.py diff --git a/mailman/HTMLFormatter.py b/mailman/web/HTMLFormatter.py index 1802a36fc..1802a36fc 100644 --- a/mailman/HTMLFormatter.py +++ b/mailman/web/HTMLFormatter.py diff --git a/mailman/web/__init__.py b/mailman/web/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/mailman/web/__init__.py diff --git a/mailman/htmlformat.py b/mailman/web/htmlformat.py index 3a95999e8..3a95999e8 100644 --- a/mailman/htmlformat.py +++ b/mailman/web/htmlformat.py @@ -101,7 +101,7 @@ case second `m'. Any other spelling is incorrect.""", 'mailman.commands' : list(commands), 'mailman.database' : 'stock = mailman.database:StockDatabase', 'mailman.mta' : 'stock = mailman.MTA:Manual', - 'mailman.styles' : 'default = mailman.app.styles:DefaultStyle', + 'mailman.styles' : 'default = mailman.core.styles:DefaultStyle', 'mailman.mta' : 'stock = mailman.MTA:Manual', 'mailman.rules' : 'default = mailman.rules:initialize', 'mailman.handlers' : 'default = mailman.pipeline:initialize', |
