summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKurt B. Kaiser <kbk@shore.net>2002-09-05 02:31:20 (GMT)
committerKurt B. Kaiser <kbk@shore.net>2002-09-05 02:31:20 (GMT)
commit63857a454d85fda475264575b7c1a031970219a0 (patch)
tree1b957ef7888fe190e287eeb34dc2bd6922a81a7c
parent342456d5d25be692c3ddd43d0446b52555251ccc (diff)
downloadcpython-63857a454d85fda475264575b7c1a031970219a0.zip
cpython-63857a454d85fda475264575b7c1a031970219a0.tar.gz
cpython-63857a454d85fda475264575b7c1a031970219a0.tar.bz2
M PyShell.py
M RemoteDebugger.py M ScriptBinding.py Restart the execution server with a clean environment and execute the active module from scratch upon activation of Run/F5. Add functionality to PyShell.py to restart the execution server in a new subprocess. The server makes a connection to the Idle client which sends a block of code to be executed. Modify ScriptBinding.py to restart the subprocess upon Run/F5, assuming that an execution is not currently in progress. Remove Import Module functionality, not required now that the code is executed in a clean environment. If the Debugger is active, also restart the subprocess side of the split debugger. Add functionality to RemoteDebugger.py to support this. At this time breakpoints will be lost in the subprocess if Run/F5 is activated. A subsequent checkin of PyShell.py will implement reloading of the breakpoints into the subprocess debugger. I'm keeping this separate as the design may change.
-rw-r--r--Lib/idlelib/PyShell.py46
-rw-r--r--Lib/idlelib/RemoteDebugger.py22
-rw-r--r--Lib/idlelib/ScriptBinding.py44
3 files changed, 55 insertions, 57 deletions
diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py
index b483ea8..9ef2ff7 100644
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -187,17 +187,19 @@ class ModifiedInterpreter(InteractiveInterpreter):
InteractiveInterpreter.__init__(self, locals=locals)
self.save_warnings_filters = None
+ port = 8833
rpcclt = None
rpcpid = None
def spawn_subprocess(self):
- port = 8833
- addr = ("localhost", port)
- # Spawn the Python execution "server"
w = ['-W' + s for s in sys.warnoptions]
args = [sys.executable] + w + ["-c", "__import__('run').main()",
- str(port)]
+ str(self.port)]
self.rpcpid = os.spawnv(os.P_NOWAIT, args[0], args)
+
+ def start_subprocess(self):
+ addr = ("localhost", self.port)
+ self.spawn_subprocess()
# Idle starts listening for connection on localhost
for i in range(6):
time.sleep(i)
@@ -221,6 +223,21 @@ class ModifiedInterpreter(InteractiveInterpreter):
self.rpcclt.register("flist", self.tkconsole.flist)
self.poll_subprocess()
+ def restart_subprocess(self):
+ # close only the subprocess debugger
+ db = self.getdebugger()
+ if db:
+ RemoteDebugger.close_subprocess_debugger(self.rpcclt)
+ # kill subprocess, spawn a new one, accept connection
+ self.rpcclt.close()
+ self.spawn_subprocess()
+ self.rpcclt.accept()
+ # restart remote debugger
+ if db:
+ gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
+ # reload remote debugger breakpoints
+ pass # XXX KBK 04Sep02 TBD
+
active_seq = None
def poll_subprocess(self):
@@ -383,15 +400,18 @@ class ModifiedInterpreter(InteractiveInterpreter):
def getdebugger(self):
return self.debugger
+ def display_executing_dialog(self):
+ tkMessageBox.showerror(
+ "Already executing",
+ "The Python Shell window is already executing a command; "
+ "please wait until it is finished.",
+ master=self.tkconsole.text)
+
def runcommand(self, code):
"Run the code without invoking the debugger"
# The code better not raise an exception!
if self.tkconsole.executing:
- tkMessageBox.showerror(
- "Already executing",
- "The Python Shell window is already executing a command; "
- "please wait until it is finished.",
- master=self.tkconsole.text)
+ display_executing_dialog()
return 0
if self.rpcclt:
self.rpcclt.remotecall("exec", "runcode", (code,), {})
@@ -402,11 +422,7 @@ class ModifiedInterpreter(InteractiveInterpreter):
def runcode(self, code):
"Override base class method"
if self.tkconsole.executing:
- tkMessageBox.showerror(
- "Already executing",
- "The Python Shell window is already executing a command; "
- "please wait until it is finished.",
- master=self.tkconsole.text)
+ display_executing_dialog()
return
#
self.checklinecache()
@@ -509,7 +525,7 @@ class PyShell(OutputWindow):
self.history = self.History(self.text)
if use_subprocess:
- self.interp.spawn_subprocess()
+ self.interp.start_subprocess()
reading = 0
executing = 0
diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py
index 84e94df..f9430d0 100644
--- a/Lib/idlelib/RemoteDebugger.py
+++ b/Lib/idlelib/RemoteDebugger.py
@@ -27,6 +27,9 @@ import Debugger
debugging = 0
+idb_adap_oid = "idb_adapter"
+gui_adap_oid = "gui_adapter"
+
#=======================================
#
# In the PYTHON subprocess:
@@ -113,6 +116,7 @@ class IdbAdapter:
def clear_break(self, filename, lineno):
msg = self.idb.clear_break(filename, lineno)
+ return msg
def clear_all_file_breaks(self, filename):
msg = self.idb.clear_all_file_breaks(filename)
@@ -183,7 +187,6 @@ def start_debugger(rpchandler, gui_adap_oid):
gui_proxy = GUIProxy(rpchandler, gui_adap_oid)
idb = Debugger.Idb(gui_proxy)
idb_adap = IdbAdapter(idb)
- idb_adap_oid = "idb_adapter"
rpchandler.register(idb_adap_oid, idb_adap)
return idb_adap_oid
@@ -325,6 +328,7 @@ class IdbProxy:
def clear_break(self, filename, lineno):
msg = self.call("clear_break", filename, lineno)
+ return msg
def clear_all_file_breaks(self, filename):
msg = self.call("clear_all_file_breaks", filename)
@@ -344,7 +348,8 @@ def start_remote_debugger(rpcclt, pyshell):
Idle debugger GUI to the subprocess debugger via the IdbProxy.
"""
- gui_adap_oid = "gui_adapter"
+ global idb_adap_oid
+
idb_adap_oid = rpcclt.remotecall("exec", "start_the_debugger",\
(gui_adap_oid,), {})
idb_proxy = IdbProxy(rpcclt, idb_adap_oid)
@@ -362,7 +367,14 @@ def close_remote_debugger(rpcclt):
is deleted in PyShell.close_remote_debugger().)
"""
- idb_adap_oid = "idb_adapter"
- rpcclt.remotecall("exec", "stop_the_debugger", (idb_adap_oid,), {})
- gui_adap_oid = "gui_adapter"
+ close_subprocess_debugger(rpcclt)
rpcclt.unregister(gui_adap_oid)
+
+def close_subprocess_debugger(rpcclt):
+ rpcclt.remotecall("exec", "stop_the_debugger", (idb_adap_oid,), {})
+
+def restart_subprocess_debugger(rpcclt):
+ idb_adap_oid_ret = rpcclt.remotecall("exec", "start_the_debugger",\
+ (gui_adap_oid,), {})
+ assert idb_adap_oid_ret == idb_adap_oid, 'Idb restarted with different oid'
+
diff --git a/Lib/idlelib/ScriptBinding.py b/Lib/idlelib/ScriptBinding.py
index 8ab0cf6..cc26510 100644
--- a/Lib/idlelib/ScriptBinding.py
+++ b/Lib/idlelib/ScriptBinding.py
@@ -5,13 +5,9 @@ This adds the following commands:
- Check module does a full syntax check of the current module.
It also runs the tabnanny to catch any inconsistent tabs.
-- Import module is equivalent to either import or reload of the
-current module. The window must have been saved previously. The
-module is added to sys.modules, and is also added to the __main__
-namespace. Output goes to the shell window.
-
-- Run module does the same but executes the module's
-code in the __main__ namespace.
+- Run module executes the module's code in the __main__ namespace. The window
+must have been saved previously. The module is added to sys.modules, and is
+also added to the __main__ namespace.
XXX Redesign this interface (yet again) as follows:
@@ -19,8 +15,6 @@ XXX Redesign this interface (yet again) as follows:
- Allow specify command line arguments in the dialog box
-- Restart the interpreter when running a script
-
"""
import sys
@@ -47,7 +41,6 @@ class ScriptBinding:
menudefs = [
('run', [None,
# ('Check module', '<<check-module>>'),
-# ('Import module', '<<import-module>>'),
('Run script', '<<run-script>>'),
]
),
@@ -113,33 +106,6 @@ class ScriptBinding:
"There's an error in your program:\n" + msg)
return 1
- def import_module_event(self, event):
- flist = self.editwin.flist
- shell = flist.open_shell()
- interp = shell.interp
-
- filename = self.getfilename()
- if not filename:
- return
-
- modname, ext = os.path.splitext(os.path.basename(filename))
-
- dir = os.path.dirname(filename)
- dir = os.path.normpath(os.path.abspath(dir))
-
- interp.runcode("""if 1:
- import sys as _sys
- if %s not in _sys.path:
- _sys.path.insert(0, %s)
- if _sys.modules.get(%s):
- del _sys
- import %s
- reload(%s)
- else:
- del _sys
- import %s
- \n""" % (`dir`, `dir`, `modname`, modname, modname, modname))
-
def run_script_event(self, event):
filename = self.getfilename()
if not filename:
@@ -147,6 +113,10 @@ class ScriptBinding:
flist = self.editwin.flist
shell = flist.open_shell()
interp = shell.interp
+ if interp.tkconsole.executing:
+ interp.display_executing_dialog()
+ return
+ interp.restart_subprocess()
# XXX Too often this discards arguments the user just set...
interp.runcommand("""if 1:
_filename = %s