diff options
| -rw-r--r-- | port_me/bumpdigests.py | 74 | ||||
| -rw-r--r-- | src/mailman/app/digests.py | 7 | ||||
| -rw-r--r-- | src/mailman/commands/cli_digests.py | 42 | ||||
| -rw-r--r-- | src/mailman/commands/tests/test_digests.py | 89 |
4 files changed, 110 insertions, 102 deletions
diff --git a/port_me/bumpdigests.py b/port_me/bumpdigests.py deleted file mode 100644 index f30772ca8..000000000 --- a/port_me/bumpdigests.py +++ /dev/null @@ -1,74 +0,0 @@ -# Copyright (C) 1998-2015 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/>. - -import sys -import optparse - -from mailman import errors -from mailman import MailList -from mailman.configuration import config -from mailman.core.i18n import _ -from mailman.version import MAILMAN_VERSION - -# Work around known problems with some RedHat cron daemons -import signal -signal.signal(signal.SIGCHLD, signal.SIG_DFL) - - - -def parseargs(): - parser = optparse.OptionParser(version=MAILMAN_VERSION, - usage=_("""\ -%prog [options] [listname ...] - -Increment the digest volume number and reset the digest number to one. All -the lists named on the command line are bumped. If no list names are given, -all lists are bumped.""")) - parser.add_option('-C', '--config', - help=_('Alternative configuration file to use')) - opts, args = parser.parse_args() - return opts, args, parser - - - -def main(): - opts, args, parser = parseargs() - config.load(opts.config) - - listnames = set(args or config.list_manager.names) - if not listnames: - print(_('Nothing to do.')) - sys.exit(0) - - for listname in listnames: - try: - # Be sure the list is locked - mlist = MailList.MailList(listname) - except errors.MMListError: - parser.print_help() - print(_('No such list: $listname'), file=sys.stderr) - sys.exit(1) - try: - mlist.bump_digest_volume() - finally: - mlist.Save() - mlist.Unlock() - - - -if __name__ == '__main__': - main() diff --git a/src/mailman/app/digests.py b/src/mailman/app/digests.py index b66a4c54c..2190fdf98 100644 --- a/src/mailman/app/digests.py +++ b/src/mailman/app/digests.py @@ -28,9 +28,7 @@ import os from mailman.config import config from mailman.email.message import Message from mailman.interfaces.digests import DigestFrequency -from mailman.interfaces.listmanager import IListManager from mailman.utilities.datetime import now as right_now -from zope.component import getUtility @@ -95,7 +93,10 @@ def maybe_send_digest_now(mlist, force=False): # us exactly how big the resulting MIME and rfc1153 digest will # actually be, but it's the most easily available metric to decide # whether the size threshold has been reached. - size = os.path.getsize(mailbox_path) + try: + size = os.path.getsize(mailbox_path) + except FileNotFoundError: + size = 0 if (size >= mlist.digest_size_threshold * 1024.0 or (force and size > 0)): # Send the digest. Because we don't want to hold up this process diff --git a/src/mailman/commands/cli_digests.py b/src/mailman/commands/cli_digests.py index 9af91f1c3..7d3de92b9 100644 --- a/src/mailman/commands/cli_digests.py +++ b/src/mailman/commands/cli_digests.py @@ -24,7 +24,8 @@ __all__ = [ import sys -from mailman.app.digests import maybe_send_digest_now +from mailman.app.digests import ( + bump_digest_number_and_volume, maybe_send_digest_now) from mailman.core.i18n import _ from mailman.interfaces.command import ICLISubCommand from mailman.interfaces.listmanager import IListManager @@ -59,33 +60,28 @@ class Digests: default=False, action='store_true', help=_("""Increment the digest volume number and reset the digest number to one. If given with --send, the volume number is - incremented after any current digests are sent.""")) + incremented before any current digests are sent.""")) def process(self, args): """See `ICLISubCommand`.""" list_manager = getUtility(IListManager) - if args.send: - if not args.lists: - # Send the digests for every list. - for mlist in list_manager.mailing_lists: - maybe_send_digest_now(mlist, force=True) - return - for list_spec in args.lists: + if args.lists: + lists = [] + for spec in args.lists: # We'll accept list-ids or fqdn list names. - if '@' in list_spec: - mlist = list_manager.get(list_spec) + if '@' in spec: + mlist = list_manager.get(spec) else: - mlist = list_manager.get_by_list_id(list_spec) + mlist = list_manager.get_by_list_id(spec) if mlist is None: - print(_('No such list found: $list_spec'), file=sys.stderr) - continue - maybe_send_digest_now(mlist, force=True) - if args.bump: - if not args.lists: - mlists = list(list_manager.mailing_lists) - else: - # We'll accept list-ids or fqdn list names. - if '@' in list_spec: - mlist = list_manager.get(list_spec) + print(_('No such list found: $spec'), file=sys.stderr) else: - mlist = list_manager.get_by_list_id(list_spec) + lists.append(mlist) + else: + lists = list(list_manager.mailing_lists) + if args.bump: + for mlist in lists: + bump_digest_number_and_volume(mlist) + if args.send: + for mlist in lists: + maybe_send_digest_now(mlist, force=True) diff --git a/src/mailman/commands/tests/test_digests.py b/src/mailman/commands/tests/test_digests.py index 2640580af..607949f6e 100644 --- a/src/mailman/commands/tests/test_digests.py +++ b/src/mailman/commands/tests/test_digests.py @@ -18,6 +18,7 @@ """Test the send-digests subcommand.""" __all__ = [ + 'TestBumpVolume', 'TestSendDigests', ] @@ -25,16 +26,19 @@ __all__ = [ import os import unittest +from datetime import timedelta from io import StringIO from mailman.app.lifecycle import create_list from mailman.commands.cli_digests import Digests from mailman.config import config +from mailman.interfaces.digests import DigestFrequency from mailman.interfaces.member import DeliveryMode from mailman.runners.digest import DigestRunner from mailman.testing.helpers import ( get_queue_messages, make_testable_runner, specialized_message_from_string as mfs, subscribe) from mailman.testing.layers import ConfigLayer +from mailman.utilities.datetime import now as right_now from unittest.mock import patch @@ -48,8 +52,6 @@ class FakeArgs: class TestSendDigests(unittest.TestCase): - """Test the send-digests subcommand.""" - layer = ConfigLayer def setUp(self): @@ -361,3 +363,86 @@ Subject: message 3 digest_contents = str(bee) self.assertIn('Subject: message 3', digest_contents) self.assertIn('Subject: message 4', digest_contents) + + def test_send_no_digest_ready(self): + # If no messages have been sent through the mailing list, no digest + # can be sent. + mailbox_path = os.path.join(self._mlist.data_path, 'digest.mmdf') + self.assertFalse(os.path.exists(mailbox_path)) + args = FakeArgs() + args.send = True + args.lists.append('ant.example.com') + self._command.process(args) + self._runner.run() + items = get_queue_messages('virgin') + self.assertEqual(len(items), 0) + + def test_bump_after_send(self): + self._mlist.digest_volume_frequency = DigestFrequency.monthly + self._mlist.volume = 7 + self._mlist.next_digest_number = 4 + self._mlist.digest_last_sent_at = right_now() + timedelta( + days=-32) + msg = mfs("""\ +To: ant@example.com +From: anne@example.com +Subject: message 1 + +""") + self._handler.process(self._mlist, msg, {}) + args = FakeArgs() + args.bump = True + args.send = True + args.lists.append('ant.example.com') + self._command.process(args) + self._runner.run() + # The volume is 8 and the digest number is 2 because a digest was sent + # after the volume/number was bumped. + self.assertEqual(self._mlist.volume, 8) + self.assertEqual(self._mlist.next_digest_number, 2) + self.assertEqual(self._mlist.digest_last_sent_at, right_now()) + items = get_queue_messages('virgin') + self.assertEqual(len(items), 1) + self.assertEqual(items[0].msg['subject'], 'Ant Digest, Vol 8, Issue 1') + + + +class TestBumpVolume(unittest.TestCase): + layer = ConfigLayer + + def setUp(self): + self._mlist = create_list('ant@example.com') + self._mlist.digest_volume_frequency = DigestFrequency.monthly + self._mlist.volume = 7 + self._mlist.next_digest_number = 4 + self.right_now = right_now() + self._command = Digests() + + def test_bump_one_list(self): + self._mlist.digest_last_sent_at = self.right_now + timedelta( + days=-32) + args = FakeArgs() + args.bump = True + args.lists.append('ant.example.com') + self._command.process(args) + self.assertEqual(self._mlist.volume, 8) + self.assertEqual(self._mlist.next_digest_number, 1) + self.assertEqual(self._mlist.digest_last_sent_at, self.right_now) + + def test_bump_two_lists(self): + self._mlist.digest_last_sent_at = self.right_now + timedelta( + days=-32) + # Create the second list. + bee = create_list('bee@example.com') + bee.digest_volume_frequency = DigestFrequency.monthly + bee.volume = 7 + bee.next_digest_number = 4 + bee.digest_last_sent_at = self.right_now + timedelta( + days=-32) + args = FakeArgs() + args.bump = True + args.lists.extend(('ant.example.com', 'bee.example.com')) + self._command.process(args) + self.assertEqual(self._mlist.volume, 8) + self.assertEqual(self._mlist.next_digest_number, 1) + self.assertEqual(self._mlist.digest_last_sent_at, self.right_now) |
