------------------------------------------------------------ revno: 6583 committer: Barry Warsaw <[EMAIL PROTECTED]> branch nick: 3.0 timestamp: Sun 2008-01-13 16:18:19 -0500 message: Merge from rfc5064 branch. added: Mailman/interfaces/archiver.py modified: Mailman/Handlers/Cleanse.py Mailman/Handlers/CookHeaders.py Mailman/Handlers/Scrubber.py Mailman/app/archiving.py Mailman/docs/cook-headers.txt Mailman/docs/scrubber.txt setup.py ------------------------------------------------------------ revno: 6582.1.1 committer: Barry Warsaw <[EMAIL PROTECTED]> branch nick: rfc5064 timestamp: Sun 2008-01-13 16:17:38 -0500 message: Add an interface IArchiver which is used to calculate urls and send messages to the archiver. Also add a plugin architecture for easily overriding the archiver, and hook this into the setup.py script. Updated CookHeaders.py and Scrubber.py handlers to use the plugged archiver. Updated doctests as appropriate. Fix a typo in the setup.py file. added: Mailman/interfaces/archiver.py modified: Mailman/Handlers/Cleanse.py Mailman/Handlers/CookHeaders.py Mailman/Handlers/Scrubber.py Mailman/app/archiving.py Mailman/docs/cook-headers.txt Mailman/docs/scrubber.txt setup.py
=== modified file 'Mailman/Handlers/Cleanse.py' --- a/Mailman/Handlers/Cleanse.py 2007-06-19 22:42:27 +0000 +++ b/Mailman/Handlers/Cleanse.py 2008-01-13 21:17:38 +0000 @@ -54,3 +54,5 @@ del msg['x-confirm-reading-to'] # Pegasus mail uses this one... sigh del msg['x-pmrqc'] + # Don't let this header be spoofed. See RFC 5064. + del msg['archived-at'] === modified file 'Mailman/Handlers/CookHeaders.py' --- a/Mailman/Handlers/CookHeaders.py 2007-10-10 04:16:12 +0000 +++ b/Mailman/Handlers/CookHeaders.py 2008-01-13 21:17:38 +0000 @@ -26,7 +26,7 @@ from Mailman import Utils from Mailman import Version -from Mailman.app.archiving import get_base_archive_url +from Mailman.app.archiving import get_archiver from Mailman.configuration import config from Mailman.i18n import _ from Mailman.interfaces import Personalization, ReplyToMunging @@ -200,6 +200,7 @@ 'List-Unsubscribe': subfieldfmt % (listinfo, mlist.leave_address), 'List-Subscribe' : subfieldfmt % (listinfo, mlist.join_address), }) + archiver = get_archiver() if msgdata.get('reduced_list_headers'): headers['X-List-Administrivia'] = 'yes' else: @@ -208,10 +209,17 @@ headers['List-Post'] = '<mailto:%s>' % mlist.posting_address # Add this header if we're archiving if mlist.archive: - archiveurl = get_base_archive_url(mlist) - if archiveurl.endswith('/'): - archiveurl = archiveurl[:-1] + archiveurl = archiver.get_list_url(mlist) headers['List-Archive'] = '<%s>' % archiveurl + # XXX RFC 2369 also defines a List-Owner header which we are not currently + # supporting, but should. + # + # Draft RFC 5064 defines an Archived-At header which contains the pointer + # directly to the message in the archive. If the currently defined + # archiver can tell us the URL, go ahead and include this header. + archived_at = archiver.get_message_url(mlist, msg) + if archived_at is not None: + headers['Archived-At'] = archived_at # First we delete any pre-existing headers because the RFC permits only # one copy of each, and we want to be sure it's ours. for h, v in headers.items(): === modified file 'Mailman/Handlers/Scrubber.py' --- a/Mailman/Handlers/Scrubber.py 2007-11-18 21:38:59 +0000 +++ b/Mailman/Handlers/Scrubber.py 2008-01-13 21:17:38 +0000 @@ -35,7 +35,7 @@ from Mailman import Utils from Mailman.Errors import DiscardMessage -from Mailman.app.archiving import get_base_archive_url +from Mailman.app.archiving import get_archiver from Mailman.configuration import config from Mailman.i18n import _ @@ -490,10 +490,9 @@ fp = open(path, 'w') fp.write(decodedpayload) fp.close() - # Now calculate the url - baseurl = get_base_archive_url(mlist) - # Private archives will likely have a trailing slash. Normalize. - if baseurl[-1] <> '/': + # Now calculate the url to the list's archive. + baseurl = get_archiver().get_list_url(mlist) + if not baseurl.endswith('/'): baseurl += '/' # Trailing space will definitely be a problem with format=flowed. # Bracket the URL instead. === modified file 'Mailman/app/archiving.py' --- a/Mailman/app/archiving.py 2007-09-21 12:51:38 +0000 +++ b/Mailman/app/archiving.py 2008-01-13 21:17:38 +0000 @@ -1,4 +1,4 @@ -# Copyright (C) 2007 by the Free Software Foundation, Inc. +# Copyright (C) 2007-2008 by the Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License @@ -17,20 +17,61 @@ """Application level archiving support.""" +__all__ = [ + 'StockArchiver', + 'get_archiver', + ] +__metaclass__ = type + + from string import Template +from zope.interface import implements +from zope.interface.verify import verifyObject +from Mailman.app.plugins import get_plugin from Mailman.configuration import config - - - -def get_base_archive_url(mlist): - if mlist.archive_private: - url = mlist.script_url('private') + '/index.html' - else: - web_host = config.domains.get(mlist.host_name, mlist.host_name) - url = Template(config.PUBLIC_ARCHIVE_URL).safe_substitute( - listname=mlist.fqdn_listname, - hostname=web_host, - fqdn_listname=mlist.fqdn_listname, - ) - return url +from Mailman.interfaces import IArchiver + + + +class StockArchiver: + """The stock Pipermail archiver.""" + + implements(IArchiver) + + def get_list_url(self, mlist): + """See `IArchiver`.""" + if mlist.archive_private: + url = mlist.script_url('private') + '/index.html' + else: + web_host = config.domains.get(mlist.host_name, mlist.host_name) + url = Template(config.PUBLIC_ARCHIVE_URL).safe_substitute( + listname=mlist.fqdn_listname, + hostname=web_host, + fqdn_listname=mlist.fqdn_listname, + ) + return url + + def get_message_url(self, mlist, message): + """See `IArchiver`.""" + # Not currently implemented. + return None + + def archive_message(self, mlist, message): + """See `IArchiver`.""" + return None + + + +_archiver = None + +def get_archiver(): + """Return the currently registered global archiver. + + Uses the plugin architecture to find the IArchiver instance. + """ + global _archiver + if _archiver is None: + _archiver = get_plugin('mailman.archiver')() + verifyObject(IArchiver, _archiver) + return _archiver === modified file 'Mailman/docs/cook-headers.txt' --- a/Mailman/docs/cook-headers.txt 2007-11-08 05:34:49 +0000 +++ b/Mailman/docs/cook-headers.txt 2008-01-13 21:17:38 +0000 @@ -285,6 +285,19 @@ ---end--- +Archived-At +----------- + +RFC 5064 (draft) defines a new Archived-At header which contains the url to +the individual message in the archives. The stock Pipermail archiver doesn't +support this because the url can't be calculated until after the message is +archived. Because this is done by the archive runner, this information isn't +available to us now. + + >>> print msg['archived-at'] + None + + Personalization --------------- === modified file 'Mailman/docs/scrubber.txt' --- a/Mailman/docs/scrubber.txt 2007-11-08 16:54:25 +0000 +++ b/Mailman/docs/scrubber.txt 2008-01-13 21:17:38 +0000 @@ -59,9 +59,9 @@ ... ... R0lGODdhAQABAIAAAAAAAAAAACwAAAAAAQABAAACAQUAOw== ... """) - >>> save_attachment(mlist, msg, '') - u'<http://www.example.com/pipermail/[EMAIL PROTECTED]//xtest.gif>' - >>> data = read_attachment('xtest.gif') + >>> save_attachment(mlist, msg, 'dir') + u'<http://www.example.com/pipermail/[EMAIL PROTECTED]/dir/xtest.gif>' + >>> data = read_attachment('dir/xtest.gif') >>> data[:6] 'GIF87a' >>> len(data) @@ -88,13 +88,13 @@ ... ... R0lGODdhAQABAIAAAAAAAAAAACwAAAAAAQABAAACAQUAOw== ... """) - >>> save_attachment(mlist, msg, '') - u'<http://www.example.com/pipermail/[EMAIL PROTECTED]/.../attachment.gif>' - >>> data = read_attachment('xtest.gif') + >>> save_attachment(mlist, msg, 'dir') + u'<http://www.example.com/pipermail/[EMAIL PROTECTED]/dir/attachment.gif>' + >>> data = read_attachment('dir/xtest.gif') Traceback (most recent call last): IOError: [Errno ...] No such file or directory: - u'.../archives/private/[EMAIL PROTECTED]/xtest.gif' - >>> data = read_attachment('attachment.gif') + u'.../archives/private/[EMAIL PROTECTED]/dir/xtest.gif' + >>> data = read_attachment('dir/attachment.gif') >>> data[:6] 'GIF87a' >>> len(data) === added file 'Mailman/interfaces/archiver.py' --- a/Mailman/interfaces/archiver.py 1970-01-01 00:00:00 +0000 +++ b/Mailman/interfaces/archiver.py 2008-01-13 21:17:38 +0000 @@ -0,0 +1,58 @@ +# Copyright (C) 2008 by the Free Software Foundation, Inc. +# +# This program 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 2 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. + +"""Interface for archiving schemes.""" + +from zope.interface import Interface, Attribute + + + +class IArchiver(Interface): + """An interface to the archiver.""" + + def get_list_url(mlist): + """Return the url to the top of the list's archive. + + :param mlist: The IMailingList object. + :returns: The url string. + """ + + def get_message_url(mlist, message): + """Return the url to the message in the archive. + + This url points directly to the message in the archive. This method + only calculates the url, it does not actually archive the message. + + :param mlist: The IMailingList object. + :param message: The message object. + :returns: The url string or None if the message's archive url cannot + be calculated. + """ + + def archive_message(mlist, message): + """Send the message to the archiver. + + This uses `get_message_url()` to calculate and return the url to the + message in the archives. + + :param mlist: The IMailingList object. + :param message: The message object. + :returns: The url string or None if the message's archive url cannot + be calculated. + """ + + # XXX How to handle attachments? === modified file 'setup.py' --- a/setup.py 2008-01-13 19:35:31 +0000 +++ b/setup.py 2008-01-13 21:17:38 +0000 @@ -82,11 +82,12 @@ include_package_data = True, entry_points = { 'console_scripts': list(scripts), - 'setuptools.file_finders': 'bzr = setuptoolsbzr:find_files_for_bzr', + 'setuptools.file_finders': 'bzr = setuptools_bzr:find_files_for_bzr', # Entry point for plugging in different database backends. + 'mailman.archiver' : 'stock = Mailman.app.archiving:StockArchiver', 'mailman.database' : 'stock = Mailman.database:StockDatabase', + 'mailman.mta' : 'stock = Mailman.MTA:Manual', 'mailman.styles' : 'default = Mailman.app.styles:DefaultStyle', - 'mailman.mta' : 'stock = Mailman.MTA:Manual', }, # Third-party requirements. install_requires = [ -- 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 Mailman-checkins@python.org Unsubscribe: http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org