~ubuntu-branches/debian/stretch/electrum/stretch

« back to all changes in this revision

Viewing changes to gui/kivy/tools/.buildozer/android/platform/python-for-android/dist/kivy/python-install/lib/python2.7/idlelib/PyShell.py

  • Committer: Package Import Robot
  • Author(s): Tristan Seligmann
  • Date: 2016-04-04 03:02:39 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20160404030239-0szgkio8yryjv7c9
Tags: 2.6.3-1
* New upstream release.
  - Drop backported install-wizard-connect.patch.
* Add Suggests: python-zbar and update the installation hint to suggest
  apt-get instead of pip (closes: #819517).
* Bump Standards-Version to 3.9.7 (no changes).
* Update Vcs-* links.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env python
 
2
 
 
3
import os
 
4
import os.path
 
5
import sys
 
6
import string
 
7
import getopt
 
8
import re
 
9
import socket
 
10
import time
 
11
import threading
 
12
import traceback
 
13
import types
 
14
 
 
15
import linecache
 
16
from code import InteractiveInterpreter
 
17
 
 
18
try:
 
19
    from Tkinter import *
 
20
except ImportError:
 
21
    print>>sys.__stderr__, "** IDLE can't import Tkinter.  " \
 
22
                           "Your Python may not be configured for Tk. **"
 
23
    sys.exit(1)
 
24
import tkMessageBox
 
25
 
 
26
from idlelib.EditorWindow import EditorWindow, fixwordbreaks
 
27
from idlelib.FileList import FileList
 
28
from idlelib.ColorDelegator import ColorDelegator
 
29
from idlelib.UndoDelegator import UndoDelegator
 
30
from idlelib.OutputWindow import OutputWindow
 
31
from idlelib.configHandler import idleConf
 
32
from idlelib import idlever
 
33
from idlelib import rpc
 
34
from idlelib import Debugger
 
35
from idlelib import RemoteDebugger
 
36
from idlelib import macosxSupport
 
37
 
 
38
IDENTCHARS = string.ascii_letters + string.digits + "_"
 
39
HOST = '127.0.0.1' # python execution server on localhost loopback
 
40
PORT = 0  # someday pass in host, port for remote debug capability
 
41
 
 
42
try:
 
43
    from signal import SIGTERM
 
44
except ImportError:
 
45
    SIGTERM = 15
 
46
 
 
47
# Override warnings module to write to warning_stream.  Initialize to send IDLE
 
48
# internal warnings to the console.  ScriptBinding.check_syntax() will
 
49
# temporarily redirect the stream to the shell window to display warnings when
 
50
# checking user's code.
 
51
global warning_stream
 
52
warning_stream = sys.__stderr__
 
53
try:
 
54
    import warnings
 
55
except ImportError:
 
56
    pass
 
57
else:
 
58
    def idle_showwarning(message, category, filename, lineno,
 
59
                         file=None, line=None):
 
60
        if file is None:
 
61
            file = warning_stream
 
62
        try:
 
63
            file.write(warnings.formatwarning(message, category, filename,
 
64
                                              lineno, file=file, line=line))
 
65
        except IOError:
 
66
            pass  ## file (probably __stderr__) is invalid, warning dropped.
 
67
    warnings.showwarning = idle_showwarning
 
68
    def idle_formatwarning(message, category, filename, lineno, line=None):
 
69
        """Format warnings the IDLE way"""
 
70
        s = "\nWarning (from warnings module):\n"
 
71
        s += '  File \"%s\", line %s\n' % (filename, lineno)
 
72
        if line is None:
 
73
            line = linecache.getline(filename, lineno)
 
74
        line = line.strip()
 
75
        if line:
 
76
            s += "    %s\n" % line
 
77
        s += "%s: %s\n>>> " % (category.__name__, message)
 
78
        return s
 
79
    warnings.formatwarning = idle_formatwarning
 
80
 
 
81
def extended_linecache_checkcache(filename=None,
 
82
                                  orig_checkcache=linecache.checkcache):
 
83
    """Extend linecache.checkcache to preserve the <pyshell#...> entries
 
84
 
 
85
    Rather than repeating the linecache code, patch it to save the
 
86
    <pyshell#...> entries, call the original linecache.checkcache()
 
87
    (skipping them), and then restore the saved entries.
 
88
 
 
89
    orig_checkcache is bound at definition time to the original
 
90
    method, allowing it to be patched.
 
91
    """
 
92
    cache = linecache.cache
 
93
    save = {}
 
94
    for key in list(cache):
 
95
        if key[:1] + key[-1:] == '<>':
 
96
            save[key] = cache.pop(key)
 
97
    orig_checkcache(filename)
 
98
    cache.update(save)
 
99
 
 
100
# Patch linecache.checkcache():
 
101
linecache.checkcache = extended_linecache_checkcache
 
102
 
 
103
 
 
104
class PyShellEditorWindow(EditorWindow):
 
105
    "Regular text edit window in IDLE, supports breakpoints"
 
106
 
 
107
    def __init__(self, *args):
 
108
        self.breakpoints = []
 
109
        EditorWindow.__init__(self, *args)
 
110
        self.text.bind("<<set-breakpoint-here>>", self.set_breakpoint_here)
 
111
        self.text.bind("<<clear-breakpoint-here>>", self.clear_breakpoint_here)
 
112
        self.text.bind("<<open-python-shell>>", self.flist.open_shell)
 
113
 
 
114
        self.breakpointPath = os.path.join(idleConf.GetUserCfgDir(),
 
115
                                           'breakpoints.lst')
 
116
        # whenever a file is changed, restore breakpoints
 
117
        if self.io.filename: self.restore_file_breaks()
 
118
        def filename_changed_hook(old_hook=self.io.filename_change_hook,
 
119
                                  self=self):
 
120
            self.restore_file_breaks()
 
121
            old_hook()
 
122
        self.io.set_filename_change_hook(filename_changed_hook)
 
123
 
 
124
    rmenu_specs = [("Set Breakpoint", "<<set-breakpoint-here>>"),
 
125
                   ("Clear Breakpoint", "<<clear-breakpoint-here>>")]
 
126
 
 
127
    def set_breakpoint(self, lineno):
 
128
        text = self.text
 
129
        filename = self.io.filename
 
130
        text.tag_add("BREAK", "%d.0" % lineno, "%d.0" % (lineno+1))
 
131
        try:
 
132
            i = self.breakpoints.index(lineno)
 
133
        except ValueError:  # only add if missing, i.e. do once
 
134
            self.breakpoints.append(lineno)
 
135
        try:    # update the subprocess debugger
 
136
            debug = self.flist.pyshell.interp.debugger
 
137
            debug.set_breakpoint_here(filename, lineno)
 
138
        except: # but debugger may not be active right now....
 
139
            pass
 
140
 
 
141
    def set_breakpoint_here(self, event=None):
 
142
        text = self.text
 
143
        filename = self.io.filename
 
144
        if not filename:
 
145
            text.bell()
 
146
            return
 
147
        lineno = int(float(text.index("insert")))
 
148
        self.set_breakpoint(lineno)
 
149
 
 
150
    def clear_breakpoint_here(self, event=None):
 
151
        text = self.text
 
152
        filename = self.io.filename
 
153
        if not filename:
 
154
            text.bell()
 
155
            return
 
156
        lineno = int(float(text.index("insert")))
 
157
        try:
 
158
            self.breakpoints.remove(lineno)
 
159
        except:
 
160
            pass
 
161
        text.tag_remove("BREAK", "insert linestart",\
 
162
                        "insert lineend +1char")
 
163
        try:
 
164
            debug = self.flist.pyshell.interp.debugger
 
165
            debug.clear_breakpoint_here(filename, lineno)
 
166
        except:
 
167
            pass
 
168
 
 
169
    def clear_file_breaks(self):
 
170
        if self.breakpoints:
 
171
            text = self.text
 
172
            filename = self.io.filename
 
173
            if not filename:
 
174
                text.bell()
 
175
                return
 
176
            self.breakpoints = []
 
177
            text.tag_remove("BREAK", "1.0", END)
 
178
            try:
 
179
                debug = self.flist.pyshell.interp.debugger
 
180
                debug.clear_file_breaks(filename)
 
181
            except:
 
182
                pass
 
183
 
 
184
    def store_file_breaks(self):
 
185
        "Save breakpoints when file is saved"
 
186
        # XXX 13 Dec 2002 KBK Currently the file must be saved before it can
 
187
        #     be run.  The breaks are saved at that time.  If we introduce
 
188
        #     a temporary file save feature the save breaks functionality
 
189
        #     needs to be re-verified, since the breaks at the time the
 
190
        #     temp file is created may differ from the breaks at the last
 
191
        #     permanent save of the file.  Currently, a break introduced
 
192
        #     after a save will be effective, but not persistent.
 
193
        #     This is necessary to keep the saved breaks synched with the
 
194
        #     saved file.
 
195
        #
 
196
        #     Breakpoints are set as tagged ranges in the text.  Certain
 
197
        #     kinds of edits cause these ranges to be deleted: Inserting
 
198
        #     or deleting a line just before a breakpoint, and certain
 
199
        #     deletions prior to a breakpoint.  These issues need to be
 
200
        #     investigated and understood.  It's not clear if they are
 
201
        #     Tk issues or IDLE issues, or whether they can actually
 
202
        #     be fixed.  Since a modified file has to be saved before it is
 
203
        #     run, and since self.breakpoints (from which the subprocess
 
204
        #     debugger is loaded) is updated during the save, the visible
 
205
        #     breaks stay synched with the subprocess even if one of these
 
206
        #     unexpected breakpoint deletions occurs.
 
207
        breaks = self.breakpoints
 
208
        filename = self.io.filename
 
209
        try:
 
210
            lines = open(self.breakpointPath,"r").readlines()
 
211
        except IOError:
 
212
            lines = []
 
213
        new_file = open(self.breakpointPath,"w")
 
214
        for line in lines:
 
215
            if not line.startswith(filename + '='):
 
216
                new_file.write(line)
 
217
        self.update_breakpoints()
 
218
        breaks = self.breakpoints
 
219
        if breaks:
 
220
            new_file.write(filename + '=' + str(breaks) + '\n')
 
221
        new_file.close()
 
222
 
 
223
    def restore_file_breaks(self):
 
224
        self.text.update()   # this enables setting "BREAK" tags to be visible
 
225
        filename = self.io.filename
 
226
        if filename is None:
 
227
            return
 
228
        if os.path.isfile(self.breakpointPath):
 
229
            lines = open(self.breakpointPath,"r").readlines()
 
230
            for line in lines:
 
231
                if line.startswith(filename + '='):
 
232
                    breakpoint_linenumbers = eval(line[len(filename)+1:])
 
233
                    for breakpoint_linenumber in breakpoint_linenumbers:
 
234
                        self.set_breakpoint(breakpoint_linenumber)
 
235
 
 
236
    def update_breakpoints(self):
 
237
        "Retrieves all the breakpoints in the current window"
 
238
        text = self.text
 
239
        ranges = text.tag_ranges("BREAK")
 
240
        linenumber_list = self.ranges_to_linenumbers(ranges)
 
241
        self.breakpoints = linenumber_list
 
242
 
 
243
    def ranges_to_linenumbers(self, ranges):
 
244
        lines = []
 
245
        for index in range(0, len(ranges), 2):
 
246
            lineno = int(float(ranges[index]))
 
247
            end = int(float(ranges[index+1]))
 
248
            while lineno < end:
 
249
                lines.append(lineno)
 
250
                lineno += 1
 
251
        return lines
 
252
 
 
253
# XXX 13 Dec 2002 KBK Not used currently
 
254
#    def saved_change_hook(self):
 
255
#        "Extend base method - clear breaks if module is modified"
 
256
#        if not self.get_saved():
 
257
#            self.clear_file_breaks()
 
258
#        EditorWindow.saved_change_hook(self)
 
259
 
 
260
    def _close(self):
 
261
        "Extend base method - clear breaks when module is closed"
 
262
        self.clear_file_breaks()
 
263
        EditorWindow._close(self)
 
264
 
 
265
 
 
266
class PyShellFileList(FileList):
 
267
    "Extend base class: IDLE supports a shell and breakpoints"
 
268
 
 
269
    # override FileList's class variable, instances return PyShellEditorWindow
 
270
    # instead of EditorWindow when new edit windows are created.
 
271
    EditorWindow = PyShellEditorWindow
 
272
 
 
273
    pyshell = None
 
274
 
 
275
    def open_shell(self, event=None):
 
276
        if self.pyshell:
 
277
            self.pyshell.top.wakeup()
 
278
        else:
 
279
            self.pyshell = PyShell(self)
 
280
            if self.pyshell:
 
281
                if not self.pyshell.begin():
 
282
                    return None
 
283
        return self.pyshell
 
284
 
 
285
 
 
286
class ModifiedColorDelegator(ColorDelegator):
 
287
    "Extend base class: colorizer for the shell window itself"
 
288
 
 
289
    def __init__(self):
 
290
        ColorDelegator.__init__(self)
 
291
        self.LoadTagDefs()
 
292
 
 
293
    def recolorize_main(self):
 
294
        self.tag_remove("TODO", "1.0", "iomark")
 
295
        self.tag_add("SYNC", "1.0", "iomark")
 
296
        ColorDelegator.recolorize_main(self)
 
297
 
 
298
    def LoadTagDefs(self):
 
299
        ColorDelegator.LoadTagDefs(self)
 
300
        theme = idleConf.GetOption('main','Theme','name')
 
301
        self.tagdefs.update({
 
302
            "stdin": {'background':None,'foreground':None},
 
303
            "stdout": idleConf.GetHighlight(theme, "stdout"),
 
304
            "stderr": idleConf.GetHighlight(theme, "stderr"),
 
305
            "console": idleConf.GetHighlight(theme, "console"),
 
306
        })
 
307
 
 
308
class ModifiedUndoDelegator(UndoDelegator):
 
309
    "Extend base class: forbid insert/delete before the I/O mark"
 
310
 
 
311
    def insert(self, index, chars, tags=None):
 
312
        try:
 
313
            if self.delegate.compare(index, "<", "iomark"):
 
314
                self.delegate.bell()
 
315
                return
 
316
        except TclError:
 
317
            pass
 
318
        UndoDelegator.insert(self, index, chars, tags)
 
319
 
 
320
    def delete(self, index1, index2=None):
 
321
        try:
 
322
            if self.delegate.compare(index1, "<", "iomark"):
 
323
                self.delegate.bell()
 
324
                return
 
325
        except TclError:
 
326
            pass
 
327
        UndoDelegator.delete(self, index1, index2)
 
328
 
 
329
 
 
330
class MyRPCClient(rpc.RPCClient):
 
331
 
 
332
    def handle_EOF(self):
 
333
        "Override the base class - just re-raise EOFError"
 
334
        raise EOFError
 
335
 
 
336
 
 
337
class ModifiedInterpreter(InteractiveInterpreter):
 
338
 
 
339
    def __init__(self, tkconsole):
 
340
        self.tkconsole = tkconsole
 
341
        locals = sys.modules['__main__'].__dict__
 
342
        InteractiveInterpreter.__init__(self, locals=locals)
 
343
        self.save_warnings_filters = None
 
344
        self.restarting = False
 
345
        self.subprocess_arglist = None
 
346
        self.port = PORT
 
347
 
 
348
    rpcclt = None
 
349
    rpcpid = None
 
350
 
 
351
    def spawn_subprocess(self):
 
352
        if self.subprocess_arglist is None:
 
353
            self.subprocess_arglist = self.build_subprocess_arglist()
 
354
        args = self.subprocess_arglist
 
355
        self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
 
356
 
 
357
    def build_subprocess_arglist(self):
 
358
        assert (self.port!=0), (
 
359
            "Socket should have been assigned a port number.")
 
360
        w = ['-W' + s for s in sys.warnoptions]
 
361
        if 1/2 > 0: # account for new division
 
362
            w.append('-Qnew')
 
363
        # Maybe IDLE is installed and is being accessed via sys.path,
 
364
        # or maybe it's not installed and the idle.py script is being
 
365
        # run from the IDLE source directory.
 
366
        del_exitf = idleConf.GetOption('main', 'General', 'delete-exitfunc',
 
367
                                       default=False, type='bool')
 
368
        if __name__ == 'idlelib.PyShell':
 
369
            command = "__import__('idlelib.run').run.main(%r)" % (del_exitf,)
 
370
        else:
 
371
            command = "__import__('run').main(%r)" % (del_exitf,)
 
372
        if sys.platform[:3] == 'win' and ' ' in sys.executable:
 
373
            # handle embedded space in path by quoting the argument
 
374
            decorated_exec = '"%s"' % sys.executable
 
375
        else:
 
376
            decorated_exec = sys.executable
 
377
        return [decorated_exec] + w + ["-c", command, str(self.port)]
 
378
 
 
379
    def start_subprocess(self):
 
380
        addr = (HOST, self.port)
 
381
        # GUI makes several attempts to acquire socket, listens for connection
 
382
        for i in range(3):
 
383
            time.sleep(i)
 
384
            try:
 
385
                self.rpcclt = MyRPCClient(addr)
 
386
                break
 
387
            except socket.error, err:
 
388
                pass
 
389
        else:
 
390
            self.display_port_binding_error()
 
391
            return None
 
392
        # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
 
393
        self.port = self.rpcclt.listening_sock.getsockname()[1]
 
394
        # if PORT was not 0, probably working with a remote execution server
 
395
        if PORT != 0:
 
396
            # To allow reconnection within the 2MSL wait (cf. Stevens TCP
 
397
            # V1, 18.6),  set SO_REUSEADDR.  Note that this can be problematic
 
398
            # on Windows since the implementation allows two active sockets on
 
399
            # the same address!
 
400
            self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
 
401
                                           socket.SO_REUSEADDR, 1)
 
