From fd600d3952393dc9808fefb9be871f78cdbdff39 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 22 Dec 2008 23:26:58 -0500 Subject: Convert more configuration variables to lazr.config. Add .push() and .pop() methods to the Configuration object. Put the 'config' object in the globals of doctests. Add some test layers for setting up the configuration and the SMTP server. --- mailman/pipeline/docs/ack-headers.txt | 1 - mailman/pipeline/docs/acknowledge.txt | 1 - mailman/pipeline/docs/after-delivery.txt | 1 - mailman/pipeline/docs/archives.txt | 1 - mailman/pipeline/docs/avoid-duplicates.txt | 1 - mailman/pipeline/docs/calc-recips.txt | 1 - mailman/pipeline/docs/cleanse.txt | 1 - mailman/pipeline/docs/cook-headers.txt | 1 - mailman/pipeline/docs/decorate.txt | 1 - mailman/pipeline/docs/digests.txt | 1 - mailman/pipeline/docs/file-recips.txt | 1 - mailman/pipeline/docs/filtering.txt | 1 - mailman/pipeline/docs/nntp.txt | 1 - mailman/pipeline/docs/reply-to.txt | 1 - mailman/pipeline/docs/replybot.txt | 1 - mailman/pipeline/docs/scrubber.txt | 1 - mailman/pipeline/docs/subject-munging.txt | 1 - mailman/pipeline/docs/tagger.txt | 1 - mailman/pipeline/docs/to-outgoing.txt | 1 - 19 files changed, 19 deletions(-) (limited to 'mailman/pipeline/docs') diff --git a/mailman/pipeline/docs/ack-headers.txt b/mailman/pipeline/docs/ack-headers.txt index 28a8eed9e..ca41df03e 100644 --- a/mailman/pipeline/docs/ack-headers.txt +++ b/mailman/pipeline/docs/ack-headers.txt @@ -7,7 +7,6 @@ transformations. Some headers get added, others get changed. Some of these changes depend on mailing list settings and others depend on how the message is getting sent through the system. We'll take things one-by-one. - >>> from mailman.configuration import config >>> from mailman.pipeline.cook_headers import process >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.subject_prefix = u'' diff --git a/mailman/pipeline/docs/acknowledge.txt b/mailman/pipeline/docs/acknowledge.txt index 76c8fdf21..ccbb70e79 100644 --- a/mailman/pipeline/docs/acknowledge.txt +++ b/mailman/pipeline/docs/acknowledge.txt @@ -5,7 +5,6 @@ When a user posts a message to a mailing list, and that user has chosen to receive acknowledgments of their postings, Mailman will sent them such an acknowledgment. - >>> from mailman.configuration import config >>> handler = config.handlers['acknowledge'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.real_name = u'XTest' diff --git a/mailman/pipeline/docs/after-delivery.txt b/mailman/pipeline/docs/after-delivery.txt index 5bc9b5936..b910e89a6 100644 --- a/mailman/pipeline/docs/after-delivery.txt +++ b/mailman/pipeline/docs/after-delivery.txt @@ -6,7 +6,6 @@ by the rest of the handlers in the incoming queue pipeline, a couple of bookkeeping pieces of information are updated. >>> import datetime - >>> from mailman.configuration import config >>> handler = config.handlers['after-delivery'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> post_time = datetime.datetime.now() - datetime.timedelta(minutes=10) diff --git a/mailman/pipeline/docs/archives.txt b/mailman/pipeline/docs/archives.txt index 67ad45c89..9595a36e0 100644 --- a/mailman/pipeline/docs/archives.txt +++ b/mailman/pipeline/docs/archives.txt @@ -8,7 +8,6 @@ archivers to work in a separate process from the main Mailman delivery processes. >>> from mailman.app.lifecycle import create_list - >>> from mailman.configuration import config >>> from mailman.queue import Switchboard >>> handler = config.handlers['to-archive'] >>> mlist = create_list(u'_xtest@example.com') diff --git a/mailman/pipeline/docs/avoid-duplicates.txt b/mailman/pipeline/docs/avoid-duplicates.txt index 9fd332d1b..e1d31716a 100644 --- a/mailman/pipeline/docs/avoid-duplicates.txt +++ b/mailman/pipeline/docs/avoid-duplicates.txt @@ -6,7 +6,6 @@ reduce the reception of duplicate messages. It does this by removing certain recipients from the list of recipients that earlier handler modules (e.g. CalcRecips) calculates. - >>> from mailman.configuration import config >>> handler = config.handlers['avoid-duplicates'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') diff --git a/mailman/pipeline/docs/calc-recips.txt b/mailman/pipeline/docs/calc-recips.txt index 057351873..550edff51 100644 --- a/mailman/pipeline/docs/calc-recips.txt +++ b/mailman/pipeline/docs/calc-recips.txt @@ -5,7 +5,6 @@ Every message that makes it through to the list membership gets sent to a set of recipient addresses. These addresses are calculated by one of the handler modules and depends on a host of factors. - >>> from mailman.configuration import config >>> handler = config.handlers['calculate-recipients'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') diff --git a/mailman/pipeline/docs/cleanse.txt b/mailman/pipeline/docs/cleanse.txt index 1597095b3..0940cdb4b 100644 --- a/mailman/pipeline/docs/cleanse.txt +++ b/mailman/pipeline/docs/cleanse.txt @@ -5,7 +5,6 @@ All messages posted to a list get their headers cleansed. Some headers are related to additional permissions that can be granted to the message and other headers can be used to fish for membership. - >>> from mailman.configuration import config >>> handler = config.handlers['cleanse'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') diff --git a/mailman/pipeline/docs/cook-headers.txt b/mailman/pipeline/docs/cook-headers.txt index 4fbdf58bb..985214079 100644 --- a/mailman/pipeline/docs/cook-headers.txt +++ b/mailman/pipeline/docs/cook-headers.txt @@ -8,7 +8,6 @@ changes depend on mailing list settings and others depend on how the message is getting sent through the system. We'll take things one-by-one. >>> from mailman.pipeline.cook_headers import process - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.subject_prefix = u'' >>> mlist.include_list_post_header = False diff --git a/mailman/pipeline/docs/decorate.txt b/mailman/pipeline/docs/decorate.txt index 60afb0170..b805e23cf 100644 --- a/mailman/pipeline/docs/decorate.txt +++ b/mailman/pipeline/docs/decorate.txt @@ -6,7 +6,6 @@ original message. A handler module takes care of this based on the settings of the mailing list and the type of message being processed. >>> from mailman.pipeline.decorate import process - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> msg_text = """\ ... From: aperson@example.org diff --git a/mailman/pipeline/docs/digests.txt b/mailman/pipeline/docs/digests.txt index df01379b9..f478c1ec0 100644 --- a/mailman/pipeline/docs/digests.txt +++ b/mailman/pipeline/docs/digests.txt @@ -8,7 +8,6 @@ digests, although only two are currently supported: MIME digests and RFC 1153 >>> from mailman.pipeline.to_digest import process >>> from mailman.queue import Switchboard - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.preferred_language = u'en' >>> mlist.web_page_url = u'http://www.example.com/' diff --git a/mailman/pipeline/docs/file-recips.txt b/mailman/pipeline/docs/file-recips.txt index e93bba9aa..d006151ba 100644 --- a/mailman/pipeline/docs/file-recips.txt +++ b/mailman/pipeline/docs/file-recips.txt @@ -5,7 +5,6 @@ Mailman can calculate the recipients for a message from a Sendmail-style include file. This file must be called members.txt and it must live in the list's data directory. - >>> from mailman.configuration import config >>> handler = config.handlers['file-recipients'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') diff --git a/mailman/pipeline/docs/filtering.txt b/mailman/pipeline/docs/filtering.txt index c5dca1531..70ca3098d 100644 --- a/mailman/pipeline/docs/filtering.txt +++ b/mailman/pipeline/docs/filtering.txt @@ -7,7 +7,6 @@ message. It does this with the MimeDel handler module, although other handlers can potentially do other kinds of finer level content filtering. >>> from mailman.pipeline.mime_delete import process - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.preferred_language = u'en' diff --git a/mailman/pipeline/docs/nntp.txt b/mailman/pipeline/docs/nntp.txt index 5652d7924..3ef3b2413 100644 --- a/mailman/pipeline/docs/nntp.txt +++ b/mailman/pipeline/docs/nntp.txt @@ -6,7 +6,6 @@ be forwarded onto an NNTP newsgroup. Typically this means Usenet, but since NNTP is to Usenet as IP is to the web, it's more general than that. >>> from mailman.queue import Switchboard - >>> from mailman.configuration import config >>> handler = config.handlers['to-usenet'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.preferred_language = u'en' diff --git a/mailman/pipeline/docs/reply-to.txt b/mailman/pipeline/docs/reply-to.txt index ad9100ce1..570ffb7ea 100644 --- a/mailman/pipeline/docs/reply-to.txt +++ b/mailman/pipeline/docs/reply-to.txt @@ -8,7 +8,6 @@ changes depend on mailing list settings and others depend on how the message is getting sent through the system. We'll take things one-by-one. >>> from mailman.pipeline.cook_headers import process - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.subject_prefix = u'' diff --git a/mailman/pipeline/docs/replybot.txt b/mailman/pipeline/docs/replybot.txt index 2e3765cab..7325417ed 100644 --- a/mailman/pipeline/docs/replybot.txt +++ b/mailman/pipeline/docs/replybot.txt @@ -7,7 +7,6 @@ responses are subject to various conditions, such as headers in the original message or the amount of time since the last auto-response. >>> from mailman.pipeline.replybot import process - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.real_name = u'XTest' >>> mlist.web_page_url = u'http://www.example.com/' diff --git a/mailman/pipeline/docs/scrubber.txt b/mailman/pipeline/docs/scrubber.txt index 744925f34..9c9367cda 100644 --- a/mailman/pipeline/docs/scrubber.txt +++ b/mailman/pipeline/docs/scrubber.txt @@ -7,7 +7,6 @@ scrub attachments from messages so that binary goop doesn't end up in an archive message. >>> from mailman.pipeline.scrubber import process, save_attachment - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.preferred_language = u'en' diff --git a/mailman/pipeline/docs/subject-munging.txt b/mailman/pipeline/docs/subject-munging.txt index 02677d6e2..b2972683b 100644 --- a/mailman/pipeline/docs/subject-munging.txt +++ b/mailman/pipeline/docs/subject-munging.txt @@ -8,7 +8,6 @@ changes depend on mailing list settings and others depend on how the message is getting sent through the system. We'll take things one-by-one. >>> from mailman.pipeline.cook_headers import process - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.subject_prefix = u'' diff --git a/mailman/pipeline/docs/tagger.txt b/mailman/pipeline/docs/tagger.txt index 778f7cc73..64996755b 100644 --- a/mailman/pipeline/docs/tagger.txt +++ b/mailman/pipeline/docs/tagger.txt @@ -10,7 +10,6 @@ expressions. The message then gets tagged with the topic names of each hit. >>> from mailman.pipeline.tagger import process >>> from mailman.queue import Switchboard - >>> from mailman.configuration import config >>> mlist = config.db.list_manager.create(u'_xtest@example.com') Topics must be enabled for Mailman to do any topic matching, even if topics diff --git a/mailman/pipeline/docs/to-outgoing.txt b/mailman/pipeline/docs/to-outgoing.txt index 3840b71ee..70f93cfae 100644 --- a/mailman/pipeline/docs/to-outgoing.txt +++ b/mailman/pipeline/docs/to-outgoing.txt @@ -10,7 +10,6 @@ basically describes how to encode the recipient's address in the originator headers for unambigous bounce processing. >>> from mailman.queue import Switchboard - >>> from mailman.configuration import config >>> handler = config.handlers['to-outgoing'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> switchboard = Switchboard(config.OUTQUEUE_DIR) -- cgit v1.2.3-70-g09d2 From b8e68e7577aa12e0e355aabe2845981f0d73e3b5 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Thu, 25 Dec 2008 23:57:07 -0500 Subject: Added a buildout hack for zope.testing so that we can add our own command line options to bin/test. More test repair, even though it's cheating. Use a bunch of variables from Defaults.py even though these will have to be moved to the schema.cfg. Update logging initialization to consult the propagate flag from the command line. Also skip mailman.root since this is not a valid logger. --- buildout.cfg | 3 +++ mailman/Archiver/HyperArch.py | 22 ++++++++++-------- mailman/Defaults.py | 2 +- mailman/Mailbox.py | 9 +++---- mailman/Message.py | 6 ++--- mailman/archiving/mailarchive.py | 15 +++++------- mailman/archiving/mhonarc.py | 5 ++-- mailman/archiving/pipermail.py | 9 +++++-- mailman/core/logging.py | 33 +++++++++++++++++++++----- mailman/core/styles.py | 15 +++++++----- mailman/docs/bounces.txt | 3 +-- mailman/docs/pipelines.txt | 6 ++--- mailman/pipeline/cleanse_dkim.py | 4 ++-- mailman/pipeline/decorate.py | 3 ++- mailman/pipeline/docs/acknowledge.txt | 3 +-- mailman/pipeline/docs/archives.txt | 3 +-- mailman/pipeline/docs/digests.txt | 16 ++++++++----- mailman/pipeline/docs/nntp.txt | 3 +-- mailman/pipeline/docs/replybot.txt | 3 +-- mailman/pipeline/docs/tagger.txt | 1 - mailman/pipeline/docs/to-outgoing.txt | 3 +-- mailman/pipeline/scrubber.py | 12 +++++----- mailman/pipeline/to_archive.py | 7 ++---- mailman/pipeline/to_digest.py | 10 ++++---- mailman/pipeline/to_outgoing.py | 10 ++++---- mailman/queue/archive.py | 12 ++++++++-- mailman/testing/helpers.py | 7 +++--- mailman/testing/layers.py | 44 ++++++++++++++++++++++++++++++++++- mailman/testing/testing.cfg | 11 +++++++++ setup.py | 1 - 30 files changed, 183 insertions(+), 98 deletions(-) (limited to 'mailman/pipeline/docs') diff --git a/buildout.cfg b/buildout.cfg index d4ba46351..e4f46a0fc 100644 --- a/buildout.cfg +++ b/buildout.cfg @@ -27,3 +27,6 @@ recipe = zc.recipe.testrunner eggs = mailman defaults = '--tests-pattern ^tests --exit-with-status'.split() +# Hack in extra arguments to zope.testrunner. +initialization = from mailman.testing.layers import ConfigLayer; + ConfigLayer.hack_options_parser() diff --git a/mailman/Archiver/HyperArch.py b/mailman/Archiver/HyperArch.py index 0395f6482..a4dc13423 100644 --- a/mailman/Archiver/HyperArch.py +++ b/mailman/Archiver/HyperArch.py @@ -43,6 +43,7 @@ from email.Header import decode_header, make_header 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 @@ -50,6 +51,7 @@ from mailman.Archiver import pipermail from mailman.Mailbox import ArchiverMailbox from mailman.config import config + log = logging.getLogger('mailman.error') # Set up i18n. Assume the current language has already been set in the caller. @@ -174,7 +176,7 @@ def quick_maketext(templatefile, dict=None, lang=None, mlist=None): listname = mlist.fqdn_listname if lang is None: if mlist is None: - lang = config.DEFAULT_SERVER_LANGUAGE + lang = Defaults.DEFAULT_SERVER_LANGUAGE else: lang = mlist.preferred_language cachekey = (templatefile, lang, listname) @@ -250,7 +252,7 @@ class Article(pipermail.Article): self._lang = lang self._mlist = mlist - if config.ARCHIVER_OBSCURES_EMAILADDRS: + if Defaults.ARCHIVER_OBSCURES_EMAILADDRS: # 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 @@ -325,7 +327,7 @@ class Article(pipermail.Article): if hasattr(self, '_mlist'): self._lang = self._mlist.preferred_language else: - self._lang = config.DEFAULT_SERVER_LANGUAGE + self._lang = Defaults.DEFAULT_SERVER_LANGUAGE if not d.has_key('cenc'): self.cenc = None if not d.has_key('decoded'): @@ -357,7 +359,7 @@ class Article(pipermail.Article): if email: self.decoded['email'] = email if subject: - if config.ARCHIVER_OBSCURES_EMAILADDRS: + if Defaults.ARCHIVER_OBSCURES_EMAILADDRS: with i18n.using_language(self._lang): atmark = _(' at ') subject = re.sub(r'([-+,.\w]+)@([-+.\w]+)', @@ -405,7 +407,7 @@ class Article(pipermail.Article): 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 config.ARCHIVER_OBSCURES_EMAILADDRS: + if Defaults.ARCHIVER_OBSCURES_EMAILADDRS: # Point the mailto url back to the list author = re.sub('@', _(' at '), self.author) emailurl = self._mlist.posting_address @@ -509,7 +511,7 @@ class Article(pipermail.Article): # Coerce the body to Unicode and replace any invalid characters. if not isinstance(body, unicode): body = unicode(body, cset, 'replace') - if config.ARCHIVER_OBSCURES_EMAILADDRS: + if Defaults.ARCHIVER_OBSCURES_EMAILADDRS: with i18n.using_language(self._lang): atmark = _(' at ') body = re.sub(r'([-+,.\w]+)@([-+.\w]+)', @@ -705,7 +707,7 @@ class HyperArchive(pipermail.T): # 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 config.PUBLIC_MBOX: + if Defaults.PUBLIC_MBOX: template = 'archtoc.html' else: template = 'archtocnombox.html' @@ -962,7 +964,7 @@ class HyperArchive(pipermail.T): def write_index_entry(self, article): subject = self.get_header("subject", article) author = self.get_header("author", article) - if config.ARCHIVER_OBSCURES_EMAILADDRS: + if Defaults.ARCHIVER_OBSCURES_EMAILADDRS: try: author = re.sub('@', _(' at '), author) except UnicodeError: @@ -1038,7 +1040,7 @@ class HyperArchive(pipermail.T): def update_archive(self, archive): self.__super_update_archive(archive) # only do this if the gzip module was imported globally, and - # gzip'ing was enabled via config.GZIP_ARCHIVE_TXT_FILES. See + # gzip'ing was enabled via Defaults.GZIP_ARCHIVE_TXT_FILES. See # above. if gzip: archz = None @@ -1135,7 +1137,7 @@ class HyperArchive(pipermail.T): if j != -1 and (j < k or k == -1): text = jr.group(1) length = len(text) - if config.ARCHIVER_OBSCURES_EMAILADDRS: + if Defaults.ARCHIVER_OBSCURES_EMAILADDRS: text = re.sub('@', atmark, text) URL = self.maillist.GetScriptURL( 'listinfo', absolute=1) diff --git a/mailman/Defaults.py b/mailman/Defaults.py index a0aad0b8e..4f4f7981e 100644 --- a/mailman/Defaults.py +++ b/mailman/Defaults.py @@ -1051,7 +1051,7 @@ DEFAULT_DIGEST_FOOTER = DEFAULT_MSG_FOOTER DEFAULT_DIGEST_IS_DEFAULT = No DEFAULT_MIME_IS_DEFAULT_DIGEST = No -DEFAULT_DIGEST_SIZE_THRESHHOLD = 30 # KB +DEFAULT_DIGEST_SIZE_THRESHOLD = 30 # KB DEFAULT_DIGEST_SEND_PERIODIC = Yes # Headers which should be kept in both RFC 1153 (plain) and MIME digests. RFC diff --git a/mailman/Mailbox.py b/mailman/Mailbox.py index cbc38585a..bb4982fc6 100644 --- a/mailman/Mailbox.py +++ b/mailman/Mailbox.py @@ -26,8 +26,8 @@ from email.Errors import MessageParseError from email.Generator import Generator from email.Parser import Parser +from mailman import Defaults from mailman.Message import Message -from mailman.config import config @@ -91,9 +91,10 @@ class ArchiverMailbox(Mailbox): # scrub() method, giving the scrubber module a chance to do its thing # before the message is archived. def __init__(self, fp, mlist): - if config.ARCHIVE_SCRUBBER: - __import__(config.ARCHIVE_SCRUBBER) - self._scrubber = sys.modules[config.ARCHIVE_SCRUBBER].process + scrubber_module = Defaults.ARCHIVE_SCRUBBER + if scrubber_module: + __import__(scrubber_module) + self._scrubber = sys.modules[scrubber_module].process else: self._scrubber = None self._mlist = mlist diff --git a/mailman/Message.py b/mailman/Message.py index c8fb17f3b..07d7f15bb 100644 --- a/mailman/Message.py +++ b/mailman/Message.py @@ -264,8 +264,7 @@ class UserNotification(Message): def _enqueue(self, mlist, **_kws): # Not imported at module scope to avoid import loop - from mailman.queue import Switchboard - virginq = Switchboard(config.VIRGINQUEUE_DIR) + virginq = config.switchboards['virgin'] # The message metadata better have a 'recip' attribute. enqueue_kws = dict( recips=self.recips, @@ -298,8 +297,7 @@ class OwnerNotification(UserNotification): def _enqueue(self, mlist, **_kws): # Not imported at module scope to avoid import loop - from mailman.queue import Switchboard - virginq = Switchboard(config.VIRGINQUEUE_DIR) + virginq = config.switchboards['virgin'] # The message metadata better have a `recip' attribute virginq.enqueue(self, listname=mlist.fqdn_listname, diff --git a/mailman/archiving/mailarchive.py b/mailman/archiving/mailarchive.py index 3edeb8c39..ded402ab4 100644 --- a/mailman/archiving/mailarchive.py +++ b/mailman/archiving/mailarchive.py @@ -32,7 +32,6 @@ from zope.interface import implements from mailman.config import config from mailman.interfaces.archiver import IArchiver -from mailman.queue import Switchboard @@ -73,15 +72,13 @@ class MailArchive: message_id_hash = urlsafe_b64encode(sha.digest()) del msg['x-message-id-hash'] msg['X-Message-ID-Hash'] = message_id_hash - return urljoin(config.MAIL_ARCHIVE_BASEURL, message_id_hash) + return urljoin(config.archiver.mail_archive.base_url, message_id_hash) @staticmethod def archive_message(mlist, msg): """See `IArchiver`.""" - if mlist.archive_private: - return - outq = Switchboard(config.OUTQUEUE_DIR) - outq.enqueue( - msg, - listname=mlist.fqdn_listname, - recips=[config.MAIL_ARCHIVE_RECIPIENT]) + if not mlist.archive_private: + config.switchboards['out'].enqueue( + msg, + listname=mlist.fqdn_listname, + recips=[config.archiver.mail_archive.recipient]) diff --git a/mailman/archiving/mhonarc.py b/mailman/archiving/mhonarc.py index 3d17ffd13..c20c34ba0 100644 --- a/mailman/archiving/mhonarc.py +++ b/mailman/archiving/mhonarc.py @@ -32,6 +32,7 @@ from string import Template 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 +54,7 @@ class MHonArc: """See `IArchiver`.""" # XXX What about private MHonArc archives? web_host = config.domains[mlist.host_name].url_host - return Template(config.PUBLIC_ARCHIVE_URL).safe_substitute( + return Template(Defaults.PUBLIC_ARCHIVE_URL).safe_substitute( listname=mlist.fqdn_listname, hostname=web_host, fqdn_listname=mlist.fqdn_listname, @@ -82,7 +83,7 @@ class MHonArc: """See `IArchiver`.""" substitutions = config.__dict__.copy() substitutions['listname'] = mlist.fqdn_listname - command = Template(config.MHONARC_COMMAND).safe_substitute( + command = Template(Defaults.MHONARC_COMMAND).safe_substitute( substitutions) proc = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, diff --git a/mailman/archiving/pipermail.py b/mailman/archiving/pipermail.py index f42f064ed..ea3ccef5e 100644 --- a/mailman/archiving/pipermail.py +++ b/mailman/archiving/pipermail.py @@ -30,6 +30,8 @@ from string import Template from zope.interface import implements from zope.interface.interface import adapter_hooks +from mailman import Defaults +from mailman.Utils import makedirs from mailman.config import config from mailman.interfaces.archiver import IArchiver, IPipermailMailingList from mailman.interfaces.mailinglist import IMailingList @@ -55,7 +57,10 @@ class PipermailMailingListAdapter: basedir = config.PRIVATE_ARCHIVE_FILE_DIR else: basedir = config.PUBLIC_ARCHIVE_FILE_DIR - return os.path.join(basedir, self._mlist.fqdn_listname) + # Make sure the archive directory exists. + archive_dir = os.path.join(basedir, self._mlist.fqdn_listname) + makedirs(archive_dir) + return archive_dir def adapt_mailing_list_for_pipermail(iface, obj): @@ -91,7 +96,7 @@ class Pipermail: url = mlist.script_url('private') + '/index.html' else: web_host = config.domains[mlist.host_name].url_host - url = Template(config.PUBLIC_ARCHIVE_URL).safe_substitute( + url = Template(config.archiver.pipermail.base_url).safe_substitute( listname=mlist.fqdn_listname, hostname=web_host, fqdn_listname=mlist.fqdn_listname, diff --git a/mailman/core/logging.py b/mailman/core/logging.py index ed400215b..8c1463be9 100644 --- a/mailman/core/logging.py +++ b/mailman/core/logging.py @@ -19,6 +19,13 @@ from __future__ import absolute_import +__metaclass__ = type +__all__ = [ + 'initialize', + 'reopen', + ] + + import os import sys import codecs @@ -75,22 +82,35 @@ class ReopenableFileHandler(logging.Handler): -def initialize(propagate=False): +def initialize(propagate=None): + """Initialize all logs. + + :param propagate: Flag specifying whether logs should propagate their + messages to the root logger. If omitted, propagation is determined + from the configuration files. + :type propagate: bool or None + """ # First, find the root logger and configure the logging subsystem. - # Initialize the root logger, then create a formatter for all the sublogs. + # Initialize the root logger, then create a formatter for all the + # sublogs. The root logger should log to stderr. logging.basicConfig(format=config.logging.root.format, datefmt=config.logging.root.datefmt, - level=as_log_level(config.logging.root.level)) - # Create the subloggers + level=as_log_level(config.logging.root.level), + stream=sys.stderr) + # Create the subloggers. for logger_config in config.logger_configs: - logger_name = 'mailman.' + logger_config.name.split('.')[-1] + sub_name = logger_config.name.split('.')[-1] + if sub_name == 'root': + continue + logger_name = 'mailman.' + sub_name log = logging.getLogger(logger_name) # Get settings from log configuration file (or defaults). log_format = logger_config.format log_datefmt = logger_config.datefmt # Propagation to the root logger is how we handle logging to stderr # when the qrunners are not run as a subprocess of mailmanctl. - log.propagate = as_boolean(logger_config.propagate) + log.propagate = (as_boolean(logger_config.propagate) + if propagate is None else propagate) # Set the logger's level. log.setLevel(as_log_level(logger_config.level)) # Create a formatter for this logger, then a handler, and link the @@ -106,5 +126,6 @@ def initialize(propagate=False): def reopen(): + """Re-open all log files.""" for handler in _handlers: handler.reopen() diff --git a/mailman/core/styles.py b/mailman/core/styles.py index 76428a955..b8fff8278 100644 --- a/mailman/core/styles.py +++ b/mailman/core/styles.py @@ -85,7 +85,8 @@ class DefaultStyle: mlist.welcome_msg = u'' mlist.goodbye_msg = u'' mlist.subscribe_policy = Defaults.DEFAULT_SUBSCRIBE_POLICY - mlist.subscribe_auto_approval = Defaults.DEFAULT_SUBSCRIBE_AUTO_APPROVAL + mlist.subscribe_auto_approval = ( + Defaults.DEFAULT_SUBSCRIBE_AUTO_APPROVAL) mlist.unsubscribe_policy = Defaults.DEFAULT_UNSUBSCRIBE_POLICY mlist.private_roster = Defaults.DEFAULT_PRIVATE_ROSTER mlist.obscure_addresses = Defaults.DEFAULT_OBSCURE_ADDRESSES @@ -98,7 +99,8 @@ class DefaultStyle: mlist.pass_mime_types = Defaults.DEFAULT_PASS_MIME_TYPES mlist.filter_filename_extensions = ( Defaults.DEFAULT_FILTER_FILENAME_EXTENSIONS) - mlist.pass_filename_extensions = Defaults.DEFAULT_PASS_FILENAME_EXTENSIONS + mlist.pass_filename_extensions = ( + Defaults.DEFAULT_PASS_FILENAME_EXTENSIONS) mlist.filter_content = Defaults.DEFAULT_FILTER_CONTENT mlist.collapse_alternatives = Defaults.DEFAULT_COLLAPSE_ALTERNATIVES mlist.convert_html_to_plaintext = ( @@ -108,13 +110,13 @@ class DefaultStyle: mlist.digestable = Defaults.DEFAULT_DIGESTABLE mlist.digest_is_default = Defaults.DEFAULT_DIGEST_IS_DEFAULT mlist.mime_is_default_digest = Defaults.DEFAULT_MIME_IS_DEFAULT_DIGEST - mlist.digest_size_threshhold = Defaults.DEFAULT_DIGEST_SIZE_THRESHHOLD + mlist.digest_size_threshold = Defaults.DEFAULT_DIGEST_SIZE_THRESHOLD mlist.digest_send_periodic = Defaults.DEFAULT_DIGEST_SEND_PERIODIC mlist.digest_header = Defaults.DEFAULT_DIGEST_HEADER mlist.digest_footer = Defaults.DEFAULT_DIGEST_FOOTER - mlist.digest_volume_frequency = Defaults.DEFAULT_DIGEST_VOLUME_FREQUENCY + mlist.digest_volume_frequency = ( + Defaults.DEFAULT_DIGEST_VOLUME_FREQUENCY) mlist.one_last_digest = {} - mlist.digest_members = {} mlist.next_digest_number = 1 mlist.nondigestable = Defaults.DEFAULT_NONDIGESTABLE mlist.personalize = Personalization.none @@ -174,7 +176,8 @@ class DefaultStyle: # Bounces mlist.bounce_processing = Defaults.DEFAULT_BOUNCE_PROCESSING mlist.bounce_score_threshold = Defaults.DEFAULT_BOUNCE_SCORE_THRESHOLD - mlist.bounce_info_stale_after = Defaults.DEFAULT_BOUNCE_INFO_STALE_AFTER + mlist.bounce_info_stale_after = ( + Defaults.DEFAULT_BOUNCE_INFO_STALE_AFTER) mlist.bounce_you_are_disabled_warnings = ( Defaults.DEFAULT_BOUNCE_YOU_ARE_DISABLED_WARNINGS) mlist.bounce_you_are_disabled_warnings_interval = ( diff --git a/mailman/docs/bounces.txt b/mailman/docs/bounces.txt index 6d0fad688..9e8bcd23b 100644 --- a/mailman/docs/bounces.txt +++ b/mailman/docs/bounces.txt @@ -30,8 +30,7 @@ Bounce a message by passing in the original message, and an optional error message. The bounced message ends up in the virgin queue, awaiting sending to the original messageauthor. - >>> from mailman.queue import Switchboard - >>> switchboard = Switchboard(config.VIRGINQUEUE_DIR) + >>> switchboard = config.switchboards['virgin'] >>> from mailman.app.bounces import bounce_message >>> bounce_message(mlist, msg) >>> len(switchboard.files) diff --git a/mailman/docs/pipelines.txt b/mailman/docs/pipelines.txt index 5a84bb4b9..94cc792cd 100644 --- a/mailman/docs/pipelines.txt +++ b/mailman/docs/pipelines.txt @@ -70,7 +70,7 @@ However there are currently no recipients for this message. And the message is now sitting in various other processing queues. >>> from mailman.testing.helpers import get_queue_messages - >>> messages = get_queue_messages(config.ARCHQUEUE_DIR) + >>> messages = get_queue_messages('archive') >>> len(messages) 1 >>> print messages[0].msg.as_string() @@ -104,13 +104,13 @@ And the message is now sitting in various other processing queues. This mailing list is not linked to an NNTP newsgroup, so there's nothing in the outgoing nntp queue. - >>> messages = get_queue_messages(config.NEWSQUEUE_DIR) + >>> messages = get_queue_messages('news') >>> len(messages) 0 This is the message that will actually get delivered to end recipients. - >>> messages = get_queue_messages(config.OUTQUEUE_DIR) + >>> messages = get_queue_messages('out') >>> len(messages) 1 >>> print messages[0].msg.as_string() diff --git a/mailman/pipeline/cleanse_dkim.py b/mailman/pipeline/cleanse_dkim.py index bc76e2726..3f3be98f8 100644 --- a/mailman/pipeline/cleanse_dkim.py +++ b/mailman/pipeline/cleanse_dkim.py @@ -31,7 +31,7 @@ __all__ = ['CleanseDKIM'] from zope.interface import implements -from mailman.config import config +from mailman import Defaults from mailman.i18n import _ from mailman.interfaces import IHandler @@ -47,7 +47,7 @@ class CleanseDKIM: def process(self, mlist, msg, msgdata): """See `IHandler`.""" - if config.REMOVE_DKIM_HEADERS: + if Defaults.REMOVE_DKIM_HEADERS: del msg['domainkey-signature'] del msg['dkim-signature'] del msg['authentication-results'] diff --git a/mailman/pipeline/decorate.py b/mailman/pipeline/decorate.py index bc684a1b1..f150d6d0c 100644 --- a/mailman/pipeline/decorate.py +++ b/mailman/pipeline/decorate.py @@ -28,6 +28,7 @@ from email.MIMEText import MIMEText from string import Template from zope.interface import implements +from mailman import Defaults from mailman import Utils from mailman.Message import Message from mailman.config import config @@ -204,7 +205,7 @@ def decorate(mlist, template, extradict=None): web_page_url = mlist.web_page_url, description = mlist.description, info = mlist.info, - cgiext = config.CGIEXT, + cgiext = Defaults.CGIEXT, ) if extradict is not None: d.update(extradict) diff --git a/mailman/pipeline/docs/acknowledge.txt b/mailman/pipeline/docs/acknowledge.txt index ccbb70e79..d1206b6f3 100644 --- a/mailman/pipeline/docs/acknowledge.txt +++ b/mailman/pipeline/docs/acknowledge.txt @@ -15,8 +15,7 @@ acknowledgment. >>> # Ensure that the virgin queue is empty, since we'll be checking this >>> # for new auto-response messages. - >>> from mailman.queue import Switchboard - >>> virginq = Switchboard(config.VIRGINQUEUE_DIR) + >>> virginq = config.switchboards['virgin'] >>> virginq.files [] diff --git a/mailman/pipeline/docs/archives.txt b/mailman/pipeline/docs/archives.txt index 9595a36e0..d81f6e27b 100644 --- a/mailman/pipeline/docs/archives.txt +++ b/mailman/pipeline/docs/archives.txt @@ -8,10 +8,9 @@ archivers to work in a separate process from the main Mailman delivery processes. >>> from mailman.app.lifecycle import create_list - >>> from mailman.queue import Switchboard >>> handler = config.handlers['to-archive'] >>> mlist = create_list(u'_xtest@example.com') - >>> switchboard = Switchboard(config.ARCHQUEUE_DIR) + >>> switchboard = config.switchboards['archive'] A helper function. diff --git a/mailman/pipeline/docs/digests.txt b/mailman/pipeline/docs/digests.txt index f478c1ec0..1d7112fd5 100644 --- a/mailman/pipeline/docs/digests.txt +++ b/mailman/pipeline/docs/digests.txt @@ -7,14 +7,13 @@ digests, although only two are currently supported: MIME digests and RFC 1153 (a.k.a. plain text) digests. >>> from mailman.pipeline.to_digest import process - >>> from mailman.queue import Switchboard >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.preferred_language = u'en' >>> mlist.web_page_url = u'http://www.example.com/' >>> mlist.real_name = u'XTest' >>> mlist.subject_prefix = u'[_XTest] ' >>> mlist.one_last_digest = set() - >>> switchboard = Switchboard(config.VIRGINQUEUE_DIR) + >>> switchboard = config.switchboards['virgin'] This is a helper function used to iterate through all the accumulated digest messages, in the order in which they were posted. This makes it easier to @@ -406,11 +405,16 @@ When messages come in with a content-type character set different than that of the list's preferred language, recipients wil get an internationalized digest. French is not enabled by default site-wide, so enable that now. -XXX We also have to set the default server language to French, otherwise the -English template will be found and the masthead won't be translated. - >>> config.languages.enable_language('fr') - >>> config.DEFAULT_SERVER_LANGUAGE = u'fr' + + # Simulate the site administrator setting the default server language to + # French in the configuration file. Without this, the English template + # will be found and the masthead won't be translated. + >>> config.push('french', """ + ... [mailman] + ... default_language: fr + ... """) + >>> mlist.preferred_language = u'fr' >>> msg = message_from_string("""\ ... From: aperson@example.org diff --git a/mailman/pipeline/docs/nntp.txt b/mailman/pipeline/docs/nntp.txt index 3ef3b2413..0120de394 100644 --- a/mailman/pipeline/docs/nntp.txt +++ b/mailman/pipeline/docs/nntp.txt @@ -5,11 +5,10 @@ Mailman has an NNTP gateway, whereby messages posted to the mailing list can be forwarded onto an NNTP newsgroup. Typically this means Usenet, but since NNTP is to Usenet as IP is to the web, it's more general than that. - >>> from mailman.queue import Switchboard >>> handler = config.handlers['to-usenet'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') >>> mlist.preferred_language = u'en' - >>> switchboard = Switchboard(config.NEWSQUEUE_DIR) + >>> switchboard = config.switchboards['news'] Gatewaying from the mailing list to the newsgroup happens through a separate 'nntp' queue and happen immediately when the message is posted through to the diff --git a/mailman/pipeline/docs/replybot.txt b/mailman/pipeline/docs/replybot.txt index 7325417ed..f9f824e4e 100644 --- a/mailman/pipeline/docs/replybot.txt +++ b/mailman/pipeline/docs/replybot.txt @@ -13,8 +13,7 @@ message or the amount of time since the last auto-response. >>> # Ensure that the virgin queue is empty, since we'll be checking this >>> # for new auto-response messages. - >>> from mailman.queue import Switchboard - >>> virginq = Switchboard(config.VIRGINQUEUE_DIR) + >>> virginq = config.switchboards['virgin'] >>> virginq.files [] diff --git a/mailman/pipeline/docs/tagger.txt b/mailman/pipeline/docs/tagger.txt index 64996755b..9f0bcd4b2 100644 --- a/mailman/pipeline/docs/tagger.txt +++ b/mailman/pipeline/docs/tagger.txt @@ -9,7 +9,6 @@ its Subject: and Keywords: headers compared against these regular expressions. The message then gets tagged with the topic names of each hit. >>> from mailman.pipeline.tagger import process - >>> from mailman.queue import Switchboard >>> mlist = config.db.list_manager.create(u'_xtest@example.com') Topics must be enabled for Mailman to do any topic matching, even if topics diff --git a/mailman/pipeline/docs/to-outgoing.txt b/mailman/pipeline/docs/to-outgoing.txt index 70f93cfae..046ed9be8 100644 --- a/mailman/pipeline/docs/to-outgoing.txt +++ b/mailman/pipeline/docs/to-outgoing.txt @@ -9,10 +9,9 @@ term somewhat incorrectly, but within the spirit of the standard, which basically describes how to encode the recipient's address in the originator headers for unambigous bounce processing. - >>> from mailman.queue import Switchboard >>> handler = config.handlers['to-outgoing'] >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> switchboard = Switchboard(config.OUTQUEUE_DIR) + >>> switchboard = config.switchboards['out'] >>> def queue_size(): ... size = len(switchboard.files) diff --git a/mailman/pipeline/scrubber.py b/mailman/pipeline/scrubber.py index abc904613..e8268f0cf 100644 --- a/mailman/pipeline/scrubber.py +++ b/mailman/pipeline/scrubber.py @@ -38,8 +38,8 @@ from locknix.lockfile import Lock from mimetypes import guess_all_extensions from zope.interface import implements +from mailman import Defaults from mailman import Utils -from mailman.config import config from mailman.core.errors import DiscardMessage from mailman.core.plugins import get_plugin from mailman.i18n import _ @@ -158,7 +158,7 @@ def replace_payload_by_text(msg, text, charset): def process(mlist, msg, msgdata=None): - sanitize = config.ARCHIVE_HTML_SANITIZER + sanitize = Defaults.ARCHIVE_HTML_SANITIZER outer = True if msgdata is None: msgdata = {} @@ -394,7 +394,7 @@ def makedirs(dir): def save_attachment(mlist, msg, dir, filter_html=True): - fsdir = os.path.join(config.PRIVATE_ARCHIVE_FILE_DIR, + fsdir = os.path.join(Defaults.PRIVATE_ARCHIVE_FILE_DIR, mlist.fqdn_listname, dir) makedirs(fsdir) # Figure out the attachment type and get the decoded data @@ -409,7 +409,7 @@ def save_attachment(mlist, msg, dir, filter_html=True): filename, fnext = os.path.splitext(filename) # For safety, we should confirm this is valid ext for content-type # but we can use fnext if we introduce fnext filtering - if config.SCRUBBER_USE_ATTACHMENT_FILENAME_EXTENSION: + if Defaults.SCRUBBER_USE_ATTACHMENT_FILENAME_EXTENSION: # HTML message doesn't have filename :-( ext = fnext or guess_extension(ctype, fnext) else: @@ -430,7 +430,7 @@ def save_attachment(mlist, msg, dir, filter_html=True): with Lock(os.path.join(fsdir, 'attachments.lock')): # Now base the filename on what's in the attachment, uniquifying it if # necessary. - if not filename or config.SCRUBBER_DONT_USE_ATTACHMENT_FILENAME: + if not filename or Defaults.SCRUBBER_DONT_USE_ATTACHMENT_FILENAME: filebase = 'attachment' else: # Sanitize the filename given in the message headers @@ -475,7 +475,7 @@ def save_attachment(mlist, msg, dir, filter_html=True): try: fp.write(decodedpayload) fp.close() - cmd = config.ARCHIVE_HTML_SANITIZER % {'filename' : tmppath} + cmd = Defaults.ARCHIVE_HTML_SANITIZER % {'filename' : tmppath} progfp = os.popen(cmd, 'r') decodedpayload = progfp.read() status = progfp.close() diff --git a/mailman/pipeline/to_archive.py b/mailman/pipeline/to_archive.py index 4d8c27cf1..6ecb860c2 100644 --- a/mailman/pipeline/to_archive.py +++ b/mailman/pipeline/to_archive.py @@ -26,7 +26,6 @@ from zope.interface import implements from mailman.config import config from mailman.i18n import _ from mailman.interfaces import IHandler -from mailman.queue import Switchboard @@ -48,7 +47,5 @@ class ToArchive: # presence. I'm keeping "X-Archive: no" for backwards compatibility. if 'x-no-archive' in msg or msg.get('x-archive', '').lower() == 'no': return - # Send the message to the archiver queue - archq = Switchboard(config.ARCHQUEUE_DIR) - # Send the message to the queue - archq.enqueue(msg, msgdata) + # Send the message to the archiver queue. + config.switchboards['archive'].enqueue(msg, msgdata) diff --git a/mailman/pipeline/to_digest.py b/mailman/pipeline/to_digest.py index 78984c92e..42f92df4e 100644 --- a/mailman/pipeline/to_digest.py +++ b/mailman/pipeline/to_digest.py @@ -48,6 +48,7 @@ from email.parser import Parser from email.utils import formatdate, getaddresses, make_msgid from zope.interface import implements +from mailman import Defaults from mailman import Message from mailman import Utils from mailman import i18n @@ -58,7 +59,6 @@ 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.queue import Switchboard _ = i18n._ @@ -268,8 +268,8 @@ def send_i18n_digests(mlist, mboxfp): # for the specific MIME or plain digests. keeper = {} all_keepers = {} - for header in (config.MIME_DIGEST_KEEP_HEADERS + - config.PLAIN_DIGEST_KEEP_HEADERS): + for header in (Defaults.MIME_DIGEST_KEEP_HEADERS + + Defaults.PLAIN_DIGEST_KEEP_HEADERS): all_keepers[header] = True all_keepers = all_keepers.keys() for keep in all_keepers: @@ -325,7 +325,7 @@ def send_i18n_digests(mlist, mboxfp): print >> plainmsg, _('[Message discarded by content filter]') continue # Honor the default setting - for h in config.PLAIN_DIGEST_KEEP_HEADERS: + for h in Defaults.PLAIN_DIGEST_KEEP_HEADERS: if msg[h]: uh = Utils.wrap('%s: %s' % (h, Utils.oneline(msg[h], in_unicode=True))) @@ -378,7 +378,7 @@ def send_i18n_digests(mlist, mboxfp): # Do our final bit of housekeeping, and then send each message to the # outgoing queue for delivery. mlist.next_digest_number += 1 - virginq = Switchboard(config.VIRGINQUEUE_DIR) + virginq = config.switchboards['virgin'] # Calculate the recipients lists plainrecips = set() mimerecips = set() diff --git a/mailman/pipeline/to_outgoing.py b/mailman/pipeline/to_outgoing.py index d8d1ec935..bbaf43301 100644 --- a/mailman/pipeline/to_outgoing.py +++ b/mailman/pipeline/to_outgoing.py @@ -28,10 +28,10 @@ __all__ = ['ToOutgoing'] from zope.interface import implements +from mailman import Defaults from mailman.config import config from mailman.i18n import _ from mailman.interfaces import IHandler, Personalization -from mailman.queue import Switchboard @@ -45,7 +45,7 @@ class ToOutgoing: def process(self, mlist, msg, msgdata): """See `IHandler`.""" - interval = config.VERP_DELIVERY_INTERVAL + interval = Defaults.VERP_DELIVERY_INTERVAL # Should we VERP this message? If personalization is enabled for this # list and VERP_PERSONALIZED_DELIVERIES is true, then yes we VERP it. # Also, if personalization is /not/ enabled, but @@ -57,7 +57,7 @@ class ToOutgoing: if 'verp' in msgdata: pass elif mlist.personalize <> Personalization.none: - if config.VERP_PERSONALIZED_DELIVERIES: + if Defaults.VERP_PERSONALIZED_DELIVERIES: msgdata['verp'] = True elif interval == 0: # Never VERP @@ -69,5 +69,5 @@ class ToOutgoing: # VERP every `interval' number of times msgdata['verp'] = not (int(mlist.post_id) % interval) # And now drop the message in qfiles/out - outq = Switchboard(config.OUTQUEUE_DIR) - outq.enqueue(msg, msgdata, listname=mlist.fqdn_listname) + config.switchboards['out'].enqueue( + msg, msgdata, listname=mlist.fqdn_listname) diff --git a/mailman/queue/archive.py b/mailman/queue/archive.py index e9fd5f7ad..7725f6f97 100644 --- a/mailman/queue/archive.py +++ b/mailman/queue/archive.py @@ -25,6 +25,7 @@ __all__ = [ import os import time +import logging from datetime import datetime from email.Utils import parsedate_tz, mktime_tz, formatdate @@ -34,6 +35,8 @@ from mailman import Defaults from mailman.core.plugins import get_plugins from mailman.queue import Runner +log = logging.getLogger('mailman.error') + class ArchiveRunner(Runner): @@ -78,5 +81,10 @@ class ArchiveRunner(Runner): # While a list archiving lock is acquired, archive the message. with Lock(os.path.join(mlist.data_path, 'archive.lck')): for archive_factory in get_plugins('mailman.archiver'): - archive_factory().archive_message(mlist, msg) - + # A problem in one archiver should not prevent any other + # archiver from running. + try: + archive = archive_factory() + archive.archive_message(mlist, msg) + except Exception: + log.exception('Broken archiver: %s' % archive.name) diff --git a/mailman/testing/helpers.py b/mailman/testing/helpers.py index 2f5b4af01..62b0d8d95 100644 --- a/mailman/testing/helpers.py +++ b/mailman/testing/helpers.py @@ -80,15 +80,14 @@ class _Bag: setattr(self, key, value) -def get_queue_messages(queue): +def get_queue_messages(queue_name): """Return and clear all the messages in the given queue. - :param queue: An ISwitchboard or a string naming a queue. + :param queue_name: A string naming a queue. :return: A list of 2-tuples where each item contains the message and message metadata. """ - if isinstance(queue, basestring): - queue = Switchboard(queue) + queue = config.switchboards[queue_name] messages = [] for filebase in queue.files: msg, msgdata = queue.dequeue(filebase) diff --git a/mailman/testing/layers.py b/mailman/testing/layers.py index bda18289c..883a5c784 100644 --- a/mailman/testing/layers.py +++ b/mailman/testing/layers.py @@ -25,7 +25,9 @@ __all__ = [ import os +import sys import shutil +import logging import tempfile from pkg_resources import resource_string @@ -33,6 +35,7 @@ from textwrap import dedent from mailman.config import config from mailman.core.initialize import initialize +from mailman.i18n import _ from mailman.testing.helpers import SMTPServer @@ -59,9 +62,27 @@ class ConfigLayer: [mailman] var_dir: %s """ % cls.var_dir) - # Read the testing config, but don't push it yet. + # Read the testing config and push it. test_config += resource_string('mailman.testing', 'testing.cfg') config.push('test config', test_config) + # Enable log message propagation. + for logger_config in config.logger_configs: + sub_name = logger_config.name.split('.')[-1] + if sub_name == 'root': + continue + logger_name = 'mailman.' + sub_name + log = logging.getLogger(logger_name) + log.propagate = True + log.setLevel(logging.DEBUG) + # zope.testing sets up logging before we get to our own initialization + # function. This messes with the root logger, so explicitly set it to + # go to stderr. + if cls.stderr: + console = logging.StreamHandler(sys.stderr) + formatter = logging.Formatter(config.logging.root.format, + config.logging.root.datefmt) + console.setFormatter(formatter) + logging.getLogger().addHandler(console) @classmethod def tearDown(cls): @@ -87,6 +108,27 @@ class ConfigLayer: config.db.message_store.delete_message(message['message-id']) config.db.commit() + # Flag to indicate that loggers should propagate to the console. + stderr = False + + @classmethod + def handle_stderr(cls, *ignore): + cls.stderr = True + + @classmethod + def hack_options_parser(cls): + """Hack our way into the zc.testing framework. + + Add our custom command line option parsing into zc.testing's. We do + the imports here so that if zc.testing isn't invoked, this stuff never + gets in the way. This is pretty fragile, depend on changes in the + zc.testing package. There should be a better way! + """ + from zope.testing.testrunner.options import parser + parser.add_option('-e', '--stderr', + action='callback', callback=cls.handle_stderr, + help=_('Propagate log errors to stderr.')) + class SMTPLayer(ConfigLayer): diff --git a/mailman/testing/testing.cfg b/mailman/testing/testing.cfg index baac7d803..8bb720ab7 100644 --- a/mailman/testing/testing.cfg +++ b/mailman/testing/testing.cfg @@ -60,7 +60,18 @@ max_restarts: 1 base_url: http://go.mail-archive.dev/ recipient: archive@mail-archive.dev +[archiver.pipermail] +base_url: http://www.example.com/pipermail/$listname + [domain.example_dot_com] email_host: example.com base_url: http://www.example.com contact_address: postmaster@example.com + +[language.ja] +description: Japanese +charset: euc-jp + +[language.fr] +description: French +charset: iso-8859-1 diff --git a/setup.py b/setup.py index 4a5acb595..1e3613611 100644 --- a/setup.py +++ b/setup.py @@ -90,7 +90,6 @@ case second `m'. Any other spelling is incorrect.""", include_package_data = True, entry_points = { 'console_scripts': list(scripts), - # Entry point for plugging in different database backends. 'mailman.archiver' : [ 'mail-archive = mailman.archiving.mailarchive:MailArchive', 'mhonarc = mailman.archiving.mhonarc:MHonArc', -- cgit v1.2.3-70-g09d2 From 1ffa4c74935a56a3c5de736fab052e33e4ab3d38 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Fri, 26 Dec 2008 09:04:33 -0500 Subject: Down to only 27 test failures. More temporary config -> Defaults changes. More fixes to smtp_direct.py. Other queue runner fixes, including allowing make_testable_runner() to take an optional 'name' which overrides the default class-calculated name. --- mailman/config/schema.cfg | 4 ++-- mailman/pipeline/docs/to-outgoing.txt | 19 ++++++++++--------- mailman/pipeline/smtp_direct.py | 23 ++++++++++++++--------- mailman/queue/bounce.py | 27 ++++++++++++++------------- mailman/queue/docs/outgoing.txt | 5 ++--- mailman/queue/outgoing.py | 13 +++++++------ mailman/testing/helpers.py | 25 +++++++++++++++---------- 7 files changed, 64 insertions(+), 52 deletions(-) (limited to 'mailman/pipeline/docs') diff --git a/mailman/config/schema.cfg b/mailman/config/schema.cfg index 0a27c28f4..59ae160f4 100644 --- a/mailman/config/schema.cfg +++ b/mailman/config/schema.cfg @@ -25,14 +25,14 @@ # delivered to a human, but which can't be delivered to a list owner (e.g. a # bounce from a list owner), will be sent to this address. It should point to # a human. -site-owner: changeme@example.com +site_owner: changeme@example.com # This address is used as the from address whenever a message comes from some # entity to which there is no natural reply recipient. Set this to a real # human or to /dev/null. It will be appended with the host name of the list # involved. This address must not bounce and it must not point to a Mailman # process. -noreply-address: noreply +noreply_address: noreply # Where all the runtime data will be kept. This directory must exist. var_dir: /tmp/mailman diff --git a/mailman/pipeline/docs/to-outgoing.txt b/mailman/pipeline/docs/to-outgoing.txt index 046ed9be8..81e870e6c 100644 --- a/mailman/pipeline/docs/to-outgoing.txt +++ b/mailman/pipeline/docs/to-outgoing.txt @@ -65,8 +65,9 @@ option to VERP personalized deliveries is set, then the message will be VERP'd. # Save the original value for clean up. - >>> verp_personalized_delivieries = config.VERP_PERSONALIZED_DELIVERIES - >>> config.VERP_PERSONALIZED_DELIVERIES = True + >>> from mailman import Defaults + >>> verp_personalized_delivieries = Defaults.VERP_PERSONALIZED_DELIVERIES + >>> Defaults.VERP_PERSONALIZED_DELIVERIES = True >>> from mailman.interfaces import Personalization >>> mlist.personalize = Personalization.individual >>> msgdata = dict(foo=1, bar=2) @@ -79,7 +80,7 @@ VERP'd. However, if the global configuration variable prohibits VERP'ing, even personalized lists will not VERP. - >>> config.VERP_PERSONALIZED_DELIVERIES = False + >>> Defaults.VERP_PERSONALIZED_DELIVERIES = False >>> msgdata = dict(foo=1, bar=2) >>> handler.process(mlist, msg, msgdata) >>> print msgdata.get('verp') @@ -93,8 +94,8 @@ 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 = config.VERP_DELIVERY_INTERVAL - >>> config.VERP_DELIVERY_INTERVAL = 0 + >>> verp_delivery_interval = Defaults.VERP_DELIVERY_INTERVAL + >>> Defaults.VERP_DELIVERY_INTERVAL = 0 >>> mlist.personalize = Personalization.none >>> msgdata = dict(foo=1, bar=2) >>> handler.process(mlist, msg, msgdata) @@ -105,7 +106,7 @@ to zero, which means non-personalized messages will never be VERP'd. If the interval is set to 1, then every message will be VERP'd. - >>> config.VERP_DELIVERY_INTERVAL = 1 + >>> Defaults.VERP_DELIVERY_INTERVAL = 1 >>> for i in range(10): ... msgdata = dict(foo=1, bar=2) ... handler.process(mlist, msg, msgdata) @@ -126,7 +127,7 @@ If the interval is set to 1, then every message will be VERP'd. If the interval is set to some other number, then one out of that many posts will be VERP'd. - >>> config.VERP_DELIVERY_INTERVAL = 3 + >>> Defaults.VERP_DELIVERY_INTERVAL = 3 >>> for i in range(10): ... mlist.post_id = i ... msgdata = dict(foo=1, bar=2) @@ -149,5 +150,5 @@ will be VERP'd. Clean up ======== - >>> config.VERP_PERSONALIZED_DELIVERIES = verp_personalized_delivieries - >>> config.VERP_DELIVERY_INTERVAL = verp_delivery_interval + >>> Defaults.VERP_PERSONALIZED_DELIVERIES = verp_personalized_delivieries + >>> Defaults.VERP_DELIVERY_INTERVAL = verp_delivery_interval diff --git a/mailman/pipeline/smtp_direct.py b/mailman/pipeline/smtp_direct.py index ab5ca0096..75c5da1ba 100644 --- a/mailman/pipeline/smtp_direct.py +++ b/mailman/pipeline/smtp_direct.py @@ -36,15 +36,16 @@ import copy import time import email import socket -import string import logging import smtplib from email.Charset import Charset from email.Header import Header from email.Utils import formataddr +from string import Template from zope.interface import implements +from mailman import Defaults from mailman import Utils from mailman.config import config from mailman.core import errors @@ -65,8 +66,11 @@ class Connection: def __connect(self): self.__conn = smtplib.SMTP() - self.__conn.connect(config.SMTPHOST, config.SMTPPORT) - self.__numsessions = config.SMTP_MAX_SESSIONS_PER_CONNECTION + host = config.mta.smtp_host + port = int(config.mta.smtp_port) + log.debug('Connecting to %s:%s', host, port) + self.__conn.connect(host, port) + self.__numsessions = Defaults.SMTP_MAX_SESSIONS_PER_CONNECTION def sendmail(self, envsender, recips, msgtext): if self.__conn is None: @@ -122,10 +126,10 @@ def process(mlist, msg, msgdata): chunks = [[recip] for recip in recips] msgdata['personalize'] = 1 deliveryfunc = verpdeliver - elif config.SMTP_MAX_RCPTS <= 0: + elif Defaults.SMTP_MAX_RCPTS <= 0: chunks = [recips] else: - chunks = chunkify(recips, config.SMTP_MAX_RCPTS) + chunks = chunkify(recips, Defaults.SMTP_MAX_RCPTS) # See if this is an unshunted message for which some were undelivered if msgdata.has_key('undelivered'): chunks = msgdata['undelivered'] @@ -316,7 +320,8 @@ def verpdeliver(mlist, msg, msgdata, envsender, failures, conn): 'mailbox': rmailbox, 'host' : DOT.join(rdomain), } - envsender = '%s@%s' % ((config.VERP_FORMAT % d), DOT.join(bdomain)) + envsender = '%s@%s' % ((Defaults.VERP_FORMAT % d), + DOT.join(bdomain)) if mlist.personalize == Personalization.full: # When fully personalizing, we want the To address to point to the # recipient, not to the mailing list @@ -378,10 +383,10 @@ def bulkdeliver(mlist, msg, msgdata, envsender, failures, conn): # Send the message refused = conn.sendmail(envsender, recips, msgtext) except smtplib.SMTPRecipientsRefused, e: - flog.error('%s recipients refused: %s', msgid, e) + log.error('%s recipients refused: %s', msgid, e) refused = e.recipients except smtplib.SMTPResponseException, e: - flog.error('%s SMTP session failure: %s, %s', + log.error('%s SMTP session failure: %s, %s', msgid, e.smtp_code, e.smtp_error) # If this was a permanent failure, don't add the recipients to the # refused, because we don't want them to be added to failures. @@ -397,7 +402,7 @@ def bulkdeliver(mlist, msg, msgdata, envsender, failures, conn): # MTA not responding, or other socket problems, or any other kind of # SMTPException. In that case, nothing got delivered, so treat this # as a temporary failure. - flog.error('%s low level smtp error: %s', msgid, e) + log.error('%s low level smtp error: %s', msgid, e) error = str(e) for r in recips: refused[r] = (-1, error) diff --git a/mailman/queue/bounce.py b/mailman/queue/bounce.py index 18fa08437..9f390130d 100644 --- a/mailman/queue/bounce.py +++ b/mailman/queue/bounce.py @@ -27,6 +27,7 @@ from email.MIMEMessage import MIMEMessage from email.MIMEText import MIMEText from email.Utils import parseaddr +from mailman import Defaults from mailman import Utils from mailman.Bouncers import BouncerAPI from mailman.Message import UserNotification @@ -80,7 +81,7 @@ class BounceMixin: self._bounce_events_fp = None self._bouncecnt = 0 self._nextaction = (datetime.datetime.now() + - config.REGISTER_BOUNCES_EVERY) + Defaults.REGISTER_BOUNCES_EVERY) def _queue_bounces(self, listname, addrs, msg): today = datetime.date.today() @@ -132,7 +133,7 @@ class BounceMixin: 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 + config.REGISTER_BOUNCES_EVERY + self._nextaction = now + Defaults.REGISTER_BOUNCES_EVERY self._register_bounces() def _probe_bounce(self, mlist, token): @@ -153,7 +154,7 @@ class BounceMixin: class BounceRunner(Runner, BounceMixin): - QDIR = config.BOUNCEQUEUE_DIR + """The bounce runner.""" def __init__(self, slice=None, numslices=1): Runner.__init__(self, slice, numslices) @@ -162,7 +163,6 @@ class BounceRunner(Runner, BounceMixin): def _dispose(self, mlist, msg, msgdata): # Make sure we have the most up-to-date state mlist.Load() - outq = Switchboard(config.OUTQUEUE_DIR) # There are a few possibilities here: # # - the message could have been VERP'd in which case, we know exactly @@ -176,14 +176,15 @@ class BounceRunner(Runner, BounceMixin): # owner address. That way, if a list owner address bounces, at least # some human has a chance to deal with it. Is this a bounce for a # message to a list owner, coming to the site owner? - if msg.get('to', '') == config.SITE_OWNER_ADDRESS: + if msg.get('to', '') == config.mailman.site_owner: # Send it on to the site owners, but craft the envelope sender to # be the noreply address, so if the site owner bounce, we won't # get stuck in a bounce loop. - outq.enqueue(msg, msgdata, - recips=[config.SITE_OWNER_ADDRESS], - envsender=config.NO_REPLY_ADDRESS, - ) + config.switchboards['out'].enqueue( + msg, msgdata, + recips=[config.mailman.site_owner], + envsender=config.mailman.noreply_address, + ) # List isn't doing bounce processing? if not mlist.bounce_processing: return @@ -241,7 +242,7 @@ def verp_bounce(mlist, msg): to = parseaddr(field)[1] if not to: continue # empty header - mo = re.search(config.VERP_REGEXP, to) + mo = re.search(Defaults.VERP_REGEXP, to) if not mo: continue # no match of regexp try: @@ -251,7 +252,7 @@ def verp_bounce(mlist, msg): addr = '%s@%s' % mo.group('mailbox', 'host') except IndexError: elog.error("VERP_REGEXP doesn't yield the right match groups: %s", - config.VERP_REGEXP) + Defaults.VERP_REGEXP) return [] return [addr] @@ -272,7 +273,7 @@ def verp_probe(mlist, msg): to = parseaddr(field)[1] if not to: continue # empty header - mo = re.search(config.VERP_PROBE_REGEXP, to) + mo = re.search(Defaults.VERP_PROBE_REGEXP, to) if not mo: continue # no match of regexp try: @@ -286,7 +287,7 @@ def verp_probe(mlist, msg): except IndexError: elog.error( "VERP_PROBE_REGEXP doesn't yield the right match groups: %s", - config.VERP_PROBE_REGEXP) + Defaults.VERP_PROBE_REGEXP) return None diff --git a/mailman/queue/docs/outgoing.txt b/mailman/queue/docs/outgoing.txt index 9af554af7..851bdf474 100644 --- a/mailman/queue/docs/outgoing.txt +++ b/mailman/queue/docs/outgoing.txt @@ -47,8 +47,7 @@ injecting a message directly into the outgoing queue. >>> handler = config.handlers['calculate-recipients'] >>> handler.process(mlist, msg, msgdata) - >>> from mailman.queue import Switchboard - >>> outgoing_queue = Switchboard(config.OUTQUEUE_DIR) + >>> outgoing_queue = config.switchboards['out'] >>> ignore = outgoing_queue.enqueue( ... msg, msgdata, ... verp=True, listname=mlist.fqdn_listname, tolist=True, @@ -59,7 +58,7 @@ upstream SMTP, which happens to be our test server. >>> from mailman.queue.outgoing import OutgoingRunner >>> from mailman.testing.helpers import make_testable_runner - >>> outgoing = make_testable_runner(OutgoingRunner) + >>> outgoing = make_testable_runner(OutgoingRunner, 'out') >>> outgoing.run() Three messages have been delivered to our SMTP server, one for each recipient. diff --git a/mailman/queue/outgoing.py b/mailman/queue/outgoing.py index 9eb287e6b..2043d8bc8 100644 --- a/mailman/queue/outgoing.py +++ b/mailman/queue/outgoing.py @@ -26,6 +26,7 @@ import logging from datetime import datetime +from mailman import Defaults from mailman import Message from mailman.config import config from mailman.core import errors @@ -41,19 +42,19 @@ log = logging.getLogger('mailman.error') class OutgoingRunner(Runner, BounceMixin): - QDIR = config.OUTQUEUE_DIR + """The outgoing queue runner.""" 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[config.DELIVERY_MODULE] + handler = config.handlers[Defaults.DELIVERY_MODULE] self._func = handler.process # 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. self._logged = False - self._retryq = Switchboard(config.RETRYQUEUE_DIR) + self._retryq = config.switchboards['retry'] def _dispose(self, mlist, msg, msgdata): # See if we should retry delivery of this message again. @@ -73,13 +74,13 @@ class OutgoingRunner(Runner, BounceMixin): # There was a problem connecting to the SMTP server. Log this # once, but crank up our sleep time so we don't fill the error # log. - port = config.SMTPPORT + port = int(config.mta.port) if port == 0: port = 'smtp' # Log this just once. if not self._logged: log.error('Cannot connect to SMTP server %s on port %s', - config.SMTPHOST, port) + config.mta.host, port) self._logged = True return True except errors.SomeRecipientsFailed, e: @@ -115,7 +116,7 @@ class OutgoingRunner(Runner, BounceMixin): return False else: # Keep trying to delivery this message for a while - deliver_until = now + config.DELIVERY_RETRY_PERIOD + deliver_until = now + Defaults.DELIVERY_RETRY_PERIOD msgdata['last_recip_count'] = len(recips) msgdata['deliver_until'] = deliver_until msgdata['recips'] = recips diff --git a/mailman/testing/helpers.py b/mailman/testing/helpers.py index 62b0d8d95..1bcadedaf 100644 --- a/mailman/testing/helpers.py +++ b/mailman/testing/helpers.py @@ -51,17 +51,21 @@ log = logging.getLogger('mailman.debug') -def make_testable_runner(runner_class): +def make_testable_runner(runner_class, name=None): """Create a queue runner that runs until its queue is empty. - :param runner_class: An IRunner + :param runner_class: The queue runner's class. + :type runner_class: class + :param name: Optional queue name; if not given, it is calculated from the + class name. + :type name: string or None :return: A runner instance. """ - assert runner_class.__name__.endswith('Runner'), ( - 'Unparseable runner class name: %s' % runner_class.__name__) - - name = runner_class.__name__[:-6].lower() + if name is None: + assert runner_class.__name__.endswith('Runner'), ( + 'Unparseable runner class name: %s' % runner_class.__name__) + name = runner_class.__name__[:-6].lower() class EmptyingRunner(runner_class): """Stop processing when the queue is empty.""" @@ -163,12 +167,11 @@ class TestableMaster(Master): class SMTPServer: """An smtp server for testing.""" - host = 'localhost' - port = 10825 - def __init__(self): self._messages = [] self._queue = Queue() + self.host = config.mta.smtp_host + self.port = int(config.mta.smtp_port) self._server = Server((self.host, self.port), self._queue) self._thread = threading.Thread(target=self._server.start) @@ -177,9 +180,11 @@ class SMTPServer: log.info('test SMTP server starting') self._thread.start() smtpd = smtplib.SMTP() + log.info('connecting to %s:%s', self.host, self.port) smtpd.connect(self.host, self.port) - smtpd.helo('test.localhost') + response = smtpd.helo('test.localhost') smtpd.quit() + log.info('SMTP server is running: %s', response) def stop(self): """Stop the smtp server.""" -- cgit v1.2.3-70-g09d2 From 2413e18a366024b9d64bf6eb7d8afee50f7441da Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Thu, 1 Jan 2009 17:07:06 -0500 Subject: All tests are now passing! --- mailman/docs/lifecycle.txt | 1 + mailman/docs/styles.txt | 3 ++- mailman/pipeline/docs/scrubber.txt | 5 +++-- mailman/pipeline/scrubber.py | 3 ++- mailman/queue/__init__.py | 5 +++-- mailman/testing/layers.py | 16 ++++++++++++---- mailman/tests/test_documentation.py | 1 - 7 files changed, 23 insertions(+), 11 deletions(-) (limited to 'mailman/pipeline/docs') diff --git a/mailman/docs/lifecycle.txt b/mailman/docs/lifecycle.txt index 8531c6245..ab5e6ac23 100644 --- a/mailman/docs/lifecycle.txt +++ b/mailman/docs/lifecycle.txt @@ -57,6 +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.core.styles import style_manager >>> style_manager.register(TestStyle()) diff --git a/mailman/docs/styles.txt b/mailman/docs/styles.txt index 6397666ae..f75a34798 100644 --- a/mailman/docs/styles.txt +++ b/mailman/docs/styles.txt @@ -14,7 +14,8 @@ modify the mailing list any way it wants. Let's start with a vanilla mailing list and a default style manager. >>> mlist = config.db.list_manager.create(u'_xtest@example.com') - >>> from mailman.core.styles import style_manager + >>> from mailman.core.styles import StyleManager + >>> style_manager = StyleManager() The default style diff --git a/mailman/pipeline/docs/scrubber.txt b/mailman/pipeline/docs/scrubber.txt index 9c9367cda..eddd1939d 100644 --- a/mailman/pipeline/docs/scrubber.txt +++ b/mailman/pipeline/docs/scrubber.txt @@ -50,7 +50,8 @@ filename suggested in the message's Content-Disposition: header or not. If enabled, the filename will be used when this header attribute is present (yes, this is an unfortunate double negative). - >>> config.SCRUBBER_DONT_USE_ATTACHMENT_FILENAME = False + >>> from mailman import Defaults + >>> Defaults.SCRUBBER_DONT_USE_ATTACHMENT_FILENAME = False >>> msg = message_from_string("""\ ... Content-Type: image/gif; name="xtest.gif" ... Content-Transfer-Encoding: base64 @@ -79,7 +80,7 @@ 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. - >>> config.SCRUBBER_DONT_USE_ATTACHMENT_FILENAME = True + >>> Defaults.SCRUBBER_DONT_USE_ATTACHMENT_FILENAME = True >>> msg = message_from_string("""\ ... Content-Type: image/gif; name="xtest.gif" ... Content-Transfer-Encoding: base64 diff --git a/mailman/pipeline/scrubber.py b/mailman/pipeline/scrubber.py index e8268f0cf..a0e88b7d8 100644 --- a/mailman/pipeline/scrubber.py +++ b/mailman/pipeline/scrubber.py @@ -40,6 +40,7 @@ from zope.interface import implements from mailman import Defaults from mailman import Utils +from mailman.config import config from mailman.core.errors import DiscardMessage from mailman.core.plugins import get_plugin from mailman.i18n import _ @@ -394,7 +395,7 @@ def makedirs(dir): def save_attachment(mlist, msg, dir, filter_html=True): - fsdir = os.path.join(Defaults.PRIVATE_ARCHIVE_FILE_DIR, + fsdir = os.path.join(config.PRIVATE_ARCHIVE_FILE_DIR, mlist.fqdn_listname, dir) makedirs(fsdir) # Figure out the attachment type and get the decoded data diff --git a/mailman/queue/__init__.py b/mailman/queue/__init__.py index 5aa72bb14..239c61326 100644 --- a/mailman/queue/__init__.py +++ b/mailman/queue/__init__.py @@ -343,7 +343,8 @@ class Runner: # permissions problem or a MemoryError due to a really large # message. Try to be graceful. try: - new_filebase = self._shunt.enqueue(msg, msgdata) + shunt = config.switchboards['shunt'] + new_filebase = shunt.enqueue(msg, msgdata) elog.error('SHUNTING: %s', new_filebase) self.switchboard.finish(filebase) except Exception, e: @@ -382,7 +383,7 @@ class Runner: if mlist is None: elog.error('Dequeuing message destined for missing list: %s', listname) - self._shunt.enqueue(msg, msgdata) + config.switchboards['shunt'].enqueue(msg, msgdata) return # Now process this message. We also want to set up the language # context for this message. The context will be the preferred diff --git a/mailman/testing/layers.py b/mailman/testing/layers.py index 5976d9e4e..656bac5bd 100644 --- a/mailman/testing/layers.py +++ b/mailman/testing/layers.py @@ -36,8 +36,9 @@ from textwrap import dedent from mailman.config import config from mailman.core import initialize -from mailman.i18n import _ from mailman.core.logging import get_handler +from mailman.core.styles import style_manager +from mailman.i18n import _ from mailman.testing.helpers import SMTPServer @@ -135,11 +136,13 @@ class ConfigLayer: cls.var_dir = None @classmethod - def testSetUp(self): - pass + def testSetUp(cls): + # Record the current (default) set of styles so that we can reset them + # easily in the tear down. + cls.styles = set(style_manager.styles) @classmethod - def testTearDown(self): + def testTearDown(cls): # Reset the database between tests. config.db._reset() # Remove all residual queue files. @@ -150,6 +153,11 @@ class ConfigLayer: for message in config.db.message_store.messages: config.db.message_store.delete_message(message['message-id']) config.db.commit() + # Reset the global style manager. + new_styles = set(style_manager.styles) - cls.styles + for style in new_styles: + style_manager.unregister(style) + cls.styles = None # Flag to indicate that loggers should propagate to the console. stderr = False diff --git a/mailman/tests/test_documentation.py b/mailman/tests/test_documentation.py index 51dc784fe..c4df8444e 100644 --- a/mailman/tests/test_documentation.py +++ b/mailman/tests/test_documentation.py @@ -38,7 +38,6 @@ import mailman from mailman.Message import Message from mailman.config import config -from mailman.core.styles import style_manager from mailman.testing.layers import SMTPLayer -- cgit v1.2.3-70-g09d2