M CallTips.py      Add support for getting calltip from subprocess,
                   refactor a bit and clean up.

M PyShell.py       Cosmetic changes, delete blank lines, add # on some
                   blank lines.

M rpc.py           Add more debugging capability

M run.py           Add support for getting calltip from subprocess
                   Move import statements
diff --git a/Lib/idlelib/CallTips.py b/Lib/idlelib/CallTips.py
index e90da49..7a3fe13 100644
--- a/Lib/idlelib/CallTips.py
+++ b/Lib/idlelib/CallTips.py
@@ -1,30 +1,38 @@
-# CallTips.py - An IDLE extension that provides "Call Tips" - ie, a floating window that
-# displays parameter information as you open parens.
+"""CallTips.py - An IDLE Extension to Jog Your Memory
 
+Call Tips are floating windows which display function/method parameter
+information as you open the parameter parenthesis, and which disappear when you
+type the closing parenthesis.  Future plans include extending the functionality
+to include class attributes.
+
+"""
+import sys
 import string
 import types
 
+import CallTipWindow
+
+import __main__
+
 class CallTips:
 
     menudefs = [
     ]
 
-    def __init__(self, editwin):
+    def __init__(self, editwin=None):
+        if editwin == None:  # subprocess and test
+            self.editwin = None
+            return
         self.editwin = editwin
         self.text = editwin.text
         self.calltip = None
-        if hasattr(self.text, "make_calltip_window"):
-            self._make_calltip_window = self.text.make_calltip_window
-        else:
-            self._make_calltip_window = self._make_tk_calltip_window
+        self._make_calltip_window = self._make_tk_calltip_window
 
     def close(self):
         self._make_calltip_window = None
 
-    # Makes a Tk based calltip window.  Used by IDLE, but not Pythonwin.
-    # See __init__ above for how this is used.
     def _make_tk_calltip_window(self):
-        import CallTipWindow
+        # See __init__ for usage
         return CallTipWindow.CallTip(self.text)
 
     def _remove_calltip_window(self):
@@ -34,7 +42,8 @@
 
     def paren_open_event(self, event):
         self._remove_calltip_window()
-        arg_text = get_arg_text(self.get_object_at_cursor())
+        name = self.get_name_at_cursor()
+        arg_text = self.fetch_tip(name)
         if arg_text:
             self.calltip_start = self.text.index("insert")
             self.calltip = self._make_calltip_window()
@@ -53,7 +62,8 @@
             # or off the calltip line, then cancel the tip.
             # (Later need to be smarter about multi-line, etc)
             if self.text.compare("insert", "<=", self.calltip_start) or \
-               self.text.compare("insert", ">", self.calltip_start + " lineend"):
+               self.text.compare("insert", ">", self.calltip_start
+                                 + " lineend"):
                 self._remove_calltip_window()
         return "" #so the event is handled normally.
 
@@ -61,29 +71,34 @@
         self._remove_calltip_window()
         return "" #so the event is handled normally.
 
-    def get_object_at_cursor(self,
-                wordchars="._" + string.ascii_letters + string.digits):
-        # Usage of ascii_letters is necessary to avoid UnicodeErrors
-        # if chars contains non-ASCII.
+    __IDCHARS = "._" + string.ascii_letters + string.digits
 
-        # XXX - This needs to be moved to a better place
-        # so the "." attribute lookup code can also use it.
-        text = self.text
-        chars = text.get("insert linestart", "insert")
-        i = len(chars)
-        while i and chars[i-1] in wordchars:
-            i = i-1
-        word = chars[i:]
-        if word:
-            # How is this for a hack!
-            import sys, __main__
+    def get_name_at_cursor(self):
+        idchars = self.__IDCHARS
+        str = self.text.get("insert linestart", "insert")
+        i = len(str)
+        while i and str[i-1] in idchars:
+            i -= 1
+        return str[i:]
+        
+    def fetch_tip(self, name):
+        interp = self.editwin and self.editwin.flist.pyshell.interp
+        rpcclt = interp and interp.rpcclt
+        if rpcclt:
+            return rpcclt.remotecall("exec", "get_the_calltip",
+                                     (name,), {})
+        else:
+            entity = self.get_entity(name)
+            return get_arg_text(entity)
+
+    def get_entity(self, name):
+        if name:
             namespace = sys.modules.copy()
             namespace.update(__main__.__dict__)
             try:
-                return eval(word, namespace)
+                return eval(name, namespace)
             except:
-                pass
-        return None # Can't find an object.
+                return None
 
 def _find_constructor(class_ob):
     # Given a class object, return a function object used for the
@@ -142,7 +157,6 @@
             if argText:
                 argText += "\n"
             argText += doc[:pos]
-
     return argText
 
 #################################################
@@ -168,17 +182,21 @@
         def t5(self, a, *args): "(a, ...)"
         def t6(self, a, b=None, *args, **kw): "(a, b=None, ..., ***)"
 
-    def test( tests ):
+    def test(tests):
+        ct = CallTips()
         failed=[]
         for t in tests:
             expected = t.__doc__ + "\n" + t.__doc__
-            if get_arg_text(t) != expected:
+            name = t.__name__
+            arg_text = ct.fetch_tip(name)
+            if arg_text != expected:
                 failed.append(t)
-                print "%s - expected %s, but got %s" % (t, `expected`, `get_arg_text(t)`)
+                print "%s - expected %s, but got %s" % (t, expected,
+                                                        get_arg_text(entity))
         print "%d of %d tests failed" % (len(failed), len(tests))
 
     tc = TC()