402
        self.spawn_subprocess()
 
403
        #time.sleep(20) # test to simulate GUI not accepting connection
 
404
        # Accept the connection from the Python execution server
 
405
        self.rpcclt.listening_sock.settimeout(10)
 
406
        try:
 
407
            self.rpcclt.accept()
 
408
        except socket.timeout, err:
 
409
            self.display_no_subprocess_error()
 
410
            return None
 
411
        self.rpcclt.register("stdin", self.tkconsole)
 
412
        self.rpcclt.register("stdout", self.tkconsole.stdout)
 
413
        self.rpcclt.register("stderr", self.tkconsole.stderr)
 
414
        self.rpcclt.register("flist", self.tkconsole.flist)
 
415
        self.rpcclt.register("linecache", linecache)
 
416
        self.rpcclt.register("interp", self)
 
417
        self.transfer_path()
 
418
        self.poll_subprocess()
 
419
        return self.rpcclt
 
420
 
 
421
    def restart_subprocess(self):
 
422
        if self.restarting:
 
423
            return self.rpcclt
 
424
        self.restarting = True
 
425
        # close only the subprocess debugger
 
426
        debug = self.getdebugger()
 
427
        if debug:
 
428
            try:
 
429
                # Only close subprocess debugger, don't unregister gui_adap!
 
