diff options
author | Kurt B. Kaiser <kbk@shore.net> | 2002-10-10 08:25:24 (GMT) |
---|---|---|
committer | Kurt B. Kaiser <kbk@shore.net> | 2002-10-10 08:25:24 (GMT) |
commit | 5afa1dfb72311b8360904363cc3ebb7cbfc8b6e4 (patch) | |
tree | 33287ebdb0fd27d9fdea4a8210b1a259df26c5b7 | |
parent | 853ddd5cb96981966b935ed75bf8af0cfd0bee24 (diff) | |
download | cpython-5afa1dfb72311b8360904363cc3ebb7cbfc8b6e4.zip cpython-5afa1dfb72311b8360904363cc3ebb7cbfc8b6e4.tar.gz cpython-5afa1dfb72311b8360904363cc3ebb7cbfc8b6e4.tar.bz2 |
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
-rw-r--r-- | Lib/idlelib/CallTips.py | 92 | ||||
-rw-r--r-- | Lib/idlelib/PyShell.py | 17 | ||||
-rw-r--r-- | Lib/idlelib/rpc.py | 5 | ||||
-rw-r--r-- | Lib/idlelib/run.py | 38 |
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 |