summaryrefslogtreecommitdiffstats
path: root/Lib/operator.py
blob: 0e2e53efc69a77dca0081ad67e2deb0accb9a288 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
"""
Operator Interface

This module exports a set of functions corresponding to the intrinsic
operators of Python.  For example, operator.add(x, y) is equivalent
to the expression x+y.  The function names are those used for special
methods; variants without leading and trailing '__' are also provided
for convenience.

This is the pure Python implementation of the module.
"""

__all__ = ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf',
           'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand',
           'iconcat', 'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul',
           'index', 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift',
           'is_', 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le',
           'length_hint', 'lshift', 'lt', 'matmul', 'methodcaller', 'mod',
           'mul', 'ne', 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift',
           'setitem', 'sub', 'truediv', 'truth', 'xor']

from builtins import abs as _abs


# Comparison Operations *******************************************************#

def lt(a, b):
    "Same as a < b."
    return a < b

def le(a, b):
    "Same as a <= b."
    return a <= b

def eq(a, b):
    "Same as a == b."
    return a == b

def ne(a, b):
    "Same as a != b."
    return a != b

def ge(a, b):
    "Same as a >= b."
    return a >= b

def gt(a, b):
    "Same as a > b."
    return a > b

# Logical Operations **********************************************************#

def not_(a):
    "Same as not a."
    return not a

def truth(a):
    "Return True if a is true, False otherwise."
    return True if a else False

def is_(a, b):
    "Same as a is b."
    return a is b

def is_not(a, b):
    "Same as a is not b."
    return a is not b

# Mathematical/Bitwise Operations *********************************************#

def abs(a):
    "Same as abs(a)."
    return _abs(a)

def add(a, b):
    "Same as a + b."
    return a + b

def and_(a, b):
    "Same as a & b."
    return a & b

def floordiv(a, b):
    "Same as a // b."
    return a // b

def index(a):
    "Same as a.__index__()."
    return a.__index__()

def inv(a):
    "Same as ~a."
    return ~a
invert = inv

def lshift(a, b):
    "Same as a << b."
    return a << b

def mod(a, b):
    "Same as a % b."
    return a % b

def mul(a, b):
    "Same as a * b."
    return a * b

def matmul(a, b):
    "Same as a @ b."
    return a @ b

def neg(a):
    "Same as -a."
    return -a

def or_(a, b):
    "Same as a | b."
    return a | b

def pos(a):
    "Same as +a."
    return +a

def pow(a, b):
    "Same as a ** b."
    return a ** b

def rshift(a, b):
    "Same as a >> b."
    return a >> b

def sub(a, b):
    "Same as a - b."
    return a - b

def truediv(a, b):
    "Same as a / b."
    return a / b

def xor(a, b):
    "Same as a ^ b."
    return a ^ b

# Sequence Operations *********************************************************#

def concat(a, b):
    "Same as a + b, for a and b sequences."
    if not hasattr(a, '__getitem__'):
        msg = "'%s' object can't be concatenated" % type(a).__name__
        raise TypeError(msg)
    return a + b

def contains(a, b):
    "Same as b in a (note reversed operands)."
    return b in a

def countOf(a, b):
    "Return the number of times b occurs in a."
    count = 0
    for i in a:
        if i == b:
            count += 1
    return count

def delitem(a, b):
    "Same as del a[b]."
    del a[b]

def getitem(a, b):
    "Same as a[b]."
    return a[b]

def indexOf(a, b):
    "Return the first index of b in a."
    for i, j in enumerate(a):
        if j == b:
            return i
    else:
        raise ValueError('sequence.index(x): x not in sequence')

def setitem(a, b, c):
    "Same as a[b] = c."
    a[b] = c

def length_hint(obj, default=0):
    """
    Return an estimate of the number of items in obj.
    This is useful for presizing containers when building from an iterable.

    If the object supports len(), the result will be exact. Otherwise, it may
    over- or under-estimate by an arbitrary amount. The result will be an
    integer >= 0.
    """
    if not isinstance(default, int):
        msg = ("'%s' object cannot be interpreted as an integer" %
               type(default).__name__)
        raise TypeError(msg)

    try:
        return len(obj)
    except TypeError:
        pass

    try:
        hint = type(obj).__length_hint__
    except AttributeError:
        return default

    try:
        val = hint(obj)
    except TypeError:
        return default
    if val is NotImplemented:
        return default
    if not isinstance(val, int):
        msg = ('__length_hint__ must be integer, not %s' %
               type(val).__name__)
        raise TypeError(msg)
    if val < 0:
        msg = '__length_hint__() should return >= 0'
        raise ValueError(msg)
    return val

