diff options
| author | Barry Warsaw | 2007-07-10 22:39:57 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2007-07-10 22:39:57 -0400 |
| commit | de429f33191b84bc261535d8deba54399fb1bd4a (patch) | |
| tree | 1d1f2b932c33f70deb34ee68c802bbd3ee2cb8df | |
| parent | bebaec0e24f3492ff4190c36074b6c51cd44589b (diff) | |
| download | mailman-de429f33191b84bc261535d8deba54399fb1bd4a.tar.gz mailman-de429f33191b84bc261535d8deba54399fb1bd4a.tar.zst mailman-de429f33191b84bc261535d8deba54399fb1bd4a.zip | |
Conversion of the ToDigest tests to doctests, along with just enough handler
module update to make the thing pass. Much more coverage is still necessary,
but this at least recreates the existing tests.
Changes to the test infrastructure to make REPORT_ONLY_FIRST_FAILURE
conditional on lower (default) verbosity. Increase the verbosity via
'bin/testall -v' and you get all the failure output.
| -rw-r--r-- | Mailman/Handlers/ToDigest.py | 60 | ||||
| -rw-r--r-- | Mailman/bin/testall.py | 3 | ||||
| -rw-r--r-- | Mailman/database/model/mailinglist.py | 2 | ||||
| -rw-r--r-- | Mailman/docs/digests.txt | 539 | ||||
| -rw-r--r-- | Mailman/testing/test_documentation.py | 12 | ||||
| -rw-r--r-- | Mailman/testing/test_handlers.py | 116 |
6 files changed, 587 insertions, 145 deletions
diff --git a/Mailman/Handlers/ToDigest.py b/Mailman/Handlers/ToDigest.py index 17ea2f89b..d30f05c71 100644 --- a/Mailman/Handlers/ToDigest.py +++ b/Mailman/Handlers/ToDigest.py @@ -52,6 +52,7 @@ from Mailman.Mailbox import Mailbox from Mailman.MemberAdaptor import ENABLED from Mailman.Queue.sbcache import get_switchboard from Mailman.configuration import config +from Mailman.constants import DeliveryMode, DeliveryStatus _ = i18n._ __i18n_templates__ = True @@ -67,7 +68,7 @@ def process(mlist, msg, msgdata): # Short circuit non-digestable lists. if not mlist.digestable or msgdata.get('isdigest'): return - mboxfile = os.path.join(mlist.fullpath(), 'digest.mbox') + mboxfile = os.path.join(mlist.full_path, 'digest.mbox') mboxfp = open(mboxfile, 'a+') mbox = Mailbox(mboxfp) mbox.AppendMessage(msg) @@ -77,7 +78,7 @@ def process(mlist, msg, msgdata): # whether the size threshold has been reached. mboxfp.flush() size = os.path.getsize(mboxfile) - if size / 1024.0 >= mlist.digest_size_threshhold: + if size / 1024.0 >= mlist.digest_size_threshold: # This is a bit of a kludge to get the mbox file moved to the digest # queue directory. try: @@ -91,7 +92,7 @@ def process(mlist, msg, msgdata): except Exception, errmsg: # Bare except is generally prohibited in Mailman, but we can't # forecast what exceptions can occur here. - log.error('send_digests() failed: %s', errmsg) + log.exception('send_digests() failed: %s', errmsg) mboxfp.close() @@ -155,19 +156,19 @@ def send_i18n_digests(mlist, mboxfp): mimemsg = Message.Message() mimemsg['Content-Type'] = 'multipart/mixed' mimemsg['MIME-Version'] = '1.0' - mimemsg['From'] = mlist.GetRequestEmail() + mimemsg['From'] = mlist.request_address mimemsg['Subject'] = digestsubj - mimemsg['To'] = mlist.GetListEmail() - mimemsg['Reply-To'] = mlist.GetListEmail() + mimemsg['To'] = mlist.posting_address + mimemsg['Reply-To'] = mlist.posting_address mimemsg['Date'] = formatdate(localtime=1) mimemsg['Message-ID'] = Utils.unique_message_id(mlist) # Set things up for the rfc1153 digest plainmsg = StringIO() rfc1153msg = Message.Message() - rfc1153msg['From'] = mlist.GetRequestEmail() + rfc1153msg['From'] = mlist.request_address rfc1153msg['Subject'] = digestsubj - rfc1153msg['To'] = mlist.GetListEmail() - rfc1153msg['Reply-To'] = mlist.GetListEmail() + rfc1153msg['To'] = mlist.posting_address + rfc1153msg['Reply-To'] = mlist.posting_address rfc1153msg['Date'] = formatdate(localtime=1) rfc1153msg['Message-ID'] = Utils.unique_message_id(mlist) separator70 = '-' * 70 @@ -179,10 +180,10 @@ def send_i18n_digests(mlist, mboxfp): mastheadtxt = Utils.maketext( 'masthead.txt', {'real_name' : mlist.real_name, - 'got_list_email': mlist.GetListEmail(), + 'got_list_email': mlist.posting_address, 'got_listinfo_url': mlist.GetScriptURL('listinfo', absolute=1), - 'got_request_email': mlist.GetRequestEmail(), - 'got_owner_email': mlist.GetOwnerEmail(), + 'got_request_email': mlist.request_address, + 'got_owner_email': mlist.owner_address, }, mlist=mlist) # MIME masthead = MIMEText(mastheadtxt.encode(lcset), _charset=lcset) @@ -377,20 +378,31 @@ def send_i18n_digests(mlist, mboxfp): mlist.next_digest_number += 1 virginq = get_switchboard(config.VIRGINQUEUE_DIR) # Calculate the recipients lists - plainrecips = [] - mimerecips = [] - drecips = mlist.getDigestMemberKeys() + mlist.one_last_digest.keys() - for user in mlist.getMemberCPAddresses(drecips): - # user might be None if someone who toggled off digest delivery - # subsequently unsubscribed from the mailing list. Also, filter out - # folks who have disabled delivery. - if user is None or mlist.getDeliveryStatus(user) <> ENABLED: + plainrecips = set() + mimerecips = set() + # When someone turns off digest delivery, they will get one last digest to + # ensure that there will be no gaps in the messages they receive. + # Currently, this dictionary contains the email addresses of those folks + # who should get one last digest. We need to find the corresponding + # IMember records. + digest_members = set(mlist.digest_members.members) + for address in mlist.one_last_digest: + member = mlist.digest_members.get_member(address) + if member: + digest_members.add(member) + for member in digest_members: + if member.delivery_status <> DeliveryStatus.enabled: continue - # Otherwise, decide whether they get MIME or RFC 1153 digests - if mlist.getMemberOption(user, config.DisableMime): - plainrecips.append(user) + # Send the digest to the case-preserved address of the digest members. + email_address = member.address.original_address + if member.delivery_mode == DeliveryMode.plaintext_digests: + plainrecips.add(email_address) + elif member.delivery_mode == DeliveryMode.mime_digests: + mimerecips.add(email_address) else: - mimerecips.append(user) + raise AssertionError( + 'Digest member "%s" unexpected delivery mode: %s' % + (email_address, member.delivery_mode)) # Zap this since we're now delivering the last digest to these folks. mlist.one_last_digest.clear() # MIME diff --git a/Mailman/bin/testall.py b/Mailman/bin/testall.py index 0b8f6db6b..005808cfe 100644 --- a/Mailman/bin/testall.py +++ b/Mailman/bin/testall.py @@ -152,6 +152,9 @@ def main(): if not args: args = ['.'] + # Store the options some place that other code can get to it. + config.opts = opts + # Turn on code coverage if selected. if opts.coverage: try: diff --git a/Mailman/database/model/mailinglist.py b/Mailman/database/model/mailinglist.py index 71007b83f..fce73cf25 100644 --- a/Mailman/database/model/mailinglist.py +++ b/Mailman/database/model/mailinglist.py @@ -91,7 +91,7 @@ class MailingList(Entity): has_field('digest_header', Unicode), has_field('digest_is_default', Boolean), has_field('digest_send_periodic', Boolean), - has_field('digest_size_threshhold', Integer), + has_field('digest_size_threshold', Integer), has_field('digest_volume_frequency', Integer), has_field('digestable', Boolean), has_field('discard_these_nonmembers', PickleType), diff --git a/Mailman/docs/digests.txt b/Mailman/docs/digests.txt new file mode 100644 index 000000000..3788651f9 --- /dev/null +++ b/Mailman/docs/digests.txt @@ -0,0 +1,539 @@ +Digests +======= + +Digests are a way for a user to receive list traffic in collections instead of +as individual messages when immediately posted. There are several forms of +digests, although only two are currently supported: MIME digests and RFC 1153 +(a.k.a. plain text) digests. + + >>> from Mailman.Handlers.ToDigest import process + >>> from Mailman.Message import Message + >>> from Mailman.Queue.Switchboard import Switchboard + >>> from Mailman.configuration import config + >>> from Mailman.database import flush + >>> from email import message_from_string + >>> mlist = config.list_manager.create('_xtest@example.com') + >>> mlist.preferred_language = 'en' + >>> mlist.web_page_url = 'http://www.example.com/' + >>> mlist.real_name = 'XTest' + >>> mlist.subject_prefix = '[_XTest] ' + >>> mlist.one_last_digest = set() + >>> flush() + >>> switchboard = Switchboard(config.VIRGINQUEUE_DIR) + +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 +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 itertools import count + >>> from string import Template + >>> def makemsg(): + ... for i in count(1): + ... text = Template("""\ + ... From: aperson@example.com + ... To: _xtest@example.com + ... Subject: Test message $i + ... + ... Here is message $i + ... """).substitute(i=i) + ... yield message_from_string(text, Message) + + +Short circuiting +---------------- + +When a message is posted to the mailing list, it is generally added to a +running collection of messages. For now, this is a Unix mailbox file, +although in the future this may end up being converted to a maildir style +mailbox. In any event, there are several factors that would bypass the +storing of posted messages to the mailbox. For example, the mailing list may +not allow digests... + + >>> mlist.digestable = False + >>> flush() + >>> msg = makemsg().next() + >>> process(mlist, msg, {}) + >>> sum(1 for mboxmsg in digest_mbox()) + 0 + >>> switchboard.files + [] + +...or they may allow digests but the message is already a digest. + + >>> mlist.digestable = True + >>> flush() + >>> process(mlist, msg, dict(isdigest=True)) + >>> sum(1 for mboxmsg in digest_mbox()) + 0 + >>> switchboard.files + [] + + +Sending a digest +---------------- + +For messages which are not digests, but which are posted to a digestable +mailing list, the messages will be stored until they reach a criteria +triggering the sending of the digest. If none of those criteria are met, then +the message will just sit in the mailbox for a while. + + >>> mlist.digest_size_threshold = 10000 + >>> flush() + >>> process(mlist, msg, {}) + >>> switchboard.files + [] + >>> sum(1 for mboxmsg in digest_mbox()) + 1 + >>> clear_mbox() + +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 +digest and an RFC 1153 plain text digest. The size threshold is in KB. + + >>> mlist.digest_size_threshold = 1 + >>> mlist.volume = 2 + >>> mlist.next_digest_number = 10 + >>> flush() + >>> size = 0 + >>> for msg in makemsg(): + ... process(mlist, msg, {}) + ... size += len(str(msg)) + ... if size > mlist.digest_size_threshold * 1024: + ... break + >>> sum(1 for mboxmsg in digest_mbox()) + 0 + >>> len(switchboard.files) + 2 + >>> for filebase in switchboard.files: + ... qmsg, qdata = switchboard.dequeue(filebase) + ... switchboard.finish(filebase) + ... if qmsg.is_multipart(): + ... mimemsg = qmsg + ... mimedata = qdata + ... else: + ... rfc1153msg = qmsg + ... rfc1153data = qdata + >>> print mimemsg.as_string() + Content-Type: multipart/mixed; boundary="..." + MIME-Version: 1.0 + From: _xtest-request@example.com + Subject: XTest Digest, Vol 2, Issue 10 + To: _xtest@example.com + Reply-To: _xtest@example.com + Date: ... + Message-ID: ... + <BLANKLINE> + --... + Content-Type: text/plain; charset="us-ascii" + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Description: XTest Digest, Vol 2, Issue 10 + <BLANKLINE> + Send XTest mailing list submissions to + _xtest@example.com + <BLANKLINE> + To subscribe or unsubscribe via the World Wide Web, visit + http://www.example.com/listinfo/_xtest@example.com + or, via email, send a message with subject or body 'help' to + _xtest-request@example.com + <BLANKLINE> + You can reach the person managing the list at + _xtest-owner@example.com + <BLANKLINE> + When replying, please edit your Subject line so it is more specific + than "Re: Contents of XTest digest..." + <BLANKLINE> + --... + Content-Type: text/plain; charset="us-ascii" + MIME-Version: 1.0 + Content-Transfer-Encoding: 7bit + Content-Description: Today's Topics (8 messages) + <BLANKLINE> + Today's Topics: + <BLANKLINE> + 1. Test message 1 (aperson@example.com) + 2. Test message 2 (aperson@example.com) + 3. Test message 3 (aperson@example.com) + 4. Test message 4 (aperson@example.com) + 5. Test message 5 (aperson@example.com) + 6. Test message 6 (aperson@example.com) + 7. Test message 7 (aperson@example.com) + 8. Test message 8 (aperson@example.com) + <BLANKLINE> + --... + Content-Type: multipart/digest; boundary="..." + MIME-Version: 1.0 + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: aperson@example.com + To: _xtest@example.com + Subject: Test message 1 + Message: 1 + <BLANKLINE> + Here is message 1 + <BLANKLINE> + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: aperson@example.com + To: _xtest@example.com + Subject: Test message 2 + Message: 2 + <BLANKLINE> + Here is message 2 + <BLANKLINE> + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: aperson@example.com + To: _xtest@example.com + Subject: Test message 3 + Message: 3 + <BLANKLINE> + Here is message 3 + <BLANKLINE> + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: aperson@example.com + To: _xtest@example.com + Subject: Test message 4 + Message: 4 + <BLANKLINE> + Here is message 4 + <BLANKLINE> + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: aperson@example.com + To: _xtest@example.com + Subject: Test message 5 + Message: 5 + <BLANKLINE> + Here is message 5 + <BLANKLINE> + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: aperson@example.com + To: _xtest@example.com + Subject: Test message 6 + Message: 6 + <BLANKLINE> + Here is message 6 + <BLANKLINE> + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: aperson@example.com + To: _xtest@example.com + Subject: Test message 7 + Message: 7 + <BLANKLINE> + Here is message 7 + <BLANKLINE> + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + From: aperson@example.com + To: _xtest@example.com + Subject: Test message 8 + Message: 8 + <BLANKLINE> + Here is message 8 + <BLANKLINE> + <BLANKLINE> + --... + --... + >>> sorted(mimedata.items()) + [('_parsemsg', False), + ('isdigest', True), + ('listname', '_xtest@example.com'), + ('received_time', ...), + ('recips', set([])), ('version', 3)] + >>> print rfc1153msg.as_string() + From: _xtest-request@example.com + Subject: XTest Digest, Vol 2, Issue 10 + To: _xtest@example.com + Reply-To: _xtest@example.com + Date: ... + Message-ID: ... + MIME-Version: 1.0 + Content-Type: text/plain; charset="us-ascii" + Content-Transfer-Encoding: 7bit + <BLANKLINE> + Send XTest mailing list submissions to + _xtest@example.com + <BLANKLINE> + To subscribe or unsubscribe via the World Wide Web, visit + http://www.example.com/listinfo/_xtest@example.com + or, via email, send a message with subject or body 'help' to + _xtest-request@example.com + <BLANKLINE> + You can reach the person managing the list at + _xtest-owner@example.com + <BLANKLINE> + When replying, please edit your Subject line so it is more specific + than "Re: Contents of XTest digest..." + <BLANKLINE> + <BLANKLINE> + Today's Topics: + <BLANKLINE> + 1. Test message 1 (aperson@example.com) + 2. Test message 2 (aperson@example.com) + 3. Test message 3 (aperson@example.com) + 4. Test message 4 (aperson@example.com) + 5. Test message 5 (aperson@example.com) + 6. Test message 6 (aperson@example.com) + 7. Test message 7 (aperson@example.com) + 8. Test message 8 (aperson@example.com) + <BLANKLINE> + <BLANKLINE> + ---------------------------------------------------------------------- + <BLANKLINE> + Message: 1 + From: aperson@example.com + Subject: Test message 1 + To: _xtest@example.com + Message-ID: ... + <BLANKLINE> + Here is message 1 + <BLANKLINE> + <BLANKLINE> + ------------------------------ + <BLANKLINE> + Message: 2 + From: aperson@example.com + Subject: Test message 2 + To: _xtest@example.com + Message-ID: ... + <BLANKLINE> + Here is message 2 + <BLANKLINE> + <BLANKLINE> + ------------------------------ + <BLANKLINE> + Message: 3 + From: aperson@example.com + Subject: Test message 3 + To: _xtest@example.com + Message-ID: ... + <BLANKLINE> + Here is message 3 + <BLANKLINE> + <BLANKLINE> + ------------------------------ + <BLANKLINE> + Message: 4 + From: aperson@example.com + Subject: Test message 4 + To: _xtest@example.com + Message-ID: ... + <BLANKLINE> + Here is message 4 + <BLANKLINE> + <BLANKLINE> + ------------------------------ + <BLANKLINE> + Message: 5 + From: aperson@example.com + Subject: Test message 5 + To: _xtest@example.com + Message-ID: ... + <BLANKLINE> + Here is message 5 + <BLANKLINE> + <BLANKLINE> + ------------------------------ + <BLANKLINE> + Message: 6 + From: aperson@example.com + Subject: Test message 6 + To: _xtest@example.com + Message-ID: ... + <BLANKLINE> + Here is message 6 + <BLANKLINE> + <BLANKLINE> + ------------------------------ + <BLANKLINE> + Message: 7 + From: aperson@example.com + Subject: Test message 7 + To: _xtest@example.com + Message-ID: ... + <BLANKLINE> + Here is message 7 + <BLANKLINE> + <BLANKLINE> + ------------------------------ + <BLANKLINE> + Message: 8 + From: aperson@example.com + Subject: Test message 8 + To: _xtest@example.com + Message-ID: ... + <BLANKLINE> + Here is message 8 + <BLANKLINE> + <BLANKLINE> + End of XTest Digest, Vol 2, Issue 10 + ************************************ + <BLANKLINE> + >>> sorted(rfc1153data.items()) + [('_parsemsg', False), + ('isdigest', True), + ('listname', '_xtest@example.com'), + ('received_time', ...), + ('recips', set([])), ('version', 3)] + + +Internationalized digests +------------------------- + +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. + + >>> mlist.preferred_language = 'fr' + >>> msg = message_from_string("""\ + ... From: aperson@example.org + ... To: _xtest@example.com + ... Subject: =?iso-2022-jp?b?GyRCMGxIVhsoQg==?= + ... MIME-Version: 1.0 + ... Content-Type: text/plain; charset=iso-2022-jp + ... Content-Transfer-Encoding: 7bit + ... + ... \x1b$B0lHV\x1b(B + ... """, Message) + +Set the digest threshold to zero so that the digests will be sent immediately. + + >>> mlist.digest_size_threshold = 0 + >>> flush() + >>> process(mlist, msg, {}) + >>> sum(1 for mboxmsg in digest_mbox()) + 0 + >>> len(switchboard.files) + 2 + >>> for filebase in switchboard.files: + ... qmsg, qdata = switchboard.dequeue(filebase) + ... switchboard.finish(filebase) + ... if qmsg.is_multipart(): + ... mimemsg = qmsg + ... mimedata = qdata + ... else: + ... rfc1153msg = qmsg + ... rfc1153data = qdata + >>> print mimemsg.as_string() + Content-Type: multipart/mixed; boundary="..." + MIME-Version: 1.0 + From: _xtest-request@example.com + Subject: XTest Digest, Vol 2, Issue 11 + To: _xtest@example.com + Reply-To: _xtest@example.com + Date: ... + Message-ID: ... + <BLANKLINE> + --... + Content-Type: text/plain; charset="iso-8859-1" + MIME-Version: 1.0 + Content-Transfer-Encoding: quoted-printable + Content-Description: XTest Digest, Vol 2, Issue 11 + <BLANKLINE> + Envoyez vos messages pour la liste XTest =E0 + _xtest@example.com + <BLANKLINE> + Pour vous (d=E9s)abonner par le web, consultez + http://www.example.com/listinfo/_xtest@example.com + <BLANKLINE> + ou, par courriel, envoyez un message avec =AB=A0help=A0=BB dans le corps ou + dans le sujet =E0 + _xtest-request@example.com + <BLANKLINE> + Vous pouvez contacter l'administrateur de la liste =E0 l'adresse + _xtest-owner@example.com + <BLANKLINE> + Si vous r=E9pondez, n'oubliez pas de changer l'objet du message afin + qu'il soit plus sp=E9cifique que =AB=A0Re: Contenu du groupe de XTest...=A0= + =BB + <BLANKLINE> + --... + Content-Type: text/plain; charset="utf-8" + MIME-Version: 1.0 + Content-Transfer-Encoding: base64 + Content-Description: Today's Topics (1 messages) + <BLANKLINE> + VGjDqG1lcyBkdSBqb3VyIDoKCiAgIDEuIOS4gOeVqiAoYXBlcnNvbkBleGFtcGxlLm9yZykK + <BLANKLINE> + --... + Content-Type: multipart/digest; boundary="..." + MIME-Version: 1.0 + <BLANKLINE> + --... + Content-Type: message/rfc822 + MIME-Version: 1.0 + <BLANKLINE> + Content-Transfer-Encoding: 7bit + From: aperson@example.org + MIME-Version: 1.0 + To: _xtest@example.com + Content-Type: text/plain; charset=iso-2022-jp + Subject: =?iso-2022-jp?b?GyRCMGxIVhsoQg==?= + Message: 1 + <BLANKLINE> + 一番 + <BLANKLINE> + <BLANKLINE> + --... + --... + >>> sorted(mimedata.items()) + [('_parsemsg', False), + ('isdigest', True), + ('listname', '_xtest@example.com'), + ('received_time', ...), + ('recips', set([])), ('version', 3)] + >>> print rfc1153msg.as_string() + From: _xtest-request@example.com + Subject: XTest Digest, Vol 2, Issue 11 + To: _xtest@example.com + Reply-To: _xtest@example.com + Date: ... + Message-ID: ... + MIME-Version: 1.0 + Content-Type: text/plain; charset="utf-8" + Content-Transfer-Encoding: base64 + <BLANKLINE> + ... + <BLANKLINE> + >>> sorted(rfc1153data.items()) + [('_parsemsg', False), + ('isdigest', True), + ('listname', '_xtest@example.com'), + ('received_time', ...), + ('recips', set([])), ('version', 3)] diff --git a/Mailman/testing/test_documentation.py b/Mailman/testing/test_documentation.py index 23641d57b..c5fb62302 100644 --- a/Mailman/testing/test_documentation.py +++ b/Mailman/testing/test_documentation.py @@ -60,15 +60,19 @@ def cleaning_teardown(testobj): def test_suite(): suite = unittest.TestSuite() docsdir = os.path.join(os.path.dirname(Mailman.__file__), 'docs') + # Under higher verbosity settings, report all doctest errors, not just the + # first one. + flags = (doctest.ELLIPSIS | + doctest.NORMALIZE_WHITESPACE | + doctest.REPORT_NDIFF) + if config.opts.verbosity <= 2: + flags |= doctest.REPORT_ONLY_FIRST_FAILURE for filename in os.listdir(docsdir): if os.path.splitext(filename)[1] == '.txt': test = doctest.DocFileSuite( 'docs/' + filename, package=Mailman, - optionflags=(doctest.ELLIPSIS - | doctest.NORMALIZE_WHITESPACE - | doctest.REPORT_NDIFF - | doctest.REPORT_ONLY_FIRST_FAILURE), + optionflags=flags, tearDown=cleaning_teardown) suite.addTest(test) return suite diff --git a/Mailman/testing/test_handlers.py b/Mailman/testing/test_handlers.py index 8b1f11e98..aa7ac0dae 100644 --- a/Mailman/testing/test_handlers.py +++ b/Mailman/testing/test_handlers.py @@ -43,7 +43,6 @@ from Mailman.Handlers import Moderate from Mailman.Handlers import Scrubber # Don't test handlers such as SMTPDirect and Sendmail here from Mailman.Handlers import ToArchive -from Mailman.Handlers import ToDigest @@ -275,124 +274,9 @@ It rocks! -class TestToDigest(TestBase): - def _makemsg(self, i=0): - msg = email.message_from_string("""From: aperson@example.org -To: _xtest@example.com -Subject: message number %(i)d - -Here is message %(i)d -""" % {'i' : i}) - return msg - - def setUp(self): - TestBase.setUp(self) - self._path = os.path.join(self._mlist.fullpath(), 'digest.mbox') - fp = open(self._path, 'w') - g = Generator(fp) - for i in range(5): - g.flatten(self._makemsg(i), unixfrom=1) - fp.close() - self._sb = Switchboard(config.VIRGINQUEUE_DIR) - - def tearDown(self): - try: - os.unlink(self._path) - except OSError, e: - if e.errno <> errno.ENOENT: raise - for f in os.listdir(config.VIRGINQUEUE_DIR): - os.unlink(os.path.join(config.VIRGINQUEUE_DIR, f)) - TestBase.tearDown(self) - - def test_short_circuit(self): - eq = self.assertEqual - mlist = self._mlist - mlist.digestable = 0 - eq(ToDigest.process(mlist, None, {}), None) - mlist.digestable = 1 - eq(ToDigest.process(mlist, None, {'isdigest': 1}), None) - eq(self._sb.files(), []) - - def test_undersized(self): - msg = self._makemsg(99) - size = os.path.getsize(self._path) + len(str(msg)) - self._mlist.digest_size_threshhold = (size + 1) * 1024 - ToDigest.process(self._mlist, msg, {}) - self.assertEqual(self._sb.files(), []) - - def test_send_a_digest(self): - eq = self.assertEqual - mlist = self._mlist - msg = self._makemsg(99) - size = os.path.getsize(self._path) + len(str(msg)) - mlist.digest_size_threshhold = 0 - ToDigest.process(mlist, msg, {}) - files = self._sb.files() - # There should be two files in the queue, one for the MIME digest and - # one for the RFC 1153 digest. - eq(len(files), 2) - # Now figure out which of the two files is the MIME digest and which - # is the RFC 1153 digest. - for filebase in files: - qmsg, qdata = self._sb.dequeue(filebase) - if qmsg.get_content_maintype() == 'multipart': - mimemsg = qmsg - mimedata = qdata - else: - rfc1153msg = qmsg - rfc1153data = qdata - eq(rfc1153msg.get_content_type(), 'text/plain') - eq(mimemsg.get_content_type(), 'multipart/mixed') - eq(mimemsg['from'], mlist.GetRequestEmail()) - eq(mimemsg['subject'], - '%(realname)s Digest, Vol %(volume)d, Issue %(issue)d' % { - 'realname': mlist.real_name, - 'volume' : mlist.volume, - 'issue' : mlist.next_digest_number - 1, - }) - eq(mimemsg['to'], mlist.GetListEmail()) - # BAW: this test is incomplete... - - def test_send_i18n_digest(self): - eq = self.assertEqual - mlist = self._mlist - mlist.preferred_language = 'fr' - msg = email.message_from_string("""\ -From: aperson@example.org -To: _xtest@example.com -Subject: =?iso-2022-jp?b?GyRCMGxIVhsoQg==?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=iso-2022-jp -Content-Transfer-Encoding: 7bit - -\x1b$B0lHV\x1b(B -""") - mlist.digest_size_threshhold = 0 - ToDigest.process(mlist, msg, {}) - files = self._sb.files() - eq(len(files), 2) - for filebase in files: - qmsg, qdata = self._sb.dequeue(filebase) - if qmsg.get_content_maintype() == 'multipart': - mimemsg = qmsg - mimedata = qdata - else: - rfc1153msg = qmsg - rfc1153data = qdata - eq(rfc1153msg.get_content_type(), 'text/plain') - eq(rfc1153msg.get_content_charset(), 'utf-8') - eq(rfc1153msg['content-transfer-encoding'], 'base64') - toc = mimemsg.get_payload()[1] - eq(toc.get_content_type(), 'text/plain') - eq(toc.get_content_charset(), 'utf-8') - eq(toc['content-transfer-encoding'], 'base64') - - - def test_suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(TestApprove)) suite.addTest(unittest.makeSuite(TestScrubber)) suite.addTest(unittest.makeSuite(TestToArchive)) - suite.addTest(unittest.makeSuite(TestToDigest)) return suite |
