Exemplo n.º 1
0
    def __init__(self,args=[],stdin=None,stdout=None,
                 completekey='tab',intro=None,debug=False,GUI='TkAgg'):
        """
        Init
        """
        # Prompt
        self.ps1 = "pds>"
        self.ps2 = "...>"
        
        # Set stdin/out
        if stdin is not None:
            sys.stdin = self.stdin = stdin
            self.use_rawinput = False
        else:
            self.stdin = sys.stdin
            self.use_rawinput = True
        if stdout is not None:
            sys.stdout = self.stdout = stdout
            #sys.stderr = stdout
        else:
            self.stdout = sys.stdout

        # Startup strings
        self.intro = self.__doc__
        if intro:
            self.intro = self.intro + intro
        if self.intro:
            self.stdout.write(str(self.intro)+"\n")

        # Interpretor
        self.interp = Interpretor()

        # Data and vars
        self.debug         = debug
        self.GUI           = GUI
        self.queue         = []
        self.error_break   = True
        self.commands      = {}

        # Builtin commands
        self.pds_commands  = {'quit':self.do_quit,
                              'exit':self.do_quit,
                              #'EOF':self.do_quit,
                              'show':self.do_show,
                              'help':self.do_help,
                              'load':self.do_load,
                              'debug':self.do_debug,
                              'fexec':self.do_execfile,
                              'save':self.do_save,
                              'restore':self.do_restore,
                              'clear':self.do_clear,
                              'addcmd':self.do_addcmd,
                              'alias':self.do_addalias}

        # run startup 
        self.startup(args=args)

        # check
        for cmd in self.pds_commands.keys():
            if cmd in PYTHON_KEY_WORDS:
                print "Warning: command '%s' is a python keyword" % cmd

        # setup readline if have it. -- add later
        self.completekey = completekey
Exemplo n.º 2
0
    def __init__(self,
                 args=[],
                 stdin=None,
                 stdout=None,
                 completekey='tab',
                 intro=None,
                 debug=False,
                 GUI='TkAgg'):
        """
        Init
        """
        # Prompt
        self.ps1 = "pds>"
        self.ps2 = "...>"

        # Set stdin/out
        if stdin is not None:
            sys.stdin = self.stdin = stdin
            self.use_rawinput = False
        else:
            self.stdin = sys.stdin
            self.use_rawinput = True
        if stdout is not None:
            sys.stdout = self.stdout = stdout
            #sys.stderr = stdout
        else:
            self.stdout = sys.stdout

        # Startup strings
        self.intro = self.__doc__
        if intro:
            self.intro = self.intro + intro
        if self.intro:
            self.stdout.write(str(self.intro) + "\n")

        # Interpretor
        self.interp = Interpretor()

        # Data and vars
        self.debug = debug
        self.GUI = GUI
        self.queue = []
        self.error_break = True
        self.commands = {}

        # Builtin commands
        self.pds_commands = {
            'quit': self.do_quit,
            'exit': self.do_quit,
            #'EOF':self.do_quit,
            'show': self.do_show,
            'help': self.do_help,
            'load': self.do_load,
            'debug': self.do_debug,
            'fexec': self.do_execfile,
            'save': self.do_save,
            'restore': self.do_restore,
            'clear': self.do_clear,
            'addcmd': self.do_addcmd,
            'alias': self.do_addalias
        }

        # run startup
        self.startup(args=args)

        # check
        for cmd in self.pds_commands.keys():
            if cmd in PYTHON_KEY_WORDS:
                print "Warning: command '%s' is a python keyword" % cmd

        # setup readline if have it. -- add later
        self.completekey = completekey