430
                RemoteDebugger.close_subprocess_debugger(self.rpcclt)
 
431
            except:
 
432
                pass
 
433
        # Kill subprocess, spawn a new one, accept connection.
 
434
        self.rpcclt.close()
 
435
        self.unix_terminate()
 
436
        console = self.tkconsole
 
437
        was_executing = console.executing
 
438
        console.executing = False
 
439
        self.spawn_subprocess()
 
440
        try:
 
441
            self.rpcclt.accept()
 
442
        except socket.timeout, err:
 
443
            self.display_no_subprocess_error()
 
444
            return None
 
445
        self.transfer_path()
 
446
        # annotate restart in shell window and mark it
 
447
        console.text.delete("iomark", "end-1c")
 
448
        if was_executing:
 
449
            console.write('\n')
 
450
            console.showprompt()
 
451
        halfbar = ((int(console.width) - 16) // 2) * '='
 
452
        console.write(halfbar + ' RESTART ' + halfbar)
 
453
        console.text.mark_set("restart", "end-1c")
 
454
        console.text.mark_gravity("restart", "left")
 
455
        console.showprompt()
 
456
        # restart subprocess debugger
 
457
        if debug:
 
458
            # Restarted debugger connects to current instance of debug GUI
 
459
            gui = RemoteDebugger.restart_subprocess_debugger(self.rpcclt)
 
460
            # reload remote debugger breakpoints for all PyShellEditWindows
 
461
            debug.load_breakpoints()
 
462
        self.restarting = False
 
463
        return self.rpcclt
 
464
 
 
465
    def __request_interrupt(self):
 
466
        self.rpcclt.remotecall("exec", "interrupt_the_server", (), {})
 
467
 
 
468
    def interrupt_subprocess(self):
 
469
        threading.Thread(target=self.__request_interrupt).start()
 
470
 
 
471
    def kill_subprocess(self):
 
472
        try:
 
473
            self.rpcclt.close()
 
474
        except AttributeError:  # no socket
 
475
            pass
 
476
        self.unix_terminate()
 
477
        self.tkconsole.executing = False
 
478
        self.rpcclt = None
 
479
 
 
480
    def unix_terminate(self):
 
481
        "UNIX: make sure subprocess is terminated and collect status"
 
482
        if hasattr(os, 'kill'):
 
483
            try:
 
484
                os.kill(self.rpcpid, SIGTERM)
 
485
            except OSError:
 
486
                # process already terminated:
 
487
                return
 
488
            else:
 
489
                try:
 
490
                    os.waitpid(self.rpcpid, 0)
 
491
                except OSError:
 
492
                    return
 
493
 
 
494
    def transfer_path(self):
 
495
        self.runcommand("""if 1:
 
496
        import sys as _sys
 
497
        _sys.path = %r
 
498
        del _sys
 
499
        \n""" % (sys.path,))
 
500
 
 
501
    active_seq = None
 
502
 
 
503
    def poll_subprocess(self):
 
504
        clt = self.rpcclt
 
505
        if clt is None:
 
506
            return
 
507
        try:
 
508
            response = clt.pollresponse(self.active_seq, wait=0.05)
 
509
        except (EOFError, IOError, KeyboardInterrupt):
 
510
            # lost connection or subprocess terminated itself, restart
 
511
            # [the KBI is from rpc.SocketIO.handle_EOF()]
 
512
            if self.tkconsole.closing:
 
513
                return
 
514
            response = None
 
515
            self.restart_subprocess()
 
516
        if response:
 
517
            self.tkconsole.resetoutput()
 
518
            self.active_seq = None
 
519
            how, what = response
 
520
            console = self.tkconsole.console
 
521
            if how == "OK":
 
522
                if what is not None:
 
523
                    print >>console, repr(what)
 
524
            elif how == "EXCEPTION":
 
525
                if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
 
526
                    self.remote_stack_viewer()
 
527
            elif how == "ERROR":
 
528
                errmsg = "PyShell.ModifiedInterpreter: Subprocess ERROR:\n"
 
529
                print >>sys.__stderr__, errmsg, what
 
530
                print >>console, errmsg, what
 
531
            # we received a response to the currently active seq number:
 
532
            try:
 
533
                self.tkconsole.endexecuting()
 
534
            except AttributeError:  # shell may have closed
 
535
                pass
 
536
        # Reschedule myself
 
537
        if not self.tkconsole.closing:
 
538
            self.tkconsole.text.after(self.tkconsole.pollinterval,
 
539
                                      self.poll_subprocess)
 
540
 
 
541
    debugger = None
 
542
 
 
543
    def setdebugger(self, debugger):
 
544
        self.debugger = debugger
 
545
 
 
546
    def getdebugger(self):
 
547
        return self.debugger
 
548
 
 
549
    def open_remote_stack_viewer(self):
 
550
        """Initiate the remote stack viewer from a separate thread.
 
551
 
 
552
        This method is called from the subprocess, and by returning from this
 
553
        method we allow the subprocess to unblock.  After a bit the shell
 
554
        requests the subprocess to open the remote stack viewer which returns a
 
555
        static object looking at the last exception.  It is queried through
 
556
        the RPC mechanism.
 
557
 
 
558
        """
 
559
        self.tkconsole.text.after(300, self.remote_stack_viewer)
 
560
        return
 
561
 
 
562
    def remote_stack_viewer(self):
 
563
        from idlelib import RemoteObjectBrowser
 
564
        oid = self.rpcclt.remotequeue("exec", "stackviewer", ("flist",), {})
 
565
        if oid is None:
 
566
            self.tkconsole.root.bell()
 
567
            return
 
568
        item = RemoteObjectBrowser.StubObjectTreeItem(self.rpcclt, oid)
 
569
        from idlelib.TreeWidget import ScrolledCanvas, TreeNode
 
570
        top = Toplevel(self.tkconsole.root)
 
571
        theme = idleConf.GetOption('main','Theme','name')
 
572
        background = idleConf.GetHighlight(theme, 'normal')['background']
 
573
        sc = ScrolledCanvas(top, bg=background, highlightthickness=0)
 
574
        sc.frame.pack(expand=1, fill="both")
 
575
        node = TreeNode(sc.canvas, None, item)
 
576
        node.expand()
 
577
        # XXX Should GC the remote tree when closing the window
 
578
 
 
579
    gid = 0
 
580
 
 
581
    def execsource(self, source):
 
582
        "Like runsource() but assumes complete exec source"
 
583
        filename = self.stuffsource(source)
 
584
        self.execfile(filename, source)
 
585
 
 
586
    def execfile(self, filename, source=None):
 
587
        "Execute an existing file"
 
588
        if source is None:
 
589
            source = open(filename, "r").read()
 
590
        try:
 
591
            code = compile(source, filename, "exec")
 
592
        except (OverflowError, SyntaxError):
 
593
            self.tkconsole.resetoutput()
 
594
            tkerr = self.tkconsole.stderr
 
595
            print>>tkerr, '*** Error in script or command!\n'
 
596
            print>>tkerr, 'Traceback (most recent call last):'
 
597
            InteractiveInterpreter.showsyntaxerror(self, filename)
 
598
            self.tkconsole.showprompt()
 
599
        else:
 
600
            self.runcode(code)
 
601
 
 
602
    def runsource(self, source):
 
603
        "Extend base class method: Stuff the source in the line cache first"
 
604
        filename = self.stuffsource(source)
 
605
        self.more = 0
 
606
        self.save_warnings_filters = warnings.filters[:]
 
607
        warnings.filterwarnings(action="error", category=SyntaxWarning)
 
608
        if isinstance(source, types.UnicodeType):
 
609
            from idlelib import IOBinding
 
610
            try:
 
611
                source = source.encode(IOBinding.encoding)
 
612
            except UnicodeError:
 
613
                self.tkconsole.resetoutput()
 
614
                self.write("Unsupported characters in input\n")
 
615
                return
 
616
        try:
 
617
            # InteractiveInterpreter.runsource() calls its runcode() method,
 
618
            # which is overridden (see below)
 
619
            return InteractiveInterpreter.runsource(self, source, filename)
 
620
        finally:
 
621
            if self.save_warnings_filters is not None:
 
622
                warnings.filters[:] = self.save_warnings_filters
 
623
                self.save_warnings_filters = None
 
624
 
 
625
    def stuffsource(self, source):
 
626
        "Stuff source in the filename cache"
 
627
        filename = "<pyshell#%d>" % self.gid
 
628
        self.gid = self.gid + 1
 
629
        lines = source.split("\n")
 
630
        linecache.cache[filename] = len(source)+1, 0, lines, filename
 
631
        return filename
 
632
 
 
633
    def prepend_syspath(self, filename):
 
634
        "Prepend sys.path with file's directory if not already included"
 
635
        self.runcommand("""if 1:
 
636
            _filename = %r
 
637
            import sys as _sys
 
638
            from os.path import dirname as _dirname
 
639
            _dir = _dirname(_filename)
 
640
            if not _dir in _sys.path:
 
641
                _sys.path.insert(0, _dir)
 
642
            del _filename, _sys, _dirname, _dir
 
643
            \n""" % (filename,))
 
644
 
 
645
    def showsyntaxerror(self, filename=None):
 
646
        """Extend base class method: Add Colorizing
 
647
 
 
648
        Color the offending position instead of printing it and pointing at it
 
649
        with a caret.
 
650
 
 
651
        """
 
652
        text = self.tkconsole.text
 
653
        stuff = self.unpackerror()
 
654
        if stuff:
 
655
            msg, lineno, offset, line = stuff
 
656
            if lineno == 1:
 
657
                pos = "iomark + %d chars" % (offset-1)
 
658
            else:
 
659
                pos = "iomark linestart + %d lines + %d chars" % \
 
660
                      (lineno-1, offset-1)
 
661
            text.tag_add("ERROR", pos)
 
662
            text.see(pos)
 
663
            char = text.get(pos)
 
664
            if char and char in IDENTCHARS:
 
665
                text.tag_add("ERROR", pos + " wordstart", pos)
 
666
            self.tkconsole.resetoutput()
 
667
            self.write("SyntaxError: %s\n" % str(msg))
 
668
        else:
 
669
            self.tkconsole.resetoutput()
 
670
            InteractiveInterpreter.showsyntaxerror(self, filename)
 
671
        self.tkconsole.showprompt()
 
672
 
 
673
    def unpackerror(self):
 
674
        type, value, tb = sys.exc_info()
 
675
        ok = type is SyntaxError
 
676
        if ok:
 
677
            try:
 
678
                msg, (dummy_filename, lineno, offset, line) = value
 
679
                if not offset:
 
680
                    offset = 0
 
681
            except:
 
682
                ok = 0
 
683
        if ok:
 
684
            return msg, lineno, offset, line
 
685
        else:
 
686
            return None
 
687
 
 
688
    def showtraceback(self):
 
689
        "Extend base class method to reset output properly"
 
690
        self.tkconsole.resetoutput()
 
691
        self.checklinecache()
 
692
        InteractiveInterpreter.showtraceback(self)
 
693
        if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"):
 
694
            self.tkconsole.open_stack_viewer()
 
695
 
 
696
    def checklinecache(self):
 
697
        c = linecache.cache
 
698
        for key in c.keys():
 
699
            if key[:1] + key[-1:] != "<>":
 
700
                del c[key]
 
701
 
 
702
    def runcommand(self, code):
 
703
        "Run the code without invoking the debugger"
 
704
        # The code better not raise an exception!
 
705
        if self.tkconsole.executing:
 
706
            self.display_executing_dialog()
 
707
            return 0
 
708
        if self.rpcclt:
 
709
            self.rpcclt.remotequeue("exec", "runcode", (code,), {})
 
710
        else:
 
711
            exec code in self.locals
 
712
        return 1
 
713
 
 
714
    def runcode(self, code):
 
715
        "Override base class method"
 
716
        if self.tkconsole.executing:
 
717
            self.interp.restart_subprocess()
 
718
        self.checklinecache()
 
719
        if self.save_warnings_filters is not None:
 
720
            warnings.filters[:] = self.save_warnings_filters
 
721
            self.save_warnings_filters = None
 
722
        debugger = self.debugger
 
723
        try:
 
724
            self.tkconsole.beginexecuting()
 
725
            if not debugger and self.rpcclt is not None:
 
726
                self.active_seq = self.rpcclt.asyncqueue("exec", "runcode",
 
727
                                                        (code,), {})
 
728
            elif debugger:
 
729
                debugger.run(code, self.locals)
 
730
            else:
 
731
                exec code in self.locals
 
732
        except SystemExit:
 
733
            if not self.tkconsole.closing:
 
734
                if tkMessageBox.askyesno(
 
735
                    "Exit?",
 
736
                    "Do you want to exit altogether?",
 
737
                    default="yes",
 
738
                    master=self.tkconsole.text):
 
739
                    raise
 
740
                else:
 
741
                    self.showtraceback()
 
742
            else:
 
743
                raise
 
744
        except:
 
745
            if use_subprocess:
 
746
                print >>self.tkconsole.stderr, \
 
747
                         "IDLE internal error in runcode()"
 
748
                self.showtraceback()
 
749
                self.tkconsole.endexecuting()
 
750
            else:
 
751
                if self.tkconsole.canceled:
 
752
                    self.tkconsole.canceled = False
 
753
                    print >>self.tkconsole.stderr, "KeyboardInterrupt"
 
754
                else:
 
755
                    self.showtraceback()
 
756
        finally:
 
757
            if not use_subprocess:
 
758
                try:
 
759
                    self.tkconsole.endexecuting()
 
760
                except AttributeError:  # shell may have closed
 
761
                    pass
 
762
 
 
763
    def write(self, s):
 
764
        "Override base class method"
 
765
        self.tkconsole.stderr.write(s)
 
766
 
 
767
    def display_port_binding_error(self):
 
768
        tkMessageBox.showerror(
 
769
            "Port Binding Error",
 
770
            "IDLE can't bind to a TCP/IP port, which is necessary to "
 
771
            "communicate with its Python execution server.  This might be "
 
772
            "because no networking is installed on this computer.  "
 
773
            "Run IDLE with the -n command line switch to start without a "
 
774
            "subprocess and refer to Help/IDLE Help 'Running without a "
 
775
            "subprocess' for further details.",
 
776
            master=self.tkconsole.text)
 
777
 
 
778
    def display_no_subprocess_error(self):
 
779
        tkMessageBox.showerror(
 
780
            "Subprocess Startup Error",
 
781
            "IDLE's subprocess didn't make connection.  Either IDLE can't "
 
782
            "start a subprocess or personal firewall software is blocking "
 
783
            "the connection.",
 
784
            master=self.tkconsole.text)
 
785
 
 
786
    def display_executing_dialog(self):
 
787
        tkMessageBox.showerror(
 
788
            "Already executing",
 
789
            "The Python Shell window is already executing a command; "
 
790
            "please wait until it is finished.",
 
791
            master=self.tkconsole.text)
 
792
 
 
793
 
 
794
class PyShell(OutputWindow):
 
795
 
 
796
    shell_title = "Python Shell"
 
797
 
 
798
    # Override classes
 
799
    ColorDelegator = ModifiedColorDelegator
 
800
    UndoDelegator = ModifiedUndoDelegator
 
801
 
 
802
    # Override menus
 
803
    menu_specs = [
 
804
        ("file", "_File"),
 
805
        ("edit", "_Edit"),
 
806
        ("debug", "_Debug"),
 
807
        ("options", "_Options"),
 
808
        ("windows", "_Windows"),
 
809
        ("help", "_Help"),
 
810
    ]
 
811
 
 
812
    if macosxSupport.runningAsOSXApp():
 
813
        del menu_specs[-3]
 
814
        menu_specs[-2] = ("windows", "_Window")
 
815
 
 
816
 
 
817
    # New classes
 
818
    from idlelib.IdleHistory import History
 
819
 
 
820
    def __init__(self, flist=None):
 
821
        if use_subprocess:
 
822
            ms = self.menu_specs
 
823
            if ms[2][0] != "shell":
 
824
                ms.insert(2, ("shell", "She_ll"))
 
825
        self.interp = ModifiedInterpreter(self)
 
826
        if flist is None:
 
827
            root = Tk()
 
828
            fixwordbreaks(root)
 
829
            root.withdraw()
 
830
            flist = PyShellFileList(root)
 
831
        #
 
832
        OutputWindow.__init__(self, flist, None, None)
 
833
        #
 
834
##        self.config(usetabs=1, indentwidth=8, context_use_ps1=1)
 
835
        self.usetabs = True
 
836
        # indentwidth must be 8 when using tabs.  See note in EditorWindow:
 
837
        self.indentwidth = 8
 
838
        self.context_use_ps1 = True
 
839
        #
 
840
        text = self.text
 
841
        text.configure(wrap="char")
 
842
        text.bind("<<newline-and-indent>>", self.enter_callback)
 
843
        text.bind("<<plain-newline-and-indent>>", self.linefeed_callback)
 
844
        text.bind("<<interrupt-execution>>", self.cancel_callback)
 
845
        text.bind("<<end-of-file>>", self.eof_callback)
 
846
        text.bind("<<open-stack-viewer>>", self.open_stack_viewer)
 
847
        text.bind("<<toggle-debugger>>", self.toggle_debugger)
 
848
        text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer)
 
