diff options
Diffstat (limited to 'Lib/idlelib')
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', |