-    tests = t1, t2, t3, t4, t5, t6, \
-            TC, tc.t1, tc.t2, tc.t3, tc.t4, tc.t5, tc.t6
+    tests = (t1, t2, t3, t4, t5, t6, 
+             TC, tc.t1, tc.t2, tc.t3, tc.t4, tc.t5, tc.t6)
 
     test(tests)
diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py
index 195942f..790609a 100644
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -414,7 +414,6 @@
         if self.tkconsole.executing:
             display_executing_dialog()
             return
-        #
         self.checklinecache()
         if self.save_warnings_filters is not None:
             warnings.filters[:] = self.save_warnings_filters
@@ -425,7 +424,6 @@
             self.active_seq = self.rpcclt.asynccall("exec", "runcode",
                                                     (code,), {})
             return
-        #
         try:
             self.tkconsole.beginexecuting()
             try:
@@ -444,7 +442,6 @@
                     self.showtraceback()
             except:
                 self.showtraceback()
-        #        
         finally:
             self.tkconsole.endexecuting()
 
@@ -480,14 +477,14 @@
             fixwordbreaks(root)
             root.withdraw()
             flist = PyShellFileList(root)
-
+        #
         OutputWindow.__init__(self, flist, None, None)
-
+        #
         import __builtin__
         __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
-
+        #
         self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
-
+        #
         text = self.text
         text.configure(wrap="char")
         text.bind("<<newline-and-indent>>", self.enter_callback)
@@ -499,7 +496,7 @@
         text.bind("<<toggle-debugger>>", self.toggle_debugger)
         text.bind("<<open-python-shell>>", self.flist.open_shell)
         text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
-
+        #
         self.save_stdout = sys.stdout
         self.save_stderr = sys.stderr
         self.save_stdin = sys.stdin
@@ -510,9 +507,9 @@
             sys.stdout = self.stdout
             sys.stderr = self.stderr
             sys.stdin = self
-
+        #
         self.history = self.History(self.text)
-
+        #
         if use_subprocess:
             self.interp.start_subprocess()
 
diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py
index cd11dfa..eeb1b4e 100644
--- a/Lib/idlelib/rpc.py
+++ b/Lib/idlelib/rpc.py
@@ -177,9 +177,12 @@
     def remotecall(self, oid, methodname, args, kwargs):
         self.debug("remotecall:", oid, methodname, args, kwargs) 
         seq = self.asynccall(oid, methodname, args, kwargs)
-        return self.asyncreturn(seq)
+        ret = self.asyncreturn(seq)
+        self.debug("return:", ret)
+        return ret
 
     def asynccall(self, oid, methodname, args, kwargs):
+        self.debug("asyncall:", oid, methodname, args, kwargs)
         request = ("call", (oid, methodname, args, kwargs))
         seq = self.putrequest(request)
         return seq
diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index 5b3c733..5b9864c 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -1,23 +1,31 @@
 import sys
 import time
 import socket
+
+import CallTips
+import RemoteDebugger
+import RemoteObjectBrowser
+import StackViewer
 import rpc
 
+import __main__
+
 def main():
     """Start the Python execution server in a subprocess
 
-    In Idle, RPCServer is instantiated with handlerclass MyHandler, which
-    inherits register/unregister methods from RPCHandler via the mix-in class
-    SocketIO.
+    In the Python subprocess, RPCServer is instantiated with handlerclass
+    MyHandler, which inherits register/unregister methods from RPCHandler via
+    the mix-in class SocketIO.
 
-    When the RPCServer is instantiated, the TCPServer initialization creates an
-    instance of run.MyHandler and calls its handle() method.  handle()
-    instantiates a run.Executive, passing it a reference to the MyHandler
-    object.  That reference is saved as an attribute of the Executive instance.
-    The Executive methods have access to the reference and can pass it on to
-    entities that they command (e.g. RemoteDebugger.Debugger.start_debugger()).
-    The latter, in turn, can call MyHandler(SocketIO) register/unregister
-    methods via the reference to register and unregister themselves.
+    When the RPCServer svr is instantiated, the TCPServer initialization
+    creates an instance of run.MyHandler and calls its handle() method.
+    handle() instantiates a run.Executive object, passing it a reference to the
+    MyHandler object.  That reference is saved as attribute rpchandler of the
+    Executive instance.  The Executive methods have access to the reference and
+    can pass it on to entities that they command
+    (e.g. RemoteDebugger.Debugger.start_debugger()).  The latter, in turn, can
+    call MyHandler(SocketIO) register/unregister methods via the reference to
+    register and unregister themselves.
 
     """
     port = 8833
@@ -55,28 +63,28 @@
 
     def __init__(self, rpchandler):
         self.rpchandler = rpchandler
-        import __main__
         self.locals = __main__.__dict__
+        self.calltip = CallTips.CallTips()
 
     def runcode(self, code):
         exec code in self.locals
 
     def start_the_debugger(self, gui_adap_oid):
-        import RemoteDebugger
         return RemoteDebugger.start_debugger(self.rpchandler, gui_adap_oid)
 
     def stop_the_debugger(self, idb_adap_oid):
         "Unregister the Idb Adapter.  Link objects and Idb then subject to GC"
         self.rpchandler.unregister(idb_adap_oid)
 
+    def get_the_calltip(self, name):
+        return self.calltip.fetch_tip(name)
+
     def stackviewer(self, flist_oid=None):
         if not hasattr(sys, "last_traceback"):
             return None
         flist = None
         if flist_oid is not None:
             flist = self.rpchandler.get_remote_proxy(flist_oid)
-        import RemoteObjectBrowser
-        import StackViewer
         tb = sys.last_traceback
         while tb and tb.tb_frame.f_globals["__name__"] in ["rpc", "run"]:
             tb = tb.tb_next