Exemplo n.º 3
0
class Shell(_NumShell):
    __doc__  = """
    ****************************************
    * Python Data Shell                    *
    * Type 'help' to get started           *
    ****************************************
    """
    
    max_save_lines = 500

    #############################################################
    def __init__(self,args=[],stdin=None,stdout=None,
                 completekey='tab',intro=None,debug=False,GUI='TkAgg'):
        """
        Init
        """
        # Prompt
        self.ps1 = "pds>"
        self.ps2 = "...>"
        
        # Set stdin/out
        if stdin is not None:
            sys.stdin = self.stdin = stdin
            self.use_rawinput = False
        else:
            self.stdin = sys.stdin
            self.use_rawinput = True
        if stdout is not None:
            sys.stdout = self.stdout = stdout
            #sys.stderr = stdout
        else:
            self.stdout = sys.stdout

        # Startup strings
        self.intro = self.__doc__
        if intro:
            self.intro = self.intro + intro
        if self.intro:
            self.stdout.write(str(self.intro)+"\n")

        # Interpretor
        self.interp = Interpretor()

        # Data and vars
        self.debug         = debug
        self.GUI           = GUI
        self.queue         = []
        self.error_break   = True
        self.commands      = {}

        # Builtin commands
        self.pds_commands  = {'quit':self.do_quit,
                              'exit':self.do_quit,
                              #'EOF':self.do_quit,
                              'show':self.do_show,
                              'help':self.do_help,
                              'load':self.do_load,
                              'debug':self.do_debug,
                              'fexec':self.do_execfile,
                              'save':self.do_save,
                              'restore':self.do_restore,
                              'clear':self.do_clear,
                              'addcmd':self.do_addcmd,
                              'alias':self.do_addalias}

        # run startup 
        self.startup(args=args)

        # check
        for cmd in self.pds_commands.keys():
            if cmd in PYTHON_KEY_WORDS:
                print "Warning: command '%s' is a python keyword" % cmd

        # setup readline if have it. -- add later
        self.completekey = completekey

    #############################################################
    def startup(self,args=[]):
        """
        set up builtins and exec startup arguments
        """
        
        # Builtins
        from builtins import __pdsbuiltins__
        self.interp.symbol_table.data["__pds__"] = __pdsbuiltins__
        
        # add module functions to __builtins__
        startup = []
        startup.append("__builtins__.update({'group':__pds__.group})")
        startup.append("__builtins__.update({'ls':__pds__._ls})")
        startup.append("__builtins__.update({'cd':__pds__._cd})")
        startup.append("__builtins__.update({'pwd':__pds__._cwd})")
        startup.append("__builtins__.update({'rimport':__pds__.rimport})")
        startup.append("__builtins__.update({'path':__pds__._path})")
        startup.append("__builtins__.update({'source':__pds__.source})")
        startup.append("__builtins__.update({'info':__pds__.info})")

        # functions we want to use with command syntax
        self.do_addcmd('ls',"__pds__.ls")
        self.do_addcmd('pwd',"__pds__.pwd")
        self.do_addcmd('cd',"__pds__.cd")
        self.do_addcmd('more',"__pds__.more")
        self.do_addcmd('path',"__pds__.path")
        self.do_addcmd('rimport',"__pds__.rimport")
        self.do_addcmd('source',"__pds__.source")
        self.do_addcmd('info',"__pds__.info")

        # if numeric/scientific stuff is included
        # load it. Note leave this here in case there
        # are cmd line args below that depend on numerics...
        if hasattr(self,'num_setup'):
            tmp = self.num_setup()
            startup = startup + tmp
        
        # any other args add to queue
        if type(args) == types.ListType:
            for a in args:
                s = a.strip()
                startup.append(s)
        self.queue = startup

        # execute the queue here before moving on
        # otherwise startup stuff is not available
        # to files executed before we start the loop
        # also allow it to run through even if there is
        # an error...
        self.error_break = False
        self.exec_queue()
        self.error_break = True

        return

    ############################################################################
    def loop(self,):
        """
        The prompt loop
        
        Repeatedly issue a prompt, accept input, parse an initial prefix
        off the received input, and dispatch to action methods, passing them
        the remainder of the line as argument.  Modified from cmd.Cmd.cmdloop.

        Note for the python interpretor to work it is important that blank
        lines are passed, and that lines are not stripped entirely (ie leave
        white space on left)
        """
        stop = COMPLETE
        while stop != QUIT:
            if stop == CONTINUE:
                prompt = self.ps2
            else:
                prompt = self.ps1
            if self.use_rawinput:
                try:
                    line = raw_input(prompt)
                except EOFError:
                    line = 'quit'
            else:
                self.stdout.write(prompt)
                self.stdout.flush()
                line = self.stdin.readline()
                if line == None:
                    line = 'quit'
                else:
                    #line = line[:-1]    # chop \n
                    line = line.rstrip() # chop \n
            # split on ';' and exec the line
            lines = split_cmd_line(line)
            for s in lines:
                stop = self.exec_line(s)
                if stop == QUIT: break
        return SUCCESS
    
    #############################################################
    def exec_queue(self):
        """
        Execute lines in self.queue
        """
        if len(self.queue) == 0:
            return  SUCCESS
        for line in self.queue:
            # split on ';' and exec the line
            lines = split_cmd_line(line)
            for s in lines:
                stop = self.exec_line(s)
                if stop == QUIT: 
                    self.queue = []
                    return QUIT
                elif (stop == EXECERROR) and (self.error_break == True):
                    self.queue = []
                    print "Error executing shell.queue"
                    return EXECERROR
        return SUCCESS
    
    #############################################################
    def exec_line(self, line):
        """
        Exec a single line
        
        This method first inspect the first token of the command line
            If its a '!' send it to the shell
            If its a 'command' call _exec_cmd()
            Otherwise pass to the interpretor

        The return value from this method should always be one of:
            QUIT, SUCCESS, COMPLETE, CONTINUE, EXECERROR
        Exceptions from the interpretor are handled here.
        
        Note for the python interpretor to work it is important that blank
        lines are passed in and that lines are not stripped entirely
        (ie leave left white space). We also let the interpretor handle
        comments (#).
        """
        s = str(line).rstrip()
        try:
            if len(s) > 0:
                #if self.debug: print '**line:%s' % (s)
                # see if its shell cmd
                if s.startswith('!'):
                    os.system(s[1:])
                    return COMPLETE
                # look for commands
                words = s.split()
                cmd = words[0].strip()
                if len(words) > 1:
                    idx = s.find(cmd)+len(cmd)
                    arg = s[idx:].strip()
                else:
                    arg = ''
            else:
                cmd = None
            # if its a cmd execute it in _exec_cmd
            if cmd:
                if cmd in self.pds_commands.keys():
                    return self._exec_cmd(cmd,arg)
                elif cmd in self.commands.keys():
                    return self._exec_cmd(cmd,arg)
            # otherwise pass to the interpretor
            return self.interp.execute(s)
        except:
            err_str = "Error executing line:\n'%s'" % s
            if self.debug:
                PrintExceptErr(err_str,print_trace=True)
            else:
                #PrintExceptErr(err_str,print_trace=False)
                PrintExceptErr(err_str,print_trace=True)
            # clear the exception and interpretors buffer
            # sys.exc_clear()
            self.interp.console.resetbuffer()
            return EXECERROR
        
    #############################################################
    def _exec_cmd(self,cmd,arg):
        """
        execute commands
        
        Note only call this from exec_line for proper
        error / exception handling! 
        """
        ret = None
        # local commands
        if cmd in self.pds_commands.keys():
            fun = self.pds_commands[cmd]
            ret = fun(arg)
        # other commands
        elif cmd in self.commands.keys():
            cmd_fun = self.commands[cmd]
            s = cmd_fun + ' ' + arg
            s = command2expr(s,symtable=self.interp.symbol_table)
            if self.debug: print '**command repacked: ', s
            ret = self.interp.execute(s)
        else:
            print "Error: uknown command: %s" % cmd
        #if ret == None:
        if ret not in (QUIT, SUCCESS, COMPLETE, CONTINUE, EXECERROR):
            return COMPLETE
        else:
            return ret

    #############################################################

    #############################################################
    ## Builtin commands
    #############################################################

    #############################################################
    def do_quit(self,arg):
        """
        Quit the shell 
        """
        try:
            self.close_pyplot()
        except:
            pass
        return QUIT
    
    #############################################################
    def do_debug(self,arg):
        """
        Toggle debug flag 
        """
        if self.debug == True:
            print "Debug off"
            self.debug = False
        else:
            print "Debug on"
            self.debug = True
        return SUCCESS

    #############################################################
    def do_load(self,fname):
        """
        Load file of pds commands for execution

        Note that file execution will halt if there is an
        error in the file.  This default behaviour can
        be changed by setting the flag self.error_break = False

        If the file has a '.sav' extension we first try to read it
        using restore (ie assume its a pickle)
        """
        if fname[-4:] == '.sav':
            if self._restore(fname) == 1: return COMPLETE
        
        if os.path.exists(fname) and os.path.isfile(fname):
            f = open(fname)
            lines = f.readlines()
            f.close()
        else:
            print 'File error: cannot find file to load for %s ' % fname
            return COMPLETE
        if len(lines) == 0: return COMPLETE

        # execute the lines through the queue
        self.queue = []
        self.queue.extend(lines)
        ret = self.exec_queue()
        if ret == EXECERROR:
            print "Error in file %s" % fname
        if self.debug: print 'load done'
        return COMPLETE

    #############################################################
    def do_execfile(self,fname):
        """
        Execute a file of python code

        Note that the file will be executed as if it was
        imported into the '__main__' namespace
        """
        if not os.path.exists(fname):
            files = []
            for p in sys.path:
                f = os.path.join(p,fname)
                if os.path.exists(f):
                    files.append(f)
            if len(files) == 0:
                print "File '%s' not found" % fname
                return SUCCESS
            elif len(files) == 1:
                fname = files[0]
            else:
                print "Warning multiple files found on path"
                print "Please specify the full path in fname or change the"
                print "working directory to the directory with the correct file"
                for f in files: print "    %s" % f
                return SUCCESS
        return self.interp.execute_file(fname)

    #############################################################
    def do_addcmd(self,*arg):
        """
        Add a command interface to a function
        
        Allows a function to be called with command syntax.
          >>addcmd mycmd, myfun
        results in
          >>mycmd arg1, arg2, key=xx
        being repackaged to
          >>myfun(arg1,arg2,key=xx)
        which is then sent to the interpretor
        """
        if len(arg) == 1:
            arg = arg[0]
            words = arg.split(',')
            if len(words) != 2:
                print "Error parsing cmd/func names"
            cmd_name = words[0].strip()
            func_name = words[1].strip()
        elif len(arg) == 2:
            cmd_name  = arg[0].strip()
            func_name = arg[1].strip()
        else:
            print "Wrong number of arguments"
            return SUCCESS
        cmd_name  = trimstring(cmd_name)
        func_name = trimstring(func_name)

        if len(cmd_name) == 0 or len(func_name) == 0:
            print "Error parsing cmd/func names"
            return SUCCESS
        
        # do a check
        if cmd_name in PYTHON_KEY_WORDS:
            print "Error: command '%s' is a python keyword" % cmd_name
            return SUCCESS
        
        if cmd_name in self.pds_commands.keys():
            print "Error: command '%s' is a builtin keyword" % cmd_name
            return SUCCESS

        if cmd_name in self.commands.keys():
            print "Warning: overwriting command '%s' " % cmd_name
            self.commands[cmd_name] = func_name
        else:
            self.commands.update({cmd_name:func_name})
        return SUCCESS

    #############################################################
    def do_addalias(self,*arg):
        """
        Create a command shortcut for a function.

        The alias is just a way of making shortcuts for repetitive taks
          >>alias myalias, 'myfun(args)'
        results in
          >>myalias
        being repackaged to
          >>myfun(args)
        which is then sent to the interpretor

        Note alias's are added to the command list
        (see 'show' and 'help addcmd')

        Example:
        --------
        pds>alias "code", "cd('~/code')"
        pds>code
        pds>pwd
        /home/bob/code
        """
        if len(arg) == 1:
            arg = arg[0]
            words = arg.split(',')
            if len(words) != 2:
                print "Error parsing cmd/func names"
            cmd_name  = words[0].strip()
            func_name = words[1].strip()
        elif len(arg) == 2:
            cmd_name  = arg[0].strip()
            func_name = arg[1].strip()
        else:
            print "Wrong number of arguments"
            return SUCCESS
        cmd_name  = trimstring(cmd_name)
        func_name = trimstring(func_name)

        if len(cmd_name) == 0 or len(func_name) == 0:
            print "Error parsing cmd/func names"
            return SUCCESS

        # do a check
        if cmd_name in PYTHON_KEY_WORDS:
            print "Error: command '%s' is a python keyword" % cmd_name
            return SUCCESS

        s = "__%s__ = lambda : %s" % (cmd_name,func_name)
        ret = self.exec_line(s)
        s = "addcmd '%s', '__%s__'" % (cmd_name,cmd_name)
        ret = self.exec_line(s)

    ##############################################################

    ##############################################################
    ## save / restore state and clear variables
    ##############################################################
    
    ##############################################################
    def do_save(self,args):
        """
        Save program state to a file
        
        Note this may fail since not all
        objects can be pickled... needs improvement!

        Examples:
        ---------
        >>save            # save all to default fname
        >>save fname      # save all to fname
        >>save data fname # save data to file
        """
        from pds.shellutil import pickle_1 as pickle
        #from pds.shellutil import pickle_2 as pickle

        # parse input, get filename
        args = split_args(args)
        dname = None
        if len(args) == 0:
            t = time.strftime("%Y_%m_%d_%H%M", time.localtime())
            fname = 'save_%s.sav' % t
        else:
            if len(args) == 1:
                fname = args[0]
            elif len(args) == 2:
                dname = args[0]
                fname = args[1]
            else:
                return
            
        # get data dictionary
        data = self.interp.symbol_table.get_data_dict(name=dname)
        if data == None: return SUCCESS

        # pickle it    
        pickle(data,fname)
        
    ##############################################################
    def do_restore(self,fname):
        """
        Restore state from a file that was created with save
        """
        self._restore(fname)
        return SUCCESS 

    def _restore(self,fname):
        from pds.shellutil import unpickle_1 as unpickle
        #from pds.shellutil import unpickle_2 as unpickle

        pdata = unpickle(fname)
        if pdata == None:
            print "No data"
            return 0
        if len(pdata) > 0:
            self.interp.symbol_table.put_data_dict(pdata)
            return 1
        return 0
    
    ##############################################################
    def do_clear(self,arg):
        """
        Clear all 'data' from the workspace

        This clears everything that looks like a variable, ie
        simple data types and class instances
        """
        args  = split_args(arg)
        if len(args) == 0:
            dname = [None]
        else:
            dname = args
        for d in dname:
            data = self.interp.symbol_table.get_data_dict(name=d)
            for key in data.keys():
                del self.interp.symbol_table.data[key]
        return SUCCESS

    ##############################################################

    #############################################################
    ##  Help and Show
    #############################################################
    
    ##############################################################
    def do_help(self,arg):
        """
        Display help.

        Example:
        --------
        >>help     # displays help options
        """
        if arg == None or len(arg) == 0:
            #print self.help_str
            print HELP_STR
            return SUCCESS
        
        (opts, args) = getopt.getopt(arg.split(), "u",["use"])
        for key,val in opts:
            if key in ("-u", "--use"):
                #print self.help_use_str
                print HELP_USE_STR
        for a in args:
            if a in self.pds_commands.keys():
                #tmp = getattr(self,a)
                tmp = self.pds_commands[a]
                help(tmp)
            elif a in self.commands.keys():
                cmd_fun = self.commands[a]
                s = "help(%s)" % cmd_fun
                ret = self.exec_line(s)
            else:
                s = "help(%s)" % a
                ret = self.exec_line(s)
        return SUCCESS

    #############################################################
    def do_show(self,arg):
        """
        List functions and variables.

        Options:  >>show -ath group
        --------
        -a = show all (include symbols with names that have a leading '_' )
        -b = show builtins (defined in __builtins__ ).  Note this option
             trumps tunnel (ie -t is ignored).  
        -t = tunnel, display attributes within a class instance or module.
             Note modules are only displayed with one level of tunneling
             (ie -t option is ignored if a module is passed as an argument).
             However, this will tunnel on all class instances.
        """
        tunnel=False
        skip=True
        (opts, args) = getopt.getopt(arg.split(), "abt",["all","builtins","tunnel"])
        for key,val in opts:
            if key in ("-a", "--all"):
                skip=False
            if key in ("-b", "--builtin"):
                self._show_builtins(_skip=skip)
                return
            if key in ("-t", "--tunnel"):
                tunnel=True
        if len(args)>0:
            #arg = ' '.join(args)
            for a in args:
                self._show(symbol=a,tunnel=tunnel,_skip=skip)
        else:
            self._show(tunnel=tunnel,_skip=skip)
        return SUCCESS

    #############################################################
        
    def _show_builtins(self,_skip=True):
        """
        """
        print "\n***** Builtins ******"
        # show python keywords
        print "\n==== Python Key Words ===="
        print show_list(PYTHON_KEY_WORDS,textwidth=TEXT_WIDTH)
        # get builtins
        d = self.interp.symbol_table.list_builtins(_skip=_skip)
        self._print_show(d)
        return SUCCESS

    #############################################################
    def _show(self,symbol=None,tunnel=False,_skip=True):
        """
        """
        if symbol:
            ty = self.interp.symbol_table.sym_type(symbol)
            if ty == None:
                print "Symbol '%s' not found" % symbol
                return SUCCESS
            elif ty in ('oth'):
                print "Symbol '%s' of uknown type" % symbol
                print type(self.interp.symbol_table.get_symbol(symbol))
                return SUCCESS
        else: 
            ty = None
            print "\n==== Commands ===="
            tmp = self.commands.keys()
            tmp = tmp + self.pds_commands.keys()
            tmp.sort()
            print show_list(tmp,textwidth=TEXT_WIDTH)

        if ty == 'var':
            tmp = self.interp.symbol_table.get_symbol(symbol)
            print repr(tmp)
            return SUCCESS
        elif ty == 'fnc':
            tmp = self.interp.symbol_table.get_symbol(symbol)
            print help(tmp)
            return SUCCESS
        else:
            d = self.interp.symbol_table.list_symbols(symbol=symbol,
                                                      tunnel=tunnel,
                                                      _skip=_skip)
            self._print_show(d)
        return SUCCESS

    #############################################################
    def _print_show(self,d):
        """
        Print stuff
        """
        if d == None: return SUCCESS
        if len(d['mod'])> 0:
            print "\n==== Modules ===="
            print show_list(d['mod'],textwidth=TEXT_WIDTH)
        if len(d['fnc'])> 0:
            print "\n==== Functions / Classes ===="
            print show_list(d['fnc'],textwidth=TEXT_WIDTH)
        if len(d['ins'])> 0:
            print "\n==== Instances ===="
            print show_list(d['ins'],textwidth=TEXT_WIDTH)
        if len(d['var'])> 0:
            print "\n==== Variables ===="
            print show_list(d['var'],textwidth=TEXT_WIDTH)
        if len(d['oth'])> 0:
            print "\n==== Other Python Objects ===="
            print show_list(d['oth'],textwidth=TEXT_WIDTH)
        print "\n"
        return SUCCESS
