summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mailman/app/docs/lifecycle.rst5
-rw-r--r--src/mailman/app/lifecycle.py3
-rw-r--r--src/mailman/config/config.py5
-rw-r--r--src/mailman/config/configure.zcml5
-rw-r--r--src/mailman/docs/NEWS.rst8
-rw-r--r--src/mailman/interfaces/styles.py2
-rw-r--r--src/mailman/runners/bounce.py2
-rw-r--r--src/mailman/runners/tests/test_bounce.py66
-rw-r--r--src/mailman/styles/default.py2
-rw-r--r--src/mailman/testing/helpers.py3
10 files changed, 83 insertions, 18 deletions
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
@@ -67,6 +67,11 @@
/>
<utility
+ factory="mailman.styles.manager.StyleManager"
+ provides="mailman.interfaces.styles.IStyleManager"
+ />
+
+ <utility
factory="mailman.app.subscriptions.SubscriptionService"
provides="mailman.interfaces.subscriptions.ISubscriptionService"
/>
diff --git a/src/mailman/docs/NEWS.rst b/src/mailman/docs/NEWS.rst
index 29d066660..226517b86 100644
--- a/src/mailman/docs/NEWS.rst
+++ b/src/mailman/docs/NEWS.rst
@@ -12,14 +12,18 @@ Here is a history of user visible changes to Mailman.
=================================
(20XX-XX-XX)
-Features
---------
+Architecture
+------------
+ * Implement the style manager as a utility instead of an attribute hanging
+ off the `mailman.config.config` object.
* PostgreSQL support contributed by Stephen A. Goss. (LP: #860159)
Bug fixes
---------
* Fixed KeyError in retry runner, contributed by Stephen A. Goss.
(LP: #872391)
+ * Fixed bogus use of `bounce_processing` attribute (should have been
+ `process_bounces`, with thanks to Vincent Fretin. (LP: #876774)
3.0 alpha 8 -- "Where's My Thing?"
diff --git a/src/mailman/interfaces/styles.py b/src/mailman/interfaces/styles.py
index 7043b703e..b9088e7dd 100644
--- a/src/mailman/interfaces/styles.py
+++ b/src/mailman/interfaces/styles.py
@@ -54,7 +54,7 @@ class IStyle(Interface):
"""
def match(mailing_list, styles):
- """Give this list a chance to match the mailing list.
+ """Give this style a chance to match the mailing list.
If the style's internal matching rules match the `mailing_list`, then
the style may append itself to the `styles` list. This list will be
diff --git a/src/mailman/runners/bounce.py b/src/mailman/runners/bounce.py
index fdfa41e78..da20f4a33 100644
--- a/src/mailman/runners/bounce.py
+++ b/src/mailman/runners/bounce.py
@@ -43,7 +43,7 @@ class BounceRunner(Runner):
def _dispose(self, mlist, msg, msgdata):
# List isn't doing bounce processing?
- if not mlist.bounce_processing:
+ if not mlist.process_bounces:
return False
# Try VERP detection first, since it's quick and easy
context = BounceContext.normal
diff --git a/src/mailman/runners/tests/test_bounce.py b/src/mailman/runners/tests/test_bounce.py
index bfe1664d6..90fd012f7 100644
--- a/src/mailman/runners/tests/test_bounce.py
+++ b/src/mailman/runners/tests/test_bounce.py
@@ -21,13 +21,13 @@ from __future__ import absolute_import, unicode_literals
__metaclass__ = type
__all__ = [
- 'test_suite',
]
import unittest
from zope.component import getUtility
+from zope.interface import implements
from mailman.app.bounces import send_probe
from mailman.app.lifecycle import create_list
@@ -35,6 +35,7 @@ from mailman.config import config
from mailman.interfaces.bounce import (
BounceContext, IBounceProcessor, UnrecognizedBounceDisposition)
from mailman.interfaces.member import MemberRole
+from mailman.interfaces.styles import IStyle, IStyleManager
from mailman.interfaces.usermanager import IUserManager
from mailman.runners.bounce import BounceRunner
from mailman.testing.helpers import (
@@ -77,7 +78,7 @@ Message-Id: <first>
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: <third>
-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: <first>
+
+""")
+ 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()