------------------------------------------------------------
revno: 6666
committer: Barry Warsaw <[email protected]>
branch nick: configs
timestamp: Tue 2009-01-06 19:55:59 -0500
message:
The conversion from Defaults.py to lazr.config is complete.
lazr.config 1.1 now has everything we need, so we don't need the special
develop hack.
make_instance is no longer necessary.
Refactor the style stuff into their own directory.
Finally! Move the delivery module into the mailman.mta package.
removed:
mailman/bin/make_instance.py
added:
mailman/styles/manager.py
renamed:
mailman/pipeline/smtp_direct.py => mailman/mta/smtp_direct.py
modified:
buildout.cfg
mailman/Archiver/HyperArch.py
mailman/Mailbox.py
mailman/app/notifications.py
mailman/app/replybot.py
mailman/archiving/mhonarc.py
mailman/config/config.py
mailman/config/schema.cfg
mailman/database/pending.py
mailman/docs/lifecycle.txt
mailman/docs/mlist-addresses.txt
mailman/docs/pipelines.txt
mailman/docs/styles.txt
mailman/interfaces/styles.py
mailman/mta/postfix.py
mailman/pipeline/cleanse_dkim.py
mailman/pipeline/docs/cook-headers.txt
mailman/pipeline/docs/scrubber.txt
mailman/pipeline/docs/to-outgoing.txt
mailman/queue/archive.py
mailman/queue/bounce.py
mailman/queue/command.py
mailman/queue/lmtp.py
mailman/queue/news.py
mailman/queue/outgoing.py
mailman/rules/docs/header-matching.txt
mailman/testing/layers.py
=== modified file 'buildout.cfg'
--- a/buildout.cfg 2009-01-05 05:54:19 +0000
+++ b/buildout.cfg 2009-01-07 00:55:59 +0000
@@ -4,8 +4,7 @@
tags
test
unzip = true
-# bzr branch lp:~barry/lazr.config/megamerge
-develop = . /Users/barry/projects/lazr/megamerge
+develop = .
[interpreter]
recipe = zc.recipe.egg
=== modified file 'mailman/Archiver/HyperArch.py'
--- a/mailman/Archiver/HyperArch.py 2009-01-03 10:47:41 +0000
+++ b/mailman/Archiver/HyperArch.py 2009-01-07 00:55:59 +0000
@@ -40,10 +40,10 @@
from email.Charset import Charset
from email.Errors import HeaderParseError
from email.Header import decode_header, make_header
+from lazr.config import as_boolean
from locknix.lockfile import Lock
from string import Template
-from mailman import Defaults
from mailman import Utils
from mailman import i18n
from mailman.Archiver import HyperDatabase
@@ -176,7 +176,7 @@
listname = mlist.fqdn_listname
if lang is None:
if mlist is None:
- lang = Defaults.DEFAULT_SERVER_LANGUAGE
+ lang = config.mailman.default_language
else:
lang = mlist.preferred_language
cachekey = (templatefile, lang, listname)
@@ -252,7 +252,7 @@
self._lang = lang
self._mlist = mlist
- if Defaults.ARCHIVER_OBSCURES_EMAILADDRS:
+ if as_boolean(config.archiver.pipermail.obscure_email_addresses):
# Avoid i18n side-effects. Note that the language for this
# article (for this list) could be different from the site-wide
# preferred language, so we need to ensure no side-effects will
@@ -327,7 +327,7 @@
if hasattr(self, '_mlist'):
self._lang = self._mlist.preferred_language
else:
- self._lang = Defaults.DEFAULT_SERVER_LANGUAGE
+ self._lang = config.mailman.default_language
if not d.has_key('cenc'):
self.cenc = None
if not d.has_key('decoded'):
@@ -359,7 +359,7 @@
if email:
self.decoded['email'] = email
if subject:
- if Defaults.ARCHIVER_OBSCURES_EMAILADDRS:
+ if as_boolean(config.archiver.pipermail.obscure_email_addresses):
with i18n.using_language(self._lang):
atmark = _(' at ')
subject = re.sub(r'([-+,.\w]+)@([-+.\w]+)',
@@ -407,7 +407,7 @@
d["subject_html"] = self.quote(self.subject)
d["subject_url"] = url_quote(self.subject)
d["in_reply_to_url"] = url_quote(self.in_reply_to)
- if Defaults.ARCHIVER_OBSCURES_EMAILADDRS:
+ if as_boolean(config.archiver.pipermail.obscure_email_addresses):
# Point the mailto url back to the list
author = re.sub('@', _(' at '), self.author)
emailurl = self._mlist.posting_address
@@ -511,7 +511,7 @@
# Coerce the body to Unicode and replace any invalid characters.
if not isinstance(body, unicode):
body = unicode(body, cset, 'replace')
- if Defaults.ARCHIVER_OBSCURES_EMAILADDRS:
+ if as_boolean(config.archiver.pipermail.obscure_email_addresses):
with i18n.using_language(self._lang):
atmark = _(' at ')
body = re.sub(r'([-+,.\w]+)@([-+.\w]+)',
@@ -707,7 +707,7 @@
# The TOC is always in the charset of the list's preferred language
d['meta'] += html_charset % Utils.GetCharSet(mlist.preferred_language)
# The site can disable public access to the mbox file.
- if Defaults.PUBLIC_MBOX:
+ if as_boolean(config.archiver.pipermail.public_mbox):
template = 'archtoc.html'
else:
template = 'archtocnombox.html'
@@ -964,7 +964,7 @@
def write_index_entry(self, article):
subject = self.get_header("subject", article)
author = self.get_header("author", article)
- if Defaults.ARCHIVER_OBSCURES_EMAILADDRS:
+ if as_boolean(config.archiver.pipermail.obscure_email_addresses):
try:
author = re.sub('@', _(' at '), author)
except UnicodeError:
@@ -1137,7 +1137,8 @@
if j != -1 and (j < k or k == -1):
text = jr.group(1)
length = len(text)
- if Defaults.ARCHIVER_OBSCURES_EMAILADDRS:
+ if as_boolean(
+ config.archiver.pipermail.obscure_email_addresses):
text = re.sub('@', atmark, text)
URL = self.maillist.script_url('listinfo')
else:
=== modified file 'mailman/Mailbox.py'
--- a/mailman/Mailbox.py 2009-01-05 05:54:19 +0000
+++ b/mailman/Mailbox.py 2009-01-07 00:55:59 +0000
@@ -22,10 +22,11 @@
import email
import mailbox
-from email.Errors import MessageParseError
-from email.Generator import Generator
+from email.errors import MessageParseError
+from email.generator import Generator
from mailman.Message import Message
+from mailman.config import config
=== modified file 'mailman/app/notifications.py'
--- a/mailman/app/notifications.py 2009-01-05 05:54:19 +0000
+++ b/mailman/app/notifications.py 2009-01-07 00:55:59 +0000
@@ -31,8 +31,10 @@
from mailman import Message
from mailman import Utils
from mailman import i18n
+from mailman.config import config
from mailman.interfaces.member import DeliveryMode
+
_ = i18n._
=== modified file 'mailman/app/replybot.py'
--- a/mailman/app/replybot.py 2009-01-05 05:54:19 +0000
+++ b/mailman/app/replybot.py 2009-01-07 00:55:59 +0000
@@ -31,6 +31,7 @@
from mailman import Utils
from mailman import i18n
+from mailman.config import config
log = logging.getLogger('mailman.vette')
=== modified file 'mailman/archiving/mhonarc.py'
--- a/mailman/archiving/mhonarc.py 2009-01-03 10:13:41 +0000
+++ b/mailman/archiving/mhonarc.py 2009-01-07 00:55:59 +0000
@@ -32,7 +32,6 @@
from urlparse import urljoin
from zope.interface import implements
-from mailman import Defaults
from mailman.config import config
from mailman.interfaces.archiver import IArchiver
@@ -53,7 +52,7 @@
"""See `IArchiver`."""
# XXX What about private MHonArc archives?
web_host = config.domains[mlist.host_name].url_host
- return Template(Defaults.PUBLIC_ARCHIVE_URL).safe_substitute(
+ return Template(config.archiver.mhonarc.base_url).safe_substitute(
listname=mlist.fqdn_listname,
hostname=web_host,
fqdn_listname=mlist.fqdn_listname,
=== removed file 'mailman/bin/make_instance.py'
--- a/mailman/bin/make_instance.py 2009-01-01 22:16:51 +0000
+++ b/mailman/bin/make_instance.py 1970-01-01 00:00:00 +0000
@@ -1,171 +0,0 @@
-# Copyright (C) 2007-2009 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/>.
-
-import os
-import grp
-import pwd
-import sys
-import errno
-import shutil
-import optparse
-import setuptools
-
-from pkg_resources import resource_string
-from string import Template
-
-from mailman import Defaults
-from mailman.version import MAILMAN_VERSION
-from mailman.i18n import _
-
-
-SPACE = ' '
-
-
-
-def parseargs():
- parser = optparse.OptionParser(version=MAILMAN_VERSION,
- usage=_("""\
-%prog [options]
-
-Create a Mailman instance by generating all the necessary basic configuration
-support and intervening directories.
-"""))
- parser.add_option('-d', '--var-dir',
- type='string', default=Defaults.DEFAULT_VAR_DIRECTORY,
- help=_("""\
-The top-level runtime data directory. All supporting runtime data will be
-placed in subdirectories of this directory. It will be created if necessary,
-although this might require superuser privileges."""))
- parser.add_option('-f', '--force',
- default=False, action='store_true', help=_("""\
-Force overwriting of mailman.cfg file with new values. Ordinarily, Mailman
-will never overwrite this file because it would cause you to lose your
-configuration data."""))
- parser.add_option('-p', '--permchecks',
- default=False, action='store_true', help=_("""\
-Perform permission checks on the runtime directory."""))
- parser.add_option('-u', '--user',
- type='string', default=None, help=_("""\
-The user id or name to use for the runtime environment. If not specified, the
-current user is used."""))
- parser.add_option('-g', '--group',
- type='string', default=None, help=_("""\
-The group id or name to use for the runtime environment. If not specified, the
-current group is used."""))
- parser.add_option('-l', '--languages',
- default=Defaults.DEFAULT_SERVER_LANGUAGE, type='string',
- help=_("""\
-Space separated list of language codes to enable. Use -L to print all
-available language codes and the name of the associated native language.
-Default is to enable just English. Use the special code 'all' to enable all
-available languages."""))
- opts, args = parser.parse_args()
- if args:
- unexpected = SPACE.join(args)
- parser.error(_('Unexpected arguments: $unexpected'))
- return parser, opts, args
-
-
-
-def instantiate(var_dir, user, group, languages, force):
- # XXX This needs to be converted to use package resources.
- etc_dir = os.path.join(var_dir, 'etc')
- # Figure out which user name and group name to use.
- if user is None:
- uid = os.getuid()
- else:
- try:
- uid = int(user)
- except ValueError:
- try:
- uid = pwd.getpwnam(user).pw_uid
- except KeyError:
- parser.print_error(_('Unknown user: $user'))
- try:
- user_name = pwd.getpwuid(uid).pw_name
- except KeyError:
- parser.print_error(_('Unknown user: $user'))
- if group is None:
- gid = os.getgid()
- else:
- try:
- gid = int(group)
- except ValueError:
- try:
- gid = grp.getgrnam(group).gr_gid
- except KeyError:
- parser.print_error(_('Unknown group: $group'))
- try:
- group_name = grp.getgrgid(gid).gr_name
- except KeyError:
- parser.print_error(_('Unknown group: $group'))
- # Make the runtime dir if it doesn't yet exist.
- try:
- omask = os.umask(0)
- try:
- os.makedirs(etc_dir, 02775)
- finally:
- os.umask(omask)
- except OSError, e:
- # Ignore the exceptions if the directory already exists
- if e.errno <> errno.EEXIST:
- raise
- os.chown(etc_dir, uid, gid)
- # Create an etc/mailman.cfg file which contains just a few configuration
- # variables about the run-time environment that can't be calculated.
- # Don't overwrite mailman.cfg unless the -f flag was given.
- out_file_path = os.path.join(etc_dir, 'mailman.cfg')
- if os.path.exists(out_file_path) and not force:
- # The logging subsystem isn't up yet, so just print this to stderr.
- print >> sys.stderr, 'File exists:', out_file_path
- print >> sys.stderr, 'Use --force to override.'
- else:
- raw = Template(resource_string('mailman.extras', 'mailman.cfg.in'))
- processed = raw.safe_substitute(var_dir=var_dir,
- user_id=uid,
- user_name=user_name,
- group_name=group_name,
- group_id=gid,
- languages=SPACE.join(languages),
- )
- with open(out_file_path, 'w') as fp:
- fp.write(processed)
- # XXX Do --permchecks
-
-
-
-def main():
- parser, opts, args = parseargs()
- available_languages = set(Defaults._DEFAULT_LANGUAGE_DATA)
- enable_languages = set(opts.languages.split())
- if 'all' in enable_languages:
- languages = available_languages
- else:
- unknown_language = enable_languages - available_languages
- if unknown_language:
- print >> sys.stderr, 'Ignoring unknown language codes:', \
- SPACE.join(unknown_language)
- languages = available_languages & enable_languages
- # We need an absolute path for var_dir.
- var_dir = os.path.abspath(opts.var_dir)
- instantiate(var_dir, opts.user, opts.group, languages, opts.force)
-
-
-
-if __name__ == '__main__':
- main()
-
=== modified file 'mailman/config/config.py'
--- a/mailman/config/config.py 2009-01-05 05:54:19 +0000
+++ b/mailman/config/config.py 2009-01-07 00:55:59 +0000
@@ -50,6 +50,7 @@
self.domains = {} # email host -> IDomain
self.switchboards = {}
self.languages = LanguageManager()
+ self.style_manager = StyleManager()
self.QFILE_SCHEMA_VERSION = version.QFILE_SCHEMA_VERSION
self._config = None
self.filename = None
@@ -149,7 +150,7 @@
# Always enable the server default language, which must be defined.
self.languages.enable_language(self._config.mailman.default_language)
self.ensure_directories_exist()
- self.style_manager = StyleManager()
+ self.style_manager.populate()
@property
def logger_configs(self):
=== modified file 'mailman/config/schema.cfg'
--- a/mailman/config/schema.cfg 2009-01-05 05:54:19 +0000
+++ b/mailman/config/schema.cfg 2009-01-07 00:55:59 +0000
@@ -266,7 +266,7 @@
incoming: mailman.mta.postfix.LMTP
# The class defining the interface to the outgoing mail transport agent.
-outgoing: mailman.mta.direct.SMTPDirect
+outgoing: mailman.mta.smtp_direct.process
# How to connect to the outgoing MTA.
smtp_host: localhost
@@ -296,6 +296,11 @@
# to 0.
max_delivery_threads: 0
+# How long should messages which have delivery failures continue to be
+# retried? After this period of time, a message that has failed recipients
+# will be dequeued and those recipients will never receive the message.
+delivery_retry_period: 5d
+
# These variables control the format and frequency of VERP-like delivery for
# better bounce detection. VERP is Variable Envelope Return Path, defined
# here:
@@ -370,6 +375,12 @@
# 1 to VERP every delivery, or to some number > 1 for only occasional VERPs.
verp_delivery_interval: 0
+# VERP format and regexp for probe messages.
+verp_probe_format: %(bounces)s+%(token)s
+verp_probe_regexp: ^(?P<bounces>[^+]+?)\+(?P<token>[...@]+)@.*$
+# Set this 'yes' to activate VERP probe for disabling by bounce.
+verp_probes: no
+
# This is the maximum number of automatic responses sent to an address because
# of -request messages or posting hold messages. This limit prevents response
# loops between Mailman and misconfigured remote email robots. Mailman
@@ -388,6 +399,17 @@
# may wish to remove these headers by setting this to 'yes'.
remove_dkim_headers: no
+# This variable describe the program to use for regenerating the transport map
+# db file, from the associated plain text files. The file being updated will
+# be appended to this string (with a separating space), so it must be
+# appropriate for os.system().
+postfix_map_cmd: /usr/sbin/postmap
+
+
+[bounces]
+# How often should the bounce qrunner process queued detected bounces?
+register_bounces_every: 15m
+
[archiver.master]
# To add new archivers, define a new section based on this one, overriding the
@@ -416,6 +438,9 @@
# This is the stock MHonArc archiver.
class: mailman.archiving.mhonarc.MHonArc
+base_url: http://$hostname/archives/$fqdn_listname
+
+
[archiver.mail_archive]
# This is the stock mail-archive.com archiver.
class: mailman.archiving.mailarchive.MailArchive
@@ -424,6 +449,29 @@
# This is the stock Pipermail archiver.
class: mailman.archiving.pipermail.Pipermail
+# This sets the default `clobber date' policy for the archiver. When a
+# message is to be archived either by Pipermail or an external archiver,
+# Mailman can modify the Date: header to be the date the message was received
+# instead of the Date: in the original message. This is useful if you
+# typically receive messages with outrageous dates. Set this to 0 to retain
+# the date of the original message, or to 1 to always clobber the date. Set
+# it to 2 to perform `smart overrides' on the date; when the date is outside
+# allowable_sane_date_skew (either too early or too late), then the received
+# date is substituted instead.
+clobber_date_policy: 2
+allowable_sane_date_skew: 15d
+
+# Pipermail archives contain the raw email addresses of the posting authors.
+# Some view this as a goldmine for spam harvesters. Set this to 'yes' to
+# moderately obscure email addresses, but note that this breaks mailto: URLs
+# in the archives too.
+obscure_email_addresses: yes
+
+# When the archive is public, should Pipermail also make the raw Unix mbox
+# file publically available?
+public_mbox: no
+
+
[archiver.prototype]
# This is a prototypical sample archiver.
class: mailman.archiving.prototype.Prototype
@@ -505,3 +553,37 @@
Subject To Cc
Message-ID Keywords
Content-Type
+
+
+[nntp]
+# Set these variables if you need to authenticate to your NNTP server for
+# Usenet posting or reading. If no authentication is necessary, specify None
+# for both variables.
+username:
+password:
+
+# Set this if you have an NNTP server you prefer gatewayed lists to use.
+host:
+
+# This controls how headers must be cleansed in order to be accepted by your
+# NNTP server. Some servers like INN reject messages containing prohibited
+# headers, or duplicate headers. The NNTP server may reject the message for
+# other reasons, but there's little that can be programmatically done about
+# that.
+#
+# These headers (case ignored) are removed from the original message. This is
+# a whitespace separate list of headers.
+remove_headers:
+ nntp-posting-host nntp-posting-date x-trace
+ x-complaints-to xref date-received posted
+ posting-version relay-version received
+
+# These headers are left alone, unless there are duplicates in the original
+# message. Any second and subsequent headers are rewritten to the second
+# named header (case preserved). This is a list of header pairs, one pair per
+# line.
+rewrite_duplicate_headers:
+ To X-Original-To
+ CC X-Original-CC
+ Content-Transfer-Encoding X-Original-Content-Transfer-Encoding
+ MIME-Version X-MIME-Version
=== modified file 'mailman/database/pending.py'
--- a/mailman/database/pending.py 2009-01-05 05:54:19 +0000
+++ b/mailman/database/pending.py 2009-01-07 00:55:59 +0000
@@ -87,7 +87,7 @@
verifyObject(IPendable, pendable)
# Calculate the token and the lifetime.
if lifetime is None:
- lifetime = as_timedelta(config.pending_request_life)
+ lifetime = as_timedelta(config.mailman.pending_request_life)
# Calculate a unique token. Algorithm vetted by the Timbot. time()
# has high resolution on Linux, clock() on Windows. random gives us
# about 45 bits in Python 2.2, 53 bits on Python 2.3. The time and
=== modified file 'mailman/docs/lifecycle.txt'
--- a/mailman/docs/lifecycle.txt 2009-01-04 05:22:08 +0000
+++ b/mailman/docs/lifecycle.txt 2009-01-07 00:55:59 +0000
@@ -58,8 +58,7 @@
... if 'test' in mailing_list.fqdn_listname:
... styles.append(self)
- >>> from mailman.core.styles import style_manager
- >>> style_manager.register(TestStyle())
+ >>> config.style_manager.register(TestStyle())
Using the higher level interface for creating a list, applies all matching
list styles.
=== modified file 'mailman/docs/mlist-addresses.txt'
--- a/mailman/docs/mlist-addresses.txt 2008-12-30 04:28:56 +0000
+++ b/mailman/docs/mlist-addresses.txt 2009-01-07 00:55:59 +0000
@@ -67,9 +67,10 @@
>>> mlist.confirm_address('wookie')
u'[email protected]'
- >>> from mailman import Defaults
- >>> old_format = Defaults.VERP_CONFIRM_FORMAT
- >>> Defaults.VERP_CONFIRM_FORMAT = '$address---$cookie'
+ >>> config.push('test config', """
+ ... [mta]
+ ... verp_confirm_format: $address---$cookie
+ ... """)
>>> mlist.confirm_address('cookie')
u'[email protected]'
- >>> config.VERP_CONFIRM_FORMAT = old_format
+ >>> config.pop('test config')
=== modified file 'mailman/docs/pipelines.txt'
--- a/mailman/docs/pipelines.txt 2009-01-03 10:13:41 +0000
+++ b/mailman/docs/pipelines.txt 2009-01-07 00:55:59 +0000
@@ -10,8 +10,8 @@
>>> from mailman.app.lifecycle import create_list
>>> mlist = create_list(u'[email protected]')
- >>> mlist.pipeline
- u'built-in'
+ >>> print mlist.pipeline
+ built-in
>>> from mailman.core.pipelines import process
@@ -49,11 +49,11 @@
<http://lists.example.com/listinfo/[email protected]>,
<mailto:[email protected]>
Archived-At:
- http://lists.example.com/pipermail/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
+ http://lists.example.com/archives/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
List-Unsubscribe:
<http://lists.example.com/listinfo/[email protected]>,
<mailto:[email protected]>
- List-Archive: <http://lists.example.com/pipermail/[email protected]>
+ List-Archive: <http://lists.example.com/archives/[email protected]>
List-Help: <mailto:[email protected]?subject=help>
<BLANKLINE>
First post!
@@ -89,11 +89,11 @@
<http://lists.example.com/listinfo/[email protected]>,
<mailto:[email protected]>
Archived-At:
- http://lists.example.com/pipermail/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
+ http://lists.example.com/archives/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
List-Unsubscribe:
<http://lists.example.com/listinfo/[email protected]>,
<mailto:[email protected]>
- List-Archive: <http://lists.example.com/pipermail/[email protected]>
+ List-Archive: <http://lists.example.com/archives/[email protected]>
List-Help: <mailto:[email protected]?subject=help>
<BLANKLINE>
First post!
@@ -132,11 +132,11 @@
<http://lists.example.com/listinfo/[email protected]>,
<mailto:[email protected]>
Archived-At:
- http://lists.example.com/pipermail/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
+ http://lists.example.com/archives/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
List-Unsubscribe:
<http://lists.example.com/listinfo/[email protected]>,
<mailto:[email protected]>
- List-Archive: <http://lists.example.com/pipermail/[email protected]>
+ List-Archive: <http://lists.example.com/archives/[email protected]>
List-Help: <mailto:[email protected]?subject=help>
<BLANKLINE>
First post!
@@ -170,11 +170,11 @@
<http://lists.example.com/listinfo/[email protected]>,
<mailto:[email protected]>
Archived-At:
- http://lists.example.com/pipermail/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
+ http://lists.example.com/archives/4CMWUN6BHVCMHMDAOSJZ2Q72G5M32MWB
List-Unsubscribe:
<http://lists.example.com/listinfo/[email protected]>,
<mailto:[email protected]>
- List-Archive: <http://lists.example.com/pipermail/[email protected]>
+ List-Archive: <http://lists.example.com/archives/[email protected]>
List-Help: <mailto:[email protected]?subject=help>
<BLANKLINE>
First post!
=== modified file 'mailman/docs/styles.txt'
--- a/mailman/docs/styles.txt 2009-01-04 05:22:08 +0000
+++ b/mailman/docs/styles.txt 2009-01-07 00:55:59 +0000
@@ -14,17 +14,21 @@
Let's start with a vanilla mailing list and a default style manager.
>>> mlist = config.db.list_manager.create(u'[email protected]')
- >>> from mailman.core.styles import StyleManager
+ >>> from mailman.styles.manager import StyleManager
>>> style_manager = StyleManager()
+ >>> style_manager.populate()
+ >>> sorted(style.name for style in style_manager.styles)
+ ['default']
The default style
-----------------
There is a default style which implements the legacy application of list
-defaults from Defaults.py. This style only matching a mailing list when no
-other styles match, and it has the lowest priority. The low priority means
-that it is matched last and if it matches, it is applied last.
+defaults from previous versions of Mailman. This style only matching a
+mailing list when no other styles match, and it has the lowest priority. The
+low priority means that it is matched last and if it matches, it is applied
+last.
>>> default_style = style_manager.get('default')
>>> default_style.name
@@ -43,17 +47,6 @@
>>> [style.name for style in style_manager.lookup(mlist)]
['default']
-If the site administrator modified their mailman.cfg file, the default style
-would pick this up and apply it to the mailing list.
-
- >>> print mlist.msg_footer
- None
- >>> from mailman import Defaults
- >>> Defaults.DEFAULT_MSG_FOOTER = u'default footer'
- >>> default_style.apply(mlist)
- >>> mlist.msg_footer
- u'default footer'
-
Registering styles
------------------
=== modified file 'mailman/interfaces/styles.py'
--- a/mailman/interfaces/styles.py 2009-01-01 22:16:51 +0000
+++ b/mailman/interfaces/styles.py 2009-01-07 00:55:59 +0000
@@ -109,3 +109,10 @@
:param style: an IStyle.
:raises KeyError: If the style's name is not currently registered.
"""
+
+ def populate():
+ """Populate the styles from the configuration files.
+
+ This clears the current set of styles and resets them from those
+ defined in the configuration files.
+ """
=== modified file 'mailman/mta/postfix.py'
--- a/mailman/mta/postfix.py 2009-01-03 10:13:41 +0000
+++ b/mailman/mta/postfix.py 2009-01-07 00:55:59 +0000
@@ -34,7 +34,6 @@
from locknix.lockfile import Lock
from zope.interface import implements
-from mailman import Defaults
from mailman import Utils
from mailman.config import config
from mailman.interfaces.mta import IMailTransportAgent
@@ -113,7 +112,7 @@
os.rename(path + '.new', path)
# Now that the new aliases file has been written, we must tell Postfix
# to generate a new .db file.
- command = Defaults.POSTFIX_MAP_CMD + ' ' + path
+ command = config.mta.postfix_map_cmd + ' ' + path
status = (os.system(command) >> 8) & 0xff
if status:
msg = 'command failure: %s, %s, %s'
=== renamed file 'mailman/pipeline/smtp_direct.py' =>
'mailman/mta/smtp_direct.py'
=== modified file 'mailman/pipeline/cleanse_dkim.py'
--- a/mailman/pipeline/cleanse_dkim.py 2009-01-05 05:54:19 +0000
+++ b/mailman/pipeline/cleanse_dkim.py 2009-01-07 00:55:59 +0000
@@ -34,6 +34,7 @@
from lazr.config import as_boolean
from zope.interface import implements
+from mailman.config import config
from mailman.i18n import _
from mailman.interfaces.handler import IHandler
=== modified file 'mailman/pipeline/docs/cook-headers.txt'
--- a/mailman/pipeline/docs/cook-headers.txt 2009-01-04 05:22:08 +0000
+++ b/mailman/pipeline/docs/cook-headers.txt 2009-01-07 00:55:59 +0000
@@ -188,7 +188,7 @@
>>> process(mlist, msg, {})
>>> list_headers(msg)
---start---
- List-Archive: <http://lists.example.com/pipermail/[email protected]>
+ List-Archive: <http://lists.example.com/archives/[email protected]>
List-Help: <mailto:[email protected]?subject=help>
List-Id: <_xtest.example.com>
List-Post: <mailto:[email protected]>
@@ -209,7 +209,7 @@
>>> process(mlist, msg, {})
>>> list_headers(msg)
---start---
- List-Archive: <http://lists.example.com/pipermail/[email protected]>
+ List-Archive: <http://lists.example.com/archives/[email protected]>
List-Help: <mailto:[email protected]?subject=help>
List-Id: My test mailing list <_xtest.example.com>
List-Post: <mailto:[email protected]>
@@ -248,7 +248,7 @@
>>> process(mlist, msg, {})
>>> list_headers(msg)
---start---
- List-Archive: <http://lists.example.com/pipermail/[email protected]>
+ List-Archive: <http://lists.example.com/archives/[email protected]>
List-Help: <mailto:[email protected]?subject=help>
List-Id: My test mailing list <_xtest.example.com>
List-Subscribe: <http://lists.example.com/listinfo/[email protected]>,
=== modified file 'mailman/pipeline/docs/scrubber.txt'
--- a/mailman/pipeline/docs/scrubber.txt 2009-01-01 22:07:06 +0000
+++ b/mailman/pipeline/docs/scrubber.txt 2009-01-07 00:55:59 +0000
@@ -50,8 +50,10 @@
enabled, the filename will be used when this header attribute is present (yes,
this is an unfortunate double negative).
- >>> from mailman import Defaults
- >>> Defaults.SCRUBBER_DONT_USE_ATTACHMENT_FILENAME = False
+ >>> config.push('test config', """
+ ... [scrubber]
+ ... use_attachment_filename: yes
+ ... """)
>>> msg = message_from_string("""\
... Content-Type: image/gif; name="xtest.gif"
... Content-Transfer-Encoding: base64
@@ -77,10 +79,13 @@
R0lGODdhAQABAIAAAAAAAAAAACwAAAAAAQABAAACAQUAOw==
The site administrator can also configure Mailman to ignore the
-Content-Disposition: filename. This is the default for reasons described in
-the Defaults.py.in file.
+Content-Disposition: filename. This is the default.
- >>> Defaults.SCRUBBER_DONT_USE_ATTACHMENT_FILENAME = True
+ >>> config.pop('test config')
+ >>> config.push('test config', """
+ ... [scrubber]
+ ... use_attachment_filename: no
+ ... """)
>>> msg = message_from_string("""\
... Content-Type: image/gif; name="xtest.gif"
... Content-Transfer-Encoding: base64
@@ -212,3 +217,9 @@
<BLANKLINE>
>>> read_url_from_message(msg)
'This is a text attachment.'
+
+
+Clean up
+--------
+
+ >>> config.pop('test config')
=== modified file 'mailman/pipeline/docs/to-outgoing.txt'
--- a/mailman/pipeline/docs/to-outgoing.txt 2009-01-04 05:22:08 +0000
+++ b/mailman/pipeline/docs/to-outgoing.txt 2009-01-07 00:55:59 +0000
@@ -64,10 +64,11 @@
option to VERP personalized deliveries is set, then the message will be
VERP'd.
- # Save the original value for clean up.
- >>> from mailman import Defaults
- >>> verp_personalized_delivieries = Defaults.VERP_PERSONALIZED_DELIVERIES
- >>> Defaults.VERP_PERSONALIZED_DELIVERIES = True
+ >>> config.push('test config', """
+ ... [mta]
+ ... verp_personalized_deliveries: yes
+ ... """)
+
>>> from mailman.interfaces.mailinglist import Personalization
>>> mlist.personalize = Personalization.individual
>>> msgdata = dict(foo=1, bar=2)
@@ -80,7 +81,12 @@
However, if the global configuration variable prohibits VERP'ing, even
personalized lists will not VERP.
- >>> Defaults.VERP_PERSONALIZED_DELIVERIES = False
+ >>> config.pop('test config')
+ >>> config.push('test config', """
+ ... [mta]
+ ... verp_personalized_deliveries: no
+ ... """)
+
>>> msgdata = dict(foo=1, bar=2)
>>> handler.process(mlist, msg, msgdata)
>>> print msgdata.get('verp')
@@ -93,9 +99,12 @@
Mailman how often to VERP even non-personalized mailing lists. It can be set
to zero, which means non-personalized messages will never be VERP'd.
- # Save the original value for clean up.
- >>> verp_delivery_interval = Defaults.VERP_DELIVERY_INTERVAL
- >>> Defaults.VERP_DELIVERY_INTERVAL = 0
+ >>> config.pop('test config')
+ >>> config.push('test config', """
+ ... [mta]
+ ... verp_delivery_interval: 0
+ ... """)
+
>>> mlist.personalize = Personalization.none
>>> msgdata = dict(foo=1, bar=2)
>>> handler.process(mlist, msg, msgdata)
@@ -106,7 +115,12 @@
If the interval is set to 1, then every message will be VERP'd.
- >>> Defaults.VERP_DELIVERY_INTERVAL = 1
+ >>> config.pop('test config')
+ >>> config.push('test config', """
+ ... [mta]
+ ... verp_delivery_interval: 1
+ ... """)
+
>>> for i in range(10):
... msgdata = dict(foo=1, bar=2)
... handler.process(mlist, msg, msgdata)
@@ -127,7 +141,12 @@
If the interval is set to some other number, then one out of that many posts
will be VERP'd.
- >>> Defaults.VERP_DELIVERY_INTERVAL = 3
+ >>> config.pop('test config')
+ >>> config.push('test config', """
+ ... [mta]
+ ... verp_delivery_interval: 3
+ ... """)
+
>>> for i in range(10):
... mlist.post_id = i
... msgdata = dict(foo=1, bar=2)
@@ -150,5 +169,4 @@
Clean up
========
- >>> Defaults.VERP_PERSONALIZED_DELIVERIES = verp_personalized_delivieries
- >>> Defaults.VERP_DELIVERY_INTERVAL = verp_delivery_interval
+ >>> config.pop('test config')
=== modified file 'mailman/queue/archive.py'
--- a/mailman/queue/archive.py 2009-01-03 10:13:41 +0000
+++ b/mailman/queue/archive.py 2009-01-07 00:55:59 +0000
@@ -30,10 +30,9 @@
from datetime import datetime
from email.Utils import parsedate_tz, mktime_tz, formatdate
-from lazr.config import as_boolean
+from lazr.config import as_boolean, as_timedelta
from locknix.lockfile import Lock
-from mailman import Defaults
from mailman.config import config
from mailman.queue import Runner
@@ -53,9 +52,9 @@
received_time = formatdate(msgdata['received_time'])
if not original_date:
clobber = True
- elif Defaults.ARCHIVER_CLOBBER_DATE_POLICY == 1:
+ elif int(config.archiver.pipermail.clobber_date_policy) == 1:
clobber = True
- elif Defaults.ARCHIVER_CLOBBER_DATE_POLICY == 2:
+ elif int(config.archiver.pipermail.clobber_date_policy) == 2:
# What's the timestamp on the original message?
timetup = parsedate_tz(original_date)
now = datetime.now()
@@ -64,8 +63,9 @@
clobber = True
else:
utc_timestamp = datetime.fromtimestamp(mktime_tz(timetup))
- clobber = (abs(now - utc_timestamp) >
- Defaults.ARCHIVER_ALLOWABLE_SANE_DATE_SKEW)
+ date_skew = as_timedelta(
+ config.archiver.pipermail.allowable_sane_date_skew)
+ clobber = (abs(now - utc_timestamp) > date_skew)
except (ValueError, OverflowError):
# The likely cause of this is that the year in the Date: field
# is horribly incorrect, e.g. (from SF bug # 571634):
=== modified file 'mailman/queue/bounce.py'
--- a/mailman/queue/bounce.py 2009-01-05 00:41:05 +0000
+++ b/mailman/queue/bounce.py 2009-01-07 00:55:59 +0000
@@ -24,8 +24,8 @@
import datetime
from email.Utils import parseaddr
+from lazr.config import as_timedelta
-from mailman import Defaults
from mailman import Utils
from mailman.Bouncers import BouncerAPI
from mailman.config import config
@@ -77,8 +77,9 @@
config.DATA_DIR, 'bounce-events-%05d.pck' % os.getpid())
self._bounce_events_fp = None
self._bouncecnt = 0
- self._nextaction = (datetime.datetime.now() +
- Defaults.REGISTER_BOUNCES_EVERY)
+ self._nextaction = (
+ datetime.datetime.now() +
+ as_timedelta(config.bounces.register_bounces_every))
def _queue_bounces(self, listname, addrs, msg):
today = datetime.date.today()
@@ -130,7 +131,8 @@
if self._nextaction > now or self._bouncecnt == 0:
return
# Let's go ahead and register the bounces we've got stored up
- self._nextaction = now + Defaults.REGISTER_BOUNCES_EVERY
+ self._nextaction = now + as_timedelta(
+ config.bounces.register_bounces_every)
self._register_bounces()
def _probe_bounce(self, mlist, token):
@@ -239,7 +241,7 @@
to = parseaddr(field)[1]
if not to:
continue # empty header
- mo = re.search(Defaults.VERP_REGEXP, to)
+ mo = re.search(config.mta.verp_regexp, to)
if not mo:
continue # no match of regexp
try:
@@ -248,8 +250,8 @@
# All is good
addr = '%...@%s' % mo.group('mailbox', 'host')
except IndexError:
- elog.error("VERP_REGEXP doesn't yield the right match groups: %s",
- Defaults.VERP_REGEXP)
+ elog.error("verp_regexp doesn't yield the right match groups: %s",
+ config.mta.verp_regexp)
return []
return [addr]
@@ -270,7 +272,7 @@
to = parseaddr(field)[1]
if not to:
continue # empty header
- mo = re.search(Defaults.VERP_PROBE_REGEXP, to)
+ mo = re.search(config.mta.verp_probe_regexp, to)
if not mo:
continue # no match of regexp
try:
@@ -283,8 +285,8 @@
return token
except IndexError:
elog.error(
- "VERP_PROBE_REGEXP doesn't yield the right match groups: %s",
- Defaults.VERP_PROBE_REGEXP)
+ "verp_probe_regexp doesn't yield the right match groups: %s",
+ config.mta.verp_probe_regexp)
return None
=== modified file 'mailman/queue/command.py'
--- a/mailman/queue/command.py 2009-01-05 00:41:05 +0000
+++ b/mailman/queue/command.py 2009-01-07 00:55:59 +0000
@@ -37,7 +37,6 @@
from email.Iterators import typed_subpart_iterator
from zope.interface import implements
-from mailman import Defaults
from mailman import Message
from mailman.config import config
from mailman.i18n import _
@@ -66,7 +65,7 @@
elif msgdata.get('toleave'):
self.command_lines.append('leave')
elif msgdata.get('toconfirm'):
- mo = re.match(Defaults.VERP_CONFIRM_REGEXP, msg.get('to', ''))
+ mo = re.match(config.mta.verp_confirm_regexp, msg.get('to', ''))
if mo:
self.command_lines.append('confirm ' + mo.group('cookie'))
# Extract the subject header and do RFC 2047 decoding.
@@ -95,8 +94,9 @@
assert isinstance(body, basestring), 'Non-string decoded payload'
lines = body.splitlines()
# Use no more lines than specified
- self.command_lines.extend(lines[:Defaults.EMAIL_COMMANDS_MAX_LINES])
- self.ignored_lines.extend(lines[Defaults.EMAIL_COMMANDS_MAX_LINES:])
+ max_lines = int(config.mailman.email_commands_max_lines)
+ self.command_lines.extend(lines[:max_lines])
+ self.ignored_lines.extend(lines[max_lines:])
def __iter__(self):
"""Return each command line, split into commands and arguments.
=== modified file 'mailman/queue/lmtp.py'
--- a/mailman/queue/lmtp.py 2009-01-05 00:41:05 +0000
+++ b/mailman/queue/lmtp.py 2009-01-07 00:55:59 +0000
@@ -29,9 +29,6 @@
[1] RFC 2033 Local Mail Transport Protocol
http://www.faqs.org/rfcs/rfc2033.html
-
-See the variable USE_LMTP in Defaults.py.in for enabling this delivery
-mechanism.
"""
import email
@@ -41,7 +38,6 @@
from email.utils import parseaddr
-from mailman import Defaults
from mailman.Message import Message
from mailman.config import config
from mailman.database.transaction import txn
@@ -63,7 +59,7 @@
ERR_451 = '451 Requested action aborted: error in processing'
ERR_501 = '501 Message has defects'
ERR_502 = '502 Error: command HELO not implemented'
-ERR_550 = Defaults.LMTP_ERR_550
+ERR_550 = '550 Requested action not taken: mailbox unavailable'
# XXX Blech
smtpd.__version__ = 'Python LMTP queue runner 1.0'
@@ -86,7 +82,7 @@
subaddress may be None if this is the list's posting address.
"""
localpart, domain = address.split('@', 1)
- localpart = localpart.split(Defaults.VERP_DELIMITER, 1)[0]
+ localpart = localpart.split(config.mta.verp_delimiter, 1)[0]
parts = localpart.split(DASH)
if parts[-1] in SUBADDRESS_NAMES:
listname = DASH.join(parts[:-1])
@@ -186,7 +182,6 @@
msgdata.update(dict(
toowner=True,
envsender=config.mailman.site_owner,
- pipeline=Defaults.OWNER_PIPELINE,
))
queue = 'in'
elif subaddress is None:
=== modified file 'mailman/queue/news.py'
--- a/mailman/queue/news.py 2009-01-05 00:41:05 +0000
+++ b/mailman/queue/news.py 2009-01-07 00:55:59 +0000
@@ -25,15 +25,15 @@
from cStringIO import StringIO
-COMMASPACE = ', '
-
-from mailman import Defaults
from mailman import Utils
+from mailman.config import config
from mailman.interfaces import NewsModeration
from mailman.queue import Runner
+COMMASPACE = ', '
log = logging.getLogger('mailman.error')
+
# Matches our Mailman crafted Message-IDs. See Utils.unique_message_id()
# XXX The move to email.utils.make_msgid() breaks this.
mcre = re.compile(r"""
@@ -64,8 +64,8 @@
nntp_host, nntp_port = Utils.nntpsplit(mlist.nntp_host)
conn = nntplib.NNTP(nntp_host, nntp_port,
readermode=True,
- user=Defaults.NNTP_USERNAME,
- password=Defaults.NNTP_PASSWORD)
+ user=config.nntp.username,
+ password=config.nntp.password)
conn.post(fp)
except nntplib.error_temp, e:
log.error('(NNTPDirect) NNTP error for list "%s": %s',
@@ -147,9 +147,12 @@
# woon't completely sanitize the message, but it will eliminate the bulk
# of the rejections based on message headers. The NNTP server may still
# reject the message because of other problems.
- for header in Defaults.NNTP_REMOVE_HEADERS:
+ for header in config.nntp.remove_headers.split():
del msg[header]
- for header, rewrite in Defaults.NNTP_REWRITE_DUPLICATE_HEADERS:
+ for rewrite_pairs in config.nntp.rewrite_duplicate_headers.splitlines():
+ if len(rewrite_pairs.strip()) == 0:
+ continue
+ header, rewrite = rewrite_pairs.split()
values = msg.get_all(header, [])
if len(values) < 2:
# We only care about duplicates
=== modified file 'mailman/queue/outgoing.py'
--- a/mailman/queue/outgoing.py 2009-01-05 00:41:05 +0000
+++ b/mailman/queue/outgoing.py 2009-01-07 00:55:59 +0000
@@ -18,12 +18,13 @@
"""Outgoing queue runner."""
import os
+import sys
import socket
import logging
from datetime import datetime
+from lazr.config import as_timedelta
-from mailman import Defaults
from mailman.config import config
from mailman.core import errors
from mailman.queue import Runner
@@ -43,9 +44,10 @@
def __init__(self, slice=None, numslices=1):
Runner.__init__(self, slice, numslices)
BounceMixin.__init__(self)
- # We look this function up only at startup time
- handler = config.handlers[Defaults.DELIVERY_MODULE]
- self._func = handler.process
+ # We look this function up only at startup time.
+ module_name, callable_name = config.mta.outgoing.rsplit('.', 1)
+ __import__(module_name)
+ self._func = getattr(sys.modules[module_name], callable_name)
# This prevents smtp server connection problems from filling up the
# error log. It gets reset if the message was successfully sent, and
# set if there was a socket.error.
@@ -112,7 +114,8 @@
return False
else:
# Keep trying to delivery this message for a while
- deliver_until = now + Defaults.DELIVERY_RETRY_PERIOD
+ deliver_until = now + as_timedelta(
+ config.mta.delivery_retry_period)
msgdata['last_recip_count'] = len(recips)
msgdata['deliver_until'] = deliver_until
msgdata['recips'] = recips
=== modified file 'mailman/rules/docs/header-matching.txt'
--- a/mailman/rules/docs/header-matching.txt 2008-12-23 04:26:58 +0000
+++ b/mailman/rules/docs/header-matching.txt 2009-01-07 00:55:59 +0000
@@ -2,15 +2,15 @@
===============
Mailman can do pattern based header matching during its normal rule
-processing. There is a set of site-wide default header matchines specified in
-the configuaration file under the HEADER_MATCHES variable.
+processing. There is a set of site-wide default header matches specified in
+the configuration file under the [spam.headers] section.
>>> from mailman.app.lifecycle import create_list
>>> mlist = create_list(u'[email protected]')
-Because the default HEADER_MATCHES variable is empty when the configuration
-file is read, we'll just extend the current header matching chain with a
-pattern that matches 4 or more stars, discarding the message if it hits.
+Because the default [spam.headers] section is empty, we'll just extend the
+current header matching chain with a pattern that matches 4 or more stars,
+discarding the message if it hits.
>>> chain = config.chains['header-match']
>>> chain.extend('x-spam-score', '[*]{4,}', 'discard')
@@ -98,7 +98,7 @@
Each mailing list can also be configured with a set of header matching regular
expression rules. These are used to impose list-specific header filtering
-with the same semantics as the global `HEADER_MATCHES` variable.
+with the same semantics as the global [spam.headers] section.
The list administrator wants to match not on four stars, but on three plus
signs, but only for the current mailing list.
=== added file 'mailman/styles/manager.py'
--- a/mailman/styles/manager.py 1970-01-01 00:00:00 +0000
+++ b/mailman/styles/manager.py 2009-01-07 00:55:59 +0000
@@ -0,0 +1,92 @@
+# Copyright (C) 2007-2009 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/>.
+
+"""Style manager."""
+
+__metaclass__ = type
+__all__ = [
+ 'StyleManager',
+ ]
+
+
+import sys
+
+from operator import attrgetter
+from zope.interface import implements
+from zope.interface.verify import verifyObject
+
+from mailman.interfaces.styles import (
+ DuplicateStyleError, IStyle, IStyleManager)
+
+
+
+class StyleManager:
+ """The built-in style manager."""
+
+ implements(IStyleManager)
+
+ def __init__(self):
+ """Install all styles from the configuration files."""
+ self._styles = {}
+
+ def populate(self):
+ self._styles.clear()
+ # Avoid circular imports.
+ from mailman.config import config
+ # Install all the styles described by the configuration files.
+ for section in config.style_configs:
+ class_path = section['class']
+ module_name, class_name = class_path.rsplit('.', 1)
+ __import__(module_name)
+ style = getattr(sys.modules[module_name], class_name)()
+ assert section.name.startswith('style'), (
+ 'Bad style section name: %s' % section.name)
+ style.name = section.name[6:]
+ style.priority = int(section.priority)
+ self.register(style)
+
+ def get(self, name):
+ """See `IStyleManager`."""
+ return self._styles.get(name)
+
+ def lookup(self, mailing_list):
+ """See `IStyleManager`."""
+ matched_styles = []
+ for style in self.styles:
+ style.match(mailing_list, matched_styles)
+ for style in matched_styles:
+ yield style
+
+ @property
+ def styles(self):
+ """See `IStyleManager`."""
+ for style in sorted(self._styles.values(),
+ key=attrgetter('priority'),
+ reverse=True):
+ yield style
+
+ def register(self, style):
+ """See `IStyleManager`."""
+ verifyObject(IStyle, style)
+ if style.name in self._styles:
+ raise DuplicateStyleError(style.name)
+ self._styles[style.name] = style
+
+ def unregister(self, style):
+ """See `IStyleManager`."""
+ # Let KeyErrors percolate up.
+ del self._styles[style.name]
=== modified file 'mailman/testing/layers.py'
--- a/mailman/testing/layers.py 2009-01-05 05:54:19 +0000
+++ b/mailman/testing/layers.py 2009-01-07 00:55:59 +0000
@@ -49,6 +49,7 @@
"""Layer for pushing and popping test configurations."""
var_dir = None
+ styles = None
@classmethod
def setUp(cls):
@@ -136,9 +137,7 @@
@classmethod
def testSetUp(cls):
- # Record the current (default) set of styles so that we can reset them
- # easily in the tear down.
- cls.styles = set(config.style_manager.styles)
+ pass
@classmethod
def testTearDown(cls):
@@ -153,10 +152,7 @@
config.db.message_store.delete_message(message['message-id'])
config.db.commit()
# Reset the global style manager.
- new_styles = set(config.style_manager.styles) - cls.styles
- for style in new_styles:
- config.style_manager.unregister(style)
- cls.styles = None
+ config.style_manager.populate()
# Flag to indicate that loggers should propagate to the console.
stderr = False
--
Primary development focus
https://code.launchpad.net/~mailman-coders/mailman/3.0
You are receiving this branch notification because you are subscribed to it.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe:
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org