[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mailman-cvs
Subject:    [Mailman-checkins] SF.net SVN: mailman: [8228] trunk/mailman
From:       bwarsaw () users ! sourceforge ! net
Date:       2007-05-30 16:54:28
Message-ID: E1HtRRL-00047N-FV () sc8-pr-svn1 ! sourceforge ! net
[Download RAW message or body]

Revision: 8228
          http://svn.sourceforge.net/mailman/?rev=8228&view=rev
Author:   bwarsaw
Date:     2007-05-30 09:54:17 -0700 (Wed, 30 May 2007)

Log Message:
-----------
Go ahead and remove the Mailman/database/tables directory since all the Elixir
classes live in Mailman/databae/model now.

Remove the TestDecorate test class from test_handlers.py and move them into a
doctest called decorate.txt (with harness in test_decorate.py).

Remove the dependence on SafeDict from the Decorate handler because I can now
use string.Template object to safely fill in header and footer templates.
Eventually I want to completely remove SafeDict from Mailman, but it's still
used in a few other places.

This also means that only $-strings will be supported in headers and footers,
and the import script will have to convert %-strings to $-strings.  Also,
'_internal_name' is no longer a supported header/footer substitution
variable.  Use $real_name or $list_name now.  Added $fqdn_listname as a
substitution variable.  Update the DEFAULT_MSG_FOOTER accordingly.

Modified Paths:
--------------
    trunk/mailman/Mailman/Defaults.py.in
    trunk/mailman/Mailman/Handlers/Decorate.py
    trunk/mailman/Mailman/database/Makefile.in
    trunk/mailman/Mailman/testing/test_handlers.py
    trunk/mailman/Makefile.in
    trunk/mailman/configure
    trunk/mailman/configure.in
    trunk/mailman/docs/NEWS.txt

Added Paths:
-----------
    trunk/mailman/Mailman/docs/decorate.txt
    trunk/mailman/Mailman/testing/test_decorate.py

Removed Paths:
-------------
    trunk/mailman/Mailman/database/tables/

Modified: trunk/mailman/Mailman/Defaults.py.in
===================================================================
--- trunk/mailman/Mailman/Defaults.py.in	2007-05-29 15:04:19 UTC (rev 8227)
+++ trunk/mailman/Mailman/Defaults.py.in	2007-05-30 16:54:17 UTC (rev 8228)
@@ -909,10 +909,11 @@
 DEFAULT_SUBJECT_PREFIX  = "[%(real_name)s] "
 # DEFAULT_SUBJECT_PREFIX = "[%(real_name)s %%d]" # for numbering
 DEFAULT_MSG_HEADER = ""
-DEFAULT_MSG_FOOTER = """_______________________________________________
-%(real_name)s mailing list
-%(real_name)s@%(host_name)s
-%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s
+DEFAULT_MSG_FOOTER = """\
+_______________________________________________
+$real_name mailing list
+$fqdn_realname
+${web_page_url}listinfo${cgiext}/${list_name}
 """
 
 # Where to put subject prefix for 'Re:' messages:

Modified: trunk/mailman/Mailman/Handlers/Decorate.py
===================================================================
--- trunk/mailman/Mailman/Handlers/Decorate.py	2007-05-29 15:04:19 UTC (rev 8227)
+++ trunk/mailman/Mailman/Handlers/Decorate.py	2007-05-30 16:54:17 UTC (rev 8228)
@@ -21,13 +21,13 @@
 import logging
 
 from email.MIMEText import MIMEText
+from string import Template
 
 from Mailman import Errors
-from Mailman import mm_cfg
 from Mailman import Utils
-from Mailman.i18n import _
 from Mailman.Message import Message
-from Mailman.SafeDict import SafeDict
+from Mailman.configuration import config
+from Mailman.i18n import _
 
 log = logging.getLogger('mailman.error')
 
@@ -42,7 +42,8 @@
         # Calculate the extra personalization dictionary.  Note that the
         # length of the recips list better be exactly 1.
         recips = msgdata.get('recips')
-        assert isinstance(recips, list) and len(recips) == 1
+        assert isinstance(recips, list) and len(recips) == 1, (
+            'The number of intended recipients must be exactly 1')
         member = recips[0].lower()
         d['user_address'] = member
         try:
@@ -56,8 +57,8 @@
         except Errors.NotAMemberError:
             pass
     # These strings are descriptive for the log file and shouldn't be i18n'd
-    header = decorate(mlist, mlist.msg_header, 'non-digest header', d)
-    footer = decorate(mlist, mlist.msg_footer, 'non-digest footer', d)
+    header = decorate(mlist, mlist.msg_header, d)
+    footer = decorate(mlist, mlist.msg_footer, d)
     # Escape hatch if both the footer and header are empty
     if not header and not footer:
         return
@@ -185,35 +186,21 @@
 
 
 
-def decorate(mlist, template, what, extradict={}):
-    # `what' is just a descriptive phrase used in the log message
-    #
-    # BAW: We've found too many situations where Python can be fooled into
-    # interpolating too much revealing data into a format string.  For
-    # example, a footer of "% silly %(real_name)s" would give a header
-    # containing all list attributes.  While we've previously removed such
-    # really bad ones like `password' and `passwords', it's much better to
-    # provide a whitelist of known good attributes, then to try to remove a
-    # blacklist of known bad ones.
-    d = SafeDict({'real_name'     : mlist.real_name,
-                  'list_name'     : mlist.internal_name(),
-                  # For backwards compatibility
-                  '_internal_name': mlist.internal_name(),
-                  'host_name'     : mlist.host_name,
-                  'web_page_url'  : mlist.web_page_url,
-                  'description'   : mlist.description,
-                  'info'          : mlist.info,
-                  'cgiext'        : mm_cfg.CGIEXT,
-                  })
-    d.update(extradict)
-    # Using $-strings?
-    if getattr(mlist, 'use_dollar_strings', 0):
-        template = Utils.to_percent(template)
-    # Interpolate into the template
-    try:
-        text = re.sub(r' *\r?\n', r'\n', template % d)
-    except (ValueError, TypeError), e:
-        log.exception('Exception while calculating %s:\n%s', what, e)
-        what = what.upper()
-        text = template
-    return text
+def decorate(mlist, template, extradict=None):
+    # Create a dictionary which includes the default set of interpolation
+    # variables allowed in headers and footers.  These will be augmented by
+    # any key/value pairs in the extradict.
+    d = dict(real_name      = mlist.real_name,
+             list_name      = mlist.list_name,
+             fqdn_listname  = mlist.fqdn_listname,
+             host_name      = mlist.host_name,
+             web_page_url   = mlist.web_page_url,
+             description    = mlist.description,
+             info           = mlist.info,
+             cgiext         = config.CGIEXT,
+             )
+    if extradict is not None:
+        d.update(extradict)
+    text = Template(template).safe_substitute(d)
+    # Turn any \r\n line endings into just \n
+    return re.sub(r' *\r?\n', r'\n', text)

Modified: trunk/mailman/Mailman/database/Makefile.in
===================================================================
--- trunk/mailman/Mailman/database/Makefile.in	2007-05-29 15:04:19 UTC (rev 8227)
+++ trunk/mailman/Mailman/database/Makefile.in	2007-05-30 16:54:17 UTC (rev 8228)
@@ -42,7 +42,7 @@
 SHELL=		/bin/sh
 
 MODULES=	*.py
-SUBDIRS=	tables model
+SUBDIRS=	model
 
 # Modes for directories and executables created by the install
 # process.  Default to group-writable directories but

Added: trunk/mailman/Mailman/docs/decorate.txt
===================================================================
--- trunk/mailman/Mailman/docs/decorate.txt	                        (rev 0)
+++ trunk/mailman/Mailman/docs/decorate.txt	2007-05-30 16:54:17 UTC (rev 8228)
@@ -0,0 +1,330 @@
+Message decoration
+==================
+
+Message decoration is the process of adding headers and footers to the
+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 email import message_from_string
+    >>> from Mailman.Handlers.Decorate import process
+    >>> from Mailman.configuration import config
+    >>> from Mailman.database import flush
+    >>> mlist = config.list_manager.create('_xtest@example.com')
+    >>> msg_text = """\
+    ... From: aperson@example.org
+    ...
+    ... Here is a message.
+    ... """
+    >>> msg = message_from_string(msg_text)
+
+
+Short circuiting
+----------------
+
+Digest messages get decorated during the digest creation phase so no extra
+decorations are added for digest messages.
+
+    >>> process(mlist, msg, dict(isdigest=True))
+    >>> print msg.as_string()
+    From: aperson@example.org
+    <BLANKLINE>
+    Here is a message.
+
+    >>> process(mlist, msg, dict(nodecorate=True))
+    >>> print msg.as_string()
+    From: aperson@example.org
+    <BLANKLINE>
+    Here is a message.
+
+
+Decorating simple text messages
+-------------------------------
+
+Text messages that have no declared content type character set are by default,
+encoded in us-ascii.  When the mailing list's preferred language is 'en'
+(i.e. English), the character set of the mailing list and of the message will
+match.  In this case, and when the header and footer have no interpolation
+placeholder variables, the message's payload will be prepended by the verbatim
+header, and appended with the verbatim footer.
+
+    >>> msg = message_from_string(msg_text)
+    >>> mlist.msg_header = 'header\n'
+    >>> mlist.msg_footer = 'footer'
+    >>> mlist.preferred_language = 'en'
+    >>> flush()
+    >>> process(mlist, msg, {})
+    >>> print msg.as_string()
+    From: aperson@example.org
+    ...
+    <BLANKLINE>
+    header
+    Here is a message.
+    footer
+
+Mailman supports a number of interpolation variables, placeholders in the
+header and footer for information to be filled in with mailing list specific
+data.  An example of such information is the mailing list's "real name" (a
+short descriptive name for the mailing list).
+
+    # XXX Remove this line after converting this test
+    >>> mlist.use_dollar_strings = True
+
+    >>> msg = message_from_string(msg_text)
+    >>> mlist.msg_header = '$real_name header\n'
+    >>> mlist.msg_footer = '$real_name footer'
+    >>> mlist.real_name = 'XTest'
+    >>> flush()
+    >>> process(mlist, msg, {})
+    >>> print msg.as_string()
+    From: aperson@example.org
+    ...
+    XTest header
+    Here is a message.
+    XTest footer
+
+You can't just pick any interpolation variable though; if you do, the variable
+will remain in the header or footer unchanged.
+
+    >>> msg = message_from_string(msg_text)
+    >>> mlist.msg_header = '$dummy header\n'
+    >>> mlist.msg_footer = '$dummy footer'
+    >>> flush()
+    >>> process(mlist, msg, {})
+    >>> print msg.as_string()
+    From: aperson@example.org
+    ...
+    $dummy header
+    Here is a message.
+    $dummy footer
+
+
+Handling RFC 3676 'format=flowed' parameters
+--------------------------------------------
+
+RFC 3676 describes a standard by which text/plain messages can marked by
+generating MUAs for better readability in compatible receiving MUAs.  The
+'format' parameter on the text/plain Content-Type header gives hints as to how
+the receiving MUA may flow and delete trailing whitespace for better display
+in a proportional font.
+
+When Mailman sees text/plain messages with such RFC 3676 parameters, it
+preserves these parameters when it concatenates headers and footers to the
+message payload.
+
+    >>> mlist.msg_header = 'header'
+    >>> mlist.msg_footer = 'footer'
+    >>> mlist.preferred_language = 'en'
+    >>> mlist.flush()
+    >>> msg = message_from_string("""\
+    ... From: aperson@example.org
+    ... Content-Type: text/plain; format=flowed; delsp=no
+    ... 
+    ... Here is a message\x20
+    ... with soft line breaks.
+    ... """)
+    >>> process(mlist, msg, {})
+    >>> # Don't use 'print' here as above because it won't be obvious from the
+    >>> # output that the soft-line break space at the end of the 'Here is a
+    >>> # message' line will be retained in the output.
+    >>> msg['content-type']
+    u'text/plain; format="flowed"; delsp="no"; charset="us-ascii"'
+    >>> [line for line in msg.get_payload().splitlines()]
+    ['header', 'Here is a message ', 'with soft line breaks.', 'footer']
+
+
+Decorating mixed-charset messages
+---------------------------------
+
+When a message has no explicit character set, it is assumed to be us-ascii.
+However, if the mailing list's preferred language has a different character
+set, Mailman will still try to concatenate the header and footer, but it will
+convert the text to utf-8 and base-64 encode the message payload.
+
+    # 'ja' = Japanese; charset = 'euc-jp'
+    >>> mlist.preferred_language = 'ja'
+    >>> mlist.msg_header = '$description header'
+    >>> mlist.msg_footer = '$description footer'
+    >>> mlist.description = u'\u65e5\u672c\u8a9e'
+    >>> flush()
+
+    >>> from email.message import Message
+    >>> msg = Message()
+    >>> msg.set_payload('Fran\xe7aise', 'iso-8859-1')
+    >>> print msg.as_string()
+    MIME-Version: 1.0
+    Content-Type: text/plain; charset="iso-8859-1"
+    Content-Transfer-Encoding: quoted-printable
+    <BLANKLINE>
+    Fran=E7aise
+    >>> process(mlist, msg, {})
+    >>> print msg.as_string()
+    MIME-Version: 1.0
+    Content-Type: text/plain; charset="utf-8"
+    Content-Transfer-Encoding: base64
+    <BLANKLINE>
+    5pel5pys6KqeIGhlYWRlcgpGcmFuw6dhaXNlCuaXpeacrOiqniBmb290ZXI=
+
+
+Sometimes the message even has an unknown character set.  In this case,
+Mailman has no choice but to decorate the original message with MIME
+attachments.
+
+    >>> mlist.preferred_language = 'en'
+    >>> mlist.msg_header = 'header'
+    >>> mlist.msg_footer = 'footer'
+    >>> flush()
+    >>> msg = message_from_string("""\
+    ... From: aperson@example.org
+    ... Content-Type: text/plain; charset=unknown
+    ... Content-Transfer-Encoding: 7bit
+    ...
+    ... Here is a message.
+    ... """)
+    >>> process(mlist, msg, {})
+    >>> msg.set_boundary('BOUNDARY')
+    >>> print msg.as_string()
+    From: aperson@example.org
+    Content-Type: multipart/mixed; boundary="BOUNDARY"
+    <BLANKLINE>
+    --BOUNDARY
+    Content-Type: text/plain; charset="us-ascii"
+    MIME-Version: 1.0
+    Content-Transfer-Encoding: 7bit
+    Content-Disposition: inline
+    <BLANKLINE>
+    header
+    --BOUNDARY
+    Content-Type: text/plain; charset=unknown
+    Content-Transfer-Encoding: 7bit
+    <BLANKLINE>
+    Here is a message.
+    <BLANKLINE>
+    --BOUNDARY
+    Content-Type: text/plain; charset="us-ascii"
+    MIME-Version: 1.0
+    Content-Transfer-Encoding: 7bit
+    Content-Disposition: inline
+    <BLANKLINE>
+    footer
+    --BOUNDARY--
+
+
+Decorating multipart messages
+-----------------------------
+
+Multipart messages have to be decorated differently.  The header and footer
+cannot be simply concatenated into the payload because that will break the
+MIME structure of the message.  Instead, the header and footer are attached as
+separate MIME subparts.
+
+When the outerpart is multipart/mixed, the header and footer can have a
+Content-Disposition of 'inline' so that MUAs can display these headers as if
+they were simply concatenated.
+
+    >>> mlist.preferred_language = 'en'
+    >>> mlist.msg_header = 'header'
+    >>> mlist.msg_footer = 'footer'
+    >>> flush()
+    >>> part_1 = message_from_string("""\
+    ... From: aperson@example.org
+    ...
+    ... Here is the first message.
+    ... """)
+    >>> part_2 = message_from_string("""\
+    ... From: bperson@example.com
+    ...
+    ... Here is the second message.
+    ... """)
+    >>> from email.mime.multipart import MIMEMultipart
+    >>> msg = MIMEMultipart('mixed', boundary='BOUNDARY',
+    ...                     _subparts=(part_1, part_2))
+    >>> process(mlist, msg, {})
+    >>> print msg.as_string()
+    Content-Type: multipart/mixed; boundary="BOUNDARY"
+    MIME-Version: 1.0
+    <BLANKLINE>
+    --BOUNDARY
+    Content-Type: text/plain; charset="us-ascii"
+    MIME-Version: 1.0
+    Content-Transfer-Encoding: 7bit
+    Content-Disposition: inline
+    <BLANKLINE>
+    header
+    --BOUNDARY
+    From: aperson@example.org
+    <BLANKLINE>
+    Here is the first message.
+    <BLANKLINE>
+    --BOUNDARY
+    From: bperson@example.com
+    <BLANKLINE>
+    Here is the second message.
+    <BLANKLINE>
+    --BOUNDARY
+    Content-Type: text/plain; charset="us-ascii"
+    MIME-Version: 1.0
+    Content-Transfer-Encoding: 7bit
+    Content-Disposition: inline
+    <BLANKLINE>
+    footer
+    --BOUNDARY--
+
+
+Decorating other content types
+------------------------------
+
+Non-multipart non-text content types will get wrapped in a multipart/mixed so
+that the header and footer can be added as attachments.
+
+    >>> msg = message_from_string("""\
+    ... From: aperson@example.org
+    ... Content-Type: image/x-beautiful
+    ...
+    ... IMAGEDATAIMAGEDATAIMAGEDATA
+    ... """)
+    >>> process(mlist, msg, {})
+    >>> msg.set_boundary('BOUNDARY')
+    >>> print msg.as_string()
+    From: aperson@example.org
+    ...
+    --BOUNDARY
+    Content-Type: text/plain; charset="us-ascii"
+    MIME-Version: 1.0
+    Content-Transfer-Encoding: 7bit
+    Content-Disposition: inline
+    <BLANKLINE>
+    header
+    --BOUNDARY
+    Content-Type: image/x-beautiful
+    <BLANKLINE>
+    IMAGEDATAIMAGEDATAIMAGEDATA
+    <BLANKLINE>
+    --BOUNDARY
+    Content-Type: text/plain; charset="us-ascii"
+    MIME-Version: 1.0
+    Content-Transfer-Encoding: 7bit
+    Content-Disposition: inline
+    <BLANKLINE>
+    footer
+    --BOUNDARY--
+
+
+Personalization
+---------------
+
+A mailing list can be 'personalized', meaning that each message is unique for
+each recipient.  When the list is personalized, additional interpolation
+variables are available, however the list of intended recipients must be
+provided in the message data, otherwise an exception occurs.
+
+    >>> process(mlist, None, dict(personalize=True))
+    Traceback (most recent call last):
+    ...
+    AssertionError: The number of intended recipients must be exactly 1
+
+And the number of intended recipients must be exactly 1.
+
+    >>> process(mlist, None, dict(personalize=True, recips=[1, 2, 3]))
+    Traceback (most recent call last):
+    ...
+    AssertionError: The number of intended recipients must be exactly 1

Added: trunk/mailman/Mailman/testing/test_decorate.py
===================================================================
--- trunk/mailman/Mailman/testing/test_decorate.py	                        (rev 0)
+++ trunk/mailman/Mailman/testing/test_decorate.py	2007-05-30 16:54:17 UTC (rev 8228)
@@ -0,0 +1,32 @@
+# Copyright (C) 2007 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.
+
+"""Doctest harness for testing message decoration."""
+
+import doctest
+import unittest
+
+options = (doctest.ELLIPSIS
+           | doctest.NORMALIZE_WHITESPACE
+           | doctest.REPORT_NDIFF)
+
+
+def test_suite():
+    suite = unittest.TestSuite()
+    suite.addTest(doctest.DocFileSuite('../docs/decorate.txt',
+                                       optionflags=options))
+    return suite

Modified: trunk/mailman/Mailman/testing/test_handlers.py
===================================================================
--- trunk/mailman/Mailman/testing/test_handlers.py	2007-05-29 15:04:19 UTC (rev 8227)
+++ trunk/mailman/Mailman/testing/test_handlers.py	2007-05-30 16:54:17 UTC (rev 8228)
@@ -42,7 +42,6 @@
 from Mailman.Handlers import CalcRecips
 from Mailman.Handlers import Cleanse
 from Mailman.Handlers import CookHeaders
-from Mailman.Handlers import Decorate
 from Mailman.Handlers import FileRecips
 from Mailman.Handlers import Hold
 from Mailman.Handlers import MimeDel
@@ -786,227 +785,6 @@
 
 
 
-class TestDecorate(TestBase):
-    def test_short_circuit(self):
-        msgdata = {'isdigest': 1}
-        rtn = Decorate.process(self._mlist, None, msgdata)
-        # Not really a great test, but there's little else to assert
-        self.assertEqual(rtn, None)
-
-    def test_no_multipart(self):
-        mlist = self._mlist
-        mlist.msg_header = 'header\n'
-        mlist.msg_footer = 'footer'
-        msg = email.message_from_string("""\
-From: aperson@example.org
-
-Here is a message.
-""")
-        Decorate.process(self._mlist, msg, {})
-        self.assertEqual(msg.get_payload(), """\
-header
-Here is a message.
-footer""")
-
-    def test_no_multipart_template(self):
-        mlist = self._mlist
-        mlist.msg_header = '%(real_name)s header\n'
-        mlist.msg_footer = '%(real_name)s footer'
-        mlist.real_name = 'XTest'
-        msg = email.message_from_string("""\
-From: aperson@example.org
-
-Here is a message.
-""")
-        Decorate.process(self._mlist, msg, {})
-        self.assertEqual(msg.get_payload(), """\
-XTest header
-Here is a message.
-XTest footer""")
-
-    def test_no_multipart_type_error(self):
-        mlist = self._mlist
-        mlist.msg_header = '%(real_name) header\n'
-        mlist.msg_footer = '%(real_name) footer'
-        mlist.real_name = 'XTest'
-        msg = email.message_from_string("""\
-From: aperson@example.org
-
-Here is a message.
-""")
-        Decorate.process(self._mlist, msg, {})
-        self.assertEqual(msg.get_payload(), """\
-%(real_name) header
-Here is a message.
-%(real_name) footer""")
-
-    def test_no_multipart_value_error(self):
-        mlist = self._mlist
-        # These will generate warnings in logs/error
-        mlist.msg_header = '%(real_name)p header\n'
-        mlist.msg_footer = '%(real_name)p footer'
-        mlist.real_name = 'XTest'
-        msg = email.message_from_string("""\
-From: aperson@example.org
-
-Here is a message.
-""")
-        Decorate.process(self._mlist, msg, {})
-        self.assertEqual(msg.get_payload(), """\
-%(real_name)p header
-Here is a message.
-%(real_name)p footer""")
-
-    def test_no_multipart_missing_key(self):
-        mlist = self._mlist
-        mlist.msg_header = '%(spooge)s header\n'
-        mlist.msg_footer = '%(spooge)s footer'
-        msg = email.message_from_string("""\
-From: aperson@example.org
-
-Here is a message.
-""")
-        Decorate.process(self._mlist, msg, {})
-        self.assertEqual(msg.get_payload(), """\
-%(spooge)s header
-Here is a message.
-%(spooge)s footer""")
-
-    def test_multipart(self):
-        eq = self.ndiffAssertEqual
-        mlist = self._mlist
-        mlist.msg_header = 'header'
-        mlist.msg_footer = 'footer'
-        msg1 = email.message_from_string("""\
-From: aperson@example.org
-
-Here is the first message.
-""")
-        msg2 = email.message_from_string("""\
-From: bperson@example.com
-
-Here is the second message.
-""")
-        msg = Message.Message()
-        msg.set_type('multipart/mixed')
-        msg.set_boundary('BOUNDARY')
-        msg.attach(msg1)
-        msg.attach(msg2)
-        Decorate.process(self._mlist, msg, {})
-        eq(msg.as_string(unixfrom=0), """\
-MIME-Version: 1.0
-Content-Type: multipart/mixed; boundary="BOUNDARY"
-
---BOUNDARY
-Content-Type: text/plain; charset="us-ascii"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Content-Disposition: inline
-
-header
---BOUNDARY
-From: aperson@example.org
-
-Here is the first message.
-
---BOUNDARY
-From: bperson@example.com
-
-Here is the second message.
-
---BOUNDARY
-Content-Type: text/plain; charset="us-ascii"
-MIME-Version: 1.0
-Content-Transfer-Encoding: 7bit
-Content-Disposition: inline
-
-footer
---BOUNDARY--""")
-
-    def test_image(self):
-        eq = self.assertEqual
-        mlist = self._mlist
-        mlist.msg_header = 'header\n'
-        mlist.msg_footer = 'footer'
-        msg = email.message_from_string("""\
-From: aperson@example.org
-Content-type: image/x-spooge
-
-IMAGEDATAIMAGEDATAIMAGEDATA
-""")
-        Decorate.process(self._mlist, msg, {})
-        eq(len(msg.get_payload()), 3)
-        self.assertEqual(msg.get_payload(1).get_payload(), """\
-IMAGEDATAIMAGEDATAIMAGEDATA
-""")
-
-    def test_personalize_assert(self):
-        raises = self.assertRaises
-        raises(AssertionError, Decorate.process,
-               self._mlist, None, {'personalize': 1})
-        raises(AssertionError, Decorate.process,
-               self._mlist, None, {'personalize': 1,
-                                   'recips': [1, 2, 3]})
-
-    def test_no_multipart_mixed_charset(self):
-        mlist = self._mlist
-        mlist.preferred_language = 'ja'
-        mlist.msg_header = '%(description)s header'
-        mlist.msg_footer = '%(description)s footer'
-        mlist.description = u'\u65e5\u672c\u8a9e'
-        msg = Message.Message()
-        msg.set_payload('Fran\xe7aise', 'iso-8859-1')
-        Decorate.process(mlist, msg, {})
-        self.assertEqual(msg.as_string(unixfrom=0), """\
-MIME-Version: 1.0
-Content-Type: text/plain; charset="utf-8"
-Content-Transfer-Encoding: base64
-
-5pel5pys6KqeIGhlYWRlcgpGcmFuw6dhaXNlCuaXpeacrOiqniBmb290ZXI=
-""")
-
-    def test_no_multipart_unknown_charset(self):
-        mlist = self._mlist
-        mlist.msg_header = 'header'
-        mlist.msg_footer = 'footer'
-        msg = email.message_from_string("""\
-From: aperson@example.org
-Content-Type: text/plain; charset=unknown
-Content-Transfer-Encoding: 7bit
-
-Here is a message.
-""")
-        Decorate.process(mlist, msg, {})
-        self.assertEqual(len(msg.get_payload()), 3)
-        self.assertEqual(msg.get_payload()[1].as_string(unixfrom=0),"""\
-Content-Type: text/plain; charset=unknown
-Content-Transfer-Encoding: 7bit
-
-Here is a message.
-""")
-
-    def test_no_multipart_flowed(self):
-        mlist = self._mlist
-        mlist.msg_header = 'header'
-        mlist.msg_footer = 'footer'
-        msg = email.message_from_string("""\
-From: aperson@example.org
-Content-Type: text/plain; format=flowed; delsp=no
-
-Here is a message 
-with soft line break.
-""")
-        Decorate.process(mlist, msg, {})
-        self.assertEqual(msg.get_param('format'), 'flowed')
-        self.assertEqual(msg.get_param('delsp'), 'no')
-        self.assertEqual(msg.get_payload(), """\
-header
-Here is a message 
-with soft line break.
-footer""")
-
-
-
 class TestFileRecips(TestBase):
     def test_short_circuit(self):
         msgdata = {'recips': 1}
@@ -1934,7 +1712,6 @@
     suite.addTest(unittest.makeSuite(TestCalcRecips))
     suite.addTest(unittest.makeSuite(TestCleanse))
     suite.addTest(unittest.makeSuite(TestCookHeaders))
-    suite.addTest(unittest.makeSuite(TestDecorate))
     suite.addTest(unittest.makeSuite(TestFileRecips))
     suite.addTest(unittest.makeSuite(TestHold))
     suite.addTest(unittest.makeSuite(TestMimeDel))

Modified: trunk/mailman/Makefile.in
===================================================================
--- trunk/mailman/Makefile.in	2007-05-29 15:04:19 UTC (rev 8227)
+++ trunk/mailman/Makefile.in	2007-05-30 16:54:17 UTC (rev 8228)
@@ -51,7 +51,7 @@
 ARCH_INDEP_DIRS= \
 	bin templates scripts cron pythonlib \
 	Mailman Mailman/bin Mailman/interfaces \
-	Mailman/database Mailman/database/tables Mailman/database/model \
+	Mailman/database Mailman/database/model \
 	Mailman/docs Mailman/ext Mailman/Cgi Mailman/Archiver \
 	Mailman/Handlers Mailman/Queue Mailman/Queue/tests \
 	Mailman/Bouncers \

Modified: trunk/mailman/configure
===================================================================
--- trunk/mailman/configure	2007-05-29 15:04:19 UTC (rev 8227)
+++ trunk/mailman/configure	2007-05-30 16:54:17 UTC (rev 8228)
@@ -1,5 +1,5 @@
 #! /bin/sh
-# From configure.in Revision: 8196 .
+# From configure.in Revision: 8224 .
 # Guess values for system-dependent variables and create Makefiles.
 # Generated by GNU Autoconf 2.61 for GNU Mailman 2.2.0a0.
 #
@@ -4841,7 +4841,7 @@
 # scripts.  They're removed on a make distclean, so we make them here.
 mkdir -p build/bin build/contrib build/cron
 
-ac_config_files="$ac_config_files misc/paths.py Mailman/Defaults.py \
Mailman/mm_cfg.py.dist src/Makefile misc/Makefile bin/Makefile Mailman/bin/Makefile \
Mailman/Makefile Mailman/Cgi/Makefile Mailman/database/Makefile \
Mailman/database/tables/Makefile Mailman/database/model/Makefile \
Mailman/docs/Makefile Mailman/ext/Makefile Mailman/interfaces/Makefile \
Mailman/Archiver/Makefile Mailman/Commands/Makefile Mailman/Handlers/Makefile \
Mailman/Bouncers/Makefile Mailman/Queue/Makefile Mailman/Queue/tests/Makefile \
Mailman/MTA/Makefile Mailman/Gui/Makefile templates/Makefile cron/Makefile \
scripts/Makefile messages/Makefile cron/crontab.in misc/mailman Makefile \
Mailman/testing/Makefile Mailman/testing/bounces/Makefile tests/Makefile \
tests/msgs/Makefile $SCRIPTS" +ac_config_files="$ac_config_files misc/paths.py \
Mailman/Defaults.py Mailman/mm_cfg.py.dist src/Makefile misc/Makefile bin/Makefile \
Mailman/bin/Makefile Mailman/Makefile Mailman/Cgi/Makefile Mailman/database/Makefile \
Mailman/database/model/Makefile Mailman/docs/Makefile Mailman/ext/Makefile \
Mailman/interfaces/Makefile Mailman/Archiver/Makefile Mailman/Commands/Makefile \
Mailman/Handlers/Makefile Mailman/Bouncers/Makefile Mailman/Queue/Makefile \
Mailman/Queue/tests/Makefile Mailman/MTA/Makefile Mailman/Gui/Makefile \
templates/Makefile cron/Makefile scripts/Makefile messages/Makefile cron/crontab.in \
misc/mailman Makefile Mailman/testing/Makefile Mailman/testing/bounces/Makefile \
tests/Makefile tests/msgs/Makefile $SCRIPTS"  
 ac_config_commands="$ac_config_commands default"
 
@@ -5427,7 +5427,6 @@
     "Mailman/Makefile") CONFIG_FILES="$CONFIG_FILES Mailman/Makefile" ;;
     "Mailman/Cgi/Makefile") CONFIG_FILES="$CONFIG_FILES Mailman/Cgi/Makefile" ;;
     "Mailman/database/Makefile") CONFIG_FILES="$CONFIG_FILES \
                Mailman/database/Makefile" ;;
-    "Mailman/database/tables/Makefile") CONFIG_FILES="$CONFIG_FILES \
                Mailman/database/tables/Makefile" ;;
     "Mailman/database/model/Makefile") CONFIG_FILES="$CONFIG_FILES \
                Mailman/database/model/Makefile" ;;
     "Mailman/docs/Makefile") CONFIG_FILES="$CONFIG_FILES Mailman/docs/Makefile" ;;
     "Mailman/ext/Makefile") CONFIG_FILES="$CONFIG_FILES Mailman/ext/Makefile" ;;

Modified: trunk/mailman/configure.in
===================================================================
--- trunk/mailman/configure.in	2007-05-29 15:04:19 UTC (rev 8227)
+++ trunk/mailman/configure.in	2007-05-30 16:54:17 UTC (rev 8228)
@@ -635,7 +635,7 @@
 AC_OUTPUT([misc/paths.py Mailman/Defaults.py Mailman/mm_cfg.py.dist
            src/Makefile misc/Makefile bin/Makefile Mailman/bin/Makefile
            Mailman/Makefile Mailman/Cgi/Makefile
-	   Mailman/database/Makefile Mailman/database/tables/Makefile
+	   Mailman/database/Makefile
 	   Mailman/database/model/Makefile Mailman/docs/Makefile
 	   Mailman/ext/Makefile Mailman/interfaces/Makefile
            Mailman/Archiver/Makefile Mailman/Commands/Makefile

Modified: trunk/mailman/docs/NEWS.txt
===================================================================
--- trunk/mailman/docs/NEWS.txt	2007-05-29 15:04:19 UTC (rev 8227)
+++ trunk/mailman/docs/NEWS.txt	2007-05-30 16:54:17 UTC (rev 8228)
@@ -24,6 +24,12 @@
     - PUBLIC_ARCHIVE_URL now takes $-string substitutions instead of %-string
       substitutions.  See documentation in Defaults.py.in for details.
 
+    - Message headers and footers now only accept $-string substitutions;
+      %-strings are no longer supported.  The substitution variable
+      '_internal_name' has been removed; use $list_name or $real_name
+      instead.  The substitution variable $fqdn_listname has been added.
+      DEFAULT_MSG_FOOTER in Defaults.py.in hsa been updated accordingly.
+
   Architecture
 
     - SQLAlchemy/Elixir based storage for all list and user data, with default


This was sent by the SourceForge.net collaborative development platform, the world's \
largest Open Source development site. _______________________________________________
Mailman-checkins mailing list
Mailman-checkins@python.org
Unsubscribe: http://mail.python.org/mailman/options/mailman-checkins/mailman-cvs%40progressive-comp.com



[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic