diff options
| author | Barry Warsaw | 2012-03-12 18:03:35 -0700 |
|---|---|---|
| committer | Barry Warsaw | 2012-03-12 18:03:35 -0700 |
| commit | ce02817cd4d3cf982ca58dfcb177a0b62fa75d54 (patch) | |
| tree | 701efb7db4b7d045b1f0bd376eb993c519f7915f | |
| parent | 3fe7d15a5c6e54cc0c201b10b9dd1329dffe2cd2 (diff) | |
| download | mailman-ce02817cd4d3cf982ca58dfcb177a0b62fa75d54.tar.gz mailman-ce02817cd4d3cf982ca58dfcb177a0b62fa75d54.tar.zst mailman-ce02817cd4d3cf982ca58dfcb177a0b62fa75d54.zip | |
| -rw-r--r-- | README.rst | 1 | ||||
| -rw-r--r-- | src/mailman/model/tests/test_user.py | 3 | ||||
| -rw-r--r-- | src/mailman/styles/docs/__init__.py | 0 | ||||
| -rw-r--r-- | src/mailman/styles/docs/styles.rst (renamed from src/mailman/app/docs/styles.rst) | 105 | ||||
| -rw-r--r-- | src/mailman/styles/tests/__init__.py | 0 | ||||
| -rw-r--r-- | src/mailman/styles/tests/test_styles.py | 90 |
6 files changed, 139 insertions, 60 deletions
diff --git a/README.rst b/README.rst index e761e28d7..9c9b026c6 100644 --- a/README.rst +++ b/README.rst @@ -43,6 +43,7 @@ Table of Contents src/mailman/model/docs/* src/mailman/core/docs/* src/mailman/app/docs/* + src/mailman/styles/docs/* src/mailman/runners/docs/* src/mailman/pipeline/docs/* src/mailman/rest/docs/* diff --git a/src/mailman/model/tests/test_user.py b/src/mailman/model/tests/test_user.py index c4c07ed22..2f04b7c3a 100644 --- a/src/mailman/model/tests/test_user.py +++ b/src/mailman/model/tests/test_user.py @@ -21,6 +21,7 @@ from __future__ import absolute_import, unicode_literals __metaclass__ = type __all__ = [ + 'TestUser', ] @@ -36,6 +37,8 @@ from mailman.utilities.datetime import now class TestUser(unittest.TestCase): + """Test users.""" + layer = ConfigLayer def setUp(self): diff --git a/src/mailman/styles/docs/__init__.py b/src/mailman/styles/docs/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/mailman/styles/docs/__init__.py diff --git a/src/mailman/app/docs/styles.rst b/src/mailman/styles/docs/styles.rst index 63ec999bf..90a02227b 100644 --- a/src/mailman/app/docs/styles.rst +++ b/src/mailman/styles/docs/styles.rst @@ -2,9 +2,10 @@ List styles =========== -List styles are a way to name and apply a canned collection of attribute -settings. Every style has a name, which must be unique within the context of -a specific style manager. There is usually only one global style manager. +List styles are a way to name and apply a template of attribute settings to +new mailing lists. Every style has a name, which must be unique within the +context of a specific style manager. There is usually only one global style +manager. Styles also have a priority, which allows you to specify the order in which multiple styles will be applied. A style has a `match` function which is used @@ -22,26 +23,26 @@ Let's start with a vanilla mailing list and a default style manager. >>> from mailman.styles.manager import StyleManager >>> style_manager = StyleManager() >>> style_manager.populate() - >>> sorted(style.name for style in style_manager.styles) - ['default'] + >>> styles = sorted(style.name for style in style_manager.styles) + >>> len(styles) + 1 + >>> print styles[0] + default The default style ================= -There is a default style which implements the legacy application of list -defaults from previous versions of Mailman. This style only matching a -mailing list when no other styles match, and it has the lowest priority. The -low priority means that it is matched last and if it matches, it is applied -last. +There is a default style which implements a legacy style roughly corresponding +to discussion mailing lists. This style matches when no other styles match, +and it has the lowest priority. The low priority means that it is matched +last and if it matches, it is applied last. >>> default_style = style_manager.get('default') - >>> default_style.name - 'default' + >>> print default_style.name + default >>> default_style.priority 0 - >>> sorted(style.name for style in style_manager.styles) - ['default'] Given a mailing list, you can ask the style manager to find all the styles that match the list. The registered styles will be sorted by decreasing @@ -49,8 +50,11 @@ priority and each style's ``match()`` method will be called in turn. The sorted list of matching styles will be returned -- but not applied -- by the style manager's ``lookup()`` method. - >>> [style.name for style in style_manager.lookup(mlist)] - ['default'] + >>> matched_styles = [style.name for style in style_manager.lookup(mlist)] + >>> len(matched_styles) + 1 + >>> print matched_styles[0] + default Registering styles @@ -60,13 +64,13 @@ New styles must implement the ``IStyle`` interface. >>> from zope.interface import implements >>> from mailman.interfaces.styles import IStyle - >>> class TestStyle(object): + >>> class TestStyle: ... implements(IStyle) ... name = 'test' ... priority = 10 ... def apply(self, mailing_list): ... # Just does something very simple. - ... mailing_list.msg_footer = 'test footer' + ... mailing_list.style_thing = 'thing 1' ... def match(self, mailing_list, styles): ... # Applies to any test list ... if 'test' in mailing_list.fqdn_listname: @@ -76,16 +80,20 @@ You can register a new style with the style manager. >>> style_manager.register(TestStyle()) -And now if you lookup matching styles, you should find only the new test +And now if you look up matching styles, you should find only the new test style. This is because the default style only gets applied when no other styles match the mailing list. - >>> sorted(style.name for style in style_manager.lookup(mlist)) - [u'test'] + >>> matched_styles = sorted( + ... style.name for style in style_manager.lookup(mlist)) + >>> len(matched_styles) + 1 + >>> print matched_styles[0] + test >>> for style in style_manager.lookup(mlist): ... style.apply(mlist) - >>> print mlist.msg_footer - test footer + >>> print mlist.style_thing + thing 1 Style priority @@ -101,16 +109,16 @@ applied last. ... priority = 5 ... # Use the base class's match() method. ... def apply(self, mailing_list): - ... mailing_list.msg_footer = 'another footer' + ... mailing_list.style_thing = 'thing 2' - >>> mlist.msg_footer = '' - >>> mlist.msg_footer - u'' + >>> mlist.style_thing = 'thing 0' + >>> print mlist.style_thing + thing 0 >>> style_manager.register(AnotherTestStyle()) >>> for style in style_manager.lookup(mlist): ... style.apply(mlist) - >>> print mlist.msg_footer - another footer + >>> print mlist.style_thing + thing 2 You can change the priority of a style, and if you reapply the styles, they will take effect in the new priority order. @@ -121,8 +129,8 @@ will take effect in the new priority order. >>> style_2.priority = 10 >>> for style in style_manager.lookup(mlist): ... style.apply(mlist) - >>> print mlist.msg_footer - test footer + >>> print mlist.style_thing + thing 1 Unregistering styles @@ -131,32 +139,9 @@ Unregistering styles You can unregister a style, making it unavailable in the future. >>> style_manager.unregister(style_2) - >>> sorted(style.name for style in style_manager.lookup(mlist)) - [u'test'] - - -Corner cases -============ - -If you register a style with the same name as an already registered style, you -get an exception. - - >>> style_manager.register(TestStyle()) - Traceback (most recent call last): - ... - DuplicateStyleError: test - -If you try to register an object that isn't a style, you get an exception. - - >>> style_manager.register(object()) - Traceback (most recent call last): - ... - DoesNotImplement: An object does not implement interface - <InterfaceClass mailman.interfaces.styles.IStyle> - -If you try to unregister a style that isn't registered, you get an exception. - - >>> style_manager.unregister(style_2) - Traceback (most recent call last): - ... - KeyError: u'another' + >>> matched_styles = sorted( + ... style.name for style in style_manager.lookup(mlist)) + >>> len(matched_styles) + 1 + >>> print matched_styles[0] + test diff --git a/src/mailman/styles/tests/__init__.py b/src/mailman/styles/tests/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/mailman/styles/tests/__init__.py diff --git a/src/mailman/styles/tests/test_styles.py b/src/mailman/styles/tests/test_styles.py new file mode 100644 index 000000000..ce8b5064d --- /dev/null +++ b/src/mailman/styles/tests/test_styles.py @@ -0,0 +1,90 @@ +# Copyright (C) 2012 by the Free Software Foundation, Inc. +# +# This file is part of GNU Mailman. +# +# GNU Mailman 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 3 of the License, or (at your option) +# any later version. +# +# GNU Mailman 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 +# GNU Mailman. If not, see <http://www.gnu.org/licenses/>. + +"""Test styles.""" + +from __future__ import absolute_import, print_function, unicode_literals + +__metaclass__ = type +__all__ = [ + 'TestStyle', + ] + + +import unittest + +from zope.component import getUtility +from zope.interface import implements +from zope.interface.exceptions import DoesNotImplement + +from mailman.interfaces.styles import ( + DuplicateStyleError, IStyle, IStyleManager) +from mailman.testing.layers import ConfigLayer + + + +class DummyStyle: + implements(IStyle) + + name = 'dummy' + priority = 1 + + def apply(self, mlist): + pass + + def match(self, mlist, styles): + styles.append(self) + + + +class TestStyle(unittest.TestCase): + """Test styles.""" + + layer = ConfigLayer + + def setUp(self): + self.manager = getUtility(IStyleManager) + + def test_register_style_again(self): + # 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') + + 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') + + 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') |