849
        if use_subprocess:
 
850
            text.bind("<<view-restart>>", self.view_restart_mark)
 
851
            text.bind("<<restart-shell>>", self.restart_shell)
 
852
        #
 
853
        self.save_stdout = sys.stdout
 
854
        self.save_stderr = sys.stderr
 
855
        self.save_stdin = sys.stdin
 
856
        from idlelib import IOBinding
 
857
        self.stdout = PseudoFile(self, "stdout", IOBinding.encoding)
 
858
        self.stderr = PseudoFile(self, "stderr", IOBinding.encoding)
 
859
        self.console = PseudoFile(self, "console", IOBinding.encoding)
 
860
        if not use_subprocess:
 
861
            sys.stdout = self.stdout
 
862
            sys.stderr = self.stderr
 
863
            sys.stdin = self
 
864
        #
 
865
        self.history = self.History(self.text)
 
866
        #
 
867
        self.pollinterval = 50  # millisec
 
868
 
 
869
    def get_standard_extension_names(self):
 
870
        return idleConf.GetExtensions(shell_only=True)
 
871
 
 
872
    reading = False
 
873
    executing = False
 
874
    canceled = False
 
875
    endoffile = False
 
876
    closing = False
 
877
 
 
878
    def set_warning_stream(self, stream):
 
