aboutsummaryrefslogtreecommitdiffstats
path: root/bin/withlist
diff options
context:
space:
mode:
Diffstat (limited to 'bin/withlist')
-rw-r--r--bin/withlist275
1 files changed, 275 insertions, 0 deletions
diff --git a/bin/withlist b/bin/withlist
new file mode 100644
index 00000000..a9bd6361
--- /dev/null
+++ b/bin/withlist
@@ -0,0 +1,275 @@
+#! @PYTHON@
+#
+# Copyright (C) 1998,1999,2000,2001,2002 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+"""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 ...]
+
+Options:
+
+ -l / --lock
+ 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).
+
+ -i / --interactive
+ Leaves you at an interactive prompt after all other processing is
+ complete. This is the default unless the -r option is given.
+
+ --run [module.]callable
+ -r [module.]callable
+ This can be used to run a script with the opened MailList object.
+ This works by attempting to import `module' (which must 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.
+
+ --all / -a
+ 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.
+
+ --quiet / -q
+ Suppress all status messages.
+
+ --help / -h
+ Print this message and exit
+
+
+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 NotAMember
+
+def changepw(mlist, addr, newpasswd):
+ try:
+ mlist.setMemberPassword(addr, newpasswd)
+ mlist.Save()
+ except NotAMember:
+ print 'No address matched:', addr
+
+and run this from the command line:
+%% bin/withlist -l -r changepw mylist somebody@somewhere.org foobar
+"""
+
+import sys
+import getopt
+import code
+
+import paths
+from Mailman import Utils
+from Mailman import MailList
+from Mailman import Errors
+from Mailman.i18n import _
+
+# `m' will be the MailList object and `r' will be the results of the callable
+m = None
+r = None
+VERBOSE = 1
+LOCK = 0
+
+
+
+def usage(code, msg=''):
+ if code:
+ fd = sys.stderr
+ else:
+ fd = sys.stdout
+ print >> fd, _(__doc__)
+ if msg:
+ print >> fd, msg
+ sys.exit(code)
+
+
+def atexit():
+ """Unlock a locked list, but do not implicitly Save() it.
+
+ This does not get run if the interpreter exits because of a signal, or if
+ os._exit() is called. It will get called if an exception occurs though.
+ """
+ global m
+ if not m:
+ return
+ if m.Locked():
+ if VERBOSE:
+ listname = m.internal_name()
+ print >> sys.stderr, _(
+ 'Unlocking (but not saving) list: %(listname)s')
+ m.Unlock()
+ if VERBOSE:
+ print >> sys.stderr, _('Finalizing')
+ del m
+
+
+
+def do_list(listname, args, func):
+ global m
+ # first try to open mailing list
+ if VERBOSE:
+ print >> sys.stderr, _('Loading list %(listname)s'),
+ if LOCK:
+ print >> sys.stderr, _('(locked)')
+ else:
+ print >> sys.stderr, _('(unlocked)')
+
+ try:
+ m = MailList.MailList(listname, lock=LOCK)
+ except Errors.MMUnknownListError:
+ print >> sys.stderr, _('Unknown list: %(listname)s')
+ m = None
+
+ # try to import the module and run the callable
+ if func:
+ return func(m, *args)
+ return None
+
+
+
+def main():
+ global VERBOSE
+ global LOCK
+ global r
+ try:
+ opts, args = getopt.getopt(
+ sys.argv[1:], 'hlr:qia',
+ ['help', 'lock', 'run=', 'quiet', 'interactive', 'all'])
+ except getopt.error, msg:
+ usage(1, msg)
+
+ run = None
+ interact = None
+ all = 0
+ for opt, arg in opts:
+ if opt in ('-h', '--help'):
+ usage(0)
+ elif opt in ('-l', '--lock'):
+ LOCK = 1
+ elif opt in ('-r', '--run'):
+ run = arg
+ elif opt in ('-q', '--quiet'):
+ VERBOSE = 0
+ elif opt in ('-i', '--interactive'):
+ interact = 1
+ elif opt in ('-a', '--all'):
+ all = 1
+
+ if len(args) < 1 and not all:
+ usage(1, _('No list name supplied.'))
+
+ if all and not run:
+ usage(1, _('--all requires --run'))
+
+ # The default for interact is 1 unless -r was given
+ if interact is None:
+ if run is None:
+ interact = 1
+ else:
+ interact = 0
+
+ # try to import the module for the callable
+ func = None
+ if run:
+ i = run.find('.')
+ if i < 0:
+ module = run
+ callable = run
+ else:
+ module = run[:i]
+ callable = run[i+1:]
+ if VERBOSE:
+ print >> sys.stderr, _('Importing %(module)s...')
+ mod = __import__(module)
+ if VERBOSE:
+ print >> sys.stderr, _('Running %(module)s.%(callable)s()...')
+ func = getattr(mod, callable)
+
+ if all:
+ r = [do_list(listname, args, func) for listname in Utils.list_names()]
+ else:
+ listname = args.pop(0).lower().strip()
+ r = do_list(listname, args, func)
+
+ # Now go to interactive mode, perhaps
+ if interact:
+ # Attempt to import the readline module, so we emulate the interactive
+ # console as closely as possible. Don't worry if it doesn't import.
+ # readline works by side-effect.
+ try:
+ import readline
+ except ImportError:
+ pass
+ namespace = globals().copy()
+ namespace.update(locals())
+ code.InteractiveConsole(namespace).interact(
+ _("The variable `m' is the %(listname)s MailList instance"))
+
+
+
+sys.exitfunc = atexit
+main()