#! /usr/bin/env python
#
# Copyright (C) 1998,1999,2000 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.

"""Start interacting with a mailing list.

This is useful for playing with a list from Python's interactive interpreter.
Run this script as follows:

%% python -i bin/withlist [options] listname

This will load the list object named by <listname> into an object called `m'
in the global namespace.  It also loads the class MailList into the global
namespace.

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.Unlock() before exiting, since the interpreter's clean up procedure
        will not cause the lock to be deleted automatically.

    --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 a
        single argument, the MailList object.

        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.

        See below for an example.

    --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:

%% python 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:

%% python bin/withlist -r listaddr.requestaddr mylist
Loading list: mylist (unlocked)
Importing listaddr ...
Running listaddr.requestaddr() ...
mylist-request@myhost.com

"""

import sys
import getopt
import string

import paths
from Mailman.Utils import write
from Mailman.MailList import MailList

m = None
r = None



def usage(msg='', code=1):
    write(__doc__ % globals(), file=sys.stderr)
    if msg:
        write(msg, file=sys.stdout)
    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():
        write('Unlocking (but not saving) list:', m.internal_name(),
              file=sys.stderr)
        m.Unlock()
    write('Finalizing', file=sys.stderr)
    del m



def main():
    global m
    global r
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'hlr:',
                                   ['help', 'lock', 'run='])
    except getopt.error, m:
        usage(m)

    if len(args) <> 1:
        usage('No list name supplied.')

    listname = args[0]
    lock = 0
    run = None

    for opt, arg in opts:
        if opt in ('-h', '--help'):
            usage(code=0)
        elif opt in ('-l', '--lock'):
            lock = 1
        elif opt in ('-r', '--run'):
            run = arg

    # first try to open mailing list
    write('Loading list:', listname, file=sys.stderr, nl=0)
    if lock:
        write('(locked)', file=sys.stderr)
    else:
        write('(unlocked)', file=sys.stderr)

    m = MailList(listname, lock=lock)

    # try to import the module and run the callable
    if run:
        i = string.find(run, '.')
        if i < 0:
            module = run
            callable = run
        else:
            module = run[:i]
            callable = run[i+1:]
        write('Importing', module, '...', file=sys.stderr)
        mod = __import__(module)
        write('Running %s.%s()' % (module, callable), '...', file=sys.stderr)
        r = getattr(mod, callable)(m)



sys.exitfunc = atexit
main()