# Generalized Lookup Objects **************************************************#

class attrgetter:
    """
    Return a callable object that fetches the given attribute(s) from its operand.
    After f = attrgetter('name'), the call f(r) returns r.name.
    After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).
    After h = attrgetter('name.first', 'name.last'), the call h(r) returns
    (r.name.first, r.name.last).
    """
    __slots__ = ('_attrs', '_call')

    def __init__(self, attr, *attrs):
        if not attrs:
            if not isinstance(attr, str):
                raise TypeError('attribute name must be a string')
            self._attrs = (attr,)
            names = attr.split('.')
            def func(obj):
                for name in names:
                    obj = getattr(obj, name)
                return obj
            self._call = func
        else:
            self._attrs = (attr,) + attrs
            getters = tuple(map(attrgetter, self._attrs))
            def func(obj):
                return tuple(getter(obj) for getter in getters)
            self._call = func

    def __call__(self, obj):
        return self._call(obj)

    def __repr__(self):
        return '%s.%s(%s)' % (self.__class__.__module__,
                              self.__class__.__qualname__,
                              ', '.join(map(repr, self._attrs)))

    def __reduce__(self):
        return self.__class__, self._attrs

class itemgetter:
    """
    Return a callable object that fetches the given item(s) from its operand.
    After f = itemgetter(2), the call f(r) returns r[2].
    After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])
    """
    __slots__ = ('_items', '_call')

    def __init__(self, item, *items):
        if not items:
            self._items = (item,)
            def func(obj):
                return obj[item]
            self._call = func
        else:
            self._items = items = (item,) + items
            def func(obj):
                return tuple(obj[i] for i in items)
            self._call = func

    def __call__(self, obj):
        return self._call(obj)

    def __repr__(self):
        return '%s.%s(%s)' % (self.__class__.__module__,
                              self.__class__.__name__,
                              ', '.join(map(repr, self._items)))

    def __reduce__(self):
        return self.__class__, self._items

class methodcaller:
    """
    Return a callable object that calls the given method on its operand.
    After f = methodcaller('name'), the call f(r) returns r.name().
    After g = methodcaller('name', 'date', foo=1), the call g(r) returns
    r.name('date', foo=1).
    """
    __slots__ = ('_name', '_args', '_kwargs')

    def __init__(*args, **kwargs):
        if len(args) < 2:
            msg = "methodcaller needs at least one argument, the method name"
            raise TypeError(msg)
        self = args[0]
        self._name = args[1]
        if not isinstance(self._name, str):
            raise TypeError('method name must be a string')
        self._args = args[2:]
        self._kwargs = kwargs

    def __call__(self, obj):
        return getattr(obj, self._name)(*self._args, **self._kwargs)

    def __repr__(self):
        args = [repr(self._name)]
        args.extend(map(repr, self._args))
        args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items())
        return '%s.%s(%s)' % (self.__class__.__module__,
                              self.__class__.__name__,
                              ', '.join(args))

    def __reduce__(self):
        if not self._kwargs:
            return self.__class__, (self._name,) + self._args
        else:
            from functools import partial
            return partial(self.__class__, self._name, **self._kwargs), self._args


# In-place Operations *********************************************************#

def iadd(a, b):
    "Same as a += b."
    a += b
    return a

def iand(a, b):
    "Same as a &= b."
    a &= b
    return a

def iconcat(a, b):
    "Same as a += b, for a and b sequences."
    if not hasattr(a, '__getitem__'):
        msg = "'%s' object can't be concatenated" % type(a).__name__
        raise TypeError(msg)
    a += b
    return a

def ifloordiv(a, b):
    "Same as a //= b."
    a //= b
    return a

def ilshift(a, b):
    "Same as a <<= b."
    a <<= b
    return a

def imod(a, b):
    "Same as a %= b."
    a %= b
    return a

def imul(a, b):
    "Same as a *= b."
    a *= b
    return a

def imatmul(a, b):
    "Same as a @= b."
    a @= b
    return a

def ior(a, b):
    "Same as a |= b."
    a |= b
    return a

def ipow(a, b):
    "Same as a **= b."
    a **=b
    return a