Exemplo n.º 4
0
class Shell(_NumShell):
    __doc__ = """
    ****************************************
    * Python Data Shell                    *
    * Type 'help' to get started           *
    ****************************************
    """

    max_save_lines = 500

    #############################################################
    def __init__(self,
                 args=[],
                 stdin=None,
                 stdout=None,
                 completekey='tab',
                 intro=None,
                 debug=False,
                 GUI='TkAgg'):
        """
        Init
        """
        # Prompt
        self.ps1 = "pds>"
        self.ps2 = "...>"

        # Set stdin/out
        if stdin is not None:
            sys.stdin = self.stdin = stdin
            self.use_rawinput = False
        else:
            self.stdin = sys.stdin
            self.use_rawinput = True
        if stdout is not None:
            sys.stdout = self.stdout = stdout
            #sys.stderr = stdout
        else:
            self.stdout = sys.stdout

        # Startup strings
        self.intro = self.__doc__
        if intro:
            self.intro = self.intro + intro
        if self.intro:
            self.stdout.write(str(self.intro) + "\n")

        # Interpretor
        self.interp = Interpretor()

        # Data and vars
        self.debug = debug
        self.GUI = GUI
        self.queue = []
        self.error_break = True
        self.commands = {}

        # Builtin commands
        self.pds_commands = {
            'quit': self.do_quit,
            'exit': self.do_quit,
            #'EOF':self.do_quit,
            'show': self.do_show,
            'help': self.do_help,
            'load': self.do_load,
            'debug': self.do_debug,
            'fexec': self.do_execfile,
            'save': self.do_save,
            'restore': self.do_restore,
            'clear': self.do_clear,
            'addcmd': self.do_addcmd,
            'alias': self.do_addalias
        }

        # run startup
        self.startup(args=args)

        # check
        for cmd in self.pds_commands.keys():
            if cmd in PYTHON_KEY_WORDS:
                print "Warning: command '%s' is a python keyword" % cmd

        # setup readline if have it. -- add later
        self.completekey = completekey

    #############################################################
    def startup(self, args=[]):
        """
        set up builtins and exec startup arguments
        """

        # Builtins
        from builtins import __pdsbuiltins__
        self.interp.symbol_table.data["__pds__"] = __pdsbuiltins__

        # add module functions to __builtins__
        startup = []
        startup.append("__builtins__.update({'group':__pds__.group})")
        startup.append("__builtins__.update({'ls':__pds__._ls})")
        startup.append("__builtins__.update({'cd':__pds__._cd})")
        startup.append("__builtins__.update({'pwd':__pds__._cwd})")
        startup.append("__builtins__.update({'rimport':__pds__.rimport})")
        startup.append("__builtins__.update({'path':__pds__._path})")
        startup.append("__builtins__.update({'source':__pds__.source})")
        startup.append("__builtins__.update({'info':__pds__.info})")

        # functions we want to use with command syntax
        self.do_addcmd('ls', "__pds__.ls")
        self.do_addcmd('pwd', "__pds__.pwd")
        self.do_addcmd('cd', "__pds__.cd")
        self.do_addcmd('more', "__pds__.more")
        self.do_addcmd('path', "__pds__.path")
        self.do_addcmd('rimport', "__pds__.rimport")
        self.do_addcmd('source', "__pds__.source")
        self.do_addcmd('info', "__pds__.info")

        # if numeric/scientific stuff is included
        # load it. Note leave this here in case there
        # are cmd line args below that depend on numerics...
        if hasattr(self, 'num_setup'):
            tmp = self.num_setup()
            startup = startup + tmp

        # any other args add to queue
        if type(args) == types.ListType:
            for a in args:
                s = a.strip()
                startup.append(s)
        self.queue = startup

        # execute the queue here before moving on
        # otherwise startup stuff is not available
        # to files executed before we start the loop
        # also allow it to run through even if there is
        # an error...
        self.error_break = False
        self.exec_queue()
        self.error_break = True

        return

    ############################################################################
    def loop(self, ):
        """
        The prompt loop
        
        Repeatedly issue a prompt, accept input, parse an initial prefix
        off the received input, and dispatch to action methods, passing them
        the remainder of the line as argument.  Modified from cmd.Cmd.cmdloop.

        Note for the python interpretor to work it is important that blank
        lines are passed, and that lines are not stripped entirely (ie leave
        white space on left)
        """
        stop = COMPLETE
        while stop != QUIT:
            if stop == CONTINUE:
                prompt = self.ps2
            else:
                prompt = self.ps1
            if self.use_rawinput:
                try:
                    line = raw_input(prompt)
                except EOFError:
                    line = 'quit'
            else:
                self.stdout.write(prompt)
                self.stdout.flush()
                line = self.stdin.readline()
                if line == None:
                    line = 'quit'
                else:
                    #line = line[:-1]    # chop \n
                    line = line.rstrip()  # chop \n
            # split on ';' and exec the line
            lines = split_cmd_line(line)
            for s in lines:
                stop = self.exec_line(s)
                if stop == QUIT: break
        return SUCCESS

    #############################################################
    def exec_queue(self):
        """
        Execute lines in self.queue
        """
        if len(self.queue) == 0:
            return SUCCESS
        for line in self.queue:
            # split on ';' and exec the line
            lines = split_cmd_line(line)
            for s in lines:
                stop = self.exec_line(s)
                if stop == QUIT:
                    self.queue = []
                    return QUIT
                elif (stop == EXECERROR) and (self.error_break == True):
                    self.queue = []
                    print "Error executing shell.queue"
                    return EXECERROR
        return SUCCESS

    #############################################################
    def exec_line(self, line):
        """
        Exec a single line
        
        This method first inspect the first token of the command line
            If its a '!' send it to the shell
            If its a 'command' call _exec_cmd()
            Otherwise pass to the interpretor

        The return value from this method should always be one of:
            QUIT, SUCCESS, COMPLETE, CONTINUE, EXECERROR
        Exceptions from the interpretor are handled here.
        
        Note for the python interpretor to work it is important that blank
        lines are passed in and that lines are not stripped entirely
        (ie leave left white space). We also let the interpretor handle
        comments (#).
        """
        s = str(line).rstrip()
        try:
            if len(s) > 0:
                #if self.debug: print '**line:%s' % (s)
                # see if its shell cmd
                if s.startswith('!'):
                    os.system(s[1:])
                    return COMPLETE
                # look for commands
                words = s.split()
                cmd = words[0].strip()
                if len(words) > 1:
                    idx = s.find(cmd) + len(cmd)
                    arg = s[idx:].strip()
                else:
                    arg = ''
            else:
                cmd = None
            # if its a cmd execute it in _exec_cmd
            if cmd:
                if cmd in self.pds_commands.keys():
                    return self._exec_cmd(cmd, arg)
                elif cmd in self.commands.keys():
                    return self._exec_cmd(cmd, arg)
            # otherwise pass to the interpretor
            return self.interp.execute(s)
        except:
            err_str = "Error executing line:\n'%s'" % s
            if self.debug:
                PrintExceptErr(err_str, print_trace=True)
            else:
                #PrintExceptErr(err_str,print_trace=False)
                PrintExceptErr(err_str, print_trace=True)
            # clear the exception and interpretors buffer
            # sys.exc_clear()
            self.interp.console.resetbuffer()
            return EXECERROR

    #############################################################
    def _exec_cmd(self, cmd, arg):
        """
        execute commands
        
        Note only call this from exec_line for proper
        error / exception handling! 
        """
        ret = None
        # local commands
        if cmd in self.pds_commands.keys():
            fun = self.pds_commands[cmd]
            ret = fun(arg)
        # other commands
        elif cmd in self.commands.keys():
            cmd_fun = self.commands[cmd]
            s = cmd_fun + ' ' + arg
            s = command2expr(s, symtable=self.interp.symbol_table)
            if self.debug: print '**command repacked: ', s
            ret = self.interp.execute(s)
        else:
            print "Error: uknown command: %s" % cmd
        #if ret == None:
        if ret not in (QUIT, SUCCESS, COMPLETE, CONTINUE, EXECERROR):
            return COMPLETE
        else:
            return ret

    #############################################################

    #############################################################
    ## Builtin commands
    #############################################################

    #############################################################
    def do_quit(self, arg):
        """
        Quit the shell 
        """
        try:
            self.close_pyplot()
        except:
            pass
        return QUIT

    #############################################################
    def do_debug(self, arg):
        """
        Toggle debug flag 
        """
        if self.debug == True:
            print "Debug off"
            self.debug = False
        else:
            print "Debug on"
            self.debug = True
        return SUCCESS

    #############################################################
    def do_load(self, fname):
        """
        Load file of pds commands for execution

        Note that file execution will halt if there is an
        error in the file.  This default behaviour can
        be changed by setting the flag self.error_break = False

        If the file has a '.sav' extension we first try to read it
        using restore (ie assume its a pickle)
        """
        if fname[-4:] == '.sav':
            if self._restore(fname) == 1: return COMPLETE

        if os.path.exists(fname) and os.path.isfile(fname):
            f = open(fname)
            lines = f.readlines()
            f.close()
        else:
            print 'File error: cannot find file to load for %s ' % fname
            return COMPLETE
        if len(lines) == 0: return COMPLETE

        # execute the lines through the queue
        self.queue = []
        self.queue.extend(lines)
        ret = self.exec_queue()
        if ret == EXECERROR:
            print "Error in file %s" % fname
        if self.debug: print 'load done'
        return COMPLETE

    #############################################################
    def do_execfile(self, fname):
        """
        Execute a file of python code

        Note that the file will be executed as if it was
        imported into the '__main__' namespace
        """
        if not os.path.exists(fname):
            files = []
            for p in sys.path:
                f = os.path.join(p, fname)
                if os.path.exists(f):
                    files.append(f)
            if len(files) == 0:
                print "File '%s' not found" % fname
                return SUCCESS
            elif len(files) == 1:
                fname = files[0]
            else:
                print "Warning multiple files found on path"
                print "Please specify the full path in fname or change the"
                print "working directory to the directory with the correct file"
                for f in files:
                    print "    %s" % f
                return SUCCESS
        return self.interp.execute_file(fname)

    #############################################################
    def do_addcmd(self, *arg):
        """
        Add a command interface to a function
        
        Allows a function to be called with command syntax.
          >>addcmd mycmd, myfun
        results in
          >>mycmd arg1, arg2, key=xx
        being repackaged to
          >>myfun(arg1,arg2,key=xx)
        which is then sent to the interpretor
        """
        if len(arg) == 1:
            arg = arg[0]
            words = arg.split(',')
            if len(words) != 2:
                print "Error parsing cmd/func names"
            cmd_name = words[0].strip()
            func_name = words[1].strip()
        elif len(arg) == 2:
            cmd_name = arg[0].strip()
            func_name = arg[1].strip()
        else:
            print "Wrong number of arguments"
            return SUCCESS
        cmd_name = trimstring(cmd_name)
        func_name = trimstring(func_name)

        if len(cmd_name) == 0 or len(func_name) == 0:
            print "Error parsing cmd/func names"
            return SUCCESS

        # do a check
        if cmd_name in PYTHON_KEY_WORDS:
            print "Error: command '%s' is a python keyword" % cmd_name
            return SUCCESS

        if cmd_name in self.pds_commands.keys():
            print "Error: command '%s' is a builtin keyword" % cmd_name
            return SUCCESS

        if cmd_name in self.commands.keys():
            print "Warning: overwriting command '%s' " % cmd_name
            self.commands[cmd_name] = func_name
        else:
            self.commands.update({cmd_name: func_name})
        return SUCCESS

    #############################################################
    def do_addalias(self, *arg):
        """
        Create a command shortcut for a function.

        The alias is just a way of making shortcuts for repetitive taks
          >>alias myalias, 'myfun(args)'
        results in
          >>myalias
        being repackaged to
          >>myfun(args)
        which is then sent to the interpretor

        Note alias's are added to the command list
        (see 'show' and 'help addcmd')

        Example:
        --------
        pds>alias "code", "cd('~/code')"
        pds>code
        pds>pwd
        /home/bob/code
        """
        if len(arg) == 1:
            arg = arg[0]
            words = arg.split(',')
            if len(words) != 2:
                print "Error parsing cmd/func names"
            cmd_name = words[0].strip()
            func_name = words[1].strip()
        elif len(arg) == 2:
            cmd_name = arg[0].strip()
            func_name = arg[1].strip()
        else:
            print "Wrong number of arguments"
            return SUCCESS
        cmd_name = trimstring(cmd_name)
        func_name = trimstring(func_name)

        if len(cmd_name) == 0 or len(func_name) == 0:
            print "Error parsing cmd/func names"
            return SUCCESS

        # do a check
        if cmd_name in PYTHON_KEY_WORDS:
            print "Error: command '%s' is a python keyword" % cmd_name
            return SUCCESS

        s = "__%s__ = lambda : %s" % (cmd_name, func_name)
        ret = self.exec_line(s)
        s = "addcmd '%s', '__%s__'" % (cmd_name, cmd_name)
        ret = self.exec_line(s)

    ##############################################################

    ##############################################################
    ## save / restore state and clear variables
    ##############################################################

    ##############################################################
    def do_save(self, args):
        """
        Save program state to a file
        
        Note this may fail since not all
        objects can be pickled... needs improvement!

        Examples:
        ---------
        >>save            # save all to default fname
        >>save fname      # save all to fname
        >>save data fname # save data to file
        """
        from pds.shellutil import pickle_1 as pickle
        #from pds.shellutil import pickle_2 as pickle

        # parse input, get filename
        args = split_args(args)
        dname = None
        if len(args) == 0:
            t = time.strftime("%Y_%m_%d_%H%M", time.localtime())
            fname = 'save_%s.sav' % t
        else:
            if len(args) == 1:
                fname = args[0]
            elif len(args) == 2:
                dname = args[0]
                fname = args[1]
            else:
                return

        # get data dictionary
        data = self.interp.symbol_table.get_data_dict(name=dname)
        if data == None: return SUCCESS

        # pickle it
        pickle(data, fname)

    ##############################################################
    def do_restore(self, fname):
        """
        Restore state from a file that was created with save
        """
        self._restore(fname)
        return SUCCESS

    def _restore(self, fname):
        from pds.shellutil import unpickle_1 as unpickle
        #from pds.shellutil import unpickle_2 as unpickle

        pdata = unpickle(fname)
        if pdata == None:
            print "No data"
            return 0
        if len(pdata) > 0:
            self.interp.symbol_table.put_data_dict(pdata)
            return 1
        return 0

    ##############################################################
    def do_clear(self, arg):
        """
        Clear all 'data' from the workspace

        This clears everything that looks like a variable, ie
        simple data types and class instances
        """
        args = split_args(arg)
        if len(args) == 0:
            dname = [None]
        else:
            dname = args
        for d in dname:
            data = self.interp.symbol_table.get_data_dict(name=d)
            for key in data.keys():
                del self.interp.symbol_table.data[key]
        return SUCCESS

    ##############################################################

    #############################################################
    ##  Help and Show
    #############################################################

    ##############################################################
    def do_help(self, arg):
        """
        Display help.

        Example:
        --------
        >>help     # displays help options
        """
        if arg == None or len(arg) == 0:
            #print self.help_str
            print HELP_STR
            return SUCCESS

        (opts, args) = getopt.getopt(arg.split(), "u", ["use"])
        for key, val in opts:
            if key in ("-u", "--use"):
                #print self.help_use_str
                print HELP_USE_STR
        for a in args:
            if a in self.pds_commands.keys():
                #tmp = getattr(self,a)
                tmp = self.pds_commands[a]
                help(tmp)
            elif a in self.commands.keys():
                cmd_fun = self.commands[a]
                s = "help(%s)" % cmd_fun
                ret = self.exec_line(s)
            else:
                s = "help(%s)" % a
                ret = self.exec_line(s)
        return SUCCESS

    #############################################################
    def do_show(self, arg):
        """
        List functions and variables.

        Options:  >>show -ath group
        --------
        -a = show all (include symbols with names that have a leading '_' )
        -b = show builtins (defined in __builtins__ ).  Note this option
             trumps tunnel (ie -t is ignored).  
        -t = tunnel, display attributes within a class instance or module.
             Note modules are only displayed with one level of tunneling
             (ie -t option is ignored if a module is passed as an argument).
             However, this will tunnel on all class instances.
        """
        tunnel = False
        skip = True
        (opts, args) = getopt.getopt(arg.split(), "abt",
                                     ["all", "builtins", "tunnel"])
        for key, val in opts:
            if key in ("-a", "--all"):
                skip = False
            if key in ("-b", "--builtin"):
                self._show_builtins(_skip=skip)
                return
            if key in ("-t", "--tunnel"):
                tunnel = True
        if len(args) > 0:
            #arg = ' '.join(args)
            for a in args:
                self._show(symbol=a, tunnel=tunnel, _skip=skip)
        else:
            self._show(tunnel=tunnel, _skip=skip)
        return SUCCESS

    #############################################################
    def _show_builtins(self, _skip=True):
        """
        """
        print "\n***** Builtins ******"
        # show python keywords
        print "\n==== Python Key Words ===="
        print show_list(PYTHON_KEY_WORDS, textwidth=TEXT_WIDTH)
        # get builtins
        d = self.interp.symbol_table.list_builtins(_skip=_skip)
        self._print_show(d)
        return SUCCESS

    #############################################################
    def _show(self, symbol=None, tunnel=False, _skip=True):
        """
        """
        if symbol:
            ty = self.interp.symbol_table.sym_type(symbol)
            if ty == None:
                print "Symbol '%s' not found" % symbol
                return SUCCESS
            elif ty in ('oth'):
                print "Symbol '%s' of uknown type" % symbol
                print type(self.interp.symbol_table.get_symbol(symbol))
                return SUCCESS
        else:
            ty = None
            print "\n==== Commands ===="
            tmp = self.commands.keys()
            tmp = tmp + self.pds_commands.keys()
            tmp.sort()
            print show_list(tmp, textwidth=TEXT_WIDTH)

        if ty == 'var':
            tmp = self.interp.symbol_table.get_symbol(symbol)
            print repr(tmp)
            return SUCCESS
        elif ty == 'fnc':
            tmp = self.interp.symbol_table.get_symbol(symbol)
            print help(tmp)
            return SUCCESS
        else:
            d = self.interp.symbol_table.list_symbols(symbol=symbol,
                                                      tunnel=tunnel,
                                                      _skip=_skip)
            self._print_show(d)
        return SUCCESS

    #############################################################
    def _print_show(self, d):
        """
        Print stuff
        """
        if d == None: return SUCCESS
        if len(d['mod']) > 0:
            print "\n==== Modules ===="
            print show_list(d['mod'], textwidth=TEXT_WIDTH)
        if len(d['fnc']) > 0:
            print "\n==== Functions / Classes ===="
            print show_list(d['fnc'], textwidth=TEXT_WIDTH)
        if len(d['ins']) > 0:
            print "\n==== Instances ===="
            print show_list(d['ins'], textwidth=TEXT_WIDTH)
        if len(d['var']) > 0:
            print "\n==== Variables ===="
            print show_list(d['var'], textwidth=TEXT_WIDTH)
        if len(d['oth']) > 0:
            print "\n==== Other Python Objects ===="
            print show_list(d['oth'], textwidth=TEXT_WIDTH)
        print "\n"
        return SUCCESS