879
        global warning_stream
 
880
        warning_stream = stream
 
881
 
 
882
    def get_warning_stream(self):
 
883
        return warning_stream
 
884
 
 
885
    def toggle_debugger(self, event=None):
 
886
        if self.executing:
 
887
            tkMessageBox.showerror("Don't debug now",
 
888
                "You can only toggle the debugger when idle",
 
889
                master=self.text)
 
890
            self.set_debugger_indicator()
 
891
            return "break"
 
892
        else:
 
893
            db = self.interp.getdebugger()
 
894
            if db:
 
895
                self.close_debugger()
 
896
            else:
 
897
                self.open_debugger()
 
898
 
 
899
    def set_debugger_indicator(self):
 
900
        db = self.interp.getdebugger()
 
901
        self.setvar("<<toggle-debugger>>", not not db)
 
902
 
 
903
    def toggle_jit_stack_viewer(self, event=None):
 
904
        pass # All we need is the variable
 
905
 
 
906
    def close_debugger(self):
 
907
        db = self.interp.getdebugger()
 
908
        if db:
 
909
            self.interp.setdebugger(None)
 
910
            db.close()
 
911
            if self.interp.rpcclt:
 
912
                RemoteDebugger.close_remote_debugger(self.interp.rpcclt)
 
913
            self.resetoutput()
 
