diff options
| author | Barry Warsaw | 2007-08-05 07:30:30 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2007-08-05 07:30:30 -0400 |
| commit | 2999c404a486cb0c7bd76407501e0a6b775c148a (patch) | |
| tree | 83645fed9d0e69654d5852067ec6ee02ab80fe31 | |
| parent | 959f34a62e0ec3cbe73da3d43640ccb6791cf3a0 (diff) | |
| download | mailman-2999c404a486cb0c7bd76407501e0a6b775c148a.tar.gz mailman-2999c404a486cb0c7bd76407501e0a6b775c148a.tar.zst mailman-2999c404a486cb0c7bd76407501e0a6b775c148a.zip | |
Added a doctest for styles.
| -rw-r--r-- | Mailman/app/styles.py | 8 | ||||
| -rw-r--r-- | Mailman/docs/styles.txt | 142 |
2 files changed, 148 insertions, 2 deletions
diff --git a/Mailman/app/styles.py b/Mailman/app/styles.py index 55d8aa690..e0bf58cde 100644 --- a/Mailman/app/styles.py +++ b/Mailman/app/styles.py @@ -45,6 +45,8 @@ class DefaultStyle: priority = 0 # the lowest priority style def apply(self, mailing_list): + # For cut-n-paste convenience. + mlist = mailing_list # Most of these were ripped from the old MailList.InitVars() method. mlist.volume = 1 mlist.post_id = 1 @@ -248,12 +250,14 @@ class StyleManager: matched_styles = [] for style in self.styles: style.match(mailing_list, matched_styles) - for style in sorted(matched_styles, key=attrgetter('priority')): + for style in matched_styles: yield style @property def styles(self): - for style in sorted(self._styles.values(), key=attrgetter('priority')): + for style in sorted(self._styles.values(), + key=attrgetter('priority'), + reverse=True): yield style def register(self, style): diff --git a/Mailman/docs/styles.txt b/Mailman/docs/styles.txt new file mode 100644 index 000000000..f5d9a807b --- /dev/null +++ b/Mailman/docs/styles.txt @@ -0,0 +1,142 @@ +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. + +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 +to determine whether the style should be applied to a particular mailing list +or not. And finally, application of a style to a mailing list can really +modify the mailing list any way it wants. + +Let's start with a vanilla mailing list and a default style manager. + + >>> from Mailman.configuration import config + >>> from Mailman.database import flush + >>> mlist = config.db.list_manager.create('_xtest@example.com') + >>> from Mailman.app.styles import style_manager + + +The default style +----------------- + +There is a default style which implements the legacy application of list +defaults from Defaults.py. 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. + + >>> default_style = style_manager.get('default') + >>> 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 +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'] + +If the site administrator modified their mailman.cfg file, the default style +would pick this up and apply it to the mailing list. + + >>> print mlist.msg_footer + None + >>> config.DEFAULT_MSG_FOOTER = u'default footer' + >>> default_style.apply(mlist) + >>> flush() + >>> mlist.msg_footer + u'default footer' + + +Registering styles +------------------ + +New styles must implement the IStyle interface. + + >>> from zope.interface import implements + >>> from Mailman.interfaces import IStyle + >>> class TestStyle(object): + ... name = 'test' + ... priority = 10 + ... def apply(self, mailing_list): + ... # Just does something very simple. + ... mailing_list.msg_footer = u'test footer' + ... def match(self, mailing_list, styles): + ... # Applies to any test list + ... if 'test' in mailing_list.fqdn_listname: + ... styles.append(self) + +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 +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)) + ['test'] + >>> for style in style_manager.lookup(mlist): + ... style.apply(mlist) + >>> flush() + >>> mlist.msg_footer + u'test footer' + + +Style priority +-------------- + +When multiple styles match a particular mailing list, they are applied in +descending order of priority. In other words, a priority zero style would be +applied last. + + >>> class AnotherTestStyle(TestStyle): + ... name = 'another' + ... priority = 5 + ... # Use the base class's match() method. + ... def apply(self, mailing_list): + ... mailing_list.msg_footer = u'another footer' + + >>> mlist.msg_footer = u'' + >>> flush() + >>> mlist.msg_footer + u'' + >>> style_manager.register(AnotherTestStyle()) + >>> for style in style_manager.lookup(mlist): + ... style.apply(mlist) + >>> flush() + >>> mlist.msg_footer + u'another footer' + +You can change the priority of a style, and if you reapply the styles, they +will take effect in the new priority order. + + >>> style_1 = style_manager.get('test') + >>> style_1.priority = 5 + >>> style_2 = style_manager.get('another') + >>> style_2.priority = 10 + >>> for style in style_manager.lookup(mlist): + ... style.apply(mlist) + >>> flush() + >>> mlist.msg_footer + u'test footer' + + +Corner cases +------------ + +If you register a style with the same name as an already registered style, you +get an exception. + + >>> style_manager.register(AnotherTestStyle()) + Traceback (most recent call last): + ... + DuplicateStyleError: another |
