summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/idlelib')
-rw-r--r--Lib/idlelib/Bindings.py8
-rw-r--r--Lib/idlelib/CREDITS.txt4
-rw-r--r--Lib/idlelib/EditorWindow.py57
-rw-r--r--Lib/idlelib/FileList.py6
-rw-r--r--Lib/idlelib/FormatParagraph.py2
-rw-r--r--Lib/idlelib/HISTORY.txt2
-rw-r--r--Lib/idlelib/IOBinding.py4
-rw-r--r--Lib/idlelib/MultiCall.py2
-rw-r--r--Lib/idlelib/MultiStatusBar.py2
-rw-r--r--Lib/idlelib/NEWS.txt41
-rw-r--r--Lib/idlelib/ObjectBrowser.py2
-rw-r--r--Lib/idlelib/PathBrowser.py2
-rw-r--r--Lib/idlelib/PyShell.py92
-rw-r--r--Lib/idlelib/RemoteDebugger.py2
-rw-r--r--Lib/idlelib/RstripExtension.py29
-rw-r--r--Lib/idlelib/TreeWidget.py2
-rw-r--r--Lib/idlelib/config-extensions.def6
-rw-r--r--Lib/idlelib/config-keys.def4
-rw-r--r--Lib/idlelib/configDialog.py11
-rw-r--r--Lib/idlelib/configHandler.py2
-rw-r--r--Lib/idlelib/extend.txt2
-rwxr-xr-xLib/idlelib/idle.bat5
-rw-r--r--Lib/idlelib/idle.py32
-rw-r--r--Lib/idlelib/idlever.py2
-rw-r--r--Lib/idlelib/macosxSupport.py107
-rw-r--r--Lib/idlelib/rpc.py14
-rw-r--r--Lib/idlelib/run.py16
27 files changed, 275 insertions, 183 deletions
diff --git a/Lib/idlelib/Bindings.py b/Lib/idlelib/Bindings.py
index 74a93d3..ec2720b 100644
--- a/Lib/idlelib/Bindings.py
+++ b/Lib/idlelib/Bindings.py
@@ -98,14 +98,6 @@ if macosxSupport.runningAsOSXApp():
# menu
del menudefs[-1][1][0:2]
- menudefs.insert(0,
- ('application', [
- ('About IDLE', '<<about-idle>>'),
- None,
- ('_Preferences....', '<<open-config-dialog>>'),
- ]))
-
-
default_keydefs = idleConf.GetCurrentKeySet()
del sys
diff --git a/Lib/idlelib/CREDITS.txt b/Lib/idlelib/CREDITS.txt
index 456079b..5ff599d 100644
--- a/Lib/idlelib/CREDITS.txt
+++ b/Lib/idlelib/CREDITS.txt
@@ -25,8 +25,8 @@ integration, debugger integration and persistent breakpoints).
Scott David Daniels, Tal Einat, Hernan Foffani, Christos Georgiou,
Jim Jewett, Martin v. Löwis, Jason Orendorff, Guilherme Polo, Josh Robb,
-Nigel Rowe, Bruce Sherwood, and Jeff Shute have submitted useful patches.
-Thanks, guys!
+Nigel Rowe, Bruce Sherwood, Jeff Shute, and Weeble have submitted useful
+patches. Thanks, guys!
For additional details refer to NEWS.txt and Changelog.
diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py
index 7cc69cb..71b768f 100644
--- a/Lib/idlelib/EditorWindow.py
+++ b/Lib/idlelib/EditorWindow.py
@@ -2,7 +2,6 @@ import sys
import os
import re
import imp
-from itertools import count
from Tkinter import *
import tkSimpleDialog
import tkMessageBox
@@ -27,8 +26,10 @@ def _sphinx_version():
major, minor, micro, level, serial = sys.version_info
release = '%s%s' % (major, minor)
if micro:
- release += '%s' % micro
- if level != 'final':
+ release += '%s' % (micro,)
+ if level == 'candidate':
+ release += 'rc%s' % (serial,)
+ elif level != 'final':
release += '%s%s' % (level[0], serial)
return release
@@ -101,8 +102,8 @@ class EditorWindow(object):
self.top = top = WindowList.ListedToplevel(root, menu=self.menubar)
if flist:
self.tkinter_vars = flist.vars
- #self.top.instance_dict makes flist.inversedict avalable to
- #configDialog.py so it can access all EditorWindow instaces
+ #self.top.instance_dict makes flist.inversedict available to
+ #configDialog.py so it can access all EditorWindow instances
self.top.instance_dict = flist.inversedict
else:
self.tkinter_vars = {} # keys: Tkinter event names
@@ -135,6 +136,14 @@ class EditorWindow(object):
if macosxSupport.runningAsOSXApp():
# Command-W on editorwindows doesn't work without this.
text.bind('<<close-window>>', self.close_event)
+ # Some OS X systems have only one mouse button,
+ # so use control-click for pulldown menus there.
+ # (Note, AquaTk defines <2> as the right button if
+ # present and the Tk Text widget already binds <2>.)
+ text.bind("<Control-Button-1>",self.right_menu_event)
+ else:
+ # Elsewhere, use right-click for pulldown menus.
+ text.bind("<3>",self.right_menu_event)
text.bind("<<cut>>", self.cut)
text.bind("<<copy>>", self.copy)
text.bind("<<paste>>", self.paste)
@@ -153,7 +162,6 @@ class EditorWindow(object):
text.bind("<<find-selection>>", self.find_selection_event)
text.bind("<<replace>>", self.replace_event)
text.bind("<<goto-line>>", self.goto_line_event)
- text.bind("<3>", self.right_menu_event)
text.bind("<<smart-backspace>>",self.smart_backspace_event)
text.bind("<<newline-and-indent>>",self.newline_and_indent_event)
text.bind("<<smart-indent>>",self.smart_indent_event)
@@ -299,9 +307,9 @@ class EditorWindow(object):
return "break"
def home_callback(self, event):
- if (event.state & 12) != 0 and event.keysym == "Home":
- # state&1==shift, state&4==control, state&8==alt
- return # <Modifier-Home>; fall back to class binding
+ if (event.state & 4) != 0 and event.keysym == "Home":
+ # state&4==Control. If <Control-Home>, use the Tk binding.
+ return
if self.text.index("iomark") and \
self.text.compare("iomark", "<=", "insert lineend") and \
@@ -384,7 +392,7 @@ class EditorWindow(object):
menudict[name] = menu = Menu(mbar, name=name)
mbar.add_cascade(label=label, menu=menu, underline=underline)
- if macosxSupport.runningAsOSXApp():
+ if macosxSupport.isCarbonAquaTk(self.root):
# Insert the application menu
menudict['application'] = menu = Menu(mbar, name='apple')
mbar.add_cascade(label='IDLE', menu=menu)
@@ -444,7 +452,11 @@ class EditorWindow(object):
def python_docs(self, event=None):
if sys.platform[:3] == 'win':
- os.startfile(self.help_url)
+ try:
+ os.startfile(self.help_url)
+ except WindowsError as why:
+ tkMessageBox.showerror(title='Document Start Failure',
+ message=str(why), parent=self.text)
else:
webbrowser.open(self.help_url)
return "break"
@@ -704,8 +716,8 @@ class EditorWindow(object):
if accel:
itemName = menu.entrycget(index, 'label')
event = ''
- if menuEventDict.has_key(menubarItem):
- if menuEventDict[menubarItem].has_key(itemName):
+ if menubarItem in menuEventDict:
+ if itemName in menuEventDict[menubarItem]:
event = menuEventDict[menubarItem][itemName]
if event:
accel = get_accelerator(keydefs, event)
@@ -739,9 +751,13 @@ class EditorWindow(object):
"Create a callback with the helpfile value frozen at definition time"
def display_extra_help(helpfile=helpfile):
if not helpfile.startswith(('www', 'http')):
- url = os.path.normpath(helpfile)
+ helpfile = os.path.normpath(helpfile)
if sys.platform[:3] == 'win':
- os.startfile(helpfile)
+ try:
+ os.startfile(helpfile)
+ except WindowsError as why:
+ tkMessageBox.showerror(title='Document Start Failure',
+ message=str(why), parent=self.text)
else:
webbrowser.open(helpfile)
return display_extra_help
@@ -777,8 +793,8 @@ class EditorWindow(object):
for instance in self.top.instance_dict.keys():
menu = instance.recent_files_menu
menu.delete(1, END) # clear, and rebuild:
- for i, file in zip(count(), rf_list):
- file_name = file[0:-1] # zap \n
+ for i, file_name in enumerate(rf_list):
+ file_name = file_name.rstrip() # zap \n
# make unicode string to display non-ASCII chars correctly
ufile_name = self._filename_to_unicode(file_name)
callback = instance.__recent_file_callback(file_name)
@@ -1525,7 +1541,12 @@ keynames = {
def get_accelerator(keydefs, eventname):
keylist = keydefs.get(eventname)
- if not keylist:
+ # issue10940: temporary workaround to prevent hang with OS X Cocoa Tk 8.5
+ # if not keylist:
+ if (not keylist) or (macosxSupport.runningAsOSXApp() and eventname in {
+ "<<open-module>>",
+ "<<goto-line>>",
+ "<<change-indentwidth>>"}):
return ""
s = keylist[0]
s = re.sub(r"-[a-z]\b", lambda m: m.group().upper(), s)
diff --git a/Lib/idlelib/FileList.py b/Lib/idlelib/FileList.py
index 5622805..8318ff1 100644
--- a/Lib/idlelib/FileList.py
+++ b/Lib/idlelib/FileList.py
@@ -25,7 +25,7 @@ class FileList:
master=self.root)
return None
key = os.path.normcase(filename)
- if self.dict.has_key(key):
+ if key in self.dict:
edit = self.dict[key]
edit.top.wakeup()
return edit
@@ -43,7 +43,7 @@ class FileList:
def new(self, filename=None):
return self.EditorWindow(self, filename)
- def close_all_callback(self, event):
+ def close_all_callback(self, *args, **kwds):
for edit in self.inversedict.keys():
reply = edit.close()
if reply == "cancel":
@@ -79,7 +79,7 @@ class FileList:
newkey = os.path.normcase(filename)
if newkey == key:
return
- if self.dict.has_key(newkey):
+ if newkey in self.dict:
conflict = self.dict[newkey]
self.inversedict[conflict] = None
tkMessageBox.showerror(
diff --git a/Lib/idlelib/FormatParagraph.py b/Lib/idlelib/FormatParagraph.py
index 02f96d4..6a5f9b5 100644
--- a/Lib/idlelib/FormatParagraph.py
+++ b/Lib/idlelib/FormatParagraph.py
@@ -54,7 +54,7 @@ class FormatParagraph:
# If the block ends in a \n, we dont want the comment
# prefix inserted after it. (Im not sure it makes sense to
# reformat a comment block that isnt made of complete
- # lines, but whatever!) Can't think of a clean soltution,
+ # lines, but whatever!) Can't think of a clean solution,
# so we hack away
block_suffix = ""
if not newdata[-1]:
diff --git a/Lib/idlelib/HISTORY.txt b/Lib/idlelib/HISTORY.txt
index c0faaad..01d73ed 100644
--- a/Lib/idlelib/HISTORY.txt
+++ b/Lib/idlelib/HISTORY.txt
@@ -13,7 +13,7 @@ What's New in IDLEfork 0.8.1?
- New tarball released as a result of the 'revitalisation' of the IDLEfork
project.
-- This release requires python 2.1 or better. Compatability with earlier
+- This release requires python 2.1 or better. Compatibility with earlier
versions of python (especially ancient ones like 1.5x) is no longer a
priority in IDLEfork development.
diff --git a/Lib/idlelib/IOBinding.py b/Lib/idlelib/IOBinding.py
index cbc1c33..a5b610e 100644
--- a/Lib/idlelib/IOBinding.py
+++ b/Lib/idlelib/IOBinding.py
@@ -521,8 +521,8 @@ class IOBinding:
savedialog = None
filetypes = [
- ("Python and text files", "*.py *.pyw *.txt", "TEXT"),
- ("All text files", "*", "TEXT"),
+ ("Python files", "*.py *.pyw", "TEXT"),
+ ("Text files", "*.txt", "TEXT"),
("All files", "*"),
]
diff --git a/Lib/idlelib/MultiCall.py b/Lib/idlelib/MultiCall.py
index 5b73481..b81c5ed 100644
--- a/Lib/idlelib/MultiCall.py
+++ b/Lib/idlelib/MultiCall.py
@@ -201,7 +201,7 @@ class _ComplexBinder:
seq, handler)))
def bind(self, triplet, func):
- if not self.bindedfuncs.has_key(triplet[2]):
+ if triplet[2] not in self.bindedfuncs:
self.bindedfuncs[triplet[2]] = [[] for s in _states]
for s in _states:
lists = [ self.bindedfuncs[detail][i]
diff --git a/Lib/idlelib/MultiStatusBar.py b/Lib/idlelib/MultiStatusBar.py
index 2d4c547..8ee2d03 100644
--- a/Lib/idlelib/MultiStatusBar.py
+++ b/Lib/idlelib/MultiStatusBar.py
@@ -9,7 +9,7 @@ class MultiStatusBar(Frame):
self.labels = {}
def set_label(self, name, text='', side=LEFT):
- if not self.labels.has_key(name):
+ if name not in self.labels:
label = Label(self, bd=1, relief=SUNKEN, anchor=W)
label.pack(side=side)
self.labels[name] = label
diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt
index bb4c143..47ff097 100644
--- a/Lib/idlelib/NEWS.txt
+++ b/Lib/idlelib/NEWS.txt
@@ -1,36 +1,37 @@
-What's New in Python 2.6.4rc1
-=============================
+What's New in IDLE 2.7.2?
+=======================
-*Release date: 07-Oct-2009*
+*Release date: XX-XX-XXXX*
-- OutputWindow/PyShell right click menu "Go to file/line" wasn't working with
- file paths containing spaces. Bug 5559.
+- <Home> toggle non-functional when NumLock set on Windows. Issue3851.
-What's New in Python 2.6.3
-==========================
-
-*Release date: 02-Oct-2009*
+What's New in IDLE 2.7?
+=======================
-What's New in IDLE 2.6.3rc1?
-============================
+*Release date: 07-03-2010*
-*Release date: 28-Sep-2009*
+- idle.py modified and simplified to better support developing experimental
+ versions of IDLE which are not installed in the standard location.
-- On OS X IDLE 2.6 shows two Preference menu items. Issue6951.
+- OutputWindow/PyShell right click menu "Go to file/line" wasn't working with
+ file paths containing spaces. Bug 5559.
- Windows: Version string for the .chm help file changed, file not being
accessed Patch 5783 Guilherme Polo
-- Tk 8.5 Text widget requires 'wordprocessor' tabstyle attr to handle
- mixed space/tab properly. Issue 5129, patch by Guilherme Polo.
-
-What's New in IDLE 2.6.2rc1?
-============================
+- Allow multiple IDLE GUI/subprocess pairs to exist simultaneously. Thanks to
+ David Scherer for suggesting the use of an ephemeral port for the GUI.
+ Patch 1529142 Weeble.
-*Release date: 06-Apr-2009*
+- Remove port spec from run.py and fix bug where subprocess fails to
+ extract port from command line when warnings are present.
+- Tk 8.5 Text widget requires 'wordprocessor' tabstyle attr to handle
+ mixed space/tab properly. Issue 5129, patch by Guilherme Polo.
+
- Issue #3549: On MacOS the preferences menu was not present
+
What's New in IDLE 2.6?
=======================
@@ -56,7 +57,7 @@ What's New in IDLE 2.6a1?
in the config dialog would cause non-Python files to be colored as if they
were Python source; improve use of ColorDelagator. Patch 1334. Tal Einat.
-- ScriptBinding event handlers weren't returning 'break'. Patch 2050, Tal Einat
+- ScriptBinding event handlers weren't returning 'break'. Patch 2050, Tal Einat.
- There was an error on exit if no sys.exitfunc was defined. Issue 1647.
diff --git a/Lib/idlelib/ObjectBrowser.py b/Lib/idlelib/ObjectBrowser.py
index 8383081..7de6988 100644
--- a/Lib/idlelib/ObjectBrowser.py
+++ b/Lib/idlelib/ObjectBrowser.py
@@ -126,7 +126,7 @@ dispatch = {
def make_objecttreeitem(labeltext, object, setfunction=None):
t = type(object)
- if dispatch.has_key(t):
+ if t in dispatch:
c = dispatch[t]
else:
c = ObjectTreeItem
diff --git a/Lib/idlelib/PathBrowser.py b/Lib/idlelib/PathBrowser.py
index 6b2c071..d88a48e 100644
--- a/Lib/idlelib/PathBrowser.py
+++ b/Lib/idlelib/PathBrowser.py
@@ -78,7 +78,7 @@ class DirBrowserTreeItem(TreeItem):
normed_name = os.path.normcase(name)
if normed_name[i:] == suff:
mod_name = name[:i]
- if not modules.has_key(mod_name):
+ if mod_name not in modules:
modules[mod_name] = None
sorted.append((normed_name, name))
allnames.remove(name)
diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py
index 6524dff..0c95df4 100644
--- a/Lib/idlelib/PyShell.py
+++ b/Lib/idlelib/PyShell.py
@@ -36,7 +36,8 @@ from idlelib import RemoteDebugger
from idlelib import macosxSupport
IDENTCHARS = string.ascii_letters + string.digits + "_"
-LOCALHOST = '127.0.0.1'
+HOST = '127.0.0.1' # python execution server on localhost loopback
+PORT = 0 # someday pass in host, port for remote debug capability
try:
from signal import SIGTERM
@@ -56,20 +57,21 @@ except ImportError:
else:
def idle_showwarning(message, category, filename, lineno,
file=None, line=None):
- file = warning_stream
+ if file is None:
+ file = warning_stream
try:
- file.write(warnings.formatwarning(message, category, filename,\
+ file.write(warnings.formatwarning(message, category, filename,
lineno, file=file, line=line))
except IOError:
pass ## file (probably __stderr__) is invalid, warning dropped.
warnings.showwarning = idle_showwarning
- def idle_formatwarning(message, category, filename, lineno,
- file=None, line=None):
+ def idle_formatwarning(message, category, filename, lineno, line=None):
"""Format warnings the IDLE way"""
s = "\nWarning (from warnings module):\n"
s += ' File \"%s\", line %s\n' % (filename, lineno)
- line = linecache.getline(filename, lineno).strip() \
- if line is None else line
+ if line is None:
+ line = linecache.getline(filename, lineno)
+ line = line.strip()
if line:
s += " %s\n" % line
s += "%s: %s\n>>> " % (category.__name__, message)
@@ -82,18 +84,17 @@ def extended_linecache_checkcache(filename=None,
Rather than repeating the linecache code, patch it to save the
<pyshell#...> entries, call the original linecache.checkcache()
- (which destroys them), and then restore the saved entries.
+ (skipping them), and then restore the saved entries.
orig_checkcache is bound at definition time to the original
method, allowing it to be patched.
-
"""
cache = linecache.cache
save = {}
- for filename in cache.keys():
- if filename[:1] + filename[-1:] == '<>':
- save[filename] = cache[filename]
- orig_checkcache()
+ for key in list(cache):
+ if key[:1] + key[-1:] == '<>':
+ save[key] = cache.pop(key)
+ orig_checkcache(filename)
cache.update(save)
# Patch linecache.checkcache():
@@ -341,17 +342,21 @@ class ModifiedInterpreter(InteractiveInterpreter):
InteractiveInterpreter.__init__(self, locals=locals)
self.save_warnings_filters = None
self.restarting = False
- self.subprocess_arglist = self.build_subprocess_arglist()
+ self.subprocess_arglist = None
+ self.port = PORT
- port = 8833
rpcclt = None
rpcpid = None
def spawn_subprocess(self):
+ if self.subprocess_arglist is None:
+ self.subprocess_arglist = self.build_subprocess_arglist()
args = self.subprocess_arglist
self.rpcpid = os.spawnv(os.P_NOWAIT, sys.executable, args)
def build_subprocess_arglist(self):
+ assert (self.port!=0), (
+ "Socket should have been assigned a port number.")
w = ['-W' + s for s in sys.warnoptions]
if 1/2 > 0: # account for new division
w.append('-Qnew')
@@ -372,11 +377,8 @@ class ModifiedInterpreter(InteractiveInterpreter):
return [decorated_exec] + w + ["-c", command, str(self.port)]
def start_subprocess(self):
- # spawning first avoids passing a listening socket to the subprocess
- self.spawn_subprocess()
- #time.sleep(20) # test to simulate GUI not accepting connection
- addr = (LOCALHOST, self.port)
- # Idle starts listening for connection on localhost
+ addr = (HOST, self.port)
+ # GUI makes several attempts to acquire socket, listens for connection
for i in range(3):
time.sleep(i)
try:
@@ -387,6 +389,18 @@ class ModifiedInterpreter(InteractiveInterpreter):
else:
self.display_port_binding_error()
return None
+ # if PORT was 0, system will assign an 'ephemeral' port. Find it out:
+ self.port = self.rpcclt.listening_sock.getsockname()[1]
+ # if PORT was not 0, probably working with a remote execution server
+ if PORT != 0:
+ # To allow reconnection within the 2MSL wait (cf. Stevens TCP
+ # V1, 18.6), set SO_REUSEADDR. Note that this can be problematic
+ # on Windows since the implementation allows two active sockets on
+ # the same address!
+ self.rpcclt.listening_sock.setsockopt(socket.SOL_SOCKET,
+ socket.SO_REUSEADDR, 1)
+ self.spawn_subprocess()
+ #time.sleep(20) # test to simulate GUI not accepting connection
# Accept the connection from the Python execution server
self.rpcclt.listening_sock.settimeout(10)
try:
@@ -753,13 +767,12 @@ class ModifiedInterpreter(InteractiveInterpreter):
def display_port_binding_error(self):
tkMessageBox.showerror(
"Port Binding Error",
- "IDLE can't bind TCP/IP port 8833, which is necessary to "
- "communicate with its Python execution server. Either "
- "no networking is installed on this computer or another "
- "process (another IDLE?) is using the port. Run IDLE with the -n "
- "command line switch to start without a subprocess and refer to "
- "Help/IDLE Help 'Running without a subprocess' for further "
- "details.",
+ "IDLE can't bind to a TCP/IP port, which is necessary to "
+ "communicate with its Python execution server. This might be "
+ "because no networking is installed on this computer. "
+ "Run IDLE with the -n command line switch to start without a "
+ "subprocess and refer to Help/IDLE Help 'Running without a "
+ "subprocess' for further details.",
master=self.tkconsole.text)
def display_no_subprocess_error(self):
@@ -972,15 +985,6 @@ class PyShell(OutputWindow):
COPYRIGHT = \
'Type "copyright", "credits" or "license()" for more information.'
- firewallmessage = """
- ****************************************************************
- Personal firewall software may warn about the connection IDLE
- makes to its subprocess using this computer's internal loopback
- interface. This connection is not visible on any external
- interface and no data is sent to or received from the Internet.
- ****************************************************************
- """
-
def begin(self):
self.resetoutput()
if use_subprocess:
@@ -991,9 +995,8 @@ class PyShell(OutputWindow):
return False
else:
nosub = "==== No Subprocess ===="
- self.write("Python %s on %s\n%s\n%s\nIDLE %s %s\n" %
- (sys.version, sys.platform, self.COPYRIGHT,
- self.firewallmessage, idlever.IDLE_VERSION, nosub))
+ self.write("Python %s on %s\n%s\n%s" %
+ (sys.version, sys.platform, self.COPYRIGHT, nosub))
self.showprompt()
import Tkinter
Tkinter._default_root = None # 03Jan04 KBK What's this?
@@ -1310,7 +1313,7 @@ def main():
global flist, root, use_subprocess
use_subprocess = True
- enable_shell = False
+ enable_shell = True
enable_edit = False
debug = False
cmd = None
@@ -1331,6 +1334,7 @@ def main():
enable_shell = True
if o == '-e':
enable_edit = True
+ enable_shell = False
if o == '-h':
sys.stdout.write(usage_msg)
sys.exit()
@@ -1381,7 +1385,6 @@ def main():
edit_start = idleConf.GetOption('main', 'General',
'editor-on-startup', type='bool')
enable_edit = enable_edit or edit_start
- enable_shell = enable_shell or not edit_start
# start editor and/or shell windows:
root = Tk(className="Idle")
@@ -1429,6 +1432,13 @@ def main():
shell.interp.prepend_syspath(script)
shell.interp.execfile(script)
+ # Check for problematic OS X Tk versions and print a warning message
+ # in the IDLE shell window; this is less intrusive than always opening
+ # a separate window.
+ tkversionwarning = macosxSupport.tkVersionWarning(root)
+ if tkversionwarning:
+ shell.interp.runcommand(''.join(("print('", tkversionwarning, "')")))
+
root.mainloop()
root.destroy()
diff --git a/Lib/idlelib/RemoteDebugger.py b/Lib/idlelib/RemoteDebugger.py
index ffeffce..647285f 100644
--- a/Lib/idlelib/RemoteDebugger.py
+++ b/Lib/idlelib/RemoteDebugger.py
@@ -230,7 +230,7 @@ class FrameProxy:
return self._get_dict_proxy(did)
def _get_dict_proxy(self, did):
- if self._dictcache.has_key(did):
+ if did in self._dictcache:
return self._dictcache[did]
dp = DictProxy(self._conn, self._oid, did)
self._dictcache[did] = dp
diff --git a/Lib/idlelib/RstripExtension.py b/Lib/idlelib/RstripExtension.py
new file mode 100644
index 0000000..19e35d4
--- /dev/null
+++ b/Lib/idlelib/RstripExtension.py
@@ -0,0 +1,29 @@
+'Provides "Strip trailing whitespace" under the "Format" menu.'
+
+__author__ = "Roger D. Serwy <roger.serwy at gmail.com>"
+
+class RstripExtension:
+
+ menudefs = [
+ ('format', [None,
+ ('Strip trailing whitespace', '<<do-rstrip>>'),
+ ]),]
+
+ def __init__(self, editwin):
+ self.editwin = editwin
+ self.editwin.text.bind("<<do-rstrip>>", self.do_rstrip)
+
+ def do_rstrip(self, event=None):
+
+ text = self.editwin.text
+ undo = self.editwin.undo
+
+ undo.undo_block_start()
+
+ end_line = int(float(text.index('end'))) + 1
+ for cur in range(1, end_line):
+ txt = text.get('%i.0' % cur, '%i.0 lineend' % cur)
+ cut = len(txt.rstrip())
+ text.delete('%i.%i' % (cur, cut), '%i.0 lineend' % cur)
+
+ undo.undo_block_stop()
diff --git a/Lib/idlelib/TreeWidget.py b/Lib/idlelib/TreeWidget.py
index 7d962fe..0feca01 100644
--- a/Lib/idlelib/TreeWidget.py
+++ b/Lib/idlelib/TreeWidget.py
@@ -409,7 +409,7 @@ class FileTreeItem(TreeItem):
class ScrolledCanvas:
def __init__(self, master, **opts):
- if not opts.has_key('yscrollincrement'):
+ if 'yscrollincrement' not in opts:
opts['yscrollincrement'] = 17
self.master = master
self.frame = Frame(master)
diff --git a/Lib/idlelib/config-extensions.def b/Lib/idlelib/config-extensions.def
index 2d5cf68..78b68f6 100644
--- a/Lib/idlelib/config-extensions.def
+++ b/Lib/idlelib/config-extensions.def
@@ -86,3 +86,9 @@ bgcolor=LightGray
fgcolor=Black
[CodeContext_bindings]
toggle-code-context=
+
+[RstripExtension]
+enable=1
+enable_shell=0
+enable_editor=1
+
diff --git a/Lib/idlelib/config-keys.def b/Lib/idlelib/config-keys.def
index fb0aaf4..fdc35ba 100644
--- a/Lib/idlelib/config-keys.def
+++ b/Lib/idlelib/config-keys.def
@@ -176,7 +176,7 @@ comment-region = <Control-Key-3>
redo = <Shift-Command-Key-Z>
close-window = <Command-Key-w>
restart-shell = <Control-Key-F6>
-save-window-as-file = <Command-Key-S>
+save-window-as-file = <Shift-Command-Key-S>
close-all-windows = <Command-Key-q>
view-restart = <Key-F6>
tabify-region = <Control-Key-5>
@@ -208,7 +208,7 @@ open-new-window = <Command-Key-n>
open-module = <Command-Key-m>
find-selection = <Shift-Command-Key-F3>
python-context-help = <Shift-Key-F1>
-save-copy-of-window-as-file = <Shift-Command-Key-s>
+save-copy-of-window-as-file = <Option-Command-Key-s>
open-window-from-file = <Command-Key-o>
python-docs = <Key-F1>
diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py
index 8d3a49d..dbaedc7 100644
--- a/Lib/idlelib/configDialog.py
+++ b/Lib/idlelib/configDialog.py
@@ -28,6 +28,7 @@ class ConfigDialog(Toplevel):
self.wm_withdraw()
self.configure(borderwidth=5)
+ self.title('IDLE Preferences')
self.geometry("+%d+%d" % (parent.winfo_rootx()+20,
parent.winfo_rooty()+30))
#Theme Elements. Each theme element key is its display name.
@@ -561,7 +562,7 @@ class ConfigDialog(Toplevel):
def AddChangedItem(self,type,section,item,value):
value=str(value) #make sure we use a string
- if not self.changedItems[type].has_key(section):
+ if section not in self.changedItems[type]:
self.changedItems[type][section]={}
self.changedItems[type][section][item]=value
@@ -708,7 +709,7 @@ class ConfigDialog(Toplevel):
return
#remove key set from config
idleConf.userCfg['keys'].remove_section(keySetName)
- if self.changedItems['keys'].has_key(keySetName):
+ if keySetName in self.changedItems['keys']:
del(self.changedItems['keys'][keySetName])
#write changes
idleConf.userCfg['keys'].Save()
@@ -735,7 +736,7 @@ class ConfigDialog(Toplevel):
return
#remove theme from config
idleConf.userCfg['highlight'].remove_section(themeName)
- if self.changedItems['highlight'].has_key(themeName):
+ if themeName in self.changedItems['highlight']:
del(self.changedItems['highlight'][themeName])
#write changes
idleConf.userCfg['highlight'].Save()
@@ -870,9 +871,9 @@ class ConfigDialog(Toplevel):
#handle any unsaved changes to this theme
if theme in self.changedItems['highlight'].keys():
themeDict=self.changedItems['highlight'][theme]
- if themeDict.has_key(element+'-foreground'):
+ if element+'-foreground' in themeDict:
colours['foreground']=themeDict[element+'-foreground']
- if themeDict.has_key(element+'-background'):
+ if element+'-background' in themeDict:
colours['background']=themeDict[element+'-background']
self.textHighlightSample.tag_config(element, **colours)
self.SetColourSample()
diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py
index b00bdcf..73487d5 100644
--- a/Lib/idlelib/configHandler.py
+++ b/Lib/idlelib/configHandler.py
@@ -246,7 +246,7 @@ class IdleConf:
else: #returning default, print warning
if warn_on_default:
warning = ('\n Warning: configHandler.py - IdleConf.GetOption -\n'
- ' problem retrieving configration option %r\n'
+ ' problem retrieving configuration option %r\n'
' from section %r.\n'
' returning default value: %r\n' %
(option, section, default))
diff --git a/Lib/idlelib/extend.txt b/Lib/idlelib/extend.txt
index f5fb3e0..165e044 100644
--- a/Lib/idlelib/extend.txt
+++ b/Lib/idlelib/extend.txt
@@ -18,7 +18,7 @@ window.
An IDLE extension class is instantiated with a single argument,
`editwin', an EditorWindow instance. The extension cannot assume much
-about this argument, but it is guarateed to have the following instance
+about this argument, but it is guaranteed to have the following instance
variables:
text a Text instance (a widget)
diff --git a/Lib/idlelib/idle.bat b/Lib/idlelib/idle.bat
index c1b5fd2..cc653dc 100755
--- a/Lib/idlelib/idle.bat
+++ b/Lib/idlelib/idle.bat
@@ -1,3 +1,4 @@
@echo off
-rem Working IDLE bat for Windows - uses start instead of absolute pathname
-start idle.pyw %1 %2 %3 %4 %5 %6 %7 %8 %9
+rem Start IDLE using the appropriate Python interpreter
+set CURRDIR=%~dp0
+start "%CURRDIR%..\..\pythonw.exe" "%CURRDIR%idle.pyw" %1 %2 %3 %4 %5 %6 %7 %8 %9
diff --git a/Lib/idlelib/idle.py b/Lib/idlelib/idle.py
index 537dd5a..a249557 100644
--- a/Lib/idlelib/idle.py
+++ b/Lib/idlelib/idle.py
@@ -1,21 +1,11 @@
-try:
- import idlelib.PyShell
-except ImportError:
- # IDLE is not installed, but maybe PyShell is on sys.path:
- try:
- import PyShell
- except ImportError:
- raise
- else:
- import os
- idledir = os.path.dirname(os.path.abspath(PyShell.__file__))
- if idledir != os.getcwd():
- # We're not in the IDLE directory, help the subprocess find run.py
- pypath = os.environ.get('PYTHONPATH', '')
- if pypath:
- os.environ['PYTHONPATH'] = pypath + ':' + idledir
- else:
- os.environ['PYTHONPATH'] = idledir
- PyShell.main()
-else:
- idlelib.PyShell.main()
+import os.path
+import sys
+
+# If we are working on a development version of IDLE, we need to prepend the
+# parent of this idlelib dir to sys.path. Otherwise, importing idlelib gets
+# the version installed with the Python used to call this module:
+idlelib_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+sys.path.insert(0, idlelib_dir)
+
+import idlelib.PyShell
+idlelib.PyShell.main()
diff --git a/Lib/idlelib/idlever.py b/Lib/idlelib/idlever.py
index 2888aaf..b6e1a1d 100644
--- a/Lib/idlelib/idlever.py
+++ b/Lib/idlelib/idlever.py
@@ -1 +1 @@
-IDLE_VERSION = "2.6.6"
+IDLE_VERSION = "2.7.1"
diff --git a/Lib/idlelib/macosxSupport.py b/Lib/idlelib/macosxSupport.py
index 7ef56f3..4be60a3 100644
--- a/Lib/idlelib/macosxSupport.py
+++ b/Lib/idlelib/macosxSupport.py
@@ -4,19 +4,57 @@ GUI application (as opposed to an X11 application).
"""
import sys
import Tkinter
+from os import path
+
+
+_appbundle = None
def runningAsOSXApp():
"""
Returns True if Python is running from within an app on OSX.
If so, assume that Python was built with Aqua Tcl/Tk rather than
- X11 Tck/Tk.
+ X11 Tcl/Tk.
+ """
+ global _appbundle
+ if _appbundle is None:
+ _appbundle = (sys.platform == 'darwin' and '.app' in sys.executable)
+ return _appbundle
+
+_carbonaquatk = None
+
+def isCarbonAquaTk(root):
+ """
+ Returns True if IDLE is using a Carbon Aqua Tk (instead of the
+ newer Cocoa Aqua Tk).
"""
- return (sys.platform == 'darwin' and '.app' in sys.executable)
+ global _carbonaquatk
+ if _carbonaquatk is None:
+ _carbonaquatk = (runningAsOSXApp() and
+ 'aqua' in root.tk.call('tk', 'windowingsystem') and
+ 'AppKit' not in root.tk.call('winfo', 'server', '.'))
+ return _carbonaquatk
+
+def tkVersionWarning(root):
+ """
+ Returns a string warning message if the Tk version in use appears to
+ be one known to cause problems with IDLE. The Apple Cocoa-based Tk 8.5
+ that was shipped with Mac OS X 10.6.
+ """
+
+ if (runningAsOSXApp() and
+ ('AppKit' in root.tk.call('winfo', 'server', '.')) and
+ (root.tk.call('info', 'patchlevel') == '8.5.7') ):
+ return (r"WARNING: The version of Tcl/Tk (8.5.7) in use may"
+ r" be unstable.\n"
+ r"Visit http://www.python.org/download/mac/tcltk/"
+ r" for current information.")
+ else:
+ return False
def addOpenEventSupport(root, flist):
"""
- This ensures that the application will respont to open AppleEvents, which
- makes is feaseable to use IDLE as the default application for python files.
+ This ensures that the application will respond to open AppleEvents, which
+ makes is feasible to use IDLE as the default application for python files.
"""
def doOpenFile(*args):
for fn in args:
@@ -73,9 +111,6 @@ def overrideRootMenu(root, flist):
WindowList.add_windows_to_menu(menu)
WindowList.register_callback(postwindowsmenu)
- menudict['application'] = menu = Menu(menubar, name='apple')
- menubar.add_cascade(label='IDLE', menu=menu)
-
def about_dialog(event=None):
from idlelib import aboutDialog
aboutDialog.AboutDialog(root, 'About IDLE')
@@ -85,41 +120,45 @@ def overrideRootMenu(root, flist):
root.instance_dict = flist.inversedict
configDialog.ConfigDialog(root, 'Settings')
+ def help_dialog(event=None):
+ from idlelib import textView
+ fn = path.join(path.abspath(path.dirname(__file__)), 'help.txt')
+ textView.view_file(root, 'Help', fn)
root.bind('<<about-idle>>', about_dialog)
root.bind('<<open-config-dialog>>', config_dialog)
+ root.createcommand('::tk::mac::ShowPreferences', config_dialog)
if flist:
root.bind('<<close-all-windows>>', flist.close_all_callback)
-
- ###check if Tk version >= 8.4.14; if so, use hard-coded showprefs binding
- tkversion = root.tk.eval('info patchlevel')
- # Note: we cannot check if the string tkversion >= '8.4.14', because
- # the string '8.4.7' is greater than the string '8.4.14'.
- if tuple(map(int, tkversion.split('.'))) >= (8, 4, 14):
- Bindings.menudefs[0] = ('application', [
+ # The binding above doesn't reliably work on all versions of Tk
+ # on MacOSX. Adding command definition below does seem to do the
+ # right thing for now.
+ root.createcommand('exit', flist.close_all_callback)
+
+ if isCarbonAquaTk(root):
+ # for Carbon AquaTk, replace the default Tk apple menu
+ menudict['application'] = menu = Menu(menubar, name='apple')
+ menubar.add_cascade(label='IDLE', menu=menu)
+ Bindings.menudefs.insert(0,
+ ('application', [
('About IDLE', '<<about-idle>>'),
- None,
- ])
- root.createcommand('::tk::mac::ShowPreferences', config_dialog)
+ None,
+ ]))
+ tkversion = root.tk.eval('info patchlevel')
+ if tuple(map(int, tkversion.split('.'))) < (8, 4, 14):
+ # for earlier AquaTk versions, supply a Preferences menu item
+ Bindings.menudefs[0][1].append(
+ ('_Preferences....', '<<open-config-dialog>>'),
+ )
else:
- for mname, entrylist in Bindings.menudefs:
- menu = menudict.get(mname)
- if not menu:
- continue
- else:
- for entry in entrylist:
- if not entry:
- menu.add_separator()
- else:
- label, eventname = entry
- underline, label = prepstr(label)
- accelerator = get_accelerator(Bindings.default_keydefs,
- eventname)
- def command(text=root, eventname=eventname):
- text.event_generate(eventname)
- menu.add_command(label=label, underline=underline,
- command=command, accelerator=accelerator)
+ # assume Cocoa AquaTk
+ # replace default About dialog with About IDLE one
+ root.createcommand('tkAboutDialog', about_dialog)
+ # replace default "Help" item in Help menu
+ root.createcommand('::tk::mac::ShowHelp', help_dialog)
+ # remove redundant "IDLE Help" from menu
+ del Bindings.menudefs[-1][1][0]
def setupApp(root, flist):
"""
diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py
index 3bac6a3..1395058 100644
--- a/Lib/idlelib/rpc.py
+++ b/Lib/idlelib/rpc.py
@@ -169,7 +169,7 @@ class SocketIO(object):
how, (oid, methodname, args, kwargs) = request
except TypeError:
return ("ERROR", "Bad request format")
- if not self.objtable.has_key(oid):
+ if oid not in self.objtable:
return ("ERROR", "Unknown object id: %r" % (oid,))
obj = self.objtable[oid]
if methodname == "__methods__":
@@ -304,7 +304,7 @@ class SocketIO(object):
# wait for notification from socket handling thread
cvar = self.cvars[myseq]
cvar.acquire()
- while not self.responses.has_key(myseq):
+ while myseq not in self.responses:
cvar.wait()
response = self.responses[myseq]
self.debug("_getresponse:%s: thread woke up: response: %s" %
@@ -518,8 +518,6 @@ class RPCClient(SocketIO):
def __init__(self, address, family=socket.AF_INET, type=socket.SOCK_STREAM):
self.listening_sock = socket.socket(family, type)
- self.listening_sock.setsockopt(socket.SOL_SOCKET,
- socket.SO_REUSEADDR, 1)
self.listening_sock.bind(address)
self.listening_sock.listen(1)
@@ -552,7 +550,7 @@ class RPCProxy(object):
return MethodProxy(self.sockio, self.oid, name)
if self.__attributes is None:
self.__getattributes()
- if self.__attributes.has_key(name):
+ if name in self.__attributes:
value = self.sockio.remotecall(self.oid, '__getattribute__',
(name,), {})
return value
@@ -572,7 +570,7 @@ def _getmethods(obj, methods):
# Adds names to dictionary argument 'methods'
for name in dir(obj):
attr = getattr(obj, name)
- if callable(attr):
+ if hasattr(attr, '__call__'):
methods[name] = 1
if type(obj) == types.InstanceType:
_getmethods(obj.__class__, methods)
@@ -583,7 +581,7 @@ def _getmethods(obj, methods):
def _getattributes(obj, attributes):
for name in dir(obj):
attr = getattr(obj, name)
- if not callable(attr):
+ if not hasattr(attr, '__call__'):
attributes[name] = 1
class MethodProxy(object):
@@ -599,4 +597,4 @@ class MethodProxy(object):
# XXX KBK 09Sep03 We need a proper unit test for this module. Previously
-# existing test code was removed at Rev 1.27.
+# existing test code was removed at Rev 1.27 (r34098).
diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py
index 270ea15..642b979 100644
--- a/Lib/idlelib/run.py
+++ b/Lib/idlelib/run.py
@@ -25,12 +25,13 @@ except ImportError:
pass
else:
def idle_formatwarning_subproc(message, category, filename, lineno,
- file=None, line=None):
+ line=None):
"""Format warnings the IDLE way"""
s = "\nWarning (from warnings module):\n"
s += ' File \"%s\", line %s\n' % (filename, lineno)
- line = linecache.getline(filename, lineno).strip() \
- if line is None else line
+ if line is None:
+ line = linecache.getline(filename, lineno)
+ line = line.strip()
if line:
s += " %s\n" % line
s += "%s: %s\n" % (category.__name__, message)
@@ -67,10 +68,13 @@ def main(del_exitfunc=False):
global quitting
global no_exitfunc
no_exitfunc = del_exitfunc
- port = 8833
#time.sleep(15) # test subprocess not responding
- if sys.argv[1:]:
- port = int(sys.argv[1])
+ try:
+ assert(len(sys.argv) > 1)
+ port = int(sys.argv[-1])
+ except:
+ print>>sys.stderr, "IDLE Subprocess: no IP port passed in sys.argv."
+ return
sys.argv[:] = [""]
sockthread = threading.Thread(target=manage_socket,
name='SockThread',