diff options
| author | Barry Warsaw | 2008-01-01 13:49:27 -0500 |
|---|---|---|
| committer | Barry Warsaw | 2008-01-01 13:49:27 -0500 |
| commit | adae635a4ca147937019fdd91aebd95a2769b9ca (patch) | |
| tree | 7cdae81b4b7715781e889f32bbd0dbba80609367 | |
| parent | 5b4bb22feca4d520afef44d1c472807e020d17b5 (diff) | |
| download | mailman-adae635a4ca147937019fdd91aebd95a2769b9ca.tar.gz mailman-adae635a4ca147937019fdd91aebd95a2769b9ca.tar.zst mailman-adae635a4ca147937019fdd91aebd95a2769b9ca.zip | |
Extended test_documentation.py to be able to find doctests in subdirectories
called 'docs' anywhere under the Mailman package. Change the rule API to
return rule classes not instances. Added the ChainJump enum, though this will
likely change soon.
Diffstat (limited to '')
| -rw-r--r-- | Mailman/app/rules.py | 4 | ||||
| -rw-r--r-- | Mailman/interfaces/rules.py | 21 | ||||
| -rw-r--r-- | Mailman/rules/__init__.py | 6 | ||||
| -rw-r--r-- | Mailman/rules/administrivia.py | 7 | ||||
| -rw-r--r-- | Mailman/rules/approved.py | 6 | ||||
| -rw-r--r-- | Mailman/rules/docs/administrivia.txt (renamed from Mailman/docs/administrivia.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/approve.txt (renamed from Mailman/docs/approve.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/implicit-dest.txt (renamed from Mailman/docs/implicit-dest.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/loop.txt (renamed from Mailman/docs/loop.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/max-size.txt (renamed from Mailman/docs/max-size.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/moderation.txt (renamed from Mailman/docs/moderation.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/news-moderation.txt (renamed from Mailman/docs/news-moderation.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/no-subject.txt (renamed from Mailman/docs/no-subject.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/recipients.txt (renamed from Mailman/docs/recipients.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/docs/rules.txt (renamed from Mailman/docs/rules.txt) | 3 | ||||
| -rw-r--r-- | Mailman/rules/docs/suspicious.txt (renamed from Mailman/docs/suspicious.txt) | 0 | ||||
| -rw-r--r-- | Mailman/rules/emergency.py | 5 | ||||
| -rw-r--r-- | Mailman/rules/implicit_dest.py | 6 | ||||
| -rw-r--r-- | Mailman/rules/loop.py | 6 | ||||
| -rw-r--r-- | Mailman/rules/max_recipients.py | 6 | ||||
| -rw-r--r-- | Mailman/rules/max_size.py | 6 | ||||
| -rw-r--r-- | Mailman/rules/moderation.py | 9 | ||||
| -rw-r--r-- | Mailman/rules/news_moderation.py (renamed from Mailman/rules/new_moderation.py) | 6 | ||||
| -rw-r--r-- | Mailman/rules/no_subject.py | 6 | ||||
| -rw-r--r-- | Mailman/rules/suspicious.py | 6 | ||||
| -rw-r--r-- | Mailman/tests/test_documentation.py | 28 |
26 files changed, 57 insertions, 74 deletions
diff --git a/Mailman/app/rules.py b/Mailman/app/rules.py index 37f5d9af4..e4c3c8c40 100644 --- a/Mailman/app/rules.py +++ b/Mailman/app/rules.py @@ -45,7 +45,7 @@ def process(mlist, msg, msgdata, rule_set=None): # Now process all rules, returning the set of rules that match. rule_matches = set() for rule in rules: - if rule.check(mlist, msg, msgdata): + if rule().check(mlist, msg, msgdata): rule_matches.add(rule.name) return rule_matches @@ -60,5 +60,5 @@ def find_rule(rule_name): for rule_set_class in get_plugins('mailman.rules'): rule = rule_set_class().get(rule_name) if rule is not None: - return rule + return rule() return None diff --git a/Mailman/interfaces/rules.py b/Mailman/interfaces/rules.py index 13edcf481..c023acf6b 100644 --- a/Mailman/interfaces/rules.py +++ b/Mailman/interfaces/rules.py @@ -17,10 +17,25 @@ """Interface describing the basics of rules.""" +from munepy import Enum from zope.interface import Interface, Attribute +class ChainJump(Enum): + # Allow the next rule in the chain to be run. + defer = 0 + # Jump to the 'accept' chain. + accept = 1 + # Jump to the 'hold' chain. + hold = 2 + # Jump to the 'reject' chain. + reject = 3 + # Jump to the 'discard' chain. + discard = 4 + + + class DuplicateRuleError(Exception): """A rule or rule name is added to a processor more than once.""" @@ -35,10 +50,14 @@ class IRule(Interface): def check(mlist, msg, msgdata): """Run the rule. + The effects of running the rule can be as simple as appending the rule + name to `msgdata['rules']` when the rule matches. The rule is allowed + to do other things, such as modify the message or metadata. + :param mlist: The mailing list object. :param msg: The message object. :param msgdata: The message metadata. - :return: A boolean specifying whether the rule was matched or not. + :return: A chain to jump to, i.e. an ChainJump enum. """ diff --git a/Mailman/rules/__init__.py b/Mailman/rules/__init__.py index 2d2f5d0a8..2a1e2ec2b 100644 --- a/Mailman/rules/__init__.py +++ b/Mailman/rules/__init__.py @@ -44,11 +44,11 @@ class BuiltinRules: if extension <> '.py': continue module_name = mypackage + '.' + basename - __import__(module_name) + __import__(module_name, fromlist='*') module = sys.modules[module_name] - for name in dir(module): + for name in module.__all__: rule = getattr(module, name) - if IRule.providedBy(rule): + if IRule.implementedBy(rule): if rule.name in self._rules or rule in rule_set: raise DuplicateRuleError(rule.name) self._rules[rule.name] = rule diff --git a/Mailman/rules/administrivia.py b/Mailman/rules/administrivia.py index 422503c71..589c4a56b 100644 --- a/Mailman/rules/administrivia.py +++ b/Mailman/rules/administrivia.py @@ -17,7 +17,7 @@ """The administrivia rule.""" -__all__ = ['administrivia_rule'] +__all__ = ['Administrivia'] __metaclass__ = type @@ -95,8 +95,3 @@ class Administrivia: if minargs <= len(words) - 1 <= maxargs: return True return False - - - -administrivia_rule = Administrivia() - diff --git a/Mailman/rules/approved.py b/Mailman/rules/approved.py index b9b041c2e..98b158dd9 100644 --- a/Mailman/rules/approved.py +++ b/Mailman/rules/approved.py @@ -17,7 +17,7 @@ """Look for moderator pre-approval.""" -__all__ = ['approve_rule'] +__all__ = ['Approved'] __metaclass__ = type @@ -114,7 +114,3 @@ def reset_payload(part, payload): part.set_param('Format', format) if delsp: part.set_param('DelSp', delsp) - - - -approve_rule = Approved() diff --git a/Mailman/docs/administrivia.txt b/Mailman/rules/docs/administrivia.txt index 0e48fdd1b..0e48fdd1b 100644 --- a/Mailman/docs/administrivia.txt +++ b/Mailman/rules/docs/administrivia.txt diff --git a/Mailman/docs/approve.txt b/Mailman/rules/docs/approve.txt index ea07058f8..ea07058f8 100644 --- a/Mailman/docs/approve.txt +++ b/Mailman/rules/docs/approve.txt diff --git a/Mailman/docs/implicit-dest.txt b/Mailman/rules/docs/implicit-dest.txt index b6fed2769..b6fed2769 100644 --- a/Mailman/docs/implicit-dest.txt +++ b/Mailman/rules/docs/implicit-dest.txt diff --git a/Mailman/docs/loop.txt b/Mailman/rules/docs/loop.txt index 3174805b9..3174805b9 100644 --- a/Mailman/docs/loop.txt +++ b/Mailman/rules/docs/loop.txt diff --git a/Mailman/docs/max-size.txt b/Mailman/rules/docs/max-size.txt index b477ecd2b..b477ecd2b 100644 --- a/Mailman/docs/max-size.txt +++ b/Mailman/rules/docs/max-size.txt diff --git a/Mailman/docs/moderation.txt b/Mailman/rules/docs/moderation.txt index 0ce6bee6e..0ce6bee6e 100644 --- a/Mailman/docs/moderation.txt +++ b/Mailman/rules/docs/moderation.txt diff --git a/Mailman/docs/news-moderation.txt b/Mailman/rules/docs/news-moderation.txt index f69fbb33d..f69fbb33d 100644 --- a/Mailman/docs/news-moderation.txt +++ b/Mailman/rules/docs/news-moderation.txt diff --git a/Mailman/docs/no-subject.txt b/Mailman/rules/docs/no-subject.txt index 3c6dc88bf..3c6dc88bf 100644 --- a/Mailman/docs/no-subject.txt +++ b/Mailman/rules/docs/no-subject.txt diff --git a/Mailman/docs/recipients.txt b/Mailman/rules/docs/recipients.txt index 98176c8bb..98176c8bb 100644 --- a/Mailman/docs/recipients.txt +++ b/Mailman/rules/docs/recipients.txt diff --git a/Mailman/docs/rules.txt b/Mailman/rules/docs/rules.txt index dbf009eeb..4e5db7012 100644 --- a/Mailman/docs/rules.txt +++ b/Mailman/rules/docs/rules.txt @@ -32,6 +32,7 @@ You can iterator over all the rules in a rule set. >>> rule = None >>> for rule in rule_set.rules: ... if rule.name == 'emergency': + ... rule = rule() ... break >>> verifyObject(IRule, rule) True @@ -80,7 +81,7 @@ For example, the emergency rule just checks to see if the emergency flag is set on the mailing list, and the message has not been pre-approved by the list administrator. - >>> rule = rule_set['emergency'] + >>> rule = rule_set['emergency']() >>> rule.name 'emergency' >>> mlist.emergency = False diff --git a/Mailman/docs/suspicious.txt b/Mailman/rules/docs/suspicious.txt index 8646e1b81..8646e1b81 100644 --- a/Mailman/docs/suspicious.txt +++ b/Mailman/rules/docs/suspicious.txt diff --git a/Mailman/rules/emergency.py b/Mailman/rules/emergency.py index 989e4fff7..e51612940 100644 --- a/Mailman/rules/emergency.py +++ b/Mailman/rules/emergency.py @@ -17,7 +17,7 @@ """The emergency hold rule.""" -__all__ = ['emergency_rule'] +__all__ = ['Emergency'] __metaclass__ = type @@ -40,6 +40,3 @@ the list administrator.""") def check(self, mlist, msg, msgdata): """See `IRule`.""" return mlist.emergency and not msgdata.get('adminapproved') - - -emergency_rule = Emergency() diff --git a/Mailman/rules/implicit_dest.py b/Mailman/rules/implicit_dest.py index e056a2e9e..19a096aa5 100644 --- a/Mailman/rules/implicit_dest.py +++ b/Mailman/rules/implicit_dest.py @@ -17,7 +17,7 @@ """The implicit destination rule.""" -__all__ = ['implicit_dest'] +__all__ = ['ImplicitDestination'] __metaclass__ = type @@ -92,7 +92,3 @@ class ImplicitDestination: pass # Nothing matched. return True - - - -implicit_dest = ImplicitDestination() diff --git a/Mailman/rules/loop.py b/Mailman/rules/loop.py index 77cedb0a6..a88858d6a 100644 --- a/Mailman/rules/loop.py +++ b/Mailman/rules/loop.py @@ -17,7 +17,7 @@ """Look for a posting loop.""" -__all__ = ['loop_rule'] +__all__ = ['Loop'] __metaclass__ = type @@ -41,7 +41,3 @@ class Loop: been_theres = [value.strip().lower() for value in msg.get_all('x-beenthere', [])] return mlist.posting_address in been_theres - - - -loop_rule = Loop() diff --git a/Mailman/rules/max_recipients.py b/Mailman/rules/max_recipients.py index 6e3451e4e..dfa23f659 100644 --- a/Mailman/rules/max_recipients.py +++ b/Mailman/rules/max_recipients.py @@ -17,7 +17,7 @@ """The maximum number of recipients rule.""" -__all__ = ['max_recipients_rule'] +__all__ = ['MaximumRecipients'] __metaclass__ = type @@ -45,7 +45,3 @@ class MaximumRecipients: recipients = getaddresses(msg.get_all('to', []) + msg.get_all('cc', [])) return len(recipients) >= mlist.max_num_recipients - - - -max_recipients_rule = MaximumRecipients() diff --git a/Mailman/rules/max_size.py b/Mailman/rules/max_size.py index 1e62b2ad8..b723fbf07 100644 --- a/Mailman/rules/max_size.py +++ b/Mailman/rules/max_size.py @@ -17,7 +17,7 @@ """The maximum message size rule.""" -__all__ = ['max_size'] +__all__ = ['MaximumSize'] __metaclass__ = type @@ -43,7 +43,3 @@ class MaximumSize: 'Message was not sized on initial parsing.') # The maximum size is specified in 1024 bytes. return msg.original_size / 1024.0 > mlist.max_message_size - - - -max_size = MaximumSize() diff --git a/Mailman/rules/moderation.py b/Mailman/rules/moderation.py index 5b0820426..9fa7cd34d 100644 --- a/Mailman/rules/moderation.py +++ b/Mailman/rules/moderation.py @@ -18,8 +18,8 @@ """Membership related rules.""" __all__ = [ - 'moderation_rule', - 'nonmember_rule', + 'Moderation', + 'NonMember', ] __metaclass__ = type @@ -62,8 +62,3 @@ class NonMember: # The sender is a member of the mailing list. return False return True - - - -moderation_rule = Moderation() -nonmember_rule = NonMember() diff --git a/Mailman/rules/new_moderation.py b/Mailman/rules/news_moderation.py index dc42dcbb7..9caf8fb4a 100644 --- a/Mailman/rules/new_moderation.py +++ b/Mailman/rules/news_moderation.py @@ -17,7 +17,7 @@ """The news moderation rule.""" -__all__ = ['news_moderation'] +__all__ = ['ModeratedNewsgroup'] __metaclass__ = type @@ -40,7 +40,3 @@ newsgroup.""") def check(self, mlist, msg, msgdata): """See `IRule`.""" return mlist.news_moderation == NewsModeration.moderated - - - -news_moderation = ModeratedNewsgroup() diff --git a/Mailman/rules/no_subject.py b/Mailman/rules/no_subject.py index ca7cbd9d2..c36d742b8 100644 --- a/Mailman/rules/no_subject.py +++ b/Mailman/rules/no_subject.py @@ -17,7 +17,7 @@ """The no-Subject header rule.""" -__all__ = ['no_subject_rule'] +__all__ = ['NoSubject'] __metaclass__ = type @@ -39,7 +39,3 @@ class NoSubject: """See `IRule`.""" subject = msg.get('subject', '').strip() return subject == '' - - - -no_subject_rule = NoSubject() diff --git a/Mailman/rules/suspicious.py b/Mailman/rules/suspicious.py index 6384f8b9e..0464a6336 100644 --- a/Mailman/rules/suspicious.py +++ b/Mailman/rules/suspicious.py @@ -17,7 +17,7 @@ """The historical 'suspicious header' rule.""" -__all__ = ['suspicious_header'] +__all__ = ['SuspiciousHeader'] __metaclass__ = type @@ -90,7 +90,3 @@ def has_matching_bounce_header(mlist, msg): if cre.search(value): return True return False - - - -suspicious_header = SuspiciousHeader() diff --git a/Mailman/tests/test_documentation.py b/Mailman/tests/test_documentation.py index 36b3c7ecb..9faf1d588 100644 --- a/Mailman/tests/test_documentation.py +++ b/Mailman/tests/test_documentation.py @@ -31,6 +31,7 @@ from Mailman.app.styles import style_manager from Mailman.configuration import config +DOT = '.' COMMASPACE = ', ' @@ -78,7 +79,12 @@ def cleaning_teardown(testobj): def test_suite(): suite = unittest.TestSuite() - docsdir = os.path.join(os.path.dirname(Mailman.__file__), 'docs') + topdir = os.path.dirname(Mailman.__file__) + packages = [] + for dirpath, dirnames, filenames in os.walk(topdir): + if 'docs' in dirnames: + docsdir = os.path.join(dirpath, 'docs')[len(topdir)+1:] + packages.append(docsdir) # Under higher verbosity settings, report all doctest errors, not just the # first one. flags = (doctest.ELLIPSIS | @@ -86,13 +92,15 @@ def test_suite(): doctest.REPORT_NDIFF) if config.opts.verbosity <= 2: flags |= doctest.REPORT_ONLY_FIRST_FAILURE - for filename in os.listdir(docsdir): - if os.path.splitext(filename)[1] == '.txt': - test = doctest.DocFileSuite( - 'docs/' + filename, - package=Mailman, - optionflags=flags, - setUp=setup, - tearDown=cleaning_teardown) - suite.addTest(test) + # Add all the doctests in all subpackages. + for docsdir in packages: + for filename in os.listdir(os.path.join('Mailman', docsdir)): + if os.path.splitext(filename)[1] == '.txt': + test = doctest.DocFileSuite( + os.path.join(docsdir, filename), + package='Mailman', + optionflags=flags, + setUp=setup, + tearDown=cleaning_teardown) + suite.addTest(test) return suite |
