diff options
| author | Barry Warsaw | 2008-03-22 21:43:38 -0400 |
|---|---|---|
| committer | Barry Warsaw | 2008-03-22 21:43:38 -0400 |
| commit | 78aeaf14e41c473655267d8a0fad175c783012e7 (patch) | |
| tree | 6a65a11c73c163299860d07409212e8215fe9165 | |
| parent | 6d9084326a4470da44c15193ddf0c4573fccb7f9 (diff) | |
| download | mailman-78aeaf14e41c473655267d8a0fad175c783012e7.tar.gz mailman-78aeaf14e41c473655267d8a0fad175c783012e7.tar.zst mailman-78aeaf14e41c473655267d8a0fad175c783012e7.zip | |
| -rw-r--r-- | mailman/bin/__init__.py | 2 | ||||
| -rw-r--r-- | mailman/bin/create_list.py (renamed from mailman/bin/newlist.py) | 99 | ||||
| -rw-r--r-- | mailman/bin/list_lists.py | 72 | ||||
| -rw-r--r-- | mailman/bin/master.py | 9 | ||||
| -rw-r--r-- | mailman/bin/qrunner.py | 17 | ||||
| -rw-r--r-- | mailman/options.py | 59 |
6 files changed, 150 insertions, 108 deletions
diff --git a/mailman/bin/__init__.py b/mailman/bin/__init__.py index f40c09d74..7c6b0b482 100644 --- a/mailman/bin/__init__.py +++ b/mailman/bin/__init__.py @@ -26,6 +26,7 @@ __all__ = [ 'cleanarch', 'config_list', 'confirm', + 'create_list', 'disabled', 'dumpdb', 'export', @@ -43,7 +44,6 @@ __all__ = [ 'make_instance', 'master', 'mmsitepass', - 'newlist', 'nightly_gzip', 'owner', 'post', diff --git a/mailman/bin/newlist.py b/mailman/bin/create_list.py index 447b66f4a..8cec2755c 100644 --- a/mailman/bin/newlist.py +++ b/mailman/bin/create_list.py @@ -17,30 +17,24 @@ from __future__ import with_statement -import sha import sys -import getpass -import datetime -import optparse from mailman import Errors from mailman import Message from mailman import Utils -from mailman import Version from mailman import i18n from mailman.app.lifecycle import create_list from mailman.configuration import config -from mailman.initialize import initialize from mailman.interfaces import ListAlreadyExistsError +from mailman.options import SingleMailingListOptions _ = i18n._ -def parseargs(): - parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, - usage=_("""\ +class ScriptOptions(SingleMailingListOptions): + usage=_("""\ %prog [options] fqdn_listname Create a new mailing list. @@ -49,79 +43,78 @@ fqdn_listname is the 'fully qualified list name', basically the posting address of the list. It must be a valid email address and the domain must be registered with Mailman. -Note that listnames are forced to lowercase.""")) - parser.add_option('-l', '--language', - type='string', action='store', - help=_("""\ +Note that listnames are forced to lowercase.""") + + def add_options(self): + super(ScriptOptions, self).add_options() + self.parser.add_option( + '--language', + type='unicode', action='store', + help=_("""\ Make the list's preferred language LANGUAGE, which must be a two letter language code.""")) - parser.add_option('-o', '--owner', - type='string', action='append', default=[], - dest='owners', help=_("""\ + self.parser.add_option( + '-o', '--owner', + type='unicode', action='append', default=[], + dest='owners', help=_("""\ Specific a listowner email address. If the address is not currently registered with Mailman, the address is registered and linked to a user. Mailman will send a confirmation message to the address, but it will also send a list creation notice to the address. More than one owner can be specified.""")) - parser.add_option('-q', '--quiet', - default=False, action='store_true', - help=_("""\ + self.parser.add_option( + '-q', '--quiet', + default=False, action='store_true', + help=_("""\ Normally the administrator is notified by email (after a prompt) that their list has been created. This option suppresses the prompt and notification.""")) - parser.add_option('-a', '--automate', - default=False, action='store_true', - help=_("""\ + self.parser.add_option( + '-a', '--automate', + default=False, action='store_true', + help=_("""\ This option suppresses the prompt prior to administrator notification but still sends the notification. It can be used to make newlist totally non-interactive but still send the notification, assuming at least one list owner is specified with the -o option..""")) - parser.add_option('-C', '--config', - help=_('Alternative configuration file to use')) - opts, args = parser.parse_args() - # We can't verify opts.language here because the configuration isn't - # loaded yet. - return parser, opts, args + + def sanity_check(self): + """Set up some defaults we couldn't set up earlier.""" + if self.options.language is None: + self.options.language = config.DEFAULT_SERVER_LANGUAGE + # Is the language known? + if self.options.language not in config.languages.enabled_codes: + self.parser.error(_('Unknown language: $opts.language')) + # Handle variable number of positional arguments + if len(self.arguments) > 0: + parser.error(_('Unexpected arguments')) def main(): - parser, opts, args = parseargs() - initialize(opts.config) - - # Set up some defaults we couldn't set up in parseargs() - if opts.language is None: - opts.language = config.DEFAULT_SERVER_LANGUAGE - # Is the language known? - if opts.language not in config.languages.enabled_codes: - parser.error(_('Unknown language: $opts.language')) - # Handle variable number of positional arguments - if len(args) == 0: - parser.error(_('You must supply a mailing list name')) - elif len(args) == 1: - fqdn_listname = args[0].lower() - elif len(args) > 1: - parser.error(_('Unexpected arguments')) + options = ScriptOptions() + options.initialize() # Create the mailing list, applying styles as appropriate. + fqdn_listname = options.options.listname try: - mlist = create_list(fqdn_listname, opts.owners) - mlist.preferred_language = opts.language + mlist = create_list(fqdn_listname, options.options.owners) + mlist.preferred_language = options.options.language except Errors.InvalidEmailAddress: - parser.error(_('Illegal list name: $fqdn_listname')) + options.parser.error(_('Illegal list name: $fqdn_listname')) except ListAlreadyExistsError: - parser.error(_('List already exists: $fqdn_listname')) + options.parser.error(_('List already exists: $fqdn_listname')) except Errors.BadDomainSpecificationError, domain: - parser.error(_('Undefined domain: $domain')) + options.parser.error(_('Undefined domain: $domain')) - config.db.flush() + config.db.commit() # Send notices to the list owners. XXX This should also be moved to the # Mailman.app.create module. - if not opts.quiet and not opts.automate: + if not options.options.quiet and not options.options.automate: print _('Hit enter to notify $fqdn_listname owners...'), sys.stdin.readline() - if not opts.quiet: + if not options.options.quiet: d = dict( listname = mlist.fqdn_listname, admin_url = mlist.script_url('admin'), @@ -136,6 +129,6 @@ def main(): with i18n.using_language(mlist.preferred_language): msg = Message.UserNotification( owner_mail, mlist.no_reply_address, - _('Your new mailing list: $listname'), + _('Your new mailing list: $fqdn_listname'), text, mlist.preferred_language) msg.send(mlist) diff --git a/mailman/bin/list_lists.py b/mailman/bin/list_lists.py index 2bd85a947..7742f1dbb 100644 --- a/mailman/bin/list_lists.py +++ b/mailman/bin/list_lists.py @@ -15,53 +15,55 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. -import optparse - from mailman import Defaults from mailman import Version from mailman.configuration import config from mailman.i18n import _ from mailman.initialize import initialize +from mailman.options import Options -def parseargs(): - parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, - usage=_("""\ +class ScriptOptions(Options): + usage=_("""\ %prog [options] -List all mailing lists.""")) - parser.add_option('-a', '--advertised', - default=False, action='store_true', - help=_("""\ +List all mailing lists.""") + + def add_options(self): + super(ScriptOptions, self).add_options() + self.parser.add_option( + '-a', '--advertised', + default=False, action='store_true', + help=_("""\ List only those mailing lists that are publicly advertised""")) - parser.add_option('-b', '--bare', - default=False, action='store_true', - help=_("""\ + self.parser.add_option( + '-b', '--bare', + default=False, action='store_true', + help=_("""\ Displays only the list name, with no description.""")) - parser.add_option('-d', '--domain', - default=[], type='string', action='append', - dest='domains', help=_("""\ + self.parser.add_option( + '-d', '--domain', + default=[], type='string', action='append', + dest='domains', help=_("""\ List only those mailing lists that match the given virtual domain, which may be either the email host or the url host name. Multiple -d options may be given.""")) - parser.add_option('-f', '--full', - default=False, action='store_true', - help=_("""\ + self.parser.add_option( + '-f', '--full', + default=False, action='store_true', + help=_("""\ Print the full list name, including the posting address.""")) - parser.add_option('-C', '--config', - help=_('Alternative configuration file to use')) - opts, args = parser.parse_args() - if args: - parser.print_help() - parser.error(_('Unexpected arguments')) - return parser, opts, args + + def sanity_check(self): + if len(self.arguments) > 0: + self.parser.error(_('Unexpected arguments')) def main(): - parser, opts, args = parseargs() - initialize(opts.config) + options = ScriptOptions() + options.initialize() mlists = [] longest = 0 @@ -69,36 +71,36 @@ def main(): listmgr = config.db.list_manager for fqdn_name in sorted(listmgr.names): mlist = listmgr.get(fqdn_name) - if opts.advertised and not mlist.advertised: + if options.options.advertised and not mlist.advertised: continue - if opts.domains: - for domain in opts.domains: + if options.options.domains: + for domain in options.options.domains: if domain in mlist.web_page_url or domain == mlist.host_name: mlists.append(mlist) break else: mlists.append(mlist) - if opts.full: + if options.options.full: name = mlist.fqdn_listname else: name = mlist.real_name longest = max(len(name), longest) - if not mlists and not opts.bare: + if not mlists and not options.options.bare: print _('No matching mailing lists found') return - if not opts.bare: + if not options.options.bare: num_mlists = len(mlists) print _('$num_mlists matching mailing lists found:') format = '%%%ds - %%.%ds' % (longest, 77 - longest) for mlist in mlists: - if opts.full: + if options.options.full: name = mlist.fqdn_listname else: name = mlist.real_name - if opts.bare: + if options.options.bare: print name else: description = mlist.description or _('[no description available]') diff --git a/mailman/bin/master.py b/mailman/bin/master.py index 6577a0079..7369dd2ca 100644 --- a/mailman/bin/master.py +++ b/mailman/bin/master.py @@ -38,11 +38,9 @@ from locknix import lockfile from munepy import Enum from mailman import Defaults -from mailman import Version from mailman import loginit from mailman.configuration import config from mailman.i18n import _ -from mailman.initialize import initialize from mailman.options import Options @@ -51,7 +49,7 @@ LOCK_LIFETIME = Defaults.days(1) + Defaults.hours(6) -class MasterOptions(Options): +class ScriptOptions(Options): """Options for the master watcher.""" usage = _("""\ @@ -405,8 +403,9 @@ qrunner %s reached maximum restart limit of %d, not restarting.""", def main(): """Main process.""" - options = MasterOptions() - initialize(options.options.config) + + options = ScriptOptions() + options.initialize() # Acquire the master lock, exiting if we can't acquire it. We'll let the # caller handle any clean up or lock breaking. No with statement here diff --git a/mailman/bin/qrunner.py b/mailman/bin/qrunner.py index 0b9c823a1..e78dfab4e 100644 --- a/mailman/bin/qrunner.py +++ b/mailman/bin/qrunner.py @@ -19,11 +19,9 @@ import sys import signal import logging -from mailman import Version from mailman import loginit from mailman.configuration import config from mailman.i18n import _ -from mailman.initialize import initialize from mailman.options import Options @@ -55,7 +53,7 @@ def r_callback(option, opt, value, parser): -class RunnerOptions(Options): +class ScriptOptions(Options): usage=_("""\ Run one or more qrunners, once or repeatedly. @@ -114,6 +112,10 @@ This should only be used when running qrunner as a subprocess of the mailmanctl startup script. It changes some of the exit-on-error behavior to work better with that framework.""")) + def initialize(self): + """Override initialization to propagate logs correctly.""" + super(ScriptOptions, self).initialize(not self.options.subproc) + def sanity_check(self): if self.arguments: self.parser.error(_('Unexpected arguments')) @@ -198,13 +200,8 @@ def set_signals(loop): def main(): global log - options = RunnerOptions() - # If we're not running as a subprocess of mailmanctl, then we'll log to - # stderr in addition to logging to the log files. We do this by passing a - # value of True to propagate, which allows the 'mailman' root logger to - # see the log messages. - initialize(options.options.config, - propagate_logs=not options.options.subproc) + options = ScriptOptions() + options.initialize() if options.options.list: prefixlen = max(len(shortname) diff --git a/mailman/options.py b/mailman/options.py index 78cf617c4..ee310f3b9 100644 --- a/mailman/options.py +++ b/mailman/options.py @@ -18,14 +18,39 @@ """Common argument parsing.""" __metaclass__ = type -__all__ = ['Options'] +__all__ = [ + 'Options', + 'SingleMailingListOptions', + ] -from optparse import OptionParser +import sys + +from copy import copy +from optparse import Option, OptionParser, OptionValueError from mailman.Version import MAILMAN_VERSION from mailman.configuration import config from mailman.i18n import _ +from mailman.initialize import initialize + + + +def check_unicode(option, opt, value): + if isinstance(value, unicode): + return value + try: + return value.decode(sys.getdefaultencoding()) + except UnicodeDecodeError: + raise OptionValueError( + "option %s: Cannot decode: %r" % (opt, value)) + + +class MailmanOption(Option): + """Extension types for unicode options.""" + TYPES = Option.TYPES + ('unicode',) + TYPE_CHECKER = copy(Option.TYPE_CHECKER) + TYPE_CHECKER['unicode'] = check_unicode @@ -36,7 +61,9 @@ class Options: usage = None def __init__(self): - self.parser = OptionParser(version=MAILMAN_VERSION, usage=self.usage) + self.parser = OptionParser(version=MAILMAN_VERSION, + option_class=MailmanOption, + usage=self.usage) self.add_common_options() self.add_options() options, arguments = self.parser.parse_args() @@ -45,7 +72,6 @@ class Options: # Also, for convenience, place the options in the configuration file # because occasional global uses are necessary. config.options = self - self.sanity_check() def add_options(self): """Allow the subclass to add its own specific arguments.""" @@ -60,3 +86,28 @@ class Options: self.parser.add_option( '-C', '--config', help=_('Alternative configuration file to use')) + + def initialize(self, propagate_logs=False): + """Initialize the configuration system. + + After initialization of the configuration system, perform sanity + checks. We do it in this order because some sanity checks require the + configuration to be initialized. + + :param propagate_logs: Flag specifying whether log messages in + sub-loggers should be propagated to the master logger (and hence + to the root logger). + """ + initialize(self.options.config, propagate_logs=propagate_logs) + self.sanity_check() + + + +class SingleMailingListOptions(Options): + """A helper for specifying the mailing list on the command line.""" + + def add_options(self): + self.parser.add_option( + '-l', '--listname', + type='unicode', help=_('The mailing list name')) + super(SingleMailingListOptions, self).add_options() |
