------------------------------------------------------------
revno: 6593
committer: Barry Warsaw <[EMAIL PROTECTED]>
branch nick: 3.0
timestamp: Sun 2008-02-17 23:34:09 -0500
message:
Added a test for the built-in pipeline. Fixed some broken handler names in
the built-in pipeline.
Fixed DEFAULT_SUBJECT_PREFIX to take $-names instead of %-names, although I'm
not entirely sure the %%d stuff still works (we need a test for this).
Added IMailingList.real_name attribute and added this to the default style. A
column for this was in the database but not in the storm object. Also
re-enabled the style's subject_prefix attribute.
Moved some of the digest test functions into Mailman.tests.helpers.
added:
Mailman/docs/pipelines.txt
modified:
Mailman/Defaults.py
Mailman/app/pipelines.py
Mailman/app/styles.py
Mailman/configuration.py
Mailman/interfaces/mailinglist.py
Mailman/pipeline/docs/digests.txt
Mailman/queue/pipeline.py
Mailman/tests/helpers.py
=== modified file 'Mailman/Defaults.py'
--- a/Mailman/Defaults.py 2008-02-17 22:34:21 +0000
+++ b/Mailman/Defaults.py 2008-02-18 04:34:09 +0000
@@ -878,8 +878,8 @@
# These format strings will be expanded w.r.t. the dictionary for the
# mailing list instance.
-DEFAULT_SUBJECT_PREFIX = u'[%(real_name)s] '
-# DEFAULT_SUBJECT_PREFIX = "[%(real_name)s %%d]" # for numbering
+DEFAULT_SUBJECT_PREFIX = u'[$mlist.real_name] '
+# DEFAULT_SUBJECT_PREFIX = "[$mlist.real_name %%d]" # for numbering
DEFAULT_MSG_HEADER = u''
DEFAULT_MSG_FOOTER = u"""\
_______________________________________________
=== modified file 'Mailman/app/pipelines.py'
--- a/Mailman/app/pipelines.py 2008-02-17 22:34:21 +0000
+++ b/Mailman/app/pipelines.py 2008-02-18 04:34:09 +0000
@@ -57,26 +57,26 @@
description = _('The built-in pipeline.')
_default_handlers = (
- 'mimedel',
+ 'mime-delete',
'scrubber',
'tagger',
'calculate-recipients',
'avoid-duplicates',
'cleanse',
- 'cleanse_dkim',
- 'cook_headers',
- 'to_digest',
- 'to_archive',
- 'to_usenet',
- 'after_delivery',
+ 'cleanse-dkim',
+ 'cook-headers',
+ 'to-digest',
+ 'to-archive',
+ 'to-usenet',
+ 'after-delivery',
'acknowledge',
- 'to_outgoing',
+ 'to-outgoing',
)
def __init__(self):
self._handlers = []
for handler_name in self._default_handlers:
- self._handler.append(config.handlers[handler_name])
+ self._handlers.append(config.handlers[handler_name])
def __iter__(self):
"""See `IPipeline`."""
@@ -96,3 +96,6 @@
'Duplicate handler "%s" found in %s' %
(handler.name, handler_finder))
config.handlers[handler.name] = handler
+ # Set up some pipelines.
+ pipeline = BuiltInPipeline()
+ config.pipelines[pipeline.name] = pipeline
=== modified file 'Mailman/app/styles.py'
--- a/Mailman/app/styles.py 2008-02-08 04:01:48 +0000
+++ b/Mailman/app/styles.py 2008-02-18 04:34:09 +0000
@@ -33,9 +33,12 @@
from Mailman.Errors import DuplicateStyleError
from Mailman.app.plugins import get_plugins
from Mailman.configuration import config
+from Mailman.i18n import _
from Mailman.interfaces import (
Action, IStyle, IStyleManager, NewsModeration, Personalization)
+__i18n_templates__ = True
+
class DefaultStyle:
@@ -52,6 +55,7 @@
mlist.post_id = 1
mlist.new_member_options = config.DEFAULT_NEW_MEMBER_OPTIONS
# This stuff is configurable
+ mlist.real_name = mlist.list_name.capitalize()
mlist.respond_to_post_requests = True
mlist.advertised = config.DEFAULT_LIST_ADVERTISED
mlist.max_num_recipients = config.DEFAULT_MAX_NUM_RECIPIENTS
@@ -135,8 +139,7 @@
# 2-tuple of the date of the last autoresponse and the number of
# autoresponses sent on that date.
mlist.hold_and_cmd_autoresponses = {}
- # XXX FIXME
- #mlist.subject_prefix = config.DEFAULT_SUBJECT_PREFIX % mlist.__dict__
+ mlist.subject_prefix = _(config.DEFAULT_SUBJECT_PREFIX)
mlist.msg_header = config.DEFAULT_MSG_HEADER
mlist.msg_footer = config.DEFAULT_MSG_FOOTER
# Set this to Never if the list's preferred language uses us-ascii,
@@ -228,6 +231,8 @@
# The processing chain that messages coming into this list get
# processed by.
mlist.start_chain = u'built-in'
+ # The default pipeline to send accepted messages through.
+ mlist.pipeline = u'built-in'
def match(self, mailing_list, styles):
# If no other styles have matched, then the default style matches.
=== modified file 'Mailman/configuration.py'
--- a/Mailman/configuration.py 2008-02-17 22:34:21 +0000
+++ b/Mailman/configuration.py 2008-02-18 04:34:09 +0000
@@ -180,6 +180,7 @@
self.chains = {}
self.rules = {}
self.handlers = {}
+ self.pipelines = {}
def add_domain(self, email_host, url_host=None):
"""Add a virtual domain.
=== added file 'Mailman/docs/pipelines.txt'
--- a/Mailman/docs/pipelines.txt 1970-01-01 00:00:00 +0000
+++ b/Mailman/docs/pipelines.txt 2008-02-18 04:34:09 +0000
@@ -0,0 +1,174 @@
+Pipelines
+=========
+
+This runner's purpose in life is to process messages that have been accepted
+for posting, applying any modifications and also sending copies of the message
+to the archives, digests, nntp, and outgoing queues. Pipelines are named and
+consist of a sequence of handlers, each of which is applied in turn. Unlike
+rules and chains, there is no way to stop a pipeline from processing the
+message once it's started.
+
+ >>> from Mailman.app.lifecycle import create_list
+ >>> mlist = create_list(u'[EMAIL PROTECTED]')
+ >>> mlist.web_page_url = u'http://lists.example.com/archives/'
+ >>> mlist.pipeline
+ u'built-in'
+ >>> from Mailman.app.pipelines import process
+
+
+Processing a message
+--------------------
+
+Messages hit the pipeline after they've been accepted for posting.
+
+ >>> msg = message_from_string("""\
+ ... From: [EMAIL PROTECTED]
+ ... To: [EMAIL PROTECTED]
+ ... Subject: My first post
+ ... Message-ID: <first>
+ ...
+ ... First post!
+ ... """)
+ >>> msgdata = {}
+ >>> process(mlist, msg, msgdata, mlist.pipeline)
+
+The message has been modified with additional headers, footer decorations,
+etc.
+
+ >>> print msg.as_string()
+ From: [EMAIL PROTECTED]
+ To: [EMAIL PROTECTED]
+ Message-ID: <first>
+ Subject: [Xtest] My first post
+ X-BeenThere: [EMAIL PROTECTED]
+ X-Mailman-Version: ...
+ Precedence: list
+ List-Id: <xtest.example.com>
+ List-Unsubscribe:
+ <http://lists.example.com/archives/listinfo/[EMAIL PROTECTED]>,
+ <mailto:[EMAIL PROTECTED]>
+ List-Archive: <http://www.example.com/pipermail/[EMAIL PROTECTED]>
+ List-Post: <mailto:[EMAIL PROTECTED]>
+ List-Help: <mailto:[EMAIL PROTECTED]>
+ List-Subscribe:
+ <http://lists.example.com/archives/listinfo/[EMAIL PROTECTED]>,
+ <mailto:[EMAIL PROTECTED]>
+ <BLANKLINE>
+ First post!
+ <BLANKLINE>
+
+And the message metadata has information about recipients and other stuff.
+However there are currently no recipients for this message.
+
+ >>> sorted(msgdata.items())
+ [('original_sender', u'[EMAIL PROTECTED]'),
+ ('origsubj', u'My first post'),
+ ('recips', set([])),
+ ('stripped_subject', <email.header.Header instance at ...>)]
+
+And the message is now sitting in various other processing queues.
+
+ >>> from Mailman.tests.helpers import get_queue_messages
+ >>> from Mailman.configuration import config
+ >>> messages = get_queue_messages(config.ARCHQUEUE_DIR)
+ >>> len(messages)
+ 1
+ >>> print messages[0].msg.as_string()
+ From: [EMAIL PROTECTED]
+ To: [EMAIL PROTECTED]
+ Message-ID: <first>
+ Subject: [Xtest] My first post
+ X-BeenThere: [EMAIL PROTECTED]
+ X-Mailman-Version: ...
+ Precedence: list
+ List-Id: <xtest.example.com>
+ List-Unsubscribe:
+ <http://lists.example.com/archives/listinfo/[EMAIL PROTECTED]>,
+ <mailto:[EMAIL PROTECTED]>
+ List-Archive: <http://www.example.com/pipermail/[EMAIL PROTECTED]>
+ List-Post: <mailto:[EMAIL PROTECTED]>
+ List-Help: <mailto:[EMAIL PROTECTED]>
+ List-Subscribe:
+ <http://lists.example.com/archives/listinfo/[EMAIL PROTECTED]>,
+ <mailto:[EMAIL PROTECTED]>
+ <BLANKLINE>
+ First post!
+ <BLANKLINE>
+ >>> print sorted(messages[0].msgdata.items())
+ [('_parsemsg', False), ('original_sender', u'[EMAIL PROTECTED]'),
+ ('origsubj', u'My first post'),
+ ('received_time', ...), ('recips', set([])),
+ ('stripped_subject', <email.header.Header instance at ...>),
+ ('version', 3)]
+
+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)
+ >>> len(messages)
+ 0
+
+This is the message that will actually get delivered to end recipients.
+
+ >>> messages = get_queue_messages(config.OUTQUEUE_DIR)
+ >>> len(messages)
+ 1
+ >>> print messages[0].msg.as_string()
+ From: [EMAIL PROTECTED]
+ To: [EMAIL PROTECTED]
+ Message-ID: <first>
+ Subject: [Xtest] My first post
+ X-BeenThere: [EMAIL PROTECTED]
+ X-Mailman-Version: ...
+ Precedence: list
+ List-Id: <xtest.example.com>
+ List-Unsubscribe:
+ <http://lists.example.com/archives/listinfo/[EMAIL PROTECTED]>,
+ <mailto:[EMAIL PROTECTED]>
+ List-Archive: <http://www.example.com/pipermail/[EMAIL PROTECTED]>
+ List-Post: <mailto:[EMAIL PROTECTED]>
+ List-Help: <mailto:[EMAIL PROTECTED]>
+ List-Subscribe:
+ <http://lists.example.com/archives/listinfo/[EMAIL PROTECTED]>,
+ <mailto:[EMAIL PROTECTED]>
+ <BLANKLINE>
+ First post!
+ <BLANKLINE>
+ >>> print sorted(messages[0].msgdata.items())
+ [('_parsemsg', False), ('listname', u'[EMAIL PROTECTED]'),
+ ('original_sender', u'[EMAIL PROTECTED]'),
+ ('origsubj', u'My first post'), ('received_time', ...),
+ ('recips', set([])),
+ ('stripped_subject', <email.header.Header instance at ...>),
+ ('version', 3)]
+
+There's now one message in the digest mailbox, getting ready to be sent.
+
+ >>> from Mailman.tests.helpers import digest_mbox
+ >>> digest = digest_mbox(mlist)
+ >>> sum(1 for mboxmsg in digest)
+ 1
+ >>> print list(digest)[0].as_string()
+ From: [EMAIL PROTECTED]
+ To: [EMAIL PROTECTED]
+ Message-ID: <first>
+ Subject: [Xtest] My first post
+ X-BeenThere: [EMAIL PROTECTED]
+ X-Mailman-Version: ...
+ Precedence: list
+ List-Id: <xtest.example.com>
+ List-Unsubscribe:
+ <http://lists.example.com/archives/listinfo/[EMAIL PROTECTED]>,
+ <mailto:[EMAIL PROTECTED]>
+ List-Archive: <http://www.example.com/pipermail/[EMAIL PROTECTED]>
+ List-Post: <mailto:[EMAIL PROTECTED]>
+ List-Help: <mailto:[EMAIL PROTECTED]>
+ List-Subscribe:
+ <http://lists.example.com/archives/listinfo/[EMAIL PROTECTED]>,
+ <mailto:[EMAIL PROTECTED]>
+ <BLANKLINE>
+ First post!
+ <BLANKLINE>
+ <BLANKLINE>
+
+ >>> digest.clear()
=== modified file 'Mailman/interfaces/mailinglist.py'
--- a/Mailman/interfaces/mailinglist.py 2008-02-08 04:01:48 +0000
+++ b/Mailman/interfaces/mailinglist.py 2008-02-18 04:34:09 +0000
@@ -61,6 +61,13 @@
posted to [EMAIL PROTECTED], then the list_name is 'mylist'.
""")
+ real_name = Attribute(
+ """The short human-readable descriptive name for the mailing list. By
+ default, this is the capitalized `list_name`, but it can be changed to
+ anything. This is used in locations such as the message footers and
+ Subject prefix.
+ """)
+
host_name = Attribute(
"""The read-only domain name 'hosting' this mailing list. This is
always the domain name part of the posting email address, and it may
=== modified file 'Mailman/pipeline/docs/digests.txt'
--- a/Mailman/pipeline/docs/digests.txt 2008-02-08 13:27:25 +0000
+++ b/Mailman/pipeline/docs/digests.txt 2008-02-18 04:34:09 +0000
@@ -21,15 +21,7 @@
messages, in the order in which they were posted. This makes it easier to
update the tests when we switch to a different mailbox format.
- >>> import os, mailbox
- >>> def digest_mbox():
- ... path = os.path.join(mlist.full_path, 'digest.mbox')
- ... return mailbox.mbox(path)
-
- >>> def clear_mbox():
- ... path = os.path.join(mlist.full_path, 'digest.mbox')
- ... os.remove(path)
-
+ >>> from Mailman.tests.helpers import digest_mbox
>>> from itertools import count
>>> from string import Template
>>> def makemsg():
@@ -57,7 +49,7 @@
>>> mlist.digestable = False
>>> msg = makemsg().next()
>>> process(mlist, msg, {})
- >>> sum(1 for mboxmsg in digest_mbox())
+ >>> sum(1 for mboxmsg in digest_mbox(mlist))
0
>>> switchboard.files
[]
@@ -66,7 +58,7 @@
>>> mlist.digestable = True
>>> process(mlist, msg, dict(isdigest=True))
- >>> sum(1 for mboxmsg in digest_mbox())
+ >>> sum(1 for mboxmsg in digest_mbox(mlist))
0
>>> switchboard.files
[]
@@ -84,9 +76,11 @@
>>> process(mlist, msg, {})
>>> switchboard.files
[]
- >>> sum(1 for mboxmsg in digest_mbox())
+ >>> digest = digest_mbox(mlist)
+ >>> sum(1 for mboxmsg in digest)
1
- >>> clear_mbox()
+ >>> import os
+ >>> os.remove(digest._path)
When the size of the digest mbox reaches the maximum size threshold, a digest
is crafted and sent out. This puts two messages in the virgin queue, an HTML
@@ -101,7 +95,7 @@
... size += len(str(msg))
... if size > mlist.digest_size_threshold * 1024:
... break
- >>> sum(1 for mboxmsg in digest_mbox())
+ >>> sum(1 for mboxmsg in digest_mbox(mlist))
0
>>> len(switchboard.files)
2
@@ -434,7 +428,7 @@
>>> mlist.digest_size_threshold = 0
>>> process(mlist, msg, {})
- >>> sum(1 for mboxmsg in digest_mbox())
+ >>> sum(1 for mboxmsg in digest_mbox(mlist))
0
>>> len(switchboard.files)
2
=== modified file 'Mailman/queue/pipeline.py'
--- a/Mailman/queue/pipeline.py 2008-02-08 13:12:04 +0000
+++ b/Mailman/queue/pipeline.py 2008-02-18 04:34:09 +0000
@@ -36,4 +36,3 @@
process(mlist, msg, msgdata, mlist.pipeline)
# Do not keep this message queued.
return False
-
=== modified file 'Mailman/tests/helpers.py'
--- a/Mailman/tests/helpers.py 2008-02-02 18:47:23 +0000
+++ b/Mailman/tests/helpers.py 2008-02-18 04:34:09 +0000
@@ -19,11 +19,18 @@
__metaclass__ = type
__all__ = [
+ 'digest_mbox',
'get_queue_messages',
'make_testable_runner',
]
+import os
+import mailbox
+
+from Mailman.queue import Switchboard
+
+
def make_testable_runner(runner_class):
"""Create a queue runner that runs until its queue is empty.
@@ -52,13 +59,26 @@
def get_queue_messages(queue):
"""Return and clear all the messages in the given queue.
- :param queue: An ISwitchboard
+ :param queue: An ISwitchboard or 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)
messages = []
for filebase in queue.files:
msg, msgdata = queue.dequeue(filebase)
messages.append(_Bag(msg=msg, msgdata=msgdata))
queue.finish(filebase)
return messages
+
+
+
+def digest_mbox(mlist):
+ """The mailing list's pending digest as a mailbox.
+
+ :param mlist: The mailing list.
+ :return: The mailing list's pending digest as a mailbox.
+ """
+ path = os.path.join(mlist.full_path, 'digest.mbox')
+ return mailbox.mbox(path)
--
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