------------------------------------------------------------
revno: 6611
committer: Barry Warsaw <[EMAIL PROTECTED]>
branch nick: bin-fixes
timestamp: Sat 2008-03-22 21:43:38 -0400
message:
Several fixes to command line scripts.
- Add an options base class that groks unicode argument types
- Rename newlist to create_list
- Update list_lists, master, qrunner
renamed:
mailman/bin/newlist.py => mailman/bin/create_list.py
modified:
mailman/bin/__init__.py
mailman/bin/list_lists.py
mailman/bin/master.py
mailman/bin/qrunner.py
mailman/options.py
mailman/bin/create_list.py
=== modified file 'mailman/bin/__init__.py'
--- a/mailman/bin/__init__.py 2008-02-25 05:24:03 +0000
+++ b/mailman/bin/__init__.py 2008-03-23 01:43:38 +0000
@@ -26,6 +26,7 @@
'cleanarch',
'config_list',
'confirm',
+ 'create_list',
'disabled',
'dumpdb',
'export',
@@ -43,7 +44,6 @@
'make_instance',
'master',
'mmsitepass',
- 'newlist',
'nightly_gzip',
'owner',
'post',
=== renamed file 'mailman/bin/newlist.py' => 'mailman/bin/create_list.py'
--- a/mailman/bin/newlist.py 2008-02-27 06:26:18 +0000
+++ b/mailman/bin/create_list.py 2008-03-23 01:43:38 +0000
@@ -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 @@
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 @@
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)
=== modified file 'mailman/bin/list_lists.py'
--- a/mailman/bin/list_lists.py 2008-02-27 06:26:18 +0000
+++ b/mailman/bin/list_lists.py 2008-03-23 01:43:38 +0000
@@ -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 @@
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]')
=== modified file 'mailman/bin/master.py'
--- a/mailman/bin/master.py 2008-03-21 17:01:48 +0000
+++ b/mailman/bin/master.py 2008-03-23 01:43:38 +0000
@@ -38,11 +38,9 @@
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 @@
-class MasterOptions(Options):
+class ScriptOptions(Options):
"""Options for the master watcher."""
usage = _("""\
@@ -405,8 +403,9 @@
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
=== modified file 'mailman/bin/qrunner.py'
--- a/mailman/bin/qrunner.py 2008-03-21 17:08:04 +0000
+++ b/mailman/bin/qrunner.py 2008-03-23 01:43:38 +0000
@@ -19,11 +19,9 @@
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 @@
-class RunnerOptions(Options):
+class ScriptOptions(Options):
usage=_("""\
Run one or more qrunners, once or repeatedly.
@@ -114,6 +112,10 @@
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 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)
=== modified file 'mailman/options.py'
--- a/mailman/options.py 2008-03-21 17:01:48 +0000
+++ b/mailman/options.py 2008-03-23 01:43:38 +0000
@@ -18,14 +18,39 @@
"""Common argument parsing."""
__metaclass__ = type
-__all__ = ['Options']
-
-
-from optparse import OptionParser
+__all__ = [
+ 'Options',
+ 'SingleMailingListOptions',
+ ]
+
+
+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 @@
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 @@
# 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 @@
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()
--
Primary development focus
https://code.launchpad.net/~mailman-coders/mailman/3.0
You are receiving this branch notification because you are subscribed to it.
_______________________________________________
Mailman-checkins mailing list
[email protected]
Unsubscribe:
http://mail.python.org/mailman/options/mailman-checkins/archive%40jab.org