914
            self.console.write("[DEBUG OFF]\n")
 
915
            sys.ps1 = ">>> "
 
916
            self.showprompt()
 
917
        self.set_debugger_indicator()
 
918
 
 
919
    def open_debugger(self):
 
920
        if self.interp.rpcclt:
 
921
            dbg_gui = RemoteDebugger.start_remote_debugger(self.interp.rpcclt,
 
922
                                                           self)
 
923
        else:
 
924
            dbg_gui = Debugger.Debugger(self)
 
925
        self.interp.setdebugger(dbg_gui)
 
926
        dbg_gui.load_breakpoints()
 
927
        sys.ps1 = "[DEBUG ON]\n>>> "
 
928
        self.showprompt()
 
929
        self.set_debugger_indicator()
 
930
 
 
931
    def beginexecuting(self):
 
932
        "Helper for ModifiedInterpreter"
 
933
        self.resetoutput()
 
934
        self.executing = 1
 
935
 
 
936
    def endexecuting(self):
 
937
        "Helper for ModifiedInterpreter"
 
938
        self.executing = 0
 
939
        self.canceled = 0
 
940
        self.showprompt()
 
941
 
 
942
    def close(self):
 
943
        "Extend EditorWindow.close()"
 
944
        if self.executing:
 
945
            response = tkMessageBox.askokcancel(
 
946
                "Kill?",
 
947
                "The program is still running!\n Do you want to kill it?",
 
948
                default="ok",
 
949
                parent=self.text)
 
950
            if response is False:
 
951
                return "cancel"
 
952
        if self.reading:
 
953
            self.top.quit()
 
954
        self.canceled = True
 
955
        self.closing = True
 
956
        # Wait for poll_subprocess() rescheduling to stop
 
957
        self.text.after(2 * self.pollinterval, self.close2)
 
958
 
 
959
    def close2(self):
 
960
        return EditorWindow.close(self)
 
961
 
 
962
    def _close(self):
 
963
        "Extend EditorWindow._close(), shut down debugger and execution server"
 
964
        self.close_debugger()
 
965
        if use_subprocess:
 
966
            self.interp.kill_subprocess()
 
967
        # Restore std streams
 
968
        sys.stdout = self.save_stdout
 
969
        sys.stderr = self.save_stderr
 
970
        sys.stdin = self.save_stdin
 
971
        # Break cycles
 
972
        self.interp = None
 
973
        self.console = None
 
974
        self.flist.pyshell = None
 
975
        self.history = None
 
976
        EditorWindow._close(self)
 
977
 
 
978
    def ispythonsource(self, filename):
 
979
        "Override EditorWindow method: never remove the colorizer"
 
980
        return True
 
981
 
 
982
    def short_title(self):
 
983
        return self.shell_title
 
984
 
 
985
    COPYRIGHT = \
 
986
          'Type "copyright", "credits" or "license()" for more information.'
 
987
 
 
988
    def begin(self):
 
989
        self.resetoutput()
 
990
        if use_subprocess:
 
991
            nosub = ''
 
992
            client = self.interp.start_subprocess()
 
993
            if not client:
 
994
                self.close()
 
995
                return False
 
996
        else:
 
997
            nosub = "==== No Subprocess ===="
 
998
        self.write("Python %s on %s\n%s\n%s" %
 
999
                   (sys.version, sys.platform, self.COPYRIGHT, nosub))
 
1000
        self.showprompt()
 
1001
        import Tkinter
 
1002
        Tkinter._default_root = None # 03Jan04 KBK What's this?
 
1003
        return True
 
1004
 
 
1005
    def readline(self):
 
1006
        save = self.reading
 
1007
        try:
 
1008
            self.reading = 1
 
1009
            self.top.mainloop()  # nested mainloop()
 
1010
        finally:
 
1011
            self.reading = save
 
1012
        line = self.text.get("iomark", "end-1c")
 
1013
        if len(line) == 0:  # may be EOF if we quit our mainloop with Ctrl-C
 
1014
            line = "\n"
 
1015
        if isinstance(line, unicode):
 
1016
            from idlelib import IOBinding
 
1017
            try:
 
1018
                line = line.encode(IOBinding.encoding)
 
1019
            except UnicodeError:
 
1020
                pass
 
1021
        self.resetoutput()
 
1022
        if self.canceled:
 
1023
            self.canceled = 0
 
1024
            if not use_subprocess:
 
1025
                raise KeyboardInterrupt
 
1026
        if self.endoffile:
 
1027
            self.endoffile = 0
 
1028
            line = ""
 
1029
        return line
 
1030
 
 
1031
    def isatty(self):
 
1032
        return True
 
1033
 
 
1034
    def cancel_callback(self, event=None):
 
1035
        try:
 
1036
            if self.text.compare("sel.first", "!=", "sel.last"):
 
1037
                return # Active selection -- always use default binding
 
1038
        except:
 
1039
            pass
 
1040
        if not (self.executing or self.reading):
 
1041
            self.resetoutput()
 
1042
            self.interp.write("KeyboardInterrupt\n")
 
1043
            self.showprompt()
 
1044
            return "break"
 
1045
        self.endoffile = 0
 
1046
        self.canceled = 1
 
1047
        if (self.executing and self.interp.rpcclt):
 
1048
            if self.interp.getdebugger():
 
1049
                self.interp.restart_subprocess()
 
1050
            else:
 
1051
                self.interp.interrupt_subprocess()
 
1052
        if self.reading:
 
1053
            self.top.quit()  # exit the nested mainloop() in readline()
 
1054
        return "break"
 
1055
 
 
1056
    def eof_callback(self, event):
 
1057
        if self.executing and not self.reading:
 
1058
            return # Let the default binding (delete next char) take over
 
1059
        if not (self.text.compare("iomark", "==", "insert") and
 
1060
                self.text.compare("insert", "==", "end-1c")):
 
1061
            return # Let the default binding (delete next char) take over
 
1062
        if not self.executing:
 
1063
            self.resetoutput()
 
1064
            self.close()
 
1065
        else:
 
1066
            self.canceled = 0
 
1067
            self.endoffile = 1
 
1068
            self.top.quit()
 
1069
        return "break"
 
1070
 
 
1071
    def linefeed_callback(self, event):
 
1072
        # Insert a linefeed without entering anything (still autoindented)
 
1073
        if self.reading:
 
1074
            self.text.insert("insert", "\n")
 
1075
            self.text.see("insert")
 
1076
        else:
 
1077
            self.newline_and_indent_event(event)
 
1078
        return "break"
 
1079
 
 
1080
    def enter_callback(self, event):
 
1081
        if self.executing and not self.reading:
 
1082
            return # Let the default binding (insert '\n') take over
 
1083
        # If some text is selected, recall the selection
 
1084
        # (but only if this before the I/O mark)
 
1085
        try:
 
1086
            sel = self.text.get("sel.first", "sel.last")
 
1087
            if sel:
 
1088
                if self.text.compare("sel.last", "<=", "iomark"):
 
1089
                    self.recall(sel, event)
 
1090
                    return "break"
 
1091
        except:
 
1092
            pass
 
1093
        # If we're strictly before the line containing iomark, recall
 
1094
        # the current line, less a leading prompt, less leading or
 
