summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2012-10-31 17:31:12 +0100
committerBarry Warsaw2012-10-31 17:31:12 +0100
commita9464c14fc6dfc23613a1ec89446393fe6476f88 (patch)
tree74a926cfe64066ebffcf9adb89e7672289173d84
parenta1666479d87e26e5c79dd1cf507b8ef0472c59aa (diff)
downloadmailman-a9464c14fc6dfc23613a1ec89446393fe6476f88.tar.gz
mailman-a9464c14fc6dfc23613a1ec89446393fe6476f88.tar.zst
mailman-a9464c14fc6dfc23613a1ec89446393fe6476f88.zip
-rw-r--r--setup.py4
-rw-r--r--src/mailman/app/tests/test_membership.py11
-rw-r--r--src/mailman/app/tests/test_subscriptions.py14
-rw-r--r--src/mailman/app/tests/test_templates.py42
-rw-r--r--src/mailman/chains/tests/test_headers.py6
-rw-r--r--src/mailman/core/errors.py6
-rw-r--r--src/mailman/core/logging.py4
-rw-r--r--src/mailman/core/tests/test_runner.py2
-rw-r--r--src/mailman/docs/INTRODUCTION.rst4
-rw-r--r--src/mailman/docs/NEWS.rst5
-rw-r--r--src/mailman/docs/START.rst7
-rw-r--r--src/mailman/docs/STYLEGUIDE.rst2
-rw-r--r--src/mailman/docs/WebUIin5.rst4
-rw-r--r--src/mailman/email/message.py6
-rw-r--r--src/mailman/handlers/tests/test_mimedel.py65
-rw-r--r--src/mailman/interfaces/address.py6
-rw-r--r--src/mailman/model/docs/listmanager.rst3
-rw-r--r--src/mailman/rest/tests/test_addresses.py36
-rw-r--r--src/mailman/rest/tests/test_domains.py16
-rw-r--r--src/mailman/rest/tests/test_lists.py32
-rw-r--r--src/mailman/rest/tests/test_membership.py95
-rw-r--r--src/mailman/rest/tests/test_moderation.py32
-rw-r--r--src/mailman/rest/tests/test_root.py32
-rw-r--r--src/mailman/rest/tests/test_users.py8
-rw-r--r--src/mailman/rules/administrivia.py2
-rw-r--r--src/mailman/runners/digest.py8
-rw-r--r--src/mailman/runners/tests/test_confirm.py2
-rw-r--r--src/mailman/runners/tests/test_join.py6
-rw-r--r--src/mailman/runners/tests/test_lmtp.py11
-rw-r--r--src/mailman/styles/tests/test_styles.py24
-rw-r--r--src/mailman/testing/helpers.py24
-rw-r--r--src/mailman/utilities/string.py14
-rw-r--r--src/mailman/utilities/tests/test_templates.py8
33 files changed, 158 insertions, 383 deletions
diff --git a/setup.py b/setup.py
index 236faa3f5..0a63d225c 100644
--- a/setup.py
+++ b/setup.py
@@ -24,8 +24,8 @@ import sys
from setuptools import setup, find_packages
from string import Template
-if sys.hexversion < 0x20600f0:
- print 'Mailman requires at least Python 2.6'
+if sys.hexversion < 0x20700f0:
+ print 'Mailman requires at least Python 2.7'
sys.exit(1)
diff --git a/src/mailman/app/tests/test_membership.py b/src/mailman/app/tests/test_membership.py
index 113ae6a52..a22a239b7 100644
--- a/src/mailman/app/tests/test_membership.py
+++ b/src/mailman/app/tests/test_membership.py
@@ -137,17 +137,14 @@ class AddMemberTest(unittest.TestCase):
'Anne Person', '123', DeliveryMode.regular,
system_preferences.preferred_language,
MemberRole.member)
- try:
+ with self.assertRaises(AlreadySubscribedError) as cm:
add_member(self._mlist, 'aperson@example.com',
'Anne Person', '123', DeliveryMode.regular,
system_preferences.preferred_language,
MemberRole.member)
- except AlreadySubscribedError as exc:
- self.assertEqual(exc.fqdn_listname, 'test@example.com')
- self.assertEqual(exc.email, 'aperson@example.com')
- self.assertEqual(exc.role, MemberRole.member)
- else:
- raise AssertionError('AlreadySubscribedError expected')
+ self.assertEqual(cm.exception.fqdn_listname, 'test@example.com')
+ self.assertEqual(cm.exception.email, 'aperson@example.com')
+ self.assertEqual(cm.exception.role, MemberRole.member)
def test_add_member_with_different_roles(self):
# Adding a member twice with different roles is okay.
diff --git a/src/mailman/app/tests/test_subscriptions.py b/src/mailman/app/tests/test_subscriptions.py
index 1c37d4cb9..c4c8f2795 100644
--- a/src/mailman/app/tests/test_subscriptions.py
+++ b/src/mailman/app/tests/test_subscriptions.py
@@ -51,19 +51,13 @@ class TestJoin(unittest.TestCase):
def test_join_user_with_bogus_id(self):
# When `subscriber` is a missing user id, an exception is raised.
- try:
+ with self.assertRaises(MissingUserError) as cm:
self._service.join('test.example.com', uuid.UUID(int=99))
- except MissingUserError as exc:
- self.assertEqual(exc.user_id, uuid.UUID(int=99))
- else:
- raise AssertionError('MissingUserError expected')
+ self.assertEqual(cm.exception.user_id, uuid.UUID(int=99))
def test_join_user_with_invalid_email_address(self):
# When `subscriber` is a string that is not an email address, an
# exception is raised.
- try:
+ with self.assertRaises(InvalidEmailAddressError) as cm:
self._service.join('test.example.com', 'bogus')
- except InvalidEmailAddressError as exc:
- self.assertEqual(exc.email, 'bogus')
- else:
- raise AssertionError('InvalidEmailAddressError expected')
+ self.assertEqual(cm.exception.email, 'bogus')
diff --git a/src/mailman/app/tests/test_templates.py b/src/mailman/app/tests/test_templates.py
index 6dfbd7109..788412a57 100644
--- a/src/mailman/app/tests/test_templates.py
+++ b/src/mailman/app/tests/test_templates.py
@@ -98,49 +98,31 @@ class TestTemplateLoader(unittest.TestCase):
self.assertEqual(content, 'Test content')
def test_uri_not_found(self):
- try:
+ with self.assertRaises(urllib2.URLError) as cm:
self._loader.get('mailman:///missing.txt')
- except urllib2.URLError as error:
- self.assertEqual(error.reason, 'No such file')
- else:
- raise AssertionError('Exception expected')
+ self.assertEqual(cm.exception.reason, 'No such file')
def test_shorter_url_error(self):
- try:
+ with self.assertRaises(urllib2.URLError) as cm:
self._loader.get('mailman:///')
- except urllib2.URLError as error:
- self.assertEqual(error.reason, 'No template specified')
- else:
- raise AssertionError('Exception expected')
+ self.assertEqual(cm.exception.reason, 'No template specified')
def test_short_url_error(self):
- try:
+ with self.assertRaises(urllib2.URLError) as cm:
self._loader.get('mailman://')
- except urllib2.URLError as error:
- self.assertEqual(error.reason, 'No template specified')
- else:
- raise AssertionError('Exception expected')
+ self.assertEqual(cm.exception.reason, 'No template specified')
def test_bad_language(self):
- try:
+ with self.assertRaises(urllib2.URLError) as cm:
self._loader.get('mailman:///xx/demo.txt')
- except urllib2.URLError as error:
- self.assertEqual(error.reason, 'Bad language or list name')
- else:
- raise AssertionError('Exception expected')
+ self.assertEqual(cm.exception.reason, 'Bad language or list name')
def test_bad_mailing_list(self):
- try:
+ with self.assertRaises(urllib2.URLError) as cm:
self._loader.get('mailman:///missing@example.com/demo.txt')
- except urllib2.URLError as error:
- self.assertEqual(error.reason, 'Bad language or list name')
- else:
- raise AssertionError('Exception expected')
+ self.assertEqual(cm.exception.reason, 'Bad language or list name')
def test_too_many_path_components(self):
- try:
+ with self.assertRaises(urllib2.URLError) as cm:
self._loader.get('mailman:///missing@example.com/en/foo/demo.txt')
- except urllib2.URLError as error:
- self.assertEqual(error.reason, 'No such file')
- else:
- raise AssertionError('Exception expected')
+ self.assertEqual(cm.exception.reason, 'No such file')
diff --git a/src/mailman/chains/tests/test_headers.py b/src/mailman/chains/tests/test_headers.py
index 65a23d891..e8856031c 100644
--- a/src/mailman/chains/tests/test_headers.py
+++ b/src/mailman/chains/tests/test_headers.py
@@ -44,8 +44,6 @@ class TestHeaderChain(unittest.TestCase):
def setUp(self):
self._mlist = create_list('test@example.com')
- # Python 2.6 does not have assertListEqual().
- self._leq = getattr(self, 'assertListEqual', self.assertEqual)
@configuration('antispam', header_checks="""
Foo: a+
@@ -71,7 +69,7 @@ class TestHeaderChain(unittest.TestCase):
self.assertEqual(link.rule.name[:13], 'header-match-')
self.assertEqual(link.action, LinkAction.defer)
post_checks.append((link.rule.header, link.rule.pattern))
- self._leq(post_checks, [
+ self.assertListEqual(post_checks, [
('Foo', 'a+'),
('Bar', 'bb?'),
])
@@ -103,7 +101,7 @@ class TestHeaderChain(unittest.TestCase):
self.assertEqual(link.rule.name[:13], 'header-match-')
self.assertEqual(link.action, LinkAction.defer)
post_checks.append((link.rule.header, link.rule.pattern))
- self._leq(post_checks, [
+ self.assertListEqual(post_checks, [
('Foo', 'foo'),
('Bar', 'bar'),
])
diff --git a/src/mailman/core/errors.py b/src/mailman/core/errors.py
index 95a318ca6..42b536d46 100644
--- a/src/mailman/core/errors.py
+++ b/src/mailman/core/errors.py
@@ -90,6 +90,12 @@ def _(s):
class HandlerError(MailmanError):
"""Base class for all handler errors."""
+ def __init__(self, message=None):
+ self.message = message
+
+ def __str__(self):
+ return self.message
+
class HoldMessage(HandlerError):
"""Base class for all message-being-held short circuits."""
diff --git a/src/mailman/core/logging.py b/src/mailman/core/logging.py
index af04b58d1..2442d4913 100644
--- a/src/mailman/core/logging.py
+++ b/src/mailman/core/logging.py
@@ -40,8 +40,8 @@ _handlers = {}
-# XXX I would love to simplify things and use Python 2.6's WatchedFileHandler,
-# but there are two problems. First, it's more difficult to handle the test
+# XXX I would love to simplify things and use Python's WatchedFileHandler, but
+# there are two problems. First, it's more difficult to handle the test
# suite's need to reopen the file handler to a different path. Does
# zope.testing's logger support fix this?
#
diff --git a/src/mailman/core/tests/test_runner.py b/src/mailman/core/tests/test_runner.py
index ad2548adc..80a503f5d 100644
--- a/src/mailman/core/tests/test_runner.py
+++ b/src/mailman/core/tests/test_runner.py
@@ -81,7 +81,7 @@ Message-ID: <ant>
self.assertEqual(event.message['message-id'], '<ant>')
self.assertEqual(event.metadata['listname'], 'test@example.com')
self.assertTrue(isinstance(event.error, RuntimeError))
- self.assertEqual(event.error.message, 'borked')
+ self.assertEqual(str(event.error), 'borked')
self.assertTrue(isinstance(event.runner, CrashingRunner))
# The message should also have ended up in the shunt queue.
shunted = get_queue_messages('shunt')
diff --git a/src/mailman/docs/INTRODUCTION.rst b/src/mailman/docs/INTRODUCTION.rst
index 11d13c239..8e334c08a 100644
--- a/src/mailman/docs/INTRODUCTION.rst
+++ b/src/mailman/docs/INTRODUCTION.rst
@@ -82,7 +82,7 @@ lists and archives, etc., are available at:
Requirements
============
-Mailman 3.0 requires `Python 2.6`_ or newer.
+Mailman 3.0 requires `Python 2.7`_ or newer.
.. _`GNU Mailman`: http://www.list.org
@@ -90,4 +90,4 @@ Mailman 3.0 requires `Python 2.6`_ or newer.
.. _`Getting Started`: START.html
.. _Python: http://www.python.org
.. _FAQ: http://wiki.list.org/display/DOC/Frequently+Asked+Questions
-.. _`Python 2.6`: http://www.python.org/download/releases/2.6.6/
+.. _`Python 2.7`: http://www.python.org/download/releases/2.7.3/
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index 11f52a3de..892cc52c4 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -12,6 +12,11 @@ Here is a history of user visible changes to Mailman.
==========================
(2012-XX-XX)
+Compatibility
+-------------
+ * Python 2.7 is not required. Python 2.6 is no longer officially supported.
+ LP: #1073506
+
REST
----
* Add list_id to JSON representation for a mailing list (given by Jimmy
diff --git a/src/mailman/docs/START.rst b/src/mailman/docs/START.rst
index da76feae0..dbf4966c4 100644
--- a/src/mailman/docs/START.rst
+++ b/src/mailman/docs/START.rst
@@ -32,14 +32,13 @@ mailman-developers@python.org mailing list.
Requirements
============
-Python 2.6 or 2.7 is required. It can either be the default 'python' on your
-$PATH or it can be accessible via the ``python2.6`` or ``python2.7`` binary.
+Python 2.7 is required. It can either be the default 'python' on your
+$PATH or it can be accessible via the ``python2.7`` binary.
If your operating system does not include Python, see http://www.python.org
downloading and installing it from source. Python 3 is not yet supported.
In this documentation, a bare ``python`` refers to the Python executable used
-to invoke ``bootstrap.py``, which might be ``python2.6`` or ``python2.7``, as
-well as the system ``python`` or an absolute path.
+to invoke ``bootstrap.py``.
Mailman 3 is now based on the `zc.buildout`_ infrastructure, which greatly
simplifies building and testing Mailman.
diff --git a/src/mailman/docs/STYLEGUIDE.rst b/src/mailman/docs/STYLEGUIDE.rst
index b744c6557..29661701b 100644
--- a/src/mailman/docs/STYLEGUIDE.rst
+++ b/src/mailman/docs/STYLEGUIDE.rst
@@ -15,7 +15,7 @@ http://barry.warsaw.us/software/STYLEGUIDE.txt
This document contains a style guide for Python programming, as used in GNU
Mailman. `PEP 8`_ is the basis for this style guide so it's recommendations
should be followed except for the differences outlined here. This document
-assumes the use of Python 2.6 or 2.7, but not (yet) Python 3.
+assumes the use of Python 2.7, but not (yet) Python 3.
* After file comments (e.g. license block), add a ``__metaclass__`` definition
so that all classes will be new-style. Following that, add an ``__all__``
diff --git a/src/mailman/docs/WebUIin5.rst b/src/mailman/docs/WebUIin5.rst
index 56f2df9fb..6419e4752 100644
--- a/src/mailman/docs/WebUIin5.rst
+++ b/src/mailman/docs/WebUIin5.rst
@@ -7,8 +7,8 @@ Mailman 3's web UI, called Postorius. If all goes as planned, you should be
done within 5 minutes. This has been tested on Ubuntu 11.04.
In order to download the components necessary you need to have the `Bazaar`_
-version control system installed on your system. Mailman and mailman.client
-need at least Python version 2.6.
+version control system installed on your system. Mailman requires Python 2.7,
+while mailman.client needs at least Python version 2.6.
It's probably a good idea to set up a virtual Python environment using
`virtualenv`_. `Here is a brief HOWTO`_.
diff --git a/src/mailman/email/message.py b/src/mailman/email/message.py
index dcea82425..601d4f839 100644
--- a/src/mailman/email/message.py
+++ b/src/mailman/email/message.py
@@ -219,11 +219,7 @@ class UserNotification(Message):
if mlist is not None:
enqueue_kws['listname'] = mlist.fqdn_listname
enqueue_kws.update(_kws)
- # Keywords must be strings in Python 2.6.
- str_keywords = dict()
- for key, val in enqueue_kws.items():
- str_keywords[str(key)] = val
- virginq.enqueue(self, **str_keywords)
+ virginq.enqueue(self, **enqueue_kws)
diff --git a/src/mailman/handlers/tests/test_mimedel.py b/src/mailman/handlers/tests/test_mimedel.py
index 6ca34b17b..74790fbf7 100644
--- a/src/mailman/handlers/tests/test_mimedel.py
+++ b/src/mailman/handlers/tests/test_mimedel.py
@@ -37,8 +37,7 @@ from mailman.interfaces.action import FilterAction
from mailman.interfaces.member import MemberRole
from mailman.interfaces.usermanager import IUserManager
from mailman.testing.helpers import (
- LogFileMark,
- get_queue_messages,
+ LogFileMark, configuration, get_queue_messages,
specialized_message_from_string as mfs)
from mailman.testing.layers import ConfigLayer
@@ -71,25 +70,17 @@ Message-ID: <ant>
def test_dispose_discard(self):
self._mlist.filter_action = FilterAction.discard
- try:
+ with self.assertRaises(errors.DiscardMessage) as cm:
mime_delete.dispose(self._mlist, self._msg, {}, 'discarding')
- except errors.DiscardMessage as error:
- pass
- else:
- raise AssertionError('DiscardMessage exception expected')
- self.assertEqual(error.message, 'discarding')
+ self.assertEqual(cm.exception.message, 'discarding')
# There should be no messages in the 'bad' queue.
self.assertEqual(len(get_queue_messages('bad')), 0)
def test_dispose_bounce(self):
self._mlist.filter_action = FilterAction.reject
- try:
+ with self.assertRaises(errors.RejectMessage) as cm:
mime_delete.dispose(self._mlist, self._msg, {}, 'rejecting')
- except errors.RejectMessage as error:
- pass
- else:
- raise AssertionError('RejectMessage exception expected')
- self.assertEqual(error.message, 'rejecting')
+ self.assertEqual(cm.exception.message, 'rejecting')
# There should be no messages in the 'bad' queue.
self.assertEqual(len(get_queue_messages('bad')), 0)
@@ -103,13 +94,9 @@ Message-ID: <ant>
self._mlist.subscribe(bart, MemberRole.moderator)
# Now set the filter action and dispose the message.
self._mlist.filter_action = FilterAction.forward
- try:
+ with self.assertRaises(errors.DiscardMessage) as cm:
mime_delete.dispose(self._mlist, self._msg, {}, 'forwarding')
- except errors.DiscardMessage as error:
- pass
- else:
- raise AssertionError('DiscardMessage exception expected')
- self.assertEqual(error.message, 'forwarding')
+ self.assertEqual(cm.exception.message, 'forwarding')
# There should now be a multipart message in the virgin queue destined
# for the mailing list owners.
messages = get_queue_messages('virgin')
@@ -143,46 +130,28 @@ message.
self.assertEqual(original['subject'], 'A disposable message')
self.assertEqual(original['message-id'], '<ant>')
+ @configuration('mailman', filtered_messages_are_preservable='no')
def test_dispose_non_preservable(self):
# Two actions can happen here, depending on a site-wide setting. If
# the site owner has indicated that filtered messages cannot be
# preserved, then this is the same as discarding them.
self._mlist.filter_action = FilterAction.preserve
- config.push('non-preservable', """
- [mailman]
- filtered_messages_are_preservable: no
- """)
- try:
+ with self.assertRaises(errors.DiscardMessage) as cm:
mime_delete.dispose(self._mlist, self._msg, {}, 'not preserved')
- except errors.DiscardMessage as error:
- pass
- else:
- raise AssertionError('DiscardMessage exception expected')
- finally:
- config.pop('non-preservable')
- self.assertEqual(error.message, 'not preserved')
+ self.assertEqual(cm.exception.message, 'not preserved')
# There should be no messages in the 'bad' queue.
self.assertEqual(len(get_queue_messages('bad')), 0)
+ @configuration('mailman', filtered_messages_are_preservable='yes')
def test_dispose_preservable(self):
# Two actions can happen here, depending on a site-wide setting. If
# the site owner has indicated that filtered messages can be
# preserved, then this is similar to discarding the message except
# that a copy is preserved in the 'bad' queue.
self._mlist.filter_action = FilterAction.preserve
- config.push('preservable', """
- [mailman]
- filtered_messages_are_preservable: yes
- """)
- try:
+ with self.assertRaises(errors.DiscardMessage) as cm:
mime_delete.dispose(self._mlist, self._msg, {}, 'preserved')
- except errors.DiscardMessage as error:
- pass
- else:
- raise AssertionError('DiscardMessage exception expected')
- finally:
- config.pop('preservable')
- self.assertEqual(error.message, 'preserved')
+ self.assertEqual(cm.exception.message, 'preserved')
# There should be no messages in the 'bad' queue.
messages = get_queue_messages('bad')
self.assertEqual(len(messages), 1)
@@ -200,13 +169,9 @@ message.
FilterAction.defer):
self._mlist.filter_action = action
mark = LogFileMark('mailman.error')
- try:
+ with self.assertRaises(errors.DiscardMessage) as cm:
mime_delete.dispose(self._mlist, self._msg, {}, 'bad action')
- except errors.DiscardMessage as error:
- pass
- else:
- raise AssertionError('DiscardMessage exception expected')
- self.assertEqual(error.message, 'bad action')
+ self.assertEqual(cm.exception.message, 'bad action')
line = mark.readline()[:-1]
self.assertTrue(line.endswith(
'{0} invalid FilterAction: test@example.com. '
diff --git a/src/mailman/interfaces/address.py b/src/mailman/interfaces/address.py
index 54bf6b283..7df15b91f 100644
--- a/src/mailman/interfaces/address.py
+++ b/src/mailman/interfaces/address.py
@@ -47,11 +47,7 @@ class EmailError(MailmanError):
self.email = email
def __str__(self):
- # This is a workaround for Python 2.6 support. When self.email
- # contains non-ascii characters, this will cause unprintable output in
- # doctests. Python 2.7 can handle it but we haven't dropped support
- # for 2.6 yet.
- return self.email.encode('us-ascii', 'backslashreplace')
+ return self.email
class AddressError(MailmanError):
diff --git a/src/mailman/model/docs/listmanager.rst b/src/mailman/model/docs/listmanager.rst
index 380fe7704..41450b15d 100644
--- a/src/mailman/model/docs/listmanager.rst
+++ b/src/mailman/model/docs/listmanager.rst
@@ -126,8 +126,7 @@ address components.
test_3@example.com
test_4@example.com
- >>> for list_name, mail_host in sorted(list_manager.name_components,
- ... key=lambda (name, host): name):
+ >>> for list_name, mail_host in sorted(list_manager.name_components):
... print list_name, '@', mail_host
test @ example.com
test_3 @ example.com
diff --git a/src/mailman/rest/tests/test_addresses.py b/src/mailman/rest/tests/test_addresses.py
index 01ce710b2..35a19f77f 100644
--- a/src/mailman/rest/tests/test_addresses.py
+++ b/src/mailman/rest/tests/test_addresses.py
@@ -48,34 +48,24 @@ class TestAddresses(unittest.TestCase):
def test_membership_of_missing_address(self):
# Try to get the memberships of a missing address.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/addresses/'
'nobody@example.com/memberships')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError 404')
+ self.assertEqual(cm.exception.code, 404)
def test_verify_a_missing_address(self):
# POSTing to the 'verify' sub-resource returns a 404.
- try:
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/addresses/'
'nobody@example.com/verify', {})
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError 404')
+ self.assertEqual(cm.exception.code, 404)
def test_unverify_a_missing_address(self):
# POSTing to the 'unverify' sub-resource returns a 404.
- try:
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/addresses/'
'nobody@example.com/unverify', {})
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError 404')
+ self.assertEqual(cm.exception.code, 404)
def test_verify_already_verified(self):
# It's okay to verify an already verified; it just doesn't change the
@@ -105,23 +95,17 @@ class TestAddresses(unittest.TestCase):
with transaction():
anne = getUtility(IUserManager).create_address('anne@example.com')
self.assertEqual(anne.verified_on, None)
- try:
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/addresses/'
'anne@example.com/verify/foo', {})
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- else:
- raise AssertionError('Expected HTTPError 400')
+ self.assertEqual(cm.exception.code, 400)
def test_unverify_bad_request(self):
# Too many segments after /verify.
with transaction():
anne = getUtility(IUserManager).create_address('anne@example.com')
self.assertEqual(anne.verified_on, None)
- try:
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/addresses/'
'anne@example.com/unverify/foo', {})
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- else:
- raise AssertionError('Expected HTTPError 400')
+ self.assertEqual(cm.exception.code, 400)
diff --git a/src/mailman/rest/tests/test_domains.py b/src/mailman/rest/tests/test_domains.py
index a86768481..dea6a0aa6 100644
--- a/src/mailman/rest/tests/test_domains.py
+++ b/src/mailman/rest/tests/test_domains.py
@@ -47,24 +47,16 @@ class TestDomains(unittest.TestCase):
def test_bogus_endpoint_extension(self):
# /domains/<domain>/lists/<anything> is not a valid endpoint.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/domains/example.com'
'/lists/wrong')
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 400)
def test_bogus_endpoint(self):
# /domains/<domain>/<!lists> does not exist.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/domains/example.com/wrong')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
def test_lists_are_deleted_when_domain_is_deleted(self):
# /domains/<domain> DELETE removes all associated mailing lists.
diff --git a/src/mailman/rest/tests/test_lists.py b/src/mailman/rest/tests/test_lists.py
index cd0ebaf8e..9686ce6a8 100644
--- a/src/mailman/rest/tests/test_lists.py
+++ b/src/mailman/rest/tests/test_lists.py
@@ -46,47 +46,31 @@ class TestListsMissing(unittest.TestCase):
def test_missing_list_roster_member_404(self):
# /lists/<missing>/roster/member gives 404
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/lists/missing@example.com'
'/roster/member')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
def test_missing_list_roster_owner_404(self):
# /lists/<missing>/roster/owner gives 404
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/lists/missing@example.com'
'/roster/owner')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
def test_missing_list_roster_moderator_404(self):
# /lists/<missing>/roster/member gives 404
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/lists/missing@example.com'
'/roster/moderator')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
def test_missing_list_configuration_404(self):
# /lists/<missing>/config gives 404
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api(
'http://localhost:9001/3.0/lists/missing@example.com/config')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
diff --git a/src/mailman/rest/tests/test_membership.py b/src/mailman/rest/tests/test_membership.py
index 18469e537..3bbe821ac 100644
--- a/src/mailman/rest/tests/test_membership.py
+++ b/src/mailman/rest/tests/test_membership.py
@@ -50,41 +50,29 @@ class TestMembership(unittest.TestCase):
def test_try_to_join_missing_list(self):
# A user tries to join a non-existent list.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/members', {
'list_id': 'missing.example.com',
'subscriber': 'nobody@example.com',
})
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- self.assertEqual(exc.msg, 'No such list')
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 400)
+ self.assertEqual(cm.exception.msg, 'No such list')
def test_try_to_leave_missing_list(self):
# A user tries to leave a non-existent list.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/lists/missing@example.com'
'/member/nobody@example.com',
method='DELETE')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- self.assertEqual(exc.msg, '404 Not Found')
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
+ self.assertEqual(cm.exception.msg, '404 Not Found')
def test_try_to_leave_list_with_bogus_address(self):
# Try to leave a mailing list using an invalid membership address.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/members/1', method='DELETE')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- self.assertEqual(exc.msg, '404 Not Found')
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
+ self.assertEqual(cm.exception.msg, '404 Not Found')
def test_try_to_leave_a_list_twice(self):
with transaction():
@@ -96,45 +84,34 @@ class TestMembership(unittest.TestCase):
# content.
self.assertEqual(content, None)
self.assertEqual(response.status, 204)
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api(url, method='DELETE')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- self.assertEqual(exc.msg, '404 Not Found')
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
+ self.assertEqual(cm.exception.msg, '404 Not Found')
def test_try_to_join_a_list_twice(self):
with transaction():
anne = self._usermanager.create_address('anne@example.com')
self._mlist.subscribe(anne)
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/members', {
'list_id': 'test.example.com',
'subscriber': 'anne@example.com',
})
- except HTTPError as exc:
- self.assertEqual(exc.code, 409)
- self.assertEqual(exc.msg, 'Member already subscribed')
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 409)
+ self.assertEqual(cm.exception.msg, 'Member already subscribed')
def test_join_with_invalid_delivery_mode(self):
- try:
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/members', {
'list_id': 'test.example.com',
'subscriber': 'anne@example.com',
'display_name': 'Anne Person',
'delivery_mode': 'invalid-mode',
})
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- self.assertEqual(exc.msg,
- 'Cannot convert parameters: delivery_mode')
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 400)
+ self.assertEqual(cm.exception.msg,
+ 'Cannot convert parameters: delivery_mode')
def test_join_email_contains_slash(self):
content, response = call_api('http://localhost:9001/3.0/members', {
@@ -196,47 +173,31 @@ class TestMembership(unittest.TestCase):
def test_get_nonexistent_member(self):
# /members/<bogus> returns 404
- try:
- # For Python 2.6
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/members/bogus')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
def test_patch_nonexistent_member(self):
# /members/<missing> PATCH returns 404
- try:
- # For Python 2.6
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/members/801', method='PATCH')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
def test_patch_member_bogus_attribute(self):
# /members/<id> PATCH 'bogus' returns 400
with transaction():
anne = self._usermanager.create_address('anne@example.com')
self._mlist.subscribe(anne)
- try:
- # For Python 2.6
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/members/1', {
'powers': 'super',
}, method='PATCH')
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- self.assertEqual(exc.msg, 'Unexpected parameters: powers')
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 400)
+ self.assertEqual(cm.exception.msg, 'Unexpected parameters: powers')
def test_member_all_without_preferences(self):
# /members/<id>/all should return a 404 when it isn't trailed by
# `preferences`
- try:
- # For Python 2.6
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/members/1/all')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
diff --git a/src/mailman/rest/tests/test_moderation.py b/src/mailman/rest/tests/test_moderation.py
index dfcedef05..2ee796c87 100644
--- a/src/mailman/rest/tests/test_moderation.py
+++ b/src/mailman/rest/tests/test_moderation.py
@@ -56,24 +56,16 @@ Something else.
def test_not_found(self):
# When a bogus mailing list is given, 404 should result.
- try:
- # For Python 2.6
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/lists/bee@example.com/held')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
def test_bad_request_id(self):
# Bad request when request_id is not an integer.
- try:
- # For Python 2.6
+ with self.assertRaises(HTTPError) as cm:
call_api(
'http://localhost:9001/3.0/lists/ant@example.com/held/bogus')
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 400)
def test_subscription_request_as_held_message(self):
# Provide the request id of a subscription request using the held
@@ -85,12 +77,9 @@ Something else.
DeliveryMode.regular, 'en')
config.db.store.commit()
url = 'http://localhost:9001/3.0/lists/ant@example.com/held/{0}'
- try:
+ with self.assertRaises(HTTPError) as cm:
call_api(url.format(subscribe_id))
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
# But using the held_id returns a valid response.
response, content = call_api(url.format(held_id))
self.assertEqual(response['key'], '<alpha>')
@@ -99,10 +88,7 @@ Something else.
# POSTing to a held message with a bad action.
held_id = hold_message(self._mlist, self._msg)
url = 'http://localhost:9001/3.0/lists/ant@example.com/held/{0}'
- try:
+ with self.assertRaises(HTTPError) as cm:
call_api(url.format(held_id), {'action': 'bogus'})
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- self.assertEqual(exc.msg, 'Cannot convert parameters: action')
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 400)
+ self.assertEqual(cm.exception.msg, 'Cannot convert parameters: action')
diff --git a/src/mailman/rest/tests/test_root.py b/src/mailman/rest/tests/test_root.py
index 90d30bd80..4a9ba0dd1 100644
--- a/src/mailman/rest/tests/test_root.py
+++ b/src/mailman/rest/tests/test_root.py
@@ -38,38 +38,25 @@ class TestSystem(unittest.TestCase):
def test_system_url_too_long(self):
# /system/foo/bar is not allowed.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/system/foo/bar')
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 400)
def test_system_url_not_preferences(self):
# /system/foo where `foo` is not `preferences`.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/system/foo')
- except HTTPError as exc:
- self.assertEqual(exc.code, 400)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 400)
def test_system_preferences_are_read_only(self):
# /system/preferences are read-only.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/system/preferences', {
'acknowledge_posts': True,
}, method='PATCH')
- except HTTPError as exc:
- self.assertEqual(exc.code, 405)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 405)
# /system/preferences are read-only.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/system/preferences', {
'acknowledge_posts': False,
'delivery_mode': 'regular',
@@ -79,7 +66,4 @@ class TestSystem(unittest.TestCase):
'receive_list_copy': True,
'receive_own_postings': True,
}, method='PUT')
- except HTTPError as exc:
- self.assertEqual(exc.code, 405)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 405)
diff --git a/src/mailman/rest/tests/test_users.py b/src/mailman/rest/tests/test_users.py
index 301027885..4595c69d8 100644
--- a/src/mailman/rest/tests/test_users.py
+++ b/src/mailman/rest/tests/test_users.py
@@ -45,10 +45,6 @@ class TestUsers(unittest.TestCase):
def test_delete_bogus_user(self):
# Try to delete a user that does not exist.
- try:
- # For Python 2.6.
+ with self.assertRaises(HTTPError) as cm:
call_api('http://localhost:9001/3.0/users/99', method='DELETE')
- except HTTPError as exc:
- self.assertEqual(exc.code, 404)
- else:
- raise AssertionError('Expected HTTPError')
+ self.assertEqual(cm.exception.code, 404)
diff --git a/src/mailman/rules/administrivia.py b/src/mailman/rules/administrivia.py
index 4c49e4ff2..6f5f41cd3 100644
--- a/src/mailman/rules/administrivia.py
+++ b/src/mailman/rules/administrivia.py
@@ -84,7 +84,7 @@ class Administrivia:
if len(line) == 0:
continue
lineno += 1
- if lineno > config.mailman.email_commands_max_lines:
+ if lineno > int(config.mailman.email_commands_max_lines):
break
lines_to_check.append(line)
# Only look at the first text/plain part.
diff --git a/src/mailman/runners/digest.py b/src/mailman/runners/digest.py
index 99710dff5..f87dd4e76 100644
--- a/src/mailman/runners/digest.py
+++ b/src/mailman/runners/digest.py
@@ -318,9 +318,9 @@ class DigestRunner(Runner):
"""See `IRunner`."""
volume = msgdata['volume']
digest_number = msgdata['digest_number']
- with nested(Mailbox(msgdata['digest_path']),
- _.using(mlist.preferred_language.code)) as (mailbox,
- language_code):
+ # Backslashes make me cry.
+ with Mailbox(msgdata['digest_path']) as mailbox, \
+ _.using(mlist.preferred_language.code):
# Create the digesters.
mime_digest = MIMEDigester(mlist, volume, digest_number)
rfc1153_digest = RFC1153Digester(mlist, volume, digest_number)
@@ -354,7 +354,7 @@ class DigestRunner(Runner):
# receive.
digest_members = set(mlist.digest_members.members)
for member in digest_members:
- if member.delivery_status <> DeliveryStatus.enabled:
+ if member.delivery_status is not DeliveryStatus.enabled:
continue
# Send the digest to the case-preserved address of the digest
# members.
diff --git a/src/mailman/runners/tests/test_confirm.py b/src/mailman/runners/tests/test_confirm.py
index 62171979c..78f6a382c 100644
--- a/src/mailman/runners/tests/test_confirm.py
+++ b/src/mailman/runners/tests/test_confirm.py
@@ -28,6 +28,7 @@ __all__ = [
import unittest
from datetime import datetime
+from email.iterators import body_line_iterator
from zope.component import getUtility
from mailman.app.lifecycle import create_list
@@ -37,7 +38,6 @@ from mailman.interfaces.registrar import IRegistrar
from mailman.interfaces.usermanager import IUserManager
from mailman.runners.command import CommandRunner
from mailman.testing.helpers import (
- body_line_iterator,
get_queue_messages,
make_testable_runner,
specialized_message_from_string as mfs)
diff --git a/src/mailman/runners/tests/test_join.py b/src/mailman/runners/tests/test_join.py
index a584fd2c2..41adcc450 100644
--- a/src/mailman/runners/tests/test_join.py
+++ b/src/mailman/runners/tests/test_join.py
@@ -28,6 +28,7 @@ __all__ = [
import unittest
+from email.iterators import body_line_iterator
from zope.component import getUtility
from mailman.app.lifecycle import create_list
@@ -38,10 +39,7 @@ from mailman.interfaces.subscriptions import ISubscriptionService
from mailman.interfaces.usermanager import IUserManager
from mailman.runners.command import CommandRunner
from mailman.testing.helpers import (
- body_line_iterator,
- get_queue_messages,
- make_testable_runner,
- reset_the_world,
+ get_queue_messages, make_testable_runner, reset_the_world,
specialized_message_from_string as mfs)
from mailman.testing.layers import ConfigLayer
diff --git a/src/mailman/runners/tests/test_lmtp.py b/src/mailman/runners/tests/test_lmtp.py
index 46d4ed986..a502c317d 100644
--- a/src/mailman/runners/tests/test_lmtp.py
+++ b/src/mailman/runners/tests/test_lmtp.py
@@ -53,22 +53,19 @@ class TestLMTP(unittest.TestCase):
def test_message_id_required(self):
# The message is rejected if it does not have a Message-ID header.
- try:
+ with self.assertRaises(smtplib.SMTPDataError) as cm:
self._lmtp.sendmail('anne@example.com', ['test@example.com'], """\
From: anne@example.com
To: test@example.com
Subject: This has no Message-ID header
""")
- except smtplib.SMTPDataError as error:
- pass
- else:
- raise AssertionError('SMTPDataError expected')
# LMTP returns a 550: Requested action not taken: mailbox unavailable
# (e.g., mailbox not found, no access, or command rejected for policy
# reasons)
- self.assertEqual(error.smtp_code, 550)
- self.assertEqual(error.smtp_error, 'No Message-ID header provided')
+ self.assertEqual(cm.exception.smtp_code, 550)
+ self.assertEqual(cm.exception.smtp_error,
+ 'No Message-ID header provided')
def test_message_id_hash_is_added(self):
self._lmtp.sendmail('anne@example.com', ['test@example.com'], """\
diff --git a/src/mailman/styles/tests/test_styles.py b/src/mailman/styles/tests/test_styles.py
index 990ce541f..a2ffc931f 100644
--- a/src/mailman/styles/tests/test_styles.py
+++ b/src/mailman/styles/tests/test_styles.py
@@ -63,28 +63,16 @@ class TestStyle(unittest.TestCase):
# Registering a style with the same name as a previous style raises an
# exception.
self.manager.register(DummyStyle())
- try:
- self.manager.register(DummyStyle())
- except DuplicateStyleError:
- pass
- else:
- raise AssertionError('DuplicateStyleError exception expected')
+ self.assertRaises(DuplicateStyleError,
+ self.manager.register, DummyStyle())
def test_register_a_non_style(self):
# You can't register something that doesn't implement the IStyle
# interface.
- try:
- self.manager.register(object())
- except DoesNotImplement:
- pass
- else:
- raise AssertionError('DoesNotImplement exception expected')
+ self.assertRaises(DoesNotImplement,
+ self.manager.register, object())
def test_unregister_a_non_registered_style(self):
# You cannot unregister a style that hasn't yet been registered.
- try:
- self.manager.unregister(DummyStyle())
- except KeyError:
- pass
- else:
- raise AssertionError('KeyError expected')
+ self.assertRaises(KeyError,
+ self.manager.unregister, DummyStyle())
diff --git a/src/mailman/testing/helpers.py b/src/mailman/testing/helpers.py
index 054dd4ff7..99f4b8961 100644
--- a/src/mailman/testing/helpers.py
+++ b/src/mailman/testing/helpers.py
@@ -249,8 +249,8 @@ def get_lmtp_client(quiet=False):
if not quiet:
print(response)
return lmtp
- except socket.error as error:
- if error[0] == errno.ECONNREFUSED:
+ except IOError as error:
+ if error.errno == errno.ECONNREFUSED:
time.sleep(0.1)
else:
raise
@@ -284,8 +284,8 @@ def wait_for_webservice():
try:
socket.socket().connect((config.webservice.hostname,
int(config.webservice.port)))
- except socket.error as error:
- if error[0] == errno.ECONNREFUSED:
+ except IOError as error:
+ if error.errno == errno.ECONNREFUSED:
time.sleep(0.1)
else:
raise
@@ -515,19 +515,3 @@ class LogFileMark:
with open(self._filename) as fp:
fp.seek(self._filepos)
return fp.readline()
-
-
-
-# In Python 2.6, body_line_iterator() uses a cStringIO.StringIO() which cannot
-# handle unicode. In Python 2.7 this works fine. I hate version checks but
-# this is the easiest way to handle it. OTOH, we could just use the manual
-# way for all Python versions instead.
-import sys
-if sys.hexversion >= 0x2070000:
- from email.iterators import body_line_iterator
-else:
- def body_line_iterator(msg, decode=False):
- payload = msg.get_payload(decode=decode)
- bytes_payload = payload.encode('utf-8')
- for line in bytes_payload.splitlines():
- yield line
diff --git a/src/mailman/utilities/string.py b/src/mailman/utilities/string.py
index 7470bd476..cd3adc536 100644
--- a/src/mailman/utilities/string.py
+++ b/src/mailman/utilities/string.py
@@ -60,19 +60,7 @@ def expand(template, substitutions, template_class=Template):
:return: The substituted string.
:rtype: string
"""
- # Python 2.6 requires ** dictionaries to have str, not unicode keys, so
- # convert as necessary. Note that string.Template uses **. For our
- # purposes, keys should always be ascii. Values though can be anything.
- cooked = substitutions.__class__()
- for key in substitutions:
- if isinstance(key, unicode):
- key = key.encode('ascii')
- cooked[key] = substitutions[key]
- try:
- return template_class(template).safe_substitute(cooked)
- except (TypeError, ValueError):
- # The template is really screwed up.
- log.exception('broken template: %s', template)
+ return template_class(template).safe_substitute(substitutions)
diff --git a/src/mailman/utilities/tests/test_templates.py b/src/mailman/utilities/tests/test_templates.py
index d205eef34..8e335f69b 100644
--- a/src/mailman/utilities/tests/test_templates.py
+++ b/src/mailman/utilities/tests/test_templates.py
@@ -224,13 +224,9 @@ class TestFind(unittest.TestCase):
self.assertEqual(self.fp.read(), 'List template')
def test_template_not_found(self):
- # Python 2.6 compatibility.
- try:
+ with self.assertRaises(TemplateNotFoundError) as cm:
find('missing.txt', self.mlist)
- except TemplateNotFoundError as error:
- self.assertEqual(error.template_file, 'missing.txt')
- else:
- raise AssertionError('TemplateNotFoundError expected')
+ self.assertEqual(cm.exception.template_file, 'missing.txt')