summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBarry Warsaw2016-03-24 09:55:18 -0400
committerBarry Warsaw2016-03-24 09:55:18 -0400
commitce9370a537683e6e4e934b8018d0fe3f2aa7f9ac (patch)
tree1c5ac62d66cfa75d6bf7abfb737ae401b49df2a8
parent8169b60bc3d5b771f3676ae12c65f6f92c67a76a (diff)
downloadmailman-ce9370a537683e6e4e934b8018d0fe3f2aa7f9ac.tar.gz
mailman-ce9370a537683e6e4e934b8018d0fe3f2aa7f9ac.tar.zst
mailman-ce9370a537683e6e4e934b8018d0fe3f2aa7f9ac.zip
-rw-r--r--src/mailman/bin/mailman.py42
-rw-r--r--src/mailman/bin/master.py30
-rw-r--r--src/mailman/bin/runner.py13
-rw-r--r--src/mailman/bin/tests/test_mailman.py6
-rw-r--r--src/mailman/bin/tests/test_master.py13
5 files changed, 37 insertions, 67 deletions
diff --git a/src/mailman/bin/mailman.py b/src/mailman/bin/mailman.py
index f9163610b..7a443e9d6 100644
--- a/src/mailman/bin/mailman.py
+++ b/src/mailman/bin/mailman.py
@@ -17,15 +17,11 @@
"""The 'mailman' command dispatcher."""
-__all__ = [
- 'main',
- ]
-
-
import os
import argparse
from functools import cmp_to_key
+from mailman import public
from mailman.core.i18n import _
from mailman.core.initialize import initialize
from mailman.interfaces.command import ICLISubCommand
@@ -34,7 +30,24 @@ from mailman.version import MAILMAN_VERSION_FULL
from zope.interface.verify import verifyObject
-
+# --help should display the subcommands by alphabetical order, except that
+# 'mailman help' should be first.
+def _help_sorter(command, other):
+ """Sorting helper."""
+ if command.name == 'help':
+ return -1
+ elif other.name == 'help':
+ return 1
+ elif command.name < other.name:
+ return -1
+ elif command.name == other.name:
+ return 0
+ else:
+ assert command.name > other.name
+ return 1
+
+
+@public
def main():
"""The `mailman` command dispatcher."""
# Create the basic parser and add all globally common options.
@@ -66,22 +79,7 @@ def main():
command = command_class()
verifyObject(ICLISubCommand, command)
subcommands.append(command)
- # --help should display the subcommands by alphabetical order, except that
- # 'mailman help' should be first.
- def sort_function(command, other):
- """Sorting helper."""
- if command.name == 'help':
- return -1
- elif other.name == 'help':
- return 1
- elif command.name < other.name:
- return -1
- elif command.name == other.name:
- return 0
- else:
- assert command.name > other.name
- return 1
- subcommands.sort(key=cmp_to_key(sort_function))
+ subcommands.sort(key=cmp_to_key(_help_sorter))
for command in subcommands:
command_parser = subparser.add_parser(
command.name, help=_(command.__doc__))
diff --git a/src/mailman/bin/master.py b/src/mailman/bin/master.py
index 7adba8f4a..77caf6966 100644
--- a/src/mailman/bin/master.py
+++ b/src/mailman/bin/master.py
@@ -17,12 +17,6 @@
"""Master subprocess watcher."""
-__all__ = [
- 'Loop',
- 'main',
- ]
-
-
import os
import sys
import errno
@@ -34,6 +28,7 @@ from datetime import timedelta
from enum import Enum
from flufl.lock import Lock, NotLockedError, TimeOutError
from lazr.config import as_boolean
+from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.core.logging import reopen
@@ -52,7 +47,6 @@ PRESERVE_ENVS = (
)
-
class MasterOptions(Options):
"""Options for the master watcher."""
@@ -111,7 +105,6 @@ given. The values for -r are passed straight through to bin/runner."""))
self.parser.error(_('Too many arguments'))
-
class WatcherState(Enum):
"""Enum for the state of the master process watcher."""
# No lock has been acquired by any process.
@@ -200,7 +193,7 @@ The master lock could not be acquired because it appears as though another
master is already running.""")
elif status is WatcherState.stale_lock:
# Hostname matches but the process does not exist.
- program = sys.argv[0]
+ program = sys.argv[0] # flake8: noqa
message = _("""\
The master lock could not be acquired. It appears as though there is a stale
master lock. Try re-running $program with the --force flag.""")
@@ -231,7 +224,6 @@ Exiting.""")
config.options.parser.error(message)
-
class PIDWatcher:
"""A class which safely manages child process ids."""
@@ -291,7 +283,7 @@ class PIDWatcher:
return self._pids.pop(pid, None)
-
+@public
class Loop:
"""Main control loop class."""
@@ -307,33 +299,33 @@ class Loop:
# Set up our signal handlers. Also set up a SIGALRM handler to
# refresh the lock once per day. The lock lifetime is 1 day + 6 hours
# so this should be plenty.
- def sigalrm_handler(signum, frame):
+ def sigalrm_handler(signum, frame): # flake8: noqa
self._lock.refresh()
signal.alarm(SECONDS_IN_A_DAY)
signal.signal(signal.SIGALRM, sigalrm_handler)
signal.alarm(SECONDS_IN_A_DAY)
# SIGHUP tells the runners to close and reopen their log files.
- def sighup_handler(signum, frame):
+ def sighup_handler(signum, frame): # flake8: noqa
reopen()
for pid in self._kids:
os.kill(pid, signal.SIGHUP)
log.info('Master watcher caught SIGHUP. Re-opening log files.')
signal.signal(signal.SIGHUP, sighup_handler)
# SIGUSR1 is used by 'mailman restart'.
- def sigusr1_handler(signum, frame):
+ def sigusr1_handler(signum, frame): # flake8: noqa
for pid in self._kids:
os.kill(pid, signal.SIGUSR1)
log.info('Master watcher caught SIGUSR1. Exiting.')
signal.signal(signal.SIGUSR1, sigusr1_handler)
# SIGTERM is what init will kill this process with when changing run
# levels. It's also the signal 'mailman stop' uses.
- def sigterm_handler(signum, frame):
+ def sigterm_handler(signum, frame): # flake8: noqa
for pid in self._kids:
os.kill(pid, signal.SIGTERM)
log.info('Master watcher caught SIGTERM. Exiting.')
signal.signal(signal.SIGTERM, sigterm_handler)
# SIGINT is what control-C gives.
- def sigint_handler(signum, frame):
+ def sigint_handler(signum, frame): # flake8: noqa
for pid in self._kids:
os.kill(pid, signal.SIGINT)
log.info('Master watcher caught SIGINT. Restarting.')
@@ -401,8 +393,8 @@ class Loop:
for runner_config in config.runner_configs:
# Strip off the 'runner.' prefix.
assert runner_config.name.startswith('runner.'), (
- 'Unexpected runner configuration section name: {0}'.format(
- runner_config.name))
+ 'Unexpected runner configuration section name: {}'.format(
+ runner_config.name))
runner_names.append(runner_config.name[7:])
# For each runner we want to start, find their config section, which
# will tell us the name of the class to instantiate, along with the
@@ -522,7 +514,7 @@ Runner {0} reached maximum restart limit of {1:d}, not restarting.""",
raise
-
+@public
def main():
"""Main process."""
diff --git a/src/mailman/bin/runner.py b/src/mailman/bin/runner.py
index d74fe10da..928365237 100644
--- a/src/mailman/bin/runner.py
+++ b/src/mailman/bin/runner.py
@@ -17,11 +17,6 @@
"""The runner process."""
-__all__ = [
- 'main',
- ]
-
-
import os
import sys
import signal
@@ -29,6 +24,7 @@ import logging
import argparse
import traceback
+from mailman import public
from mailman.config import config
from mailman.core.i18n import _
from mailman.core.initialize import initialize
@@ -45,7 +41,6 @@ if os.environ.get('COVERAGE_PROCESS_START') is not None:
coverage.process_startup()
-
class ROptionAction(argparse.Action):
"""Callback for -r/--runner option."""
def __call__(self, parser, namespace, values, option_string=None):
@@ -65,7 +60,6 @@ class ROptionAction(argparse.Action):
setattr(namespace, self.dest, (runner, rslice, rrange))
-
def make_runner(name, slice, range, once=False):
# Several conventions for specifying the runner name are supported. It
# could be one of the shortcut names. If the name is a full module path,
@@ -100,7 +94,7 @@ def make_runner(name, slice, range, once=False):
return runner_class(name, slice)
-
+@public
def main():
global log
@@ -192,7 +186,8 @@ def main():
longest = max(len(name) for name in descriptions)
for shortname in sorted(descriptions):
classname = descriptions[shortname]
- name = (' ' * (longest - len(shortname))) + shortname
+ spaces = longest - len(shortname)
+ name = (' ' * spaces) + shortname # flake8: noqa
print(_('$name runs $classname'))
sys.exit(0)
diff --git a/src/mailman/bin/tests/test_mailman.py b/src/mailman/bin/tests/test_mailman.py
index 282432030..7c9d2f2bc 100644
--- a/src/mailman/bin/tests/test_mailman.py
+++ b/src/mailman/bin/tests/test_mailman.py
@@ -17,11 +17,6 @@
"""Test mailman command utilities."""
-__all__ = [
- 'TestMailmanCommand',
- ]
-
-
import unittest
from io import StringIO
@@ -29,7 +24,6 @@ from mailman.bin.mailman import main
from unittest.mock import patch
-
class TestMailmanCommand(unittest.TestCase):
def test_mailman_command_without_subcommand_prints_help(self):
# Issue #137: Running `mailman` without a subcommand raises an
diff --git a/src/mailman/bin/tests/test_master.py b/src/mailman/bin/tests/test_master.py
index 50f4d1ab5..32dbbceed 100644
--- a/src/mailman/bin/tests/test_master.py
+++ b/src/mailman/bin/tests/test_master.py
@@ -17,22 +17,16 @@
"""Test master watcher utilities."""
-__all__ = [
- 'TestMasterLock',
- ]
-
-
import os
-import errno
import tempfile
import unittest
+from contextlib import suppress
from datetime import timedelta
from flufl.lock import Lock
from mailman.bin import master
-
class TestMasterLock(unittest.TestCase):
def setUp(self):
fd, self.lock_file = tempfile.mkstemp()
@@ -43,11 +37,8 @@ class TestMasterLock(unittest.TestCase):
def tearDown(self):
# Unlocking removes the lock file, but just to be safe (i.e. in case
# of errors).
- try:
+ with suppress(FileNotFoundError):
os.remove(self.lock_file)
- except OSError as error:
- if error.errno != errno.ENOENT:
- raise
def test_acquire_lock_1(self):
lock = master.acquire_lock_1(False, self.lock_file)