def irshift(a, b):
    "Same as a >>= b."
    a >>= b
    return a

def isub(a, b):
    "Same as a -= b."
    a -= b
    return a

def itruediv(a, b):
    "Same as a /= b."
    a /= b
    return a

def ixor(a, b):
    "Same as a ^= b."
    a ^= b
    return a


try:
    from _operator import *
except ImportError:
    pass
else:
    from _operator import __doc__

# All of these "__func__ = func" assignments have to happen after importing
# from _operator to make sure they're set to the right function
__lt__ = lt
__le__ = le
__eq__ = eq
__ne__ = ne
__ge__ = ge
__gt__ = gt
__not__ = not_
__abs__ = abs
__add__ = add
__and__ = and_
__floordiv__ = floordiv
__index__ = index
__inv__ = inv
__invert__ = invert
__lshift__ = lshift
__mod__ = mod
__mul__ = mul
__matmul__ = matmul
__neg__ = neg
__or__ = or_
__pos__ = pos
__pow__ = pow
__rshift__ = rshift
__sub__ = sub
__truediv__ = truediv
__xor__ = xor
__concat__ = concat
__contains__ = contains
__delitem__ = delitem
__getitem__ = getitem
__setitem__ = setitem
__iadd__ = iadd
__iand__ = iand
__iconcat__ = iconcat
__ifloordiv__ = ifloordiv
__ilshift__ = ilshift
__imod__ = imod
__imul__ = imul
__imatmul__ = imatmul
__ior__ = ior
__ipow__ = ipow
__irshift__ = irshift
__isub__ = isub
__itruediv__ = itruediv
__ixor__ = ixor
class="hl opt">.exc_info() ok = type is SyntaxError if ok: try: msg, (dummy_filename, lineno, offset, line) = value except: ok = 0 if ok: return msg, lineno, offset, line else: return None def showtraceback(self): # Extend base class method to reset output properly text = self.tkconsole.text self.tkconsole.resetoutput() self.checklinecache() InteractiveInterpreter.showtraceback(self) def checklinecache(self): c = linecache.cache for key in c.keys(): if key[:1] + key[-1:] != "<>": del c[key] debugger = None def setdebugger(self, debugger): self.debugger = debugger def getdebugger(self): return self.debugger def runcode(self, code): # Override base class method if self.save_warnings_filters is not None: warnings.filters[:] = self.save_warnings_filters self.save_warnings_filters = None debugger = self.debugger try: self.tkconsole.beginexecuting() try: if debugger: debugger.run(code, self.locals) else: exec code in self.locals except SystemExit: if tkMessageBox.askyesno( "Exit?", "Do you want to exit altogether?", default="yes", master=self.tkconsole.text): raise else: self.showtraceback() if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"): self.tkconsole.open_stack_viewer() except: self.showtraceback() if self.tkconsole.getvar("<<toggle-jit-stack-viewer>>"): self.tkconsole.open_stack_viewer() finally: self.tkconsole.endexecuting() def write(self, s): # Override base class write self.tkconsole.console.write(s) class PyShell(OutputWindow): shell_title = "Python Shell" # Override classes ColorDelegator = ModifiedColorDelegator UndoDelegator = ModifiedUndoDelegator # Override menu bar specs menu_specs = PyShellEditorWindow.menu_specs[:] menu_specs.insert(len(menu_specs)-2, ("debug", "_Debug")) # New classes from IdleHistory import History def __init__(self, flist=None): self.interp = ModifiedInterpreter(self) if flist is None: root = Tk() fixwordbreaks(root) root.withdraw() flist = PyShellFileList(root) OutputWindow.__init__(self, flist, None, None) import __builtin__ __builtin__.quit = __builtin__.exit = "To exit, type Ctrl-D." self.auto = self.extensions["AutoIndent"] # Required extension self.auto.config(usetabs=1, indentwidth=8, context_use_ps1=1) text = self.text text.configure(wrap="char") text.bind("<<newline-and-indent>>", self.enter_callback) text.bind("<<plain-newline-and-indent>>", self.linefeed_callback) text.bind("<<interrupt-execution>>", self.cancel_callback) text.bind("<<beginning-of-line>>", self.home_callback) text.bind("<<end-of-file>>", self.eof_callback) text.bind("<<open-stack-viewer>>", self.open_stack_viewer) text.bind("<<toggle-debugger>>", self.toggle_debugger) text.bind("<<open-python-shell>>", self.flist.open_shell) text.bind("<<toggle-jit-stack-viewer>>", self.toggle_jit_stack_viewer) self.save_stdout = sys.stdout self.save_stderr = sys.stderr self.save_stdin = sys.stdin sys.stdout = PseudoFile(self, "stdout") sys.stderr = PseudoFile(self, "stderr") sys.stdin = self self.console = PseudoFile(self, "console") self.history = self.History(self.text) reading = 0 executing = 0 canceled = 0 endoffile = 0 def toggle_debugger(self, event=None): if self.executing: tkMessageBox.showerror("Don't debug now", "You can only toggle the debugger when idle", master=self.text) self.set_debugger_indicator() return "break" else: db = self.interp.getdebugger() if db: self.close_debugger() else: self.open_debugger() def set_debugger_indicator(self): db = self.interp.getdebugger() self.setvar("<<toggle-debugger>>", not not db) def toggle_jit_stack_viewer( self, event=None): pass # All we need is the variable def close_debugger(self): db = self.interp.getdebugger() if db: self.interp.setdebugger(None) db.close() self.resetoutput() self.console.write("[DEBUG OFF]\n") sys.ps1 = ">>> " self.showprompt() self.set_debugger_indicator() def open_debugger(self): import Debugger self.interp.setdebugger(Debugger.Debugger(self)) sys.ps1 = "[DEBUG ON]\n>>> " self.showprompt() self.set_debugger_indicator() def beginexecuting(self): # Helper for ModifiedInterpreter self.resetoutput() self.executing = 1 ##self._cancel_check = self.cancel_check ##sys.settrace(self._cancel_check) def endexecuting(self): # Helper for ModifiedInterpreter ##sys.settrace(None) ##self._cancel_check = None self.executing = 0 self.canceled = 0 def close(self): # Extend base class method if self.executing: # XXX Need to ask a question here if not tkMessageBox.askokcancel( "Kill?", "The program is still running; do you want to kill it?", default="ok", master=self.text): return "cancel" self.canceled = 1 if self.reading: self.top.quit() return "cancel" return OutputWindow.close(self) def _close(self): self.close_debugger() # Restore std streams sys.stdout = self.save_stdout sys.stderr = self.save_stderr sys.stdin = self.save_stdin # Break cycles self.interp = None self.console = None self.auto = None self.flist.pyshell = None self.history = None OutputWindow._close(self) # Really EditorWindow._close def ispythonsource(self, filename): # Override this so EditorWindow never removes the colorizer return 1 def short_title(self): return self.shell_title COPYRIGHT = \ 'Type "copyright", "credits" or "license" for more information.' def begin(self): self.resetoutput() self.write("Python %s on %s\n%s\nIDLE Fork %s -- press F1 for help\n" % (sys.version, sys.platform, self.COPYRIGHT, idlever.IDLE_VERSION)) try: sys.ps1 except AttributeError: sys.ps1 = ">>> " self.showprompt() import Tkinter Tkinter._default_root = None def interact(self): self.begin() self.top.mainloop() def readline(self): save = self.reading try: self.reading = 1 self.top.mainloop() finally: self.reading = save line = self.text.get("iomark", "end-1c") self.resetoutput() if self.canceled: self.canceled = 0 raise KeyboardInterrupt if self.endoffile: self.endoffile = 0 return "" return line def isatty(self): return 1 def cancel_callback(self, event): try: if self.text.compare("sel.first", "!=", "sel.last"): return # Active selection -- always use default binding except: pass if not (self.executing or self.reading): self.resetoutput() self.write("KeyboardInterrupt\n") self.showprompt() return "break" self.endoffile = 0 self.canceled = 1 if self.reading: self.top.quit() return "break" def eof_callback(self, event): if self.executing and not self.reading: return # Let the default binding (delete next char) take over if not (self.text.compare("iomark", "==", "insert") and self.text.compare("insert", "==", "end-1c")): return # Let the default binding (delete next char) take over if not self.executing: ## if not tkMessageBox.askokcancel( ## "Exit?", ## "Are you sure you want to exit?", ## default="ok", master=self.text): ## return "break" self.resetoutput() self.close() else: self.canceled = 0 self.endoffile = 1 self.top.quit() return "break" def home_callback(self, event): if event.state != 0 and event.keysym == "Home": return # <Modifier-Home>; fall back to class binding if self.text.compare("iomark", "<=", "insert") and \ self.text.compare("insert linestart", "<=", "iomark"): self.text.mark_set("insert", "iomark") self.text.tag_remove("sel", "1.0", "end") self.text.see("insert") return "break" def linefeed_callback(self, event): # Insert a linefeed without entering anything (still autoindented) if self.reading: self.text.insert("insert", "\n") self.text.see("insert") else: self.auto.auto_indent(event) return "break" def enter_callback(self, event): if self.executing and not self.reading: return # Let the default binding (insert '\n') take over # If some text is selected, recall the selection # (but only if this before the I/O mark) try: sel = self.text.get("sel.first", "sel.last") if sel: if self.text.compare("sel.last", "<=", "iomark"): self.recall(sel) return "break" except: pass # If we're strictly before the line containing iomark, recall # the current line, less a leading prompt, less leading or # trailing whitespace if self.text.compare("insert", "<", "iomark linestart"): # Check if there's a relevant stdin range -- if so, use it prev = self.text.tag_prevrange("stdin", "insert") if prev and self.text.compare("insert", "<", prev[1]): self.recall(self.text.get(prev[0], prev[1])) return "break" next = self.text.tag_nextrange("stdin", "insert") if next and self.text.compare("insert lineend", ">=", next[0]): self.recall(self.text.get(next[0], next[1])) return "break" # No stdin mark -- just get the current line self.recall(self.text.get("insert linestart", "insert lineend")) return "break" # If we're in the current input and there's only whitespace # beyond the cursor, erase that whitespace first s = self.text.get("insert", "end-1c") if s and not string.strip(s): self.text.delete("insert", "end-1c") # If we're in the current input before its last line, # insert a newline right at the insert point if self.text.compare("insert", "<", "end-1c linestart"): self.auto.auto_indent(event) return "break" # We're in the last line; append a newline and submit it self.text.mark_set("insert", "end-1c") if self.reading: self.text.insert("insert", "\n") self.text.see("insert") else: self.auto.auto_indent(event) self.text.tag_add("stdin", "iomark", "end-1c") self.text.update_idletasks() if self.reading: self.top.quit() # Break out of recursive mainloop() in raw_input() else: self.runit() return "break" def recall(self, s): if self.history: self.history.recall(s) def runit(self): line = self.text.get("iomark", "end-1c") # Strip off last newline and surrounding whitespace. # (To allow you to hit return twice to end a statement.) i = len(line) while i > 0 and line[i-1] in " \t": i = i-1 if i > 0 and line[i-1] == "\n": i = i-1 while i > 0 and line[i-1] in " \t": i = i-1 line = line[:i] more = self.interp.runsource(line) if not more: self.showprompt() def cancel_check(self, frame, what, args, dooneevent=tkinter.dooneevent, dontwait=tkinter.DONT_WAIT): # Hack -- use the debugger hooks to be able to handle events # and interrupt execution at any time. # This slows execution down quite a bit, so you may want to # disable this (by not calling settrace() in runcode() above) # for full-bore (uninterruptable) speed. # XXX This should become a user option. if self.canceled: return dooneevent(dontwait) if self.canceled: self.canceled = 0 raise KeyboardInterrupt return self._cancel_check def open_stack_viewer(self, event=None): try: sys.last_traceback except: tkMessageBox.showerror("No stack trace", "There is no stack trace yet.\n" "(sys.last_traceback is not defined)", master=self.text) return from StackViewer import StackBrowser sv = StackBrowser(self.root, self.flist) def showprompt(self): self.resetoutput() try: s = str(sys.ps1) except: s = "" self.console.write(s) self.text.mark_set("insert", "end-1c") def resetoutput(self): source = self.text.get("iomark", "end-1c") if self.history: self.history.history_store(source) if self.text.get("end-2c") != "\n": self.text.insert("end-1c", "\n") self.text.mark_set("iomark", "end-1c") sys.stdout.softspace = 0 def write(self, s, tags=()): self.text.mark_gravity("iomark", "right") OutputWindow.write(self, s, tags, "iomark") self.text.mark_gravity("iomark", "left") if self.canceled: self.canceled = 0 raise KeyboardInterrupt class PseudoFile: def __init__(self, shell, tags): self.shell = shell self.tags = tags def write(self, s): self.shell.write(s, self.tags) def writelines(self, l): map(self.write, l) def flush(self): pass def isatty(self): return 1 usage_msg = """\ usage: idle.py [-c command] [-d] [-i] [-r script] [-s] [-t title] [arg] ... idle file(s) (without options) edit the file(s) -c cmd run the command in a shell -d enable the debugger -i open an interactive shell -i file(s) open a shell and also an editor window for each file -r script run a file as a script in a shell -s run $IDLESTARTUP or $PYTHONSTARTUP before anything else -t title set title of shell window Remaining arguments are applied to the command (-c) or script (-r). """ class usageError: def __init__(self, string): self.string = string def __repr__(self): return self.string class main: def __init__(self, noshell=1): global flist, root root = Tk(className="Idle") fixwordbreaks(root) root.withdraw() flist = PyShellFileList(root) dbg=OnDemandOutputWindow(flist) dbg.set_title('IDLE Debugging Messages') sys.stdout = PseudoFile(dbg,['stdout']) sys.stderr = PseudoFile(dbg,['stderr']) try: self.server = protocol.Server(connection_hook = self.address_ok) protocol.publish( 'IDLE', self.connect ) self.main(sys.argv[1:], noshell) return except protocol.connectionLost: try: client = protocol.Client() IDLE = client.getobject('IDLE') if IDLE: try: IDLE.remote( sys.argv[1:] ) except usageError, msg: sys.stderr.write("Error: %s\n" % str(msg)) sys.stderr.write(usage_msg) return except protocol.connectionLost: pass #maybe the following should be handled by a tkmessagebox for #users who don't start idle from a console?? print """\ IDLE cannot run. IDLE needs to use a specific TCP/IP port (7454) in order to execute and debug programs. IDLE is unable to bind to this port, and so cannot start. Here are some possible causes of this problem: 1. TCP/IP networking is not installed or not working on this computer 2. Another program is running that uses this port 3. Another copy of IDLE stopped responding but is still bound to the port 4. Personal firewall software is preventing IDLE from using this port IDLE makes and accepts connections only with this computer, and does not communicate over the internet in any way. It's use of port 7454 should not be a security risk on a single-user machine. """ dbg.owin.gotoline(1) dbg.owin.remove_selection() root.mainloop() # wait for user to read message def idle(self): spawn.kill_zombies() self.server.rpc_loop() root.after(25, self.idle) # We permit connections from localhost only def address_ok(self, addr): return addr[0] == '127.0.0.1' def connect(self, client, addr): return self def remote( self, argv ): # xxx Should make this behavior match the behavior in main, or redo # command line options entirely. try: opts, args = getopt.getopt(argv, "c:deist:") except getopt.error, msg: raise usageError(msg) for filename in args: flist.open(filename) if not args: flist.new() def main(self, argv, noshell): cmd = None edit = 0 debug = 0 interactive = 0 script = None startup = 0 try: opts, args = getopt.getopt(argv, "c:dir:st:") except getopt.error, msg: sys.stderr.write("Error: %s\n" % str(msg)) sys.stderr.write(usage_msg) sys.exit(2) for o, a in opts: noshell = 0 # There are options, bring up a shell if o == '-c': cmd = a if o == '-d': debug = 1 if o == '-i': interactive = 1 if o == '-r': script = a if o == '-s': startup = 1 if o == '-t': PyShell.shell_title = a if noshell: edit=1 if interactive and args and args[0] != "-": edit = 1 for i in range(len(sys.path)): sys.path[i] = os.path.abspath(sys.path[i]) pathx = [] if edit: for filename in args: pathx.append(os.path.dirname(filename)) elif args and args[0] != "-": pathx.append(os.path.dirname(args[0])) else: pathx.append(os.curdir) for dir in pathx: dir = os.path.abspath(dir) if not dir in sys.path: sys.path.insert(0, dir) if edit: for filename in args: flist.open(filename) if not args: flist.new() else: if cmd: sys.argv = ["-c"] + args else: sys.argv = args or [""] if noshell: flist.pyshell = None else: shell = PyShell(flist) interp = shell.interp flist.pyshell = shell if startup: filename = os.environ.get("IDLESTARTUP") or \ os.environ.get("PYTHONSTARTUP") if filename and os.path.isfile(filename): interp.execfile(filename) if debug: shell.open_debugger() if cmd: interp.execsource(cmd) elif script: if os.path.isfile(script): interp.execfile(script) else: print "No script file: ", script shell.begin() self.idle() root.mainloop() root.destroy() if __name__ == "__main__": main()