summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/idlelib')
-rw-r--r--Lib/idlelib/CallTips.py92
-rw-r--r--Lib/idlelib/PyShell.py17
-rw-r--r--Lib/idlelib/rpc.py5
-rw-r--r--Lib/idlelib/run.py38
4 files changed, 89 insertions, 63 deletions
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 @@ class CallTips:
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 @@ class CallTips:
# 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 @@ class CallTips:
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.
-
- # 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__
+ __IDCHARS = "._" + string.ascii_letters + string.digits
+
+ 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 @@ def get_arg_text(ob):
if argText:
argText += "\n"
argText += doc[:pos]
-
return argText
#################################################
@@ -168,17 +182,21 @@ if __name__=='__main__':
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 @@ class ModifiedInterpreter(InteractiveInterpreter):
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 @@ class ModifiedInterpreter(InteractiveInterpreter):
self.active_seq = self.rpcclt.asynccall("exec", "runcode",
(code,), {})
return
- #
try:
self.tkconsole.beginexecuting()
try:
@@ -444,7 +442,6 @@ class ModifiedInterpreter(InteractiveInterpreter):
self.showtraceback()
except:
self.showtraceback()
- #
finally:
self.tkconsole.endexecuting()
@@ -480,14 +477,14 @@ class PyShell(OutputWindow):
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 @@ class PyShell(OutputWindow):
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 @@ class PyShell(OutputWindow):
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 @@ class SocketIO:
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 @@ class Executive:
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