1095
        # trailing whitespace
 
1096
        if self.text.compare("insert", "<", "iomark linestart"):
 
1097
            # Check if there's a relevant stdin range -- if so, use it
 
1098
            prev = self.text.tag_prevrange("stdin", "insert")
 
1099
            if prev and self.text.compare("insert", "<", prev[1]):
 
1100
                self.recall(self.text.get(prev[0], prev[1]), event)
 
1101
                return "break"
 
1102
            next = self.text.tag_nextrange("stdin", "insert")
 
1103
            if next and self.text.compare("insert lineend", ">=", next[0]):
 
1104
                self.recall(self.text.get(next[0], next[1]), event)
 
1105
                return "break"
 
1106
            # No stdin mark -- just get the current line, less any prompt
 
1107
            indices = self.text.tag_nextrange("console", "insert linestart")
 
1108
            if indices and \
 
1109
               self.text.compare(indices[0], "<=", "insert linestart"):
 
1110
                self.recall(self.text.get(indices[1], "insert lineend"), event)
 
1111
            else:
 
1112
                self.recall(self.text.get("insert linestart", "insert lineend"), event)
 
1113
            return "break"
 
1114
        # If we're between the beginning of the line and the iomark, i.e.
 
1115
        # in the prompt area, move to the end of the prompt
 
1116
        if self.text.compare("insert", "<", "iomark"):
 
1117
            self.text.mark_set("insert", "iomark")
 
1118
        # If we're in the current input and there's only whitespace
 
1119
        # beyond the cursor, erase that whitespace first
 
1120
        s = self.text.get("insert", "end-1c")
 
1121
        if s and not s.strip():
 
1122
            self.text.delete("insert", "end-1c")
 
1123
        # If we're in the current input before its last line,
 
1124
        # insert a newline right at the insert point
 
1125
        if self.text.compare("insert", "<", "end-1c linestart"):
 
1126
            self.newline_and_indent_event(event)
 
1127
            return "break"
 
1128
        # We're in the last line; append a newline and submit it
 
1129
        self.text.mark_set("insert", "end-1c")
 
1130
        if self.reading:
 
1131
            self.text.insert("insert", "\n")
 
1132
            self.text.see("insert")
 
1133
        else:
 
1134
            self.newline_and_indent_event(event)
 
1135
        self.text.tag_add("stdin", "iomark", "end-1c")
 
1136
        self.text.update_idletasks()
 
1137
        if self.reading:
 
1138
            self.top.quit() # Break out of recursive mainloop() in raw_input()
 
1139
        else:
 
1140
            self.runit()
 
1141
        return "break"
 
1142
 
 
1143
    def recall(self, s, event):
 
1144
        # remove leading and trailing empty or whitespace lines
 
1145
        s = re.sub(r'^\s*\n', '' , s)
 
1146
        s = re.sub(r'\n\s*$', '', s)
 
1147
        lines = s.split('\n')
 
1148
        self.text.undo_block_start()
 
1149
        try:
 
1150
            self.text.tag_remove("sel", "1.0", "end")
 
1151
            self.text.mark_set("insert", "end-1c")
 
1152
            prefix = self.text.get("insert linestart", "insert")
 
1153
            if prefix.rstrip().endswith(':'):
 
1154
                self.newline_and_indent_event(event)
 
1155
                prefix = self.text.get("insert linestart", "insert")
 
1156
            self.text.insert("insert", lines[0].strip())
 
1157
            if len(lines) > 1:
 
1158
                orig_base_indent = re.search(r'^([ \t]*)', lines[0]).group(0)
 
1159
                new_base_indent  = re.search(r'^([ \t]*)', prefix).group(0)
 
1160
                for line in lines[1:]:
 
1161
                    if line.startswith(orig_base_indent):
 
1162
                        # replace orig base indentation with new indentation
 
1163
                        line = new_base_indent + line[len(orig_base_indent):]
 
1164
                    self.text.insert('insert', '\n'+line.rstrip())
 
1165
        finally:
 
1166
            self.text.see("insert")
 
1167
            self.text.undo_block_stop()
 
1168
 
 
1169
    def runit(self):
 
1170
        line = self.text.get("iomark", "end-1c")
 
1171
        # Strip off last newline and surrounding whitespace.
 
1172
        # (To allow you to hit return twice to end a statement.)
 
1173
        i = len(line)
 
1174
        while i > 0 and line[i-1] in " \t":
 
1175
            i = i-1
 
1176
        if i > 0 and line[i-1] == "\n":
 
1177
            i = i-1
 
1178
        while i > 0 and line[i-1] in " \t":
 
1179
            i = i-1
 
1180
        line = line[:i]
 
1181
        more = self.interp.runsource(line)
 
1182
 
 
1183
    def open_stack_viewer(self, event=None):
 
1184
        if self.interp.rpcclt:
 
1185
            return self.interp.remote_stack_viewer()
 
1186
        try:
 
1187
            sys.last_traceback
 
1188
        except:
 
1189
            tkMessageBox.showerror("No stack trace",
 
1190
                "There is no stack trace yet.\n"
 
1191
                "(sys.last_traceback is not defined)",
 
1192
                master=self.text)
 
1193
            return
 
1194
        from idlelib.StackViewer import StackBrowser
 
1195
        sv = StackBrowser(self.root, self.flist)
 
1196
 
 
1197
    def view_restart_mark(self, event=None):
 
1198
        self.text.see("iomark")
 
1199
        self.text.see("restart")
 
1200
 
 
1201
    def restart_shell(self, event=None):
 
1202
        self.interp.restart_subprocess()
 
1203
 
 
1204
    def showprompt(self):
 
1205
        self.resetoutput()
 
1206
        try:
 
1207
            s = str(sys.ps1)
 
1208
        except:
 
1209
            s = ""
 
1210
        self.console.write(s)
 
1211
        self.text.mark_set("insert", "end-1c")
 
1212
        self.set_line_and_column()
 
1213
        self.io.reset_undo()
 
1214
 
 
1215
    def resetoutput(self):
 
1216
        source = self.text.get("iomark", "end-1c")
 
1217
        if self.history:
 
1218
            self.history.history_store(source)
 
1219
        if self.text.get("end-2c") != "\n":
 
1220
            self.text.insert("end-1c", "\n")
 
1221
        self.text.mark_set("iomark", "end-1c")
 
1222
        self.set_line_and_column()
 
1223
        sys.stdout.softspace = 0
 
1224
 
 
1225
    def write(self, s, tags=()):
 
1226
        try:
 
1227
            self.text.mark_gravity("iomark", "right")
 
1228
            OutputWindow.write(self, s, tags, "iomark")
 
1229
            self.text.mark_gravity("iomark", "left")
 
1230
        except:
 
1231
            pass
 
1232
        if self.canceled:
 
1233
            self.canceled = 0
 
1234
            if not use_subprocess:
 
1235
                raise KeyboardInterrupt
 
1236
 
 
1237
class PseudoFile(object):
 
1238
 
 
1239
    def __init__(self, shell, tags, encoding=None):
 
1240
        self.shell = shell
 
1241
        self.tags = tags
 
1242
        self.softspace = 0
 
1243
        self.encoding = encoding
 
1244
 
 
1245
    def write(self, s):
 
1246
        self.shell.write(s, self.tags)
 
1247
 
 
1248
    def writelines(self, lines):
 
1249
        for line in lines:
 
1250
            self.write(line)
 
1251
 
 
1252
    def flush(self):
 
1253
        pass
 
1254
 
 
1255
    def isatty(self):
 
1256
        return True
 
