diff options
| author | bwarsaw | 2006-12-29 22:20:25 +0000 |
|---|---|---|
| committer | bwarsaw | 2006-12-29 22:20:25 +0000 |
| commit | f4a456a83b630feb294724ab462c87ca1ce1c3ae (patch) | |
| tree | c5c88540dae8306d11671f603d8975b01803ea16 /Mailman/bin/withlist.py | |
| parent | ae185106a624bfa7888aa8722d35194d3c5150e8 (diff) | |
| download | mailman-f4a456a83b630feb294724ab462c87ca1ce1c3ae.tar.gz mailman-f4a456a83b630feb294724ab462c87ca1ce1c3ae.tar.zst mailman-f4a456a83b630feb294724ab462c87ca1ce1c3ae.zip | |
Diffstat (limited to 'Mailman/bin/withlist.py')
| -rw-r--r-- | Mailman/bin/withlist.py | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/Mailman/bin/withlist.py b/Mailman/bin/withlist.py new file mode 100644 index 000000000..63513d70b --- /dev/null +++ b/Mailman/bin/withlist.py @@ -0,0 +1,249 @@ +# Copyright (C) 1998-2006 by the Free Software Foundation, Inc. +# +# This program 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 2 +# of the License, or (at your option) any later version. +# +# This program 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 this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. + +import os +import sys +import atexit +import optparse + +from Mailman import Errors +from Mailman import MailList +from Mailman import Utils +from Mailman import Version +from Mailman import interact +from Mailman.configuration import config +from Mailman.i18n import _ +from Mailman.initialize import initialize + +__i18n_templates__ = True + +LAST_MLIST = None +VERBOSE = True +LOCK = False + + + +def exitfunc(mlist): + """Unlock a locked list, but do not implicitly Save() it.""" + if mlist.Locked(): + if VERBOSE: + listname = mlist.fqdn_listname + print >> sys.stderr, _( + 'Unlocking (but not saving) list: $listname') + mlist.Unlock() + if VERBOSE: + print >> sys.stderr, _('Finalizing') + + + +def do_list(listname, args, func): + global LAST_MLIST + + if '@' not in listname: + listname += '@' + config.DEFAULT_EMAIL_HOST + + if VERBOSE: + print >> sys.stderr, _('Loading list $listname'), + if LOCK: + print >> sys.stderr, _('(locked)') + else: + print >> sys.stderr, _('(unlocked)') + + try: + mlist = MailList.MailList(listname, lock=LOCK) + atexit.register(exitfunc, mlist) + LAST_MLIST = mlist + except Errors.MMUnknownListError: + print >> sys.stderr, _('Unknown list: $listname') + + # try to import the module and run the callable + if func: + return func(mlist, *args) + return None + + + +def parseargs(): + parser = optparse.OptionParser(version=Version.MAILMAN_VERSION, + usage=_("""\ +%prog [options] listname [args ...] + +General framework for interacting with a mailing list object. + +There are two ways to use this script: interactively or programmatically. +Using it interactively allows you to play with, examine and modify a MailList +object from Python's interactive interpreter. When running interactively, a +MailList object called 'm' will be available in the global namespace. It also +loads the class MailList into the global namespace. + +Programmatically, you can write a function to operate on a MailList object, +and this script will take care of the housekeeping (see below for examples). +In that case, the general usage syntax is: + + % bin/withlist [options] listname [args ...] + +Here's an example of how to use the -r option. Say you have a file in the +Mailman installation directory called 'listaddr.py', with the following +two functions: + + def listaddr(mlist): + print mlist.GetListEmail() + + def requestaddr(mlist): + print mlist.GetRequestEmail() + +Now, from the command line you can print the list's posting address by running +the following from the command line: + + % bin/withlist -r listaddr mylist + Loading list: mylist (unlocked) + Importing listaddr ... + Running listaddr.listaddr() ... + mylist@myhost.com + +And you can print the list's request address by running: + + % bin/withlist -r listaddr.requestaddr mylist + Loading list: mylist (unlocked) + Importing listaddr ... + Running listaddr.requestaddr() ... + mylist-request@myhost.com + +As another example, say you wanted to change the password for a particular +user on a particular list. You could put the following function in a file +called 'changepw.py': + + from Mailman.Errors import NotAMemberError + + def changepw(mlist, addr, newpasswd): + try: + mlist.setMemberPassword(addr, newpasswd) + mlist.Save() + except NotAMemberError: + print 'No address matched:', addr + +and run this from the command line: + + % bin/withlist -l -r changepw mylist somebody@somewhere.org foobar""")) + parser.add_option('-l', '--lock', + default=False, action='store_true', help=_("""\ +Lock the list when opening. Normally the list is opened unlocked (e.g. for +read-only operations). You can always lock the file after the fact by typing +'m.Lock()' + +Note that if you use this option, you should explicitly call m.Save() before +exiting, since the interpreter's clean up procedure will not automatically +save changes to the MailList object (but it will unlock the list).""")) + parser.add_option('-i', '--interactive', + default=None, action='store_true', help=_("""\ +Leaves you at an interactive prompt after all other processing is complete. +This is the default unless the -r option is given.""")) + parser.add_option('-r', '--run', + type='string', help=_("""\ +This can be used to run a script with the opened MailList object. This works +by attempting to import 'module' (which must be in the directory containing +withlist, or already be accessible on your sys.path), and then calling +'callable' from the module. callable can be a class or function; it is called +with the MailList object as the first argument. If additional args are given +on the command line, they are passed as subsequent positional args to the +callable. + +Note that 'module.' is optional; if it is omitted then a module with the name +'callable' will be imported. + +The global variable 'r' will be set to the results of this call.""")) + parser.add_option('-a', '--all', + default=False, action='store_true', help=_("""\ +This option only works with the -r option. Use this if you want to execute +the script on all mailing lists. When you use -a you should not include a +listname argument on the command line. The variable 'r' will be a list of all +the results.""")) + parser.add_option('-q', '--quiet', + default=False, action='store_true', + help=_('Suppress all status messages.')) + parser.add_option('-C', '--config', + help=_('Alternative configuration file to use')) + opts, args = parser.parse_args() + return parser, opts, args + + + +def main(): + global LAST_MLIST, LOCK, VERBOSE + + parser, opts, args = parseargs() + initialize(opts.config, not opts.quiet) + + VERBOSE = not opts.quiet + LOCK = opts.lock + + # Append our bin directory to sys.path so that any withlist scripts living + # their can be simply imported. + sys.path.append(config.BIN_DIR) + + # The default for interact is true unless -r was given + if opts.interactive is None: + if not opts.run: + opts.interactive = True + else: + opts.interactive = False + + dolist = True + if len(args) < 1 and not opts.all: + warning = _('No list name supplied.') + if opts.interactive: + # Let them keep going + print >> sys.stderr, warning + dolist = False + else: + parser.error(warning) + + if opts.all and not opts.run: + parser.error(_('--all requires --run')) + + # Try to import the module for the callable + func = None + if opts.run: + i = opts.run.find('.') + if i < 0: + module = opts.run + callable = opts.run + else: + module = opts.run[:i] + callable = opts.run[i+1:] + if VERBOSE: + print >> sys.stderr, _('Importing $module ...') + mod = __import__(module) + if VERBOSE: + print >> sys.stderr, _('Running ${module}.${callable}() ...') + func = getattr(mod, callable) + + r = None + if opts.all: + r = [do_list(listname, args, func) for listname in Utils.list_names()] + elif dolist: + listname = args.pop(0).lower().strip() + r = do_list(listname, args, func) + + # Now go to interactive mode, perhaps + if opts.interactive: + if dolist: + banner = _("The variable 'm' is the $listname MailList instance") + else: + banner = interact.DEFAULT_BANNER + overrides = dict(m=LAST_MLIST, r=r) + interact.interact(upframe=False, banner=banner, overrides=overrides) |
