PyShell.py revision 5afa1dfb72311b8360904363cc3ebb7cbfc8b6e4
17aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer#! /usr/bin/env python
27aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
37aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport os
47aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport sys
57aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport string
67aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport getopt
77aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport re
85d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport socket
95d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport time
105d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport traceback
11628339807e76d075a610aa6dd963e702ef25afc8Kurt B. Kaiserimport types
12628339807e76d075a610aa6dd963e702ef25afc8Kurt B. Kaiserimport warnings
137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport linecache
157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom code import InteractiveInterpreter
167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom Tkinter import *
187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport tkMessageBox
197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom EditorWindow import EditorWindow, fixwordbreaks
217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom FileList import FileList
227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom ColorDelegator import ColorDelegator
237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererfrom UndoDelegator import UndoDelegator
24969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiserfrom OutputWindow import OutputWindow
259930061ce28b1fc60d267ae3474c74a41e655cd5Steven M. Gavafrom configHandler import idleConf
267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererimport idlever
277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
285d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyimport rpc
29ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiserimport RemoteDebugger
305d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
31b97641994617115321719d4ecf797a461e2d5cf2Kurt B. KaiserIDENTCHARS = string.ascii_letters + string.digits + "_"
32b97641994617115321719d4ecf797a461e2d5cf2Kurt B. Kaiser
33969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser# XX hardwire this for now, remove later  KBK 09Jun02
34969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiseruse_subprocess = 1 # Set to 1 to spawn subprocess for command execution
355d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
365d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey# Change warnings module to write to sys.__stderr__
375d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teytry:
385d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    import warnings
395d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyexcept ImportError:
405d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    pass
415d2af63cc36ca1141e1ec7412fc33866f3908408Chui Teyelse:
425d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def idle_showwarning(message, category, filename, lineno):
435d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        file = sys.__stderr__
445d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        file.write(warnings.formatwarning(message, category, filename, lineno))
455d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    warnings.showwarning = idle_showwarning
465d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# We need to patch linecache.checkcache, because we don't want it
487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# to throw away our <pyshell#...> entries.
497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# Rather than repeating its code here, we save those entries,
507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer# then call the original function, and then restore the saved entries.
517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererdef linecache_checkcache(orig_checkcache=linecache.checkcache):
527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    cache = linecache.cache
537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    save = {}
547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    for filename in cache.keys():
557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if filename[:1] + filename[-1:] == '<>':
567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            save[filename] = cache[filename]
577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    orig_checkcache()
587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    cache.update(save)
597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererlinecache.checkcache = linecache_checkcache
607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShellEditorWindow(EditorWindow):
62ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser    "Regular text edit window when a shell is present"
637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # XXX ought to merge with regular editor window
647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, *args):
667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        apply(EditorWindow.__init__, (self,) + args)
677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
68669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        self.text.bind("<<clear-breakpoint-here>>",
69669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser                       self.clear_breakpoint_here)
707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.bind("<<open-python-shell>>", self.flist.open_shell)
717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    rmenu_specs = [
73669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        ("Set Breakpoint", "<<set-breakpoint-here>>"),
74669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        ("Clear Breakpoint", "<<clear-breakpoint-here>>")
757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    ]
767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def set_breakpoint_here(self, event=None):
787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not self.flist.pyshell or not self.flist.pyshell.interp.debugger:
797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.bell()
807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.flist.pyshell.interp.debugger.set_breakpoint_here(self)
827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
83669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser    def clear_breakpoint_here(self, event=None):
84669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        if not self.flist.pyshell or not self.flist.pyshell.interp.debugger:
85669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser            self.text.bell()
86669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser            return
87669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser        self.flist.pyshell.interp.debugger.clear_breakpoint_here(self)
88669f4c3850eaaf4e00a79032ef960a79e6ca6ad7Kurt B. Kaiser
897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShellFileList(FileList):
9183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: file list when a shell is present"
927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    EditorWindow = PyShellEditorWindow
947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    pyshell = None
967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_shell(self, event=None):
987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.pyshell:
997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.pyshell.wakeup()
1007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
1017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.pyshell = PyShell(self)
1027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.pyshell.begin()
1037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.pyshell
1047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedColorDelegator(ColorDelegator):
10783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: colorizer for the shell window itself"
108b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava
109b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava    def __init__(self):
110b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        ColorDelegator.__init__(self)
111b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        self.LoadTagDefs()
1127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def recolorize_main(self):
1147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tag_remove("TODO", "1.0", "iomark")
1157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tag_add("SYNC", "1.0", "iomark")
1167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ColorDelegator.recolorize_main(self)
117b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava
118b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava    def LoadTagDefs(self):
119b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        ColorDelegator.LoadTagDefs(self)
120b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        theme = idleConf.GetOption('main','Theme','name')
121b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        self.tagdefs.update({
122b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stdin": {'background':None,'foreground':None},
123b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stdout": idleConf.GetHighlight(theme, "stdout"),
124b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "stderr": idleConf.GetHighlight(theme, "stderr"),
125b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "console": idleConf.GetHighlight(theme, "console"),
126b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            "ERROR": idleConf.GetHighlight(theme, "error"),
127b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava            None: idleConf.GetHighlight(theme, "normal"),
128b77d343bc846c2049a4cffb1dfd65eb49d1728b4Steven M. Gava        })
1297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedUndoDelegator(UndoDelegator):
13183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser    "Extend base class: forbid insert/delete before the I/O mark"
1327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def insert(self, index, chars, tags=None):
1347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
1357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.delegate.compare(index, "<", "iomark"):
1367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.delegate.bell()
1377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return
1387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
1397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
1407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        UndoDelegator.insert(self, index, chars, tags)
1417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def delete(self, index1, index2=None):
1437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
1447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.delegate.compare(index1, "<", "iomark"):
1457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.delegate.bell()
1467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return
1477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except TclError:
1487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
1497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        UndoDelegator.delete(self, index1, index2)
1507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass ModifiedInterpreter(InteractiveInterpreter):
1527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
1537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, tkconsole):
1547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole = tkconsole
1557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        locals = sys.modules['__main__'].__dict__
1567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        InteractiveInterpreter.__init__(self, locals=locals)
15794bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        self.save_warnings_filters = None
1587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
15963857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser    port = 8833
1605d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    rpcclt = None
1615d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    rpcpid = None
1625d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
163f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds    def spawn_subprocess(self):
164f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds        w = ['-W' + s for s in sys.warnoptions]
165f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds        args = [self.find_executable()] + w \
166f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds             + ["-c", "__import__('run').main()", str(self.port)]
1675d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.rpcpid = os.spawnv(os.P_NOWAIT, args[0], args)
16863857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser
169f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds    def find_executable(self):
170f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds        if sys.platform == 'darwin' and sys.executable.count('.app'):
171f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds            # On Mac OS X, avoid calling sys.executable because it ignores
172f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds            # command-line options (sys.executable is an applet)
173f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds            #
174f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds            # Instead, find the executable by looking relative to
175f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds            # sys.prefix.
176f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds            executable = os.path.join(sys.prefix, 'Resources',
177f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds                                'Python.app', 'Contents', 'MacOS', 'python')
178f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds            return executable
179f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds        else:
180f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds            return sys.executable
181f2324b9e8964a7aef964ae6168827ad300f920d6Tony Lownds
18263857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser    def start_subprocess(self):
18363857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        addr = ("localhost", self.port)
18463857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        self.spawn_subprocess()
1858dcdb77132563c734c228e815498c47e487f95cfKurt B. Kaiser        # Idle starts listening for connection on localhost
1868dcdb77132563c734c228e815498c47e487f95cfKurt B. Kaiser        for i in range(6):
1875d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            time.sleep(i)
1885d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            try:
1895d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                self.rpcclt = rpc.RPCClient(addr)
1905d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                break
1915d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            except socket.error, err:
1928dcdb77132563c734c228e815498c47e487f95cfKurt B. Kaiser                if i < 3:
193b417936d4080004b6a7811fb411c6f77db4cc262Kurt B. Kaiser                    print>>sys.__stderr__, ". ",
194b417936d4080004b6a7811fb411c6f77db4cc262Kurt B. Kaiser                else:
195b417936d4080004b6a7811fb411c6f77db4cc262Kurt B. Kaiser                    print>>sys.__stderr__,"\nIdle socket error: " + err[1]\
196b417936d4080004b6a7811fb411c6f77db4cc262Kurt B. Kaiser                                                    + ", retrying..."
1975d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
198969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            display_port_binding_error()
1995d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
200b417936d4080004b6a7811fb411c6f77db4cc262Kurt B. Kaiser        # Accept the connection from the Python execution server
201b417936d4080004b6a7811fb411c6f77db4cc262Kurt B. Kaiser        self.rpcclt.accept()
202969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stdin", self.tkconsole)
203969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stdout", self.tkconsole.stdout)
204969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.rpcclt.register("stderr", self.tkconsole.stderr)
2055d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.rpcclt.register("flist", self.tkconsole.flist)
2065d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.poll_subprocess()
2075d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
20863857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser    def restart_subprocess(self):
20963857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        # close only the subprocess debugger
21063857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        db = self.getdebugger()
21163857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        if db:
21263857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            RemoteDebugger.close_subprocess_debugger(self.rpcclt)
21363857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        # kill subprocess, spawn a new one, accept connection
21463857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        self.rpcclt.close()
21563857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        self.spawn_subprocess()
21663857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        self.rpcclt.accept()
21763857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        # restart remote debugger
21863857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        if db:
21963857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
22063857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            # reload remote debugger breakpoints
22163857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            pass   # XXX KBK 04Sep02 TBD
22263857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser
2235d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    active_seq = None
2245d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2255d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def poll_subprocess(self):
2265d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        clt = self.rpcclt
2275d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if clt is None:
2285d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
2295d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        response = clt.pollresponse(self.active_seq)
2305d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.tkconsole.text.after(50, self.poll_subprocess)
2315d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if response:
2325d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.resetoutput()
2335d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.active_seq = None
2345d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            how, what = response
2355d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            file = self.tkconsole.console
2365d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            if how == "OK":
2375d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if what is not None:
2385d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    print >>file, `what`
2395d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            elif how == "EXCEPTION":
2405d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                mod, name, args, tb = what
2415d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                print >>file, 'Traceback (most recent call last):'
2425d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                while tb and tb[0][0] in ("run.py", "rpc.py"):
2435d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    del tb[0]
2445d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                while tb and tb[-1][0] in ("run.py", "rpc.py"):
2455d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    del tb[-1]
2465d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                for i in range(len(tb)):
2475d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    fn, ln, nm, line = tb[i]
2485d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    if not line and fn.startswith("<pyshell#"):
2495d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                        line = linecache.getline(fn, ln)
2505d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                        tb[i] = fn, ln, nm, line
2515d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                traceback.print_list(tb, file=file)
2525d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if mod and mod != "exceptions":
2535d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    name = mod + "." + name
2545d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                print >>file, name + ":", " ".join(map(str, args))
2555d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
2565d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                    self.remote_stack_viewer()
2575d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            elif how == "ERROR":
2585d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                print >>sys.__stderr__, "Oops:", how, what
2595d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                print >>file, "Oops:", how, what
2605d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.endexecuting()
2615d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2625d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def kill_subprocess(self):
2635d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        clt = self.rpcclt
2645d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.rpcclt = None
2655d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if clt is not None:
2665d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            clt.close()
2675d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2685d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def remote_stack_viewer(self):
2695d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        import RemoteObjectBrowser
2705d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        oid = self.rpcclt.remotecall("exec", "stackviewer", ("flist",), {})
2715d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if oid is None:
2725d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.root.bell()
2735d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
2745d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
2755d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        from TreeWidget import ScrolledCanvas, TreeNode
2765d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        top = Toplevel(self.tkconsole.root)
2775d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sc = ScrolledCanvas(top, bg="white", highlightthickness=0)
2785d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sc.frame.pack(expand=1, fill="both")
2795d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        node = TreeNode(sc.canvas, None, item)
2805d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        node.expand()
2815d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        # XXX Should GC the remote tree when closing the window
2825d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
2837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    gid = 0
2847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
2857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def execsource(self, source):
28683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Like runsource() but assumes complete exec source"
2877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.stuffsource(source)
2887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.execfile(filename, source)
2897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
2907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def execfile(self, filename, source=None):
29183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Execute an existing file"
2927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if source is None:
2937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            source = open(filename, "r").read()
2947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
2957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            code = compile(source, filename, "exec")
2967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except (OverflowError, SyntaxError):
2977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.resetoutput()
2987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            InteractiveInterpreter.showsyntaxerror(self, filename)
2997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
3007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.runcode(code)
3017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runsource(self, source):
30383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend base class method: Stuff the source in the line cache first"
3047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = self.stuffsource(source)
3057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.more = 0
30694bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        self.save_warnings_filters = warnings.filters[:]
30794bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        warnings.filterwarnings(action="error", category=SyntaxWarning)
308837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        if isinstance(source, types.UnicodeType):
309837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser            import IOBinding
310837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser            try:
311837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser                source = source.encode(IOBinding.encoding)
312837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser            except UnicodeError:
313837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser                self.tkconsole.resetoutput()
314837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser                self.write("Unsupported characters in input")
315837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser                return
31694bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        try:
31794bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            return InteractiveInterpreter.runsource(self, source, filename)
31894bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        finally:
31994bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            if self.save_warnings_filters is not None:
32094bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                warnings.filters[:] = self.save_warnings_filters
32194bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                self.save_warnings_filters = None
3227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def stuffsource(self, source):
32483118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Stuff source in the filename cache"
3257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        filename = "<pyshell#%d>" % self.gid
3267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.gid = self.gid + 1
327837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        lines = source.split("\n")
3287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        linecache.cache[filename] = len(source)+1, 0, lines, filename
3297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return filename
330837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser
3317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showsyntaxerror(self, filename=None):
33283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        """Extend base class method: Add Colorizing
33383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser
33483118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        Color the offending position instead of printing it and pointing at it
33583118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        with a caret.
33683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser
33783118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        """
3387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text = self.tkconsole.text
3397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        stuff = self.unpackerror()
3407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not stuff:
3417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.resetoutput()
3427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            InteractiveInterpreter.showsyntaxerror(self, filename)
3437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
3447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        msg, lineno, offset, line = stuff
3457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if lineno == 1:
3467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pos = "iomark + %d chars" % (offset-1)
3477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
3487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pos = "iomark linestart + %d lines + %d chars" % (lineno-1,
3497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                                                              offset-1)
3507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.tag_add("ERROR", pos)
3517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.see(pos)
3527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        char = text.get(pos)
353837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        if char and char in IDENTCHARS:
3547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            text.tag_add("ERROR", pos + " wordstart", pos)
3557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole.resetoutput()
3567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.write("SyntaxError: %s\n" % str(msg))
3577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def unpackerror(self):
3597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        type, value, tb = sys.exc_info()
3607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ok = type is SyntaxError
3617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if ok:
3627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
3637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                msg, (dummy_filename, lineno, offset, line) = value
3647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except:
3657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                ok = 0
3667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if ok:
3677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return msg, lineno, offset, line
3687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
3697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return None
3707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showtraceback(self):
37283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend base class method to reset output properly"
3737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole.resetoutput()
3747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.checklinecache()
3757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        InteractiveInterpreter.showtraceback(self)
3765d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
3775d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.open_stack_viewer()
3787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def checklinecache(self):
3807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        c = linecache.cache
3817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        for key in c.keys():
3827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if key[:1] + key[-1:] != "<>":
3837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                del c[key]
3847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    debugger = None
3867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def setdebugger(self, debugger):
3887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.debugger = debugger
3897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
3907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def getdebugger(self):
3917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.debugger
3927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
39363857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser    def display_executing_dialog(self):
39463857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser        tkMessageBox.showerror(
39563857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            "Already executing",
39663857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            "The Python Shell window is already executing a command; "
39763857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            "please wait until it is finished.",
39863857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            master=self.tkconsole.text)
39963857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser
4005d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def runcommand(self, code):
40183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Run the code without invoking the debugger"
4025d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        # The code better not raise an exception!
4035d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.executing:
40463857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            display_executing_dialog()
4055d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return 0
4065d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.rpcclt:
4075d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.rpcclt.remotecall("exec", "runcode", (code,), {})
4085d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
4095d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            exec code in self.locals
4105d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        return 1
4115d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
4127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runcode(self, code):
41383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override base class method"
4145d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.tkconsole.executing:
41563857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            display_executing_dialog()
4165d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
4175d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.checklinecache()
41894bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser        if self.save_warnings_filters is not None:
41994bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            warnings.filters[:] = self.save_warnings_filters
42094bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser            self.save_warnings_filters = None
4217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        debugger = self.debugger
4225d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if not debugger and self.rpcclt is not None:
4235d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.tkconsole.beginexecuting()
4245d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.active_seq = self.rpcclt.asynccall("exec", "runcode",
4255d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                                                    (code,), {})
4265d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return
4277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
4287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.beginexecuting()
4297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            try:
4307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                if debugger:
4317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    debugger.run(code, self.locals)
4327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                else:
4337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    exec code in self.locals
4347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except SystemExit:
4357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                if tkMessageBox.askyesno(
4367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    "Exit?",
4377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    "Do you want to exit altogether?",
4387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    default="yes",
4397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    master=self.tkconsole.text):
4407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    raise
4417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                else:
4427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    self.showtraceback()
4437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            except:
4447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.showtraceback()
4457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        finally:
4467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.tkconsole.endexecuting()
4477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s):
44983118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override base class method"
4507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tkconsole.console.write(s)
4517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PyShell(OutputWindow):
4537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    shell_title = "Python Shell"
4557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # Override classes
4577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    ColorDelegator = ModifiedColorDelegator
4587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    UndoDelegator = ModifiedUndoDelegator
4597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
460dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser    # Override menus: Run and Format not desired in shell; add Debug
461dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser    menu_specs = [
462dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("file", "_File"),
463dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("edit", "_Edit"),
464dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("debug", "_Debug"),
465dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("settings", "_Settings"),
466dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("windows", "_Windows"),
467dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        ("help", "_Help"),
468dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser    ]
4697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    # New classes
4717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    from IdleHistory import History
4727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
4737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, flist=None):
4747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp = ModifiedInterpreter(self)
4757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if flist is None:
4767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            root = Tk()
4777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            fixwordbreaks(root)
4787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            root.withdraw()
4797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            flist = PyShellFileList(root)
4805afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
4817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        OutputWindow.__init__(self, flist, None, None)
4825afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
4837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        import __builtin__
4847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D."
4855afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
486ee7afca550f69ace3e20d25b84432f45c246c600Kurt B. Kaiser        self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
4875afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
4887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text = self.text
4897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.configure(wrap="char")
4907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<newline-and-indent>>", self.enter_callback)
4917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
4927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<interrupt-execution>>", self.cancel_callback)
4937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<beginning-of-line>>", self.home_callback)
4947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<end-of-file>>", self.eof_callback)
4957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
4967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<toggle-debugger>>", self.toggle_debugger)
4977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<open-python-shell>>", self.flist.open_shell)
4987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
4995afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
5007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stdout = sys.stdout
5017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stderr = sys.stderr
5027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.save_stdin = sys.stdin
5035d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.stdout = PseudoFile(self, "stdout")
5045d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.stderr = PseudoFile(self, "stderr")
5057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console = PseudoFile(self, "console")
5065d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if not use_subprocess:
5075d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stdout = self.stdout
5085d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stderr = self.stderr
5095d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            sys.stdin = self
5105afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
5117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.history = self.History(self.text)
5125afa1dfb72311b8360904363cc3ebb7cbfc8b6e4Kurt B. Kaiser        #
5135d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if use_subprocess:
51463857a454d85fda475264575b7c1a031970219a0Kurt B. Kaiser            self.interp.start_subprocess()
5155d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
5167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    reading = 0
5177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    executing = 0
5187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    canceled = 0
5197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    endoffile = 0
5207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def toggle_debugger(self, event=None):
5227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing:
5237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror("Don't debug now",
5247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "You can only toggle the debugger when idle",
5257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.text)
5267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.set_debugger_indicator()
5277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
5287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
5297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            db = self.interp.getdebugger()
5307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if db:
5317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.close_debugger()
5327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            else:
5337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.open_debugger()
5347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def set_debugger_indicator(self):
5367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        db = self.interp.getdebugger()
5377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.setvar("<<toggle-debugger>>", not not db)
5387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def toggle_jit_stack_viewer( self, event=None):
5407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        pass # All we need is the variable
5417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def close_debugger(self):
5437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        db = self.interp.getdebugger()
5447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if db:
5457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.interp.setdebugger(None)
5467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            db.close()
547ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser            if self.interp.rpcclt:
548ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser                RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
5497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
5507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.console.write("[DEBUG OFF]\n")
5517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.ps1 = ">>> "
5527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.showprompt()
5537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.set_debugger_indicator()
5547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_debugger(self):
5560e3a57731b4b1ffbfae151cf23289bbd51148163Kurt B. Kaiser        # XXX KBK 13Jun02 An RPC client always exists now? Open remote
5570e3a57731b4b1ffbfae151cf23289bbd51148163Kurt B. Kaiser        # debugger and return...dike the rest of this fcn and combine
5580e3a57731b4b1ffbfae151cf23289bbd51148163Kurt B. Kaiser        # with open_remote_debugger?
5595d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.interp.rpcclt:
5605d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return self.open_remote_debugger()
5617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        import Debugger
5627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp.setdebugger(Debugger.Debugger(self))
5637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.ps1 = "[DEBUG ON]\n>>> "
5647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.showprompt()
5657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.set_debugger_indicator()
5667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5675d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey    def open_remote_debugger(self):
5685d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt, self)
5695d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.interp.setdebugger(gui)
5705d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        sys.ps1 = "[DEBUG ON]\n>>> "
5715d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.showprompt()
5725d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_debugger_indicator()
5735d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey
5747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def beginexecuting(self):
575ffd3a4217a557bad4984621c22f5ae312d708169Kurt B. Kaiser        "Helper for ModifiedInterpreter"
5767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
5777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.executing = 1
5787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ##self._cancel_check = self.cancel_check
5797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ##sys.settrace(self._cancel_check)
5807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def endexecuting(self):
58283118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Helper for ModifiedInterpreter"
5837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ##sys.settrace(None)
5847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        ##self._cancel_check = None
5857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.executing = 0
5867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.canceled = 0
5875d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.showprompt()
5887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
5897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def close(self):
59083118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend EditorWindow.close()"
5917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing:
5927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # XXX Need to ask a question here
5937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if not tkMessageBox.askokcancel(
5947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "Kill?",
5957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "The program is still running; do you want to kill it?",
5967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                default="ok",
5977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.text):
5987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "cancel"
5997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 1
6007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.reading:
6017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.top.quit()
6027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "cancel"
60383118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        return EditorWindow.close(self)
6047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def _close(self):
60683118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Extend EditorWindow._close(), shut down debugger and execution server"
6077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.close_debugger()
6085d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.interp.kill_subprocess()
6097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Restore std streams
6107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdout = self.save_stdout
6117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stderr = self.save_stderr
6127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdin = self.save_stdin
6137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Break cycles
6147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.interp = None
6157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console = None
6167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.flist.pyshell = None
6177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.history = None
61883118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        EditorWindow._close(self)
6197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def ispythonsource(self, filename):
62183118c6cb36cf9a424bec1b9a2ef8c8760bae8f5Kurt B. Kaiser        "Override EditorWindow method: never remove the colorizer"
622837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        return True
6237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def short_title(self):
6257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self.shell_title
6267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
62794bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser    COPYRIGHT = \
62894bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser              'Type "copyright", "credits" or "license" for more information.'
62994bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser
6307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def begin(self):
6317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
632969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        self.write("Python %s on %s\n%s\nGRPC IDLE Fork %s\n" %
63394bd77415fc44ada4ceba856a81fe029c12bf313Kurt B. Kaiser                   (sys.version, sys.platform, self.COPYRIGHT,
6347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    idlever.IDLE_VERSION))
6357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
6367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.ps1
6377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except AttributeError:
6387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.ps1 = ">>> "
6397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.showprompt()
6407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        import Tkinter
6417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        Tkinter._default_root = None
6427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def interact(self):
6447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.begin()
6457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.top.mainloop()
6467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def readline(self):
6487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        save = self.reading
6497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
6507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.reading = 1
6517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.mainloop()
6527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        finally:
6537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.reading = save
6547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = self.text.get("iomark", "end-1c")
6557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
6567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
6577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
6587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            raise KeyboardInterrupt
6597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.endoffile:
6607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.endoffile = 0
6617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return ""
6627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return line
6637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6647aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def isatty(self):
665837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        return True
6667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def cancel_callback(self, event):
6687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
6697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if self.text.compare("sel.first", "!=", "sel.last"):
6707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return # Active selection -- always use default binding
6717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
6727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
6737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not (self.executing or self.reading):
6747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
6757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.write("KeyboardInterrupt\n")
6767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.showprompt()
6777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
6787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.endoffile = 0
6797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
6805d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.canceled = 1
6817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit()
6825d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        elif (self.executing and self.interp.rpcclt and
6835d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey              self.interp.rpcpid and hasattr(os, "kill")):
6845d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            try:
6855d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                from signal import SIGINT
6865d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            except ImportError:
6875d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey                SIGINT = 2
6885d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            os.kill(self.interp.rpcpid, SIGINT)
6895d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        else:
6905d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            self.canceled = 1
6917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
6927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
6937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def eof_callback(self, event):
6947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing and not self.reading:
6957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (delete next char) take over
6967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not (self.text.compare("iomark", "==", "insert") and
6977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.text.compare("insert", "==", "end-1c")):
6987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (delete next char) take over
6997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if not self.executing:
7007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.resetoutput()
7017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.close()
7027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
7037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
7047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.endoffile = 1
7057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit()
7067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
7077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def home_callback(self, event):
7097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if event.state != 0 and event.keysym == "Home":
7107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # <Modifier-Home>; fall back to class binding
7117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("iomark", "<=", "insert") and \
7127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer           self.text.compare("insert linestart", "<=", "iomark"):
7137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.mark_set("insert", "iomark")
7147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.tag_remove("sel", "1.0", "end")
7157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
7167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
7177aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7187aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def linefeed_callback(self, event):
7197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Insert a linefeed without entering anything (still autoindented)
7207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
7217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("insert", "\n")
7227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
7237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
724ee7afca550f69ace3e20d25b84432f45c246c600Kurt B. Kaiser            self.auto_indent(event)
7257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
7267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def enter_callback(self, event):
7287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.executing and not self.reading:
7297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return # Let the default binding (insert '\n') take over
7307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If some text is selected, recall the selection
7317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # (but only if this before the I/O mark)
7327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
7337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sel = self.text.get("sel.first", "sel.last")
7347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if sel:
7357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                if self.text.compare("sel.last", "<=", "iomark"):
7367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    self.recall(sel)
7377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                    return "break"
7387aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
7397aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            pass
7407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're strictly before the line containing iomark, recall
7417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # the current line, less a leading prompt, less leading or
7427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # trailing whitespace
7437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("insert", "<", "iomark linestart"):
7447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # Check if there's a relevant stdin range -- if so, use it
7457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            prev = self.text.tag_prevrange("stdin", "insert")
7467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if prev and self.text.compare("insert", "<", prev[1]):
7477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.recall(self.text.get(prev[0], prev[1]))
7487aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "break"
7497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            next = self.text.tag_nextrange("stdin", "insert")
7507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            if next and self.text.compare("insert lineend", ">=", next[0]):
7517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                self.recall(self.text.get(next[0], next[1]))
7527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                return "break"
7537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            # No stdin mark -- just get the current line
7547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.recall(self.text.get("insert linestart", "insert lineend"))
7557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
7567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're in the current input and there's only whitespace
7577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # beyond the cursor, erase that whitespace first
7587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        s = self.text.get("insert", "end-1c")
759837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        if s and not s.strip():
7607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.delete("insert", "end-1c")
7617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # If we're in the current input before its last line,
7627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # insert a newline right at the insert point
7637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.compare("insert", "<", "end-1c linestart"):
764ee7afca550f69ace3e20d25b84432f45c246c600Kurt B. Kaiser            self.auto_indent(event)
7657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return "break"
7667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # We're in the last line; append a newline and submit it
7677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("insert", "end-1c")
7687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
7697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("insert", "\n")
7707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.see("insert")
7717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
772ee7afca550f69ace3e20d25b84432f45c246c600Kurt B. Kaiser            self.auto_indent(event)
7737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.tag_add("stdin", "iomark", "end-1c")
7747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.update_idletasks()
7757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.reading:
7767aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.top.quit() # Break out of recursive mainloop() in raw_input()
7777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        else:
7787aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.runit()
7797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return "break"
7807aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def recall(self, s):
7827aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.history:
7837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.history.recall(s)
7847aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7857aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def runit(self):
7867aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = self.text.get("iomark", "end-1c")
7877aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Strip off last newline and surrounding whitespace.
7887aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # (To allow you to hit return twice to end a statement.)
7897aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        i = len(line)
7907aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        while i > 0 and line[i-1] in " \t":
7917aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
7927aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if i > 0 and line[i-1] == "\n":
7937aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
7947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        while i > 0 and line[i-1] in " \t":
7957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            i = i-1
7967aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        line = line[:i]
7977aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        more = self.interp.runsource(line)
7987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
7997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def cancel_check(self, frame, what, args,
8007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                     dooneevent=tkinter.dooneevent,
8017aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                     dontwait=tkinter.DONT_WAIT):
8027aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # Hack -- use the debugger hooks to be able to handle events
8037aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # and interrupt execution at any time.
8047aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # This slows execution down quite a bit, so you may want to
8057aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # disable this (by not calling settrace() in runcode() above)
8067aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # for full-bore (uninterruptable) speed.
8077aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        # XXX This should become a user option.
8087aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
8097aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
8107aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        dooneevent(dontwait)
8117aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
8127aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
8137aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            raise KeyboardInterrupt
8147aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        return self._cancel_check
8157aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8167aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def open_stack_viewer(self, event=None):
8175d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        if self.interp.rpcclt:
8185d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey            return self.interp.remote_stack_viewer()
8197aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
8207aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            sys.last_traceback
8217aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
8227aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            tkMessageBox.showerror("No stack trace",
8237aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "There is no stack trace yet.\n"
8247aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                "(sys.last_traceback is not defined)",
8257aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer                master=self.text)
8267aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            return
8277aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        from StackViewer import StackBrowser
8287aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sv = StackBrowser(self.root, self.flist)
8297aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8307aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def showprompt(self):
8317aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.resetoutput()
8327aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        try:
8337aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            s = str(sys.ps1)
8347aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        except:
8357aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            s = ""
8367aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.console.write(s)
8377aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("insert", "end-1c")
8385d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_line_and_column()
839dc1e70987f49aa23bf1d07f32c476edeba0cec30Kurt B. Kaiser        self.io.reset_undo()
8407aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8417aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def resetoutput(self):
8427aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        source = self.text.get("iomark", "end-1c")
8437aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.history:
8447aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.history.history_store(source)
8457aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.text.get("end-2c") != "\n":
8467aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.text.insert("end-1c", "\n")
8477aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_set("iomark", "end-1c")
8485d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.set_line_and_column()
8497aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        sys.stdout.softspace = 0
8507aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8517aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s, tags=()):
8527aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_gravity("iomark", "right")
8537aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        OutputWindow.write(self, s, tags, "iomark")
8547aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.text.mark_gravity("iomark", "left")
8557aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        if self.canceled:
8567aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            self.canceled = 0
8577aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer            raise KeyboardInterrupt
8587aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8597aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererclass PseudoFile:
8607aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8617aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def __init__(self, shell, tags):
8627aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.shell = shell
8637aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.tags = tags
8645d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey        self.softspace = 0
8657aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8667aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def write(self, s):
8677aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        self.shell.write(s, self.tags)
8687aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8697aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def writelines(self, l):
8707aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        map(self.write, l)
8717aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8727aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def flush(self):
8737aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer        pass
8747aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
8757aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    def isatty(self):
876837d15c5b5deee769079faa94117d8a83adb53ecKurt B. Kaiser        return True
8777aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
878969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
8797aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererusage_msg = """\
88096d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiserusage: idle.py [-c command] [-d] [-i] [-r script] [-s] [-t title] [arg] ...
8817aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
88296d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiseridle file(s)    (without options) edit the file(s)
8837aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
88496d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-c cmd     run the command in a shell
88596d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-d         enable the debugger
8865d2af63cc36ca1141e1ec7412fc33866f3908408Chui Tey-e         edit mode; arguments are files to be edited
88796d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-i         open an interactive shell
88896d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-i file(s) open a shell and also an editor window for each file
889969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser-r
89096d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-s         run $IDLESTARTUP or $PYTHONSTARTUP before anything else
89196d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser-t title   set title of shell window
89296d88422373ffb32aef75157647e0575a0471c03Kurt B. Kaiser
89396d88422373ffb32aef75157647e0575a0471c03Kurt B. KaiserRemaining arguments are applied to the command (-c) or script (-r).
8947aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer"""
8957aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
896969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiserdef main():
897969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    cmd = None
898969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    edit = 0
899969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    debug = 0
900969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    script = None
901969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    startup = 0
902969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
903969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    try:
904969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        opts, args = getopt.getopt(sys.argv[1:], "c:deir:st:")
905969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    except getopt.error, msg:
906969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.stderr.write("Error: %s\n" % str(msg))
907969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.stderr.write(usage_msg)
908969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.exit(2)
909969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
910969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for o, a in opts:
911969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-c':
912969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            cmd = a
913969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-d':
914969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            debug = 1
915969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-e':
916969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            edit = 1
917969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-r':
918969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            script = a
919969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-s':
920969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            startup = 1
921969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if o == '-t':
922969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            PyShell.shell_title = a
923969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
924969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if args and args[0] != "-": edit = 1
925969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
926969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for i in range(len(sys.path)):
927969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        sys.path[i] = os.path.abspath(sys.path[i])
928969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
929969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    pathx = []
930969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if edit:
931969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        for filename in args:
932969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            pathx.append(os.path.dirname(filename))
933969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    elif args and args[0] != "-":
934969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        pathx.append(os.path.dirname(args[0]))
935969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    else:
936969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        pathx.append(os.curdir)
937969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    for dir in pathx:
938969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        dir = os.path.abspath(dir)
939969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if not dir in sys.path:
940969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            sys.path.insert(0, dir)
941969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
942969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    global flist, root
943969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root = Tk(className="Idle")
944969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    fixwordbreaks(root)
945969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.withdraw()
946969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    flist = PyShellFileList(root)
947969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
948969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if edit:
949969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        for filename in args:
950969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            flist.open(filename)
951969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if not args:
952969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            flist.new()
953969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    else:
954969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if cmd:
955969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            sys.argv = ["-c"] + args
956969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        else:
957969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            sys.argv = args or [""]
958969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
959969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    shell = PyShell(flist)
960969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    interp = shell.interp
961969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    flist.pyshell = shell
962969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
963969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if startup:
964969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        filename = os.environ.get("IDLESTARTUP") or \
965969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser                   os.environ.get("PYTHONSTARTUP")
966969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if filename and os.path.isfile(filename):
967969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            interp.execfile(filename)
968969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
969969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if debug:
970969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        shell.open_debugger()
971969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    if cmd:
972969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        interp.execsource(cmd)
973969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    elif script:
974969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        if os.path.isfile(script):
975969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            interp.execfile(script)
976969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser        else:
977969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser            print "No script file: ", script
978969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    shell.begin()
979969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.mainloop()
980969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    root.destroy()
981969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser
982969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiserdef display_port_binding_error():
983969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser    print """\
9841f733baa04a56eed0a5823158205fc04502e3050Steven M. GavaIDLE cannot run.
9851f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava
986969de458aa12e831942637bbcd9994b29dc86252Kurt B. KaiserIDLE needs to use a specific TCP/IP port (8833) in order to execute and
9871f733baa04a56eed0a5823158205fc04502e3050Steven M. Gavadebug programs. IDLE is unable to bind to this port, and so cannot
9881f733baa04a56eed0a5823158205fc04502e3050Steven M. Gavastart. Here are some possible causes of this problem:
9891f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava
9901f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava  1. TCP/IP networking is not installed or not working on this computer
9911f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava  2. Another program is running that uses this port
992969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaiser  3. Personal firewall software is preventing IDLE from using this port
9931f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava
9941f733baa04a56eed0a5823158205fc04502e3050Steven M. GavaIDLE makes and accepts connections only with this computer, and does not
995969de458aa12e831942637bbcd9994b29dc86252Kurt B. Kaisercommunicate over the internet in any way. Its use of port 8833 should not
9961f733baa04a56eed0a5823158205fc04502e3050Steven M. Gavabe a security risk on a single-user machine.
9971f733baa04a56eed0a5823158205fc04502e3050Steven M. Gava"""
9987aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer
9997aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Schererif __name__ == "__main__":
10007aced17437a6b05bc4b0b5ff93aa6a5d3a374d68David Scherer    main()
1001