Below is the file 'nfs4client.py' from this revision. You can also download the file.

#!/usr/bin/env python

#
# nfs4client.py - NFS4 interactive client in python
#
# Written by Fred Isaman   <iisaman@citi.umich.edu>
# Copyright (C) 2006 University of Michigan, Center for
#                    Information Technology Integration
#

import sys
if sys.hexversion < 0x02030000:
    print "Requires python 2.3 or higher"
    sys.exit(1)
import os
# Allow to be run stright from package root
if  __name__ == "__main__":
    if os.path.isfile(os.path.join(sys.path[0], 'lib', 'testmod.py')):
        sys.path.insert(1, os.path.join(sys.path[0], 'lib'))

import readline
try:
    import readline
except ImportError:
    print "Module readline not available."
#else:
#    import rlcompleter
#    readline.parse_and_bind("tab: complete")
#import cmd
import nfs4.nfs4lib as nfs4lib
import nfs4.nfs4_type as nfs4_type
import nfs4.nfs4_const as nfs4_const
import nfs4.nfs4_pack as nfs4_pack
import code
import traceback

class PyShell(code.InteractiveConsole):
    def __init__(self, server):
        self.client = nfs4lib.NFS4Client("myid", server, homedir = [])
        self.modify_packers()
        locals = {'__builtins__': globals()['__builtins__'],
                  '__name__':'__main__',
                  '__doc__':None}
        code.InteractiveConsole.__init__(self, locals)
        self.myimport(nfs4_type)
        self.myimport(nfs4_const)
        self.importops()
        #self.oldcompleter = readline.get_completer()
        readline.set_completer(self.complete)
        readline.parse_and_bind("tab: complete")

    def myimport(self, mod):
        """Basically do a 'from <mod> import *' """
        for attr in dir(mod):
            if attr[0] != '_':
                self.locals[attr] = getattr(mod, attr)

    def importops(self):
        d = self.locals
        for attr in dir(self.client):
            if attr.endswith("_op"):
                key = attr[:-3].upper()
                d[key] = getattr(self.client, attr)
        d["COMPOUND"] = self.client.compound
        d["NULL"] = self.client.null
        d['fattr4_from_dict'] = nfs4lib.dict2fattr
        d['fattr4_to_dict'] = nfs4lib.fattr2dict
        d['fattr4_names'] = nfs4lib.get_bitnumattr_dict()
        d['bitmap4_from_list'] = nfs4lib.list2attrmask
        d['bitmap4_to_list'] = nfs4lib.attrmask2list

    def complete(self, text, state):
        def mygetattr(inst, attr):
            if inst is None:
                return self.locals[attr]
            else:
                return getattr(inst, attr)
        #print "\nCalled complete(%s, %i)" % (text, state)
        if text.startswith('.'):
            # XXX TODO - handle array indexing
            line = readline.get_line_buffer()
            # print "Line: ", repr(line)
            return None
        vars = text.split('.')
        base = vars[:-1]
        # Look up base variable
        if base:
            try:
                inst = eval('.'.join(base), self.locals)
            except:
                print "\nFAIL"
                traceback.print_exc()
                return None
        else:
            inst = None
        # Get list of base variable attributes
        count = 0
        if inst is None:
            list = self.locals.keys()
        else:
            list = dir(inst)
        # Scan through list, and report possible completions
        for attr in list:
            if attr.startswith(vars[-1]):
                count += 1
                if count > state:
                    if callable(mygetattr(inst, attr)):
                        return '.'.join(base + [attr+'('])
                    else:
                        return '.'.join(base + [attr])
        return None

    def modify_packers(self):
        def allow_dict(f):
            def wrapper(data):
                if type(data) is dict:
                    data = nfs4lib.dict2fattr(data)
                return f(data)
            return wrapper
        self.client.nfs4packer.pack_fattr4 = allow_dict(self.client.nfs4packer.pack_fattr4)

        def show_dict(f):
            def wrapper():
                data = f()
                return nfs4lib.fattr2dict(data)
            return wrapper
        self.client.nfs4unpacker.unpack_fattr4 = show_dict(self.client.nfs4unpacker.unpack_fattr4)

        def new_entry_repr(self):
            out = []
            if self.cookie is not None:
                out += ['cookie=%s' % repr(self.cookie)]
            if self.name is not None:
                out += ['name=%s' % repr(self.name)]
            if self.attrs is not None:
                out += ['attrs=%s' % repr(self.attrs)]
            return 'entry4(%s)' % ', '.join(out)
        nfs4_type.entry4.__repr__ = new_entry_repr

        def show_simple_list(f):
            def wrapper():
                data = f()
                e = data.entries
                array = [e[0]]
                while e[0].nextentry:
                    e = e[0].nextentry
                    array.append(e[0])
                data.entries = array
                return data
            return wrapper
        self.client.nfs4unpacker.unpack_dirlist4 = show_simple_list(self.client.nfs4unpacker.unpack_dirlist4)

def main(server):
    c = PyShell(server)
    c.interact("Try COMPOUND([PUTROOTFH()])")
    print "Goodbye!"

if __name__ == "__main__":
    main(sys.argv[1])