M CallTipWindow.py
M CallTips.py

Calltip fetch was erroring when an Edit window was used without a Shell.
Also, fix CallTipWindow.py so test code will run and add a comment about a
bug which causes the calltip window to override all others.
diff --git a/Lib/idlelib/CallTipWindow.py b/Lib/idlelib/CallTipWindow.py
index 1542fe7..d089a87 100644
--- a/Lib/idlelib/CallTipWindow.py
+++ b/Lib/idlelib/CallTipWindow.py
@@ -1,7 +1,9 @@
-# A CallTip window class for Tkinter/IDLE.
-# After ToolTip.py, which uses ideas gleaned from PySol
+"""A CallTip window class for Tkinter/IDLE.
 
-# Used by the CallTips IDLE extension.
+After ToolTip.py, which uses ideas gleaned from PySol
+Used by the CallTips IDLE extension.
+
+"""
 from Tkinter import *
 
 class CallTip:
@@ -13,13 +15,11 @@
         self.x = self.y = 0
 
     def showtip(self, text):
-        # SF bug 546078:  IDLE calltips cause application error.
-        # There were crashes on various Windows flavors, and even a
-        # crashing X server on Linux, with very long calltips.
+        " Display text in calltip window"
+        # truncate overly long calltip
         if len(text) >= 79:
             text = text[:75] + ' ...'
         self.text = text
-
         if self.tipwindow or not self.text:
             return
         self.widget.see("insert")
@@ -27,6 +27,10 @@
         x = x + self.widget.winfo_rootx() + 2
         y = y + cy + self.widget.winfo_rooty()
         self.tipwindow = tw = Toplevel(self.widget)
+        # XXX 12 Dec 2002 KBK The following command has two effects: It removes
+        #     the calltip window border (good) but also causes (at least on
+        #     Linux) the calltip to show as a top level window, burning through
+        #     any other window dragged over it.  Also, shows on all viewports!
         tw.wm_overrideredirect(1)
         tw.wm_geometry("+%d+%d" % (x, y))
         try:
@@ -68,7 +72,7 @@
         text.bind("<<calltip-hide>>", self.calltip_hide)
 
         text.focus_set()
-        # root.mainloop() # not in idle
+        root.mainloop()
 
     def calltip_show(self, event):
         self.calltip.showtip("Hello world")
diff --git a/Lib/idlelib/CallTips.py b/Lib/idlelib/CallTips.py
index 7a3fe13..fa43032 100644
--- a/Lib/idlelib/CallTips.py
+++ b/Lib/idlelib/CallTips.py
@@ -1,9 +1,10 @@
 """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.
+Call Tips are floating windows which display function, class, and method
+parameter and docstring information when you type an opening parenthesis, and
+which disappear when you type a closing parenthesis.
+
+Future plans include extending the functionality to include class attributes.
 
 """
 import sys
@@ -82,8 +83,21 @@
         return str[i:]
         
     def fetch_tip(self, name):
-        interp = self.editwin and self.editwin.flist.pyshell.interp
-        rpcclt = interp and interp.rpcclt
+        """Return the argument list and docstring of a function or class 
+        
+        If there is a Python subprocess, get the calltip there.  Otherwise,
+        either fetch_tip() is running in the subprocess itself or it was called
+        in an IDLE EditorWindow before any script had been run.
+
+        The subprocess environment is that of the most recently run script.  If
+        two unrelated modules are being edited some calltips in the current
+        module may be inoperative if the module was not the last to run.
+
+        """  
+        try:
+            rpcclt = self.editwin.flist.pyshell.interp.rpcclt
+        except:
+            rpcclt = None
         if rpcclt:
             return rpcclt.remotecall("exec", "get_the_calltip",
                                      (name,), {})
@@ -92,6 +106,7 @@
             return get_arg_text(entity)
 
     def get_entity(self, name):
+        "Lookup name in a namespace spanning sys.modules and __main.dict__"
         if name:
             namespace = sys.modules.copy()
             namespace.update(__main__.__dict__)
@@ -112,7 +127,7 @@
     return None
 
 def get_arg_text(ob):
-    # Get a string describing the arguments for the given object.
+    "Get a string describing the arguments for the given object"
     argText = ""
     if ob is not None:
         argOffset = 0