1257
 
 
1258
 
 
1259
usage_msg = """\
 
1260
 
 
1261
USAGE: idle  [-deins] [-t title] [file]*
 
1262
       idle  [-dns] [-t title] (-c cmd | -r file) [arg]*
 
1263
       idle  [-dns] [-t title] - [arg]*
 
1264
 
 
1265
  -h         print this help message and exit
 
1266
  -n         run IDLE without a subprocess (see Help/IDLE Help for details)
 
1267
 
 
1268
The following options will override the IDLE 'settings' configuration:
 
1269
 
 
1270
  -e         open an edit window
 
1271
  -i         open a shell window
 
1272
 
 
1273
The following options imply -i and will open a shell:
 
1274
 
 
1275
  -c cmd     run the command in a shell, or
 
1276
  -r file    run script from file
 
1277
 
 
1278
  -d         enable the debugger
 
1279
  -s         run $IDLESTARTUP or $PYTHONSTARTUP before anything else
 
1280
  -t title   set title of shell window
 
1281
 
 
1282
A default edit window will be bypassed when -c, -r, or - are used.
 
1283
 
 
1284
[arg]* are passed to the command (-c) or script (-r) in sys.argv[1:].
 
1285
 
 
1286
Examples:
 
1287
 
 
1288
idle
 
1289
        Open an edit window or shell depending on IDLE's configuration.
 
1290
 
 
1291
idle foo.py foobar.py
 
1292
        Edit the files, also open a shell if configured to start with shell.
 
1293
 
 
1294
idle -est "Baz" foo.py
 
1295
        Run $IDLESTARTUP or $PYTHONSTARTUP, edit foo.py, and open a shell
 
1296
        window with the title "Baz".
 
1297
 
 
1298
idle -c "import sys; print sys.argv" "foo"
 
1299
        Open a shell window and run the command, passing "-c" in sys.argv[0]
 
1300
        and "foo" in sys.argv[1].
 
1301
 
 
1302
idle -d -s -r foo.py "Hello World"
 
1303
        Open a shell window, run a startup script, enable the debugger, and
 
1304
        run foo.py, passing "foo.py" in sys.argv[0] and "Hello World" in
 
1305
        sys.argv[1].
 
1306
 
 
1307
echo "import sys; print sys.argv" | idle - "foobar"
 
1308
        Open a shell window, run the script piped in, passing '' in sys.argv[0]
 
1309
        and "foobar" in sys.argv[1].
 
1310
"""
 
1311
 
 
1312
def main():
 
1313
    global flist, root, use_subprocess
 
1314
 
 
1315
    use_subprocess = True
 
1316
    enable_shell = True
 
1317
    enable_edit = False
 
1318
    debug = False
 
1319
    cmd = None
 
1320
    script = None
 
1321
    startup = False
 
1322
    try:
 
1323
        opts, args = getopt.getopt(sys.argv[1:], "c:deihnr:st:")
 
1324
    except getopt.error, msg:
 
1325
        sys.stderr.write("Error: %s\n" % str(msg))
 
1326
        sys.stderr.write(usage_msg)
 
1327
        sys.exit(2)
 
1328
    for o, a in opts:
 
1329
        if o == '-c':
 
1330
            cmd = a
 
1331
            enable_shell = True
 
1332
        if o == '-d':
 
1333
            debug = True
 
1334
            enable_shell = True
 
1335
        if o == '-e':
 
1336
            enable_edit = True
 
1337
            enable_shell = False
 
1338
        if o == '-h':
 
1339
            sys.stdout.write(usage_msg)
 
1340
            sys.exit()
 
1341
        if o == '-i':
 
1342
            enable_shell = True
 
1343
        if o == '-n':
 
1344
            use_subprocess = False
 
1345
        if o == '-r':
 
1346
            script = a
 
1347
            if os.path.isfile(script):
 
1348
                pass
 
1349
            else:
 
1350
                print "No script file: ", script
 
1351
                sys.exit()
 
1352
            enable_shell = True
 
1353
        if o == '-s':
 
1354
            startup = True
 
1355
            enable_shell = True
 
1356
        if o == '-t':
 
1357
            PyShell.shell_title = a
 
1358
            enable_shell = True
 
1359
    if args and args[0] == '-':
 
1360
        cmd = sys.stdin.read()
 
1361
        enable_shell = True
 
1362
    # process sys.argv and sys.path:
 
1363
    for i in range(len(sys.path)):
 
1364
        sys.path[i] = os.path.abspath(sys.path[i])
 
1365
    if args and args[0] == '-':
 
1366
        sys.argv = [''] + args[1:]
 
1367
    elif cmd:
 
1368
        sys.argv = ['-c'] + args
 
1369
    elif script:
 
1370
        sys.argv = [script] + args
 
1371
    elif args:
 
1372
        enable_edit = True
 
1373
        pathx = []
 
1374
        for filename in args:
 
1375
            pathx.append(os.path.dirname(filename))
 
1376
        for dir in pathx:
 
1377
            dir = os.path.abspath(dir)
 
1378
            if dir not in sys.path:
 
1379
                sys.path.insert(0, dir)
 
1380
    else:
 
1381
        dir = os.getcwd()
 
1382
        if not dir in sys.path:
 
1383
            sys.path.insert(0, dir)
 
1384
    # check the IDLE settings configuration (but command line overrides)
 
1385
    edit_start = idleConf.GetOption('main', 'General',
 
1386
                                    'editor-on-startup', type='bool')
 
1387
    enable_edit = enable_edit or edit_start
 
1388
    # start editor and/or shell windows:
 
1389
    root = Tk(className="Idle")
 
1390
 
 
1391
    fixwordbreaks(root)
 
1392
    root.withdraw()
 
1393
    flist = PyShellFileList(root)
 
1394
    macosxSupport.setupApp(root, flist)
 
1395
 
 
1396
    if enable_edit:
 
1397
        if not (cmd or script):
 
1398
            for filename in args:
 
1399
                flist.open(filename)
 
1400
            if not args:
 
1401
                flist.new()
 
1402
    if enable_shell:
 
1403
        shell = flist.open_shell()
 
1404
        if not shell:
 
1405
            return # couldn't open shell
 
1406
 
 
1407
        if macosxSupport.runningAsOSXApp() and flist.dict:
 
1408
            # On OSX: when the user has double-clicked on a file that causes
 
1409
            # IDLE to be launched the shell window will open just in front of
 
1410
            # the file she wants to see. Lower the interpreter window when
 
1411
            # there are open files.
 
1412
            shell.top.lower()
 
1413
 
 
1414
    shell = flist.pyshell
 
1415
    # handle remaining options:
 
1416
    if debug:
 
1417
        shell.open_debugger()
 
1418
    if startup:
 
1419
        filename = os.environ.get("IDLESTARTUP") or \
 
1420
                   os.environ.get("PYTHONSTARTUP")
 
1421
        if filename and os.path.isfile(filename):
 
1422
            shell.interp.execfile(filename)
 
1423
    if shell and cmd or script:
 
1424
        shell.interp.runcommand("""if 1:
 
1425
            import sys as _sys
 
1426
            _sys.argv = %r
 
1427
            del _sys
 
1428
            \n""" % (sys.argv,))
 
1429
        if cmd:
 
1430
            shell.interp.execsource(cmd)
 
1431
        elif script:
 
1432
            shell.interp.prepend_syspath(script)
 
1433
            shell.interp.execfile(script)
 
1434
 
 
1435
    # Check for problematic OS X Tk versions and print a warning message
 
1436
    # in the IDLE shell window; this is less intrusive than always opening
 
1437
    # a separate window.
 
1438
    tkversionwarning = macosxSupport.tkVersionWarning(root)
 
1439
    if tkversionwarning:
 
1440
        shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
 
1441
 
 
1442
    root.mainloop()
 
1443
    root.destroy()
 
1444
 
 
1445
if __name__ == "__main__":
 
1446
    sys.modules['PyShell'] = sys.modules['__main__']
 
1447
    main()