From 42d13a8672d73aca2fc889633dbf7b3ff2a9c7ee Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Mon, 24 Oct 2011 22:40:59 -0400 Subject: * Implement the style manager as a utility instead of an attribute hanging off the `mailman.config.config` object. * Fixed bogus use of `bounce_processing` attribute (should have been `process_bounces`, with thanks to Vincent Fretin. (LP: #876774) --- src/mailman/app/docs/lifecycle.rst | 5 ++- src/mailman/app/lifecycle.py | 3 +- src/mailman/config/config.py | 5 +-- src/mailman/config/configure.zcml | 5 +++ src/mailman/docs/NEWS.rst | 8 +++- src/mailman/interfaces/styles.py | 2 +- src/mailman/runners/bounce.py | 2 +- src/mailman/runners/tests/test_bounce.py | 66 +++++++++++++++++++++++++++++--- src/mailman/styles/default.py | 2 +- src/mailman/testing/helpers.py | 3 +- 10 files changed, 83 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/mailman/app/docs/lifecycle.rst b/src/mailman/app/docs/lifecycle.rst index 4a8b732e1..d8356db74 100644 --- a/src/mailman/app/docs/lifecycle.rst +++ b/src/mailman/app/docs/lifecycle.rst @@ -58,7 +58,9 @@ Start by registering a test style. ... if 'test' in mailing_list.fqdn_listname: ... styles.append(self) - >>> config.style_manager.register(TestStyle()) + >>> from zope.component import getUtility + >>> from mailman.interfaces.styles import IStyleManager + >>> getUtility(IStyleManager).register(TestStyle()) Using the higher level interface for creating a list, applies all matching list styles. @@ -111,7 +113,6 @@ the system, they won't be created again. :: >>> from mailman.interfaces.usermanager import IUserManager - >>> from zope.component import getUtility >>> user_manager = getUtility(IUserManager) >>> user_a = user_manager.get_user('aperson@example.com') diff --git a/src/mailman/app/lifecycle.py b/src/mailman/app/lifecycle.py index 5ee943840..a96bf96c1 100644 --- a/src/mailman/app/lifecycle.py +++ b/src/mailman/app/lifecycle.py @@ -38,6 +38,7 @@ from mailman.interfaces.domain import ( BadDomainSpecificationError, IDomainManager) from mailman.interfaces.listmanager import IListManager from mailman.interfaces.member import MemberRole +from mailman.interfaces.styles import IStyleManager from mailman.interfaces.usermanager import IUserManager from mailman.utilities.modules import call_name @@ -71,7 +72,7 @@ def create_list(fqdn_listname, owners=None): if domain not in getUtility(IDomainManager): raise BadDomainSpecificationError(domain) mlist = getUtility(IListManager).create(fqdn_listname) - for style in config.style_manager.lookup(mlist): + for style in getUtility(IStyleManager).lookup(mlist): style.apply(mlist) # Coordinate with the MTA, as defined in the configuration file. call_name(config.mta.incoming).create(mlist) diff --git a/src/mailman/config/config.py b/src/mailman/config/config.py index c687777a3..7d54643c7 100644 --- a/src/mailman/config/config.py +++ b/src/mailman/config/config.py @@ -38,7 +38,7 @@ import mailman.templates from mailman import version from mailman.interfaces.languages import ILanguageManager -from mailman.styles.manager import StyleManager +from mailman.interfaces.styles import IStyleManager from mailman.utilities.filesystem import makedirs from mailman.utilities.modules import call_name @@ -59,7 +59,6 @@ class Configuration: def __init__(self): self.switchboards = {} - self.style_manager = StyleManager() self.QFILE_SCHEMA_VERSION = version.QFILE_SCHEMA_VERSION self._config = None self.filename = None @@ -136,7 +135,7 @@ class Configuration: 'System default language code not defined: %s' % self._config.mailman.default_language) self.ensure_directories_exist() - self.style_manager.populate() + getUtility(IStyleManager).populate() # Set the default system language. from mailman.core.i18n import _ _.default = self.mailman.default_language diff --git a/src/mailman/config/configure.zcml b/src/mailman/config/configure.zcml index b5317aa69..bc08eb8c5 100644 --- a/src/mailman/config/configure.zcml +++ b/src/mailman/config/configure.zcml @@ -66,6 +66,11 @@ provides="mailman.interfaces.requests.IRequests" /> + + def test_does_no_processing(self): # If the mailing list does no bounce processing, the messages are # simply discarded. - self._mlist.bounce_processing = False + self._mlist.process_bounces = False self._bounceq.enqueue(self._msg, self._msgdata) self._runner.run() self.assertEqual(len(get_queue_messages('bounces')), 0) @@ -230,7 +231,60 @@ Message-Id: -def test_suite(): - suite = unittest.TestSuite() - suite.addTest(unittest.makeSuite(TestBounceRunner)) - return suite +# Create a style for the mailing list which sets the absolute minimum +# attributes. In particular, this will not set the bogus `bounce_processing` +# attribute which the default style set (before LP: #876774 was fixed). + +class TestStyle: + implements(IStyle) + + name = 'test' + priority = 10 + + def apply(self, mailing_list): + """See `IStyle`.""" + mailing_list.preferred_language = 'en' + + def match(self, mailing_list, styles): + styles.append(self) + + +class TestBounceRunnerBug876774(unittest.TestCase): + """Test LP: #876774. + + Quoting: + + It seems that bounce_processing is defined in src/mailman/styles/default.py + The style are applied at mailing-list creation, but bounce_processing + attribute is not persisted, the src/mailman/database/mailman.sql file + doesn't define it. + """ + layer = ConfigLayer + + def setUp(self): + self._style = TestStyle() + self._style_manager = getUtility(IStyleManager) + self._style_manager.register(self._style) + # Now we can create the mailing list. + self._mlist = create_list('test@example.com') + self._bounceq = config.switchboards['bounces'] + self._processor = getUtility(IBounceProcessor) + self._runner = make_testable_runner(BounceRunner, 'bounces') + + def tearDown(self): + self._style_manager.unregister(self._style) + + def test_bug876774(self): + # LP: #876774, see above. + bounce = message_from_string("""\ +From: mail-daemon@example.com +To: test-bounces+anne=example.com@example.com +Message-Id: + +""") + self._bounceq.enqueue(bounce, dict(listname='test@example.com')) + self.assertEqual(len(self._bounceq.files), 1) + self._runner.run() + self.assertEqual(len(get_queue_messages('bounces')), 0) + events = list(self._processor.events) + self.assertEqual(len(events), 0) diff --git a/src/mailman/styles/default.py b/src/mailman/styles/default.py index eba7c7757..134930d0a 100644 --- a/src/mailman/styles/default.py +++ b/src/mailman/styles/default.py @@ -165,7 +165,7 @@ ${listinfo_page} # Bounces mlist.forward_unrecognized_bounces_to = ( UnrecognizedBounceDisposition.administrators) - mlist.bounce_processing = True + mlist.process_bounces = True mlist.bounce_score_threshold = 5.0 mlist.bounce_info_stale_after = datetime.timedelta(days=7) mlist.bounce_you_are_disabled_warnings = 3 diff --git a/src/mailman/testing/helpers.py b/src/mailman/testing/helpers.py index 144ae1ffb..a7fc4e289 100644 --- a/src/mailman/testing/helpers.py +++ b/src/mailman/testing/helpers.py @@ -61,6 +61,7 @@ from mailman.config import config from mailman.email.message import Message from mailman.interfaces.member import MemberRole from mailman.interfaces.messages import IMessageStore +from mailman.interfaces.styles import IStyleManager from mailman.interfaces.usermanager import IUserManager from mailman.utilities.mailbox import Mailbox @@ -371,7 +372,7 @@ def reset_the_world(): message_store.delete_message(message['message-id']) config.db.commit() # Reset the global style manager. - config.style_manager.populate() + getUtility(IStyleManager).populate() -- cgit v1.3.1