diff options
Diffstat (limited to 'Lib/idlelib')
56 files changed, 2213 insertions, 1096 deletions
diff --git a/Lib/idlelib/AutoComplete.py b/Lib/idlelib/AutoComplete.py index b20512dfa0..ff085d5c70 100644 --- a/Lib/idlelib/AutoComplete.py +++ b/Lib/idlelib/AutoComplete.py @@ -1,6 +1,6 @@  """AutoComplete.py - An IDLE extension for automatically completing names. -This extension can complete either attribute names of file names. It can pop +This extension can complete either attribute names or file names. It can pop  a window with all available names, for the user to select from.  """  import os @@ -64,7 +64,7 @@ class AutoComplete:      def try_open_completions_event(self, event):          """Happens when it would be nice to open a completion list, but not -        really necessary, for example after an dot, so function +        really necessary, for example after a dot, so function          calls won't be made.          """          lastchar = self.text.get("insert-1c") diff --git a/Lib/idlelib/Bindings.py b/Lib/idlelib/Bindings.py index ab25ff18b6..e19a279b1b 100644 --- a/Lib/idlelib/Bindings.py +++ b/Lib/idlelib/Bindings.py @@ -69,6 +69,8 @@ menudefs = [   ('shell', [     ('_View Last Restart', '<<view-restart>>'),     ('_Restart Shell', '<<restart-shell>>'), +   None, +   ('_Interrupt Execution', '<<interrupt-execution>>'),     ]),   ('debug', [     ('_Go to File/Line', '<<goto-file-line>>'), diff --git a/Lib/idlelib/CREDITS.txt b/Lib/idlelib/CREDITS.txt index 5ff599dee1..3a50eb8e7f 100644 --- a/Lib/idlelib/CREDITS.txt +++ b/Lib/idlelib/CREDITS.txt @@ -24,7 +24,7 @@ Noam Raphael (Code Context, Call Tips, many other patches), and Chui Tey (RPC  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, +Jim Jewett, Martin v. Löwis, Jason Orendorff, Guilherme Polo, Josh Robb,  Nigel Rowe, Bruce Sherwood, Jeff Shute, and Weeble have submitted useful  patches.  Thanks, guys! diff --git a/Lib/idlelib/CallTipWindow.py b/Lib/idlelib/CallTipWindow.py index 8e68a76b2a..9eec17506d 100644 --- a/Lib/idlelib/CallTipWindow.py +++ b/Lib/idlelib/CallTipWindow.py @@ -9,7 +9,7 @@ HIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-hide>>"  HIDE_SEQUENCES = ("<Key-Escape>", "<FocusOut>")  CHECKHIDE_VIRTUAL_EVENT_NAME = "<<calltipwindow-checkhide>>"  CHECKHIDE_SEQUENCES = ("<KeyRelease>", "<ButtonRelease>") -CHECKHIDE_TIME = 100 # miliseconds +CHECKHIDE_TIME = 100 # milliseconds  MARK_RIGHT = "calltipwindowregion_right" diff --git a/Lib/idlelib/ChangeLog b/Lib/idlelib/ChangeLog index 985871bee7..0c36664512 100644 --- a/Lib/idlelib/ChangeLog +++ b/Lib/idlelib/ChangeLog @@ -20,7 +20,7 @@ IDLEfork ChangeLog  2001-07-19 14:49  elguavas  	* ChangeLog, EditorWindow.py, INSTALLATION, NEWS.txt, README.txt, -	TODO.txt, idlever.py:  +	TODO.txt, idlever.py:  	minor tidy-ups ready for 0.8.1 alpha tarball release  2001-07-17 15:12  kbk @@ -172,7 +172,7 @@ IDLEfork ChangeLog  	all this work w/ a future-stmt just looks harder and harder."  	--tim_one -	(From Rel 1.8: "Hack to make this still work with Python 1.5.2.  +	(From Rel 1.8: "Hack to make this still work with Python 1.5.2.  	;-( " --fdrake)  2001-07-14 14:51  kbk @@ -193,7 +193,7 @@ IDLEfork ChangeLog  	test() to _test()."  --GvR  	This was an interesting merge. The join completely missed removing -	goodname(), which was adjacent, but outside of, a small conflict.  +	goodname(), which was adjacent, but outside of, a small conflict.  	I only caught it by comparing the 1.1.3.2/1.1.3.3 diff.  CVS ain't  	infallible. @@ -516,12 +516,12 @@ IDLEfork ChangeLog  2000-08-15 22:51  nowonder -	* IDLEFORK.html:  +	* IDLEFORK.html:  	corrected email address  2000-08-15 22:47  nowonder -	* IDLEFORK.html:  +	* IDLEFORK.html:  	added .html file for http://idlefork.sourceforge.net  2000-08-15 11:13  dscherer @@ -1574,7 +1574,7 @@ Mon Oct 12 23:59:27 1998  Guido van Rossum  <guido@cnri.reston.va.us>  	* Attic/PopupMenu.py: Pass a root to the help window.  	* SearchBinding.py: -	Add parent argument to 'to to line number' dialog box. +	Add parent argument to 'go to line number' dialog box.  Sat Oct 10 19:15:32 1998  Guido van Rossum  <guido@cnri.reston.va.us> diff --git a/Lib/idlelib/CodeContext.py b/Lib/idlelib/CodeContext.py index 44783b69d0..7d25adaa4c 100644 --- a/Lib/idlelib/CodeContext.py +++ b/Lib/idlelib/CodeContext.py @@ -57,18 +57,18 @@ class CodeContext:              # Calculate the border width and horizontal padding required to              # align the context with the text in the main Text widget.              # -            # All values are passed through int(str(<value>)), since some +            # All values are passed through getint(), since some              # values may be pixel objects, which can't simply be added to ints.              widgets = self.editwin.text, self.editwin.text_frame              # Calculate the required vertical padding              padx = 0              for widget in widgets: -                padx += int(str( widget.pack_info()['padx'] )) -                padx += int(str( widget.cget('padx') )) +                padx += widget.tk.getint(widget.pack_info()['padx']) +                padx += widget.tk.getint(widget.cget('padx'))              # Calculate the required border width              border = 0              for widget in widgets: -                border += int(str( widget.cget('border') )) +                border += widget.tk.getint(widget.cget('border'))              self.label = tkinter.Label(self.editwin.top,                                         text="\n" * (self.context_depth - 1),                                         anchor=W, justify=LEFT, diff --git a/Lib/idlelib/ColorDelegator.py b/Lib/idlelib/ColorDelegator.py index 9f31349604..02eac47068 100644 --- a/Lib/idlelib/ColorDelegator.py +++ b/Lib/idlelib/ColorDelegator.py @@ -2,6 +2,7 @@ import time  import re  import keyword  import builtins +from tkinter import TkVersion  from idlelib.Delegator import Delegator  from idlelib.configHandler import idleConf @@ -32,6 +33,28 @@ def make_pat():  prog = re.compile(make_pat(), re.S)  idprog = re.compile(r"\s+(\w+)", re.S) +def color_config(text):  # Called from htest, Editor, and Turtle Demo. +    '''Set color opitons of Text widget. + +    Should be called whenever ColorDelegator is called. +    ''' +    # Not automatic because ColorDelegator does not know 'text'. +    theme = idleConf.CurrentTheme() +    normal_colors = idleConf.GetHighlight(theme, 'normal') +    cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg') +    select_colors = idleConf.GetHighlight(theme, 'hilite') +    text.config( +        foreground=normal_colors['foreground'], +        background=normal_colors['background'], +        insertbackground=cursor_color, +        selectforeground=select_colors['foreground'], +        selectbackground=select_colors['background'], +        ) +    if TkVersion >= 8.5: +        text.config( +            inactiveselectbackground=select_colors['background']) + +  class ColorDelegator(Delegator):      def __init__(self): @@ -233,6 +256,7 @@ class ColorDelegator(Delegator):          for tag in self.tagdefs:              self.tag_remove(tag, "1.0", "end") +  def _color_delegator(parent):  # htest #      from tkinter import Toplevel, Text      from idlelib.Percolator import Percolator @@ -247,6 +271,7 @@ def _color_delegator(parent):  # htest #      text.insert("insert", source)      text.focus_set() +    color_config(text)      p = Percolator(text)      d = ColorDelegator()      p.insertfilter(d) diff --git a/Lib/idlelib/Debugger.py b/Lib/idlelib/Debugger.py index 250422edbb..d5e217dde9 100644 --- a/Lib/idlelib/Debugger.py +++ b/Lib/idlelib/Debugger.py @@ -372,7 +372,7 @@ class StackViewer(ScrolledList):      def __init__(self, master, flist, gui):          if macosxSupport.isAquaTk():              # At least on with the stock AquaTk version on OSX 10.4 you'll -            # get an shaking GUI that eventually kills IDLE if the width +            # get a shaking GUI that eventually kills IDLE if the width              # argument is specified.              ScrolledList.__init__(self, master)          else: diff --git a/Lib/idlelib/Delegator.py b/Lib/idlelib/Delegator.py index c4765163f8..dc2a1aaeea 100644 --- a/Lib/idlelib/Delegator.py +++ b/Lib/idlelib/Delegator.py @@ -1,10 +1,10 @@  class Delegator: -    # The cache is only used to be able to change delegates! -      def __init__(self, delegate=None):          self.delegate = delegate          self.__cache = set() +        # Cache is used to only remove added attributes +        # when changing the delegate.      def __getattr__(self, name):          attr = getattr(self.delegate, name) # May raise AttributeError @@ -13,6 +13,9 @@ class Delegator:          return attr      def resetcache(self): +        "Removes added attributes while leaving original attributes." +        # Function is really about resetting delagator dict +        # to original state.  Cache is just a means          for key in self.__cache:              try:                  delattr(self, key) @@ -21,5 +24,10 @@ class Delegator:          self.__cache.clear()      def setdelegate(self, delegate): +        "Reset attributes and change delegate."          self.resetcache()          self.delegate = delegate + +if __name__ == '__main__': +    from unittest import main +    main('idlelib.idle_test.test_delegator', verbosity=2) diff --git a/Lib/idlelib/EditorWindow.py b/Lib/idlelib/EditorWindow.py index b5868be3fb..9944da3e70 100644 --- a/Lib/idlelib/EditorWindow.py +++ b/Lib/idlelib/EditorWindow.py @@ -90,7 +90,7 @@ helpDialog = HelpDialog()  # singleton instance, no longer used  class EditorWindow(object):      from idlelib.Percolator import Percolator -    from idlelib.ColorDelegator import ColorDelegator +    from idlelib.ColorDelegator import ColorDelegator, color_config      from idlelib.UndoDelegator import UndoDelegator      from idlelib.IOBinding import IOBinding, filesystemencoding, encoding      from idlelib import Bindings @@ -742,20 +742,7 @@ class EditorWindow(object):          # Called from self.filename_change_hook and from configDialog.py          self._rmcolorizer()          self._addcolorizer() -        theme = idleConf.CurrentTheme() -        normal_colors = idleConf.GetHighlight(theme, 'normal') -        cursor_color = idleConf.GetHighlight(theme, 'cursor', fgBg='fg') -        select_colors = idleConf.GetHighlight(theme, 'hilite') -        self.text.config( -            foreground=normal_colors['foreground'], -            background=normal_colors['background'], -            insertbackground=cursor_color, -            selectforeground=select_colors['foreground'], -            selectbackground=select_colors['background'], -            ) -        if TkVersion >= 8.5: -            self.text.config( -                inactiveselectbackground=select_colors['background']) +        EditorWindow.color_config(self.text)      IDENTCHARS = string.ascii_letters + string.digits + "_" diff --git a/Lib/idlelib/HISTORY.txt b/Lib/idlelib/HISTORY.txt index 01d73ed2ba..731fabd185 100644 --- a/Lib/idlelib/HISTORY.txt +++ b/Lib/idlelib/HISTORY.txt @@ -11,7 +11,7 @@ What's New in IDLEfork 0.8.1?  *Release date: 22-Jul-2001*  - New tarball released as a result of the 'revitalisation' of the IDLEfork -  project.  +  project.  - This release requires python 2.1 or better. Compatibility with earlier    versions of python (especially ancient ones like 1.5x) is no longer a @@ -26,8 +26,8 @@ What's New in IDLEfork 0.8.1?    not working, but I believe this was the case with the previous IDLE fork    release (0.7.1) as well. -- This release is being made now to mark the point at which IDLEfork is  -  launching into a new stage of development.  +- This release is being made now to mark the point at which IDLEfork is +  launching into a new stage of development.  - IDLEfork CVS will now be branched to enable further development and    exploration of the two "execution in a remote process" patches submitted by @@ -96,7 +96,7 @@ IDLEfork 0.7.1 - 29 May 2000      instead of the IDLE help; shift-TAB is now a synonym for unindent.  - New modules: -   +    ExecBinding.py         Executes program through loader    loader.py              Bootstraps user program    protocol.py            RPC protocol diff --git a/Lib/idlelib/IOBinding.py b/Lib/idlelib/IOBinding.py index 5ec9d546fd..84f39a2fee 100644 --- a/Lib/idlelib/IOBinding.py +++ b/Lib/idlelib/IOBinding.py @@ -10,6 +10,7 @@ import tkinter.filedialog as tkFileDialog  import tkinter.messagebox as tkMessageBox  from tkinter.simpledialog import askstring +from idlelib.configHandler import idleConf  # Try setting the locale, so that we can find out @@ -61,7 +62,7 @@ locale_encoding = locale_encoding.lower()  encoding = locale_encoding  ### KBK 07Sep07  This is used all over IDLE, check!                              ### 'encoding' is used below in encode(), check! -coding_re = re.compile(r'^[ \t\f]*#.*coding[:=][ \t]*([-\w.]+)', re.ASCII) +coding_re = re.compile(r'^[ \t\f]*#.*?coding[:=][ \t]*([-\w.]+)', re.ASCII)  blank_re = re.compile(r'^[ \t\f]*(?:[#\r\n]|$)', re.ASCII)  def coding_spec(data): @@ -525,7 +526,6 @@ class IOBinding:  def _io_binding(parent):  # htest #      from tkinter import Toplevel, Text -    from idlelib.configHandler import idleConf      root = Toplevel(parent)      root.title("Test IOBinding") @@ -536,14 +536,23 @@ def _io_binding(parent):  # htest #              self.text = text              self.flist = None              self.text.bind("<Control-o>", self.open) +            self.text.bind('<Control-p>', self.print)              self.text.bind("<Control-s>", self.save) +            self.text.bind("<Alt-s>", self.saveas) +            self.text.bind('<Control-c>', self.savecopy)          def get_saved(self): return 0          def set_saved(self, flag): pass          def reset_undo(self): pass          def open(self, event):              self.text.event_generate("<<open-window-from-file>>") +        def print(self, event): +            self.text.event_generate("<<print-window>>")          def save(self, event):              self.text.event_generate("<<save-window>>") +        def saveas(self, event): +            self.text.event_generate("<<save-window-as-file>>") +        def savecopy(self, event): +            self.text.event_generate("<<save-copy-of-window-as-file>>")      text = Text(root)      text.pack() diff --git a/Lib/idlelib/MultiCall.py b/Lib/idlelib/MultiCall.py index 251a84d083..8462854921 100644 --- a/Lib/idlelib/MultiCall.py +++ b/Lib/idlelib/MultiCall.py @@ -111,7 +111,7 @@ class _SimpleBinder:                      raise  # An int in range(1 << len(_modifiers)) represents a combination of modifiers -# (if the least significent bit is on, _modifiers[0] is on, and so on). +# (if the least significant bit is on, _modifiers[0] is on, and so on).  # _state_subsets gives for each combination of modifiers, or *state*,  # a list of the states which are a subset of it. This list is ordered by the  # number of modifiers is the state - the most specific state comes first. diff --git a/Lib/idlelib/NEWS.txt b/Lib/idlelib/NEWS.txt index 8b8e10b5ea..72905c18dd 100644 --- a/Lib/idlelib/NEWS.txt +++ b/Lib/idlelib/NEWS.txt @@ -1,6 +1,91 @@ -What's New in Idle 3.4.4? +What's New in IDLE 3.5.3?  ========================= -*Release date: 2015-12-20* +*Release date: 2017-01-01?* + +- Issue #15308: Add 'interrupt execution' (^C) to Shell menu. +  Patch by Roger Serwy, updated by Bayard Randel. + +- Issue #27922: Stop IDLE tests from 'flashing' gui widgets on the screen. + +- Add version to title of IDLE help window. + +- Issue #25564: In section on IDLE -- console differences, mention that +  using exec means that __builtins__ is defined for each statement. + +- Issue #27714: text_textview and test_autocomplete now pass when re-run +  in the same process.  This occurs when test_idle fails when run with the +  -w option but without -jn.  Fix warning from test_config. + +- Issue #25507: IDLE no longer runs buggy code because of its tkinter imports. +  Users must include the same imports required to run directly in Python. + +- Issue #27452: add line counter and crc to IDLE configHandler test dump. + +- Issue #27365: Allow non-ascii chars in IDLE NEWS.txt, for contributor names. + +- Issue #27245: IDLE: Cleanly delete custom themes and key bindings. +  Previously, when IDLE was started from a console or by import, a cascade +  of warnings was emitted.  Patch by Serhiy Storchaka. + + +What's New in IDLE 3.5.2? +========================= +*Release date: 2016-06-26* + +- Issue #5124: Paste with text selected now replaces the selection on X11. +  This matches how paste works on Windows, Mac, most modern Linux apps, +  and ttk widgets.  Original patch by Serhiy Storchaka. + +- Issue #24759: Make clear in idlelib.idle_test.__init__ that the directory +  is a private implementation of test.test_idle and tool for maintainers. + +- Issue #27196: Stop 'ThemeChangef' warnings when running IDLE tests. +  These persisted after other warnings were suppressed in #20567. +  Apply Serhiy Storchaka's update_idletasks solution to four test files. +  Record this additional advice in idle_test/README.txt + +- Issue #20567: Revise idle_test/README.txt with advice about avoiding +  tk warning messages from tests.  Apply advice to several IDLE tests. + +- Issue #27117: Make colorizer htest and turtledemo work with dark themes. +  Move code for configuring text widget colors to a new function. + +- Issue #26673: When tk reports font size as 0, change to size 10. +  Such fonts on Linux prevented the configuration dialog from opening. + +- Issue #21939: Add test for IDLE's percolator. +  Original patch by Saimadhav Heblikar. + +- Issue #21676: Add test for IDLE's replace dialog. +  Original patch by Saimadhav Heblikar. + +- Issue #18410: Add test for IDLE's search dialog. +  Original patch by Westley MartÃnez. + +- Issue #21703: Add test for undo delegator. +  Original patch by Saimadhav Heblikar . + +- Issue #27044: Add ConfigDialog.remove_var_callbacks to stop memory leaks. + +- Issue #23977: Add more asserts to test_delegator. + +- Issue #20640: Add tests for idlelib.configHelpSourceEdit. +  Patch by Saimadhav Heblikar. + +- In the 'IDLE-console differences' section of the IDLE doc, clarify +  how running with IDLE affects sys.modules and the standard streams. + +- Issue #25507: fix incorrect change in IOBinding that prevented printing. +  Augment IOBinding htest to include all major IOBinding functions. + +- Issue #25905: Revert unwanted conversion of ' to ’ RIGHT SINGLE QUOTATION +  MARK in README.txt and open this and NEWS.txt with 'ascii'. +  Re-encode CREDITS.txt to utf-8 and open it with 'utf-8'. + + +What's New in IDLE 3.5.1? +========================= +*Release date: 2015-12-06*  - Issue 15348: Stop the debugger engine (normally in a user process)    before closing the debugger window (running in the IDLE process). @@ -96,6 +181,11 @@ What's New in Idle 3.4.4?  - Issue #24790: Remove extraneous code (which also create 2 & 3 conflicts). + +What's New in IDLE 3.5.0? +========================= +*Release date: 2015-09-13* +  - Issue #23672: Allow Idle to edit and run files with astral chars in name.    Patch by Mohd Sanad Zaki Rizvi. @@ -112,11 +202,6 @@ What's New in Idle 3.4.4?  - Issue #23184: remove unused names and imports in idlelib.    Initial patch by Al Sweigart. - -What's New in Idle 3.4.3? -========================= -*Release date: 2015-02-25* -  - Issue #20577: Configuration of the max line length for the FormatParagraph    extension has been moved from the General tab of the Idle preferences dialog    to the FormatParagraph tab of the Config Extensions dialog. @@ -129,7 +214,7 @@ What's New in Idle 3.4.3?    Changes are written to HOME/.idlerc/config-extensions.cfg.    Original patch by Tal Einat. -- Issue #16233: A module browser (File : Class Browser, Alt+C) requires a +- Issue #16233: A module browser (File : Class Browser, Alt+C) requires an    editor window with a filename.  When Class Browser is requested otherwise,    from a shell, output window, or 'Untitled' editor, Idle no longer displays    an error box.  It now pops up an  Open Module box (Alt+M). If a valid name @@ -145,16 +230,11 @@ What's New in Idle 3.4.3?  - Issue #23180: Rename IDLE "Windows" menu item to "Window".    Patch by Al Sweigart. - -What's New in IDLE 3.4.2? -========================= -*Release date: 2014-10-06* -  - Issue #17390: Adjust Editor window title; remove 'Python',    move version to end.  - Issue #14105: Idle debugger breakpoints no longer disappear -  when inseting or deleting lines. +  when inserting or deleting lines.  - Issue #17172: Turtledemo can now be run from Idle.    Currently, the entry is on the Help menu, but it may move to Run. @@ -184,14 +264,8 @@ What's New in IDLE 3.4.2?  - Issue #18409: Add unittest for AutoComplete. Patch by Phil Webster. -- Issue #18104: Add idlelib/idle_test/htest.py with a few sample tests to begin -  consolidating and improving human-validated tests of Idle. Change other files -  as needed to work with htest.  Running the module as __main__ runs all tests. - - -What's New in IDLE 3.4.1? -========================= -*Release date: 2014-05-18* +- Issue #21477: htest.py - Improve framework, complete set of tests. +  Patches by Saimadhav Heblikar  - Issue #18104: Add idlelib/idle_test/htest.py with a few sample tests to begin    consolidating and improving human-validated tests of Idle. Change other files @@ -241,7 +315,7 @@ What's New in IDLE 3.3.0?  - Issue # 12510: Attempt to get certain tool tips no longer crashes IDLE.    Erroneous tool tips have been corrected. Default added for callables. -- Issue10365: File open dialog now works instead of crashing even when +- Issue #10365: File open dialog now works instead of crashing even when    parent window is closed while dialog is open.  - Issue 14876: use user-selected font for highlight configuration. @@ -277,23 +351,18 @@ What's New in IDLE 3.2.1?  - Issue #1028: Ctrl-space binding to show completions was causing IDLE to exit.    Tk < 8.5 was sending invalid Unicode null; replaced with valid null. -- <Home> toggle failing on Tk 8.5, causing IDLE exits and strange selection -  behavior. Issue 4676.  Improve selection extension behaviour. +- Issue #4676: <Home> toggle failing on Tk 8.5, causing IDLE exits and strange selection +  behavior. Improve selection extension behaviour. -- <Home> toggle non-functional when NumLock set on Windows.  Issue 3851. +- Issue #3851: <Home> toggle non-functional when NumLock set on Windows.  What's New in IDLE 3.1b1?  =========================  *Release date: 06-May-09* -- Use of 'filter' in keybindingDialog.py was causing custom key assignment to -  fail.  Patch 5707 amaury.forgeotdarc. - - -What's New in IDLE 3.1a1? -========================= -*Release date: 07-Mar-09* +- Issue #5707: Use of 'filter' in keybindingDialog.py was causing custom key assignment to +  fail.  Patch by Amaury Forgeot d'Arc.  - Issue #4815: Offer conversion to UTF-8 if source files have    no encoding declaration and are not encoded in UTF-8. @@ -308,684 +377,6 @@ What's New in IDLE 3.1a1?  - Issue #2665: On Windows, an IDLE installation upgraded from an old version    would not start if a custom theme was defined. - -What's New in IDLE 2.7? (UNRELEASED, but merged into 3.1 releases above.) -======================= -*Release date: XX-XXX-2010* - -- idle.py modified and simplified to better support developing experimental -  versions of IDLE which are not installed in the standard location. - -- 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 - -- 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. - -- 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 3.0 final? -============================= -*Release date: 03-Dec-2008* - -- IDLE would print a "Unhandled server exception!" message when internal -  debugging is enabled. - -- Issue #4455: IDLE failed to display the windows list when two windows have -  the same title. - -- Issue #4383: When IDLE cannot make the connection to its subprocess, it would -  fail to properly display the error message. - - -What's New in IDLE 3.0a3? -========================= -*Release date: 29-Feb-2008* - -- help() was not paging to the shell.  Issue1650. - -- CodeContext was not importing. - -- Corrected two 3.0 compatibility errors reported by Mark Summerfield: -  http://mail.python.org/pipermail/python-3000/2007-December/011491.html - -- Shell was not colorizing due to bug introduced at r57998,  Bug 1586. - -- Issue #1585: IDLE uses non-existent xrange() function. - - -What's New in IDLE 3.0a2? -========================= -*Release date: 06-Dec-2007* - -- Windows EOL sequence not converted correctly, encoding error. -  Caused file save to fail. Bug 1130. - - -What's New in IDLE 3.0a1? -========================= -*Release date: 31-Aug-2007* - -- IDLE converted to Python 3000 syntax. - -- Strings became Unicode. - -- CallTips module now uses the inspect module to produce the argspec. - -- IDLE modules now use absolute import instead of implied relative import. - -- atexit call replaces sys.exitfunc.  The functionality of delete-exitfunc flag -  in config-main.cfg remains unchanged: if set, registered exit functions will -  be cleared before IDLE exits. - - -What's New in IDLE 2.6 -====================== -*Release date: 01-Oct-2008*, merged into 3.0 releases detailed above (3.0rc2) - -- Issue #2665: On Windows, an IDLE installation upgraded from an old version -  would not start if a custom theme was defined. - -- Home / Control-A toggles between left margin and end of leading white -  space.  issue1196903, patch by Jeff Shute. - -- Improved AutoCompleteWindow logic.  issue2062, patch by Tal Einat. - -- Autocompletion of filenames now support alternate separators, e.g. the -  '/' char on Windows.  issue2061 Patch by Tal Einat. - -- Configured selection highlighting colors were ignored; updating highlighting -  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 - -- There was an error on exit if no sys.exitfunc was defined. Issue 1647. - -- Could not open files in .idlerc directory if latter was hidden on Windows. -  Issue 1743, Issue 1862. - -- Configure Dialog: improved layout for keybinding.  Patch 1457 Tal Einat. - -- tabpage.py updated: tabbedPages.py now supports multiple dynamic rows -  of tabs.  Patch 1612746 Tal Einat. - -- Add confirmation dialog before printing.  Patch 1717170 Tal Einat. - -- Show paste position if > 80 col.  Patch 1659326 Tal Einat. - -- Update cursor color without restarting.  Patch 1725576 Tal Einat. - -- Allow keyboard interrupt only when user code is executing in subprocess. -  Patch 1225 Tal Einat (reworked from IDLE-Spoon). - -- configDialog cleanup. Patch 1730217 Tal Einat. - -- textView cleanup. Patch 1718043 Tal Einat. - -- Clean up EditorWindow close. - -- Patch 1693258: Fix for duplicate "preferences" menu-OS X. Backport of r56204. - -- OSX: Avoid crash for those versions of Tcl/Tk which don't have a console - -- Bug in idlelib.MultiCall: Options dialog was crashing IDLE if there was an -  option in config-extensions w/o a value. Patch #1672481, Tal Einat - -- Corrected some bugs in AutoComplete.  Also, Page Up/Down in ACW implemented; -  mouse and cursor selection in ACWindow implemented; double Tab inserts -  current selection and closes ACW (similar to double-click and Return); scroll -  wheel now works in ACW.  Added AutoComplete instructions to IDLE Help. - -- AutoCompleteWindow moved below input line, will move above if there -  isn't enough space.  Patch 1621265 Tal Einat - -- Calltips now 'handle' tuples in the argument list (display '<tuple>' :) -  Suggested solution by Christos Georgiou, Bug 791968. - -- Add 'raw' support to configHandler. Patch 1650174 Tal Einat. - -- Avoid hang when encountering a duplicate in a completion list. Bug 1571112. - -- Patch #1362975: Rework CodeContext indentation algorithm to -  avoid hard-coding pixel widths. - -- Bug #813342: Start the IDLE subprocess with -Qnew if the parent -  is started with that option. - -- Honor the "Cancel" action in the save dialog (Debian bug #299092) - -- Some syntax errors were being caught by tokenize during the tabnanny -  check, resulting in obscure error messages.  Do the syntax check -  first.  Bug 1562716, 1562719 - -- IDLE's version number takes a big jump to match the version number of -  the Python release of which it's a part. - - -What's New in IDLE 1.2? -======================= -*Release date: 19-SEP-2006* - -- File menu hotkeys: there were three 'p' assignments.  Reassign the -  'Save Copy As' and 'Print' hotkeys to 'y' and 't'.  Change the -  Shell hotkey from 's' to 'l'. - -- IDLE honors new quit() and exit() commands from site.py Quitter() object. -  Patch 1540892, Jim Jewett - -- The 'with' statement is now a Code Context block opener. -  Patch 1540851, Jim Jewett - -- Retrieval of previous shell command was not always preserving indentation -  (since 1.2a1) Patch 1528468 Tal Einat. - -- Changing tokenize (39046) to detect dedent broke tabnanny check (since 1.2a1) - -- ToggleTab dialog was setting indent to 8 even if cancelled (since 1.2a1). - -- When used w/o subprocess, all exceptions were preceded by an error -  message claiming they were IDLE internal errors (since 1.2a1). - -- Bug #1525817: Don't truncate short lines in IDLE's tool tips. - -- Bug #1517990: IDLE keybindings on MacOS X now work correctly - -- Bug #1517996: IDLE now longer shows the default Tk menu when a -  path browser, class browser or debugger is the frontmost window on MacOS X - -- EditorWindow.test() was failing.  Bug 1417598 - -- EditorWindow failed when used stand-alone if sys.ps1 not set. -  Bug 1010370 Dave Florek - -- Tooltips failed on new-syle class __init__ args.  Bug 1027566 Loren Guthrie - -- Avoid occasional failure to detect closing paren properly. -  Patch 1407280 Tal Einat - -- Rebinding Tab key was inserting 'tab' instead of 'Tab'.  Bug 1179168. - -- Colorizer now handles #<builtin> correctly, also unicode strings and -  'as' keyword in comment directly following import command. Closes 1325071. -  Patch 1479219 Tal Einat - -- Patch #1162825: Support non-ASCII characters in IDLE window titles. - -- Source file f.flush() after writing; trying to avoid lossage if user -  kills GUI. - -- Options / Keys / Advanced dialog made functional.  Also, allow binding -  of 'movement' keys. - -- 'syntax' patch adds improved calltips and a new class attribute listbox. -  MultiCall module allows binding multiple actions to an event. -  Patch 906702 Noam Raphael - -- Better indentation after first line of string continuation. -  IDLEfork Patch 681992, Noam Raphael - -- Fixed CodeContext alignment problem, following suggestion from Tal Einat. - -- Increased performance in CodeContext extension  Patch 936169 Noam Raphael - -- Mac line endings were incorrect when pasting code from some browsers -  when using X11 and the Fink distribution.  Python Bug 1263656. - -- <Enter> when cursor is on a previous command retrieves that command.  Instead -  of replacing the input line, the previous command is now appended to the -  input line. Indentation is preserved, and undo is enabled. -  Patch 1196917  Jeff Shute - -- Clarify "tab/space" Error Dialog and "Tab Width" Dialog associated with -  the Untabify command. - -- Corrected "tab/space" Error Dialog to show correct menu for Untabify. -  Patch 1196980 Jeff Shute - -- New files are colorized by default, and colorizing is removed when -  saving as non-Python files. Patch 1196895 Jeff Shute -  Closes Python Bugs 775012 and 800432, partial fix IDLEfork 763524 - -- Improve subprocess link error notification. - -- run.py: use Queue's blocking feature instead of sleeping in the main -  loop.  Patch # 1190163 Michiel de Hoon - -- Add config-main option to make the 'history' feature non-cyclic. -  Default remains cyclic.  Python Patch 914546 Noam Raphael. - -- Removed ability to configure tabs indent from Options dialog.  This 'feature' -  has never worked and no one has complained.  It is still possible to set a -  default tabs (v. spaces) indent 'manually' via config-main.def (or to turn on -  tabs for the current EditorWindow via the Format menu) but IDLE will -  encourage indentation via spaces. - -- Enable setting the indentation width using the Options dialog. -  Bug # 783877 - -- Add keybindings for del-word-left and del-word-right. - -- Discourage using an indent width other than 8 when using tabs to indent -  Python code. - -- Restore use of EditorWindow.set_indentation_params(), was dead code since -  Autoindent was merged into EditorWindow.  This allows IDLE to conform to the -  indentation width of a loaded file.  (But it still will not switch to tabs -  even if the file uses tabs.)  Any change in indent width is local to that -  window. - -- Add Tabnanny check before Run/F5, not just when Checking module. - -- If an extension can't be loaded, print warning and skip it instead of -  erroring out. - -- Improve error handling when .idlerc can't be created (warn and exit). - -- The GUI was hanging if the shell window was closed while a raw_input() -  was pending.  Restored the quit() of the readline() mainloop(). -  http://mail.python.org/pipermail/idle-dev/2004-December/002307.html - -- The remote procedure call module rpc.py can now access data attributes of -  remote registered objects.  Changes to these attributes are local, however. - - -What's New in IDLE 1.1? -======================= -*Release date: 30-NOV-2004* - -- On OpenBSD, terminating IDLE with ctrl-c from the command line caused a -  stuck subprocess MainThread because only the SocketThread was exiting. - -- Saving a Keyset w/o making changes (by using the "Save as New Custom Key Set" -  button) caused IDLE to fail on restart (no new keyset was created in -  config-keys.cfg).  Also true for Theme/highlights.  Python Bug 1064535. - -- A change to the linecache.py API caused IDLE to exit when an exception was -  raised while running without the subprocess (-n switch).  Python Bug 1063840. - -- When paragraph reformat width was made configurable, a bug was -  introduced that caused reformatting of comment blocks to ignore how -  far the block was indented, effectively adding the indentation width -  to the reformat width.  This has been repaired, and the reformat -  width is again a bound on the total width of reformatted lines. - -- Improve keyboard focus binding, especially in Windows menu.  Improve -  window raising, especially in the Windows menu and in the debugger. -  IDLEfork 763524. - -- If user passes a non-existent filename on the commandline, just -  open a new file, don't raise a dialog.  IDLEfork 854928. - -- EditorWindow.py was not finding the .chm help file on Windows.  Typo -  at Rev 1.54.  Python Bug 990954 - -- checking sys.platform for substring 'win' was breaking IDLE docs on Mac -  (darwin).  Also, Mac Safari browser requires full file:// URIs.  SF 900580. - -- Redirect the warning stream to the shell during the ScriptBinding check of -  user code and format the warning similarly to an exception for both that -  check and for runtime warnings raised in the subprocess. - -- CodeContext hint pane visibility state is now persistent across sessions. -  The pane no longer appears in the shell window.  Added capability to limit -  extensions to shell window or editor windows.  Noam Raphael addition -  to Patch 936169. - -- Paragraph reformat width is now a configurable parameter in the -  Options GUI. - -- New Extension: CodeContext.  Provides block structuring hints for code -  which has scrolled above an edit window. Patch 936169 Noam Raphael. - -- If nulls somehow got into the strings in recent-files.lst -  EditorWindow.update_recent_files_list() was failing.  Python Bug 931336. - -- If the normal background is changed via Configure/Highlighting, it will -  update immediately, thanks to the previously mentioned patch by Nigel Rowe. - -- Add a highlight theme for builtin keywords.  Python Patch 805830 Nigel Rowe -  This also fixed IDLEfork bug [ 693418 ] Normal text background color not -  refreshed and Python bug [897872 ] Unknown color name on HP-UX - -- rpc.py:SocketIO - Large modules were generating large pickles when downloaded -  to the execution server.  The return of the OK response from the subprocess -  initialization was interfering and causing the sending socket to be not -  ready.  Add an IO ready test to fix this.  Moved the polling IO ready test -  into pollpacket(). - -- Fix typo in rpc.py, s/b "pickle.PicklingError" not "pickle.UnpicklingError". - -- Added a Tk error dialog to run.py inform the user if the subprocess can't -  connect to the user GUI process.  Added a timeout to the GUI's listening -  socket.  Added Tk error dialogs to PyShell.py to announce a failure to bind -  the port or connect to the subprocess.  Clean up error handling during -  connection initiation phase.  This is an update of Python Patch 778323. - -- Print correct exception even if source file changed since shell was -  restarted.  IDLEfork Patch 869012 Noam Raphael - -- Keybindings with the Shift modifier now work correctly.  So do bindings which -  use the Space key.  Limit unmodified user keybindings to the function keys. -  Python Bug 775353, IDLEfork Bugs 755647, 761557 - -- After an exception, run.py was not setting the exception vector. Noam -  Raphael suggested correcting this so pdb's postmortem pm() would work. -  IDLEfork Patch 844675 - -- IDLE now does not fail to save the file anymore if the Tk buffer is not a -  Unicode string, yet eol_convention is.  Python Bugs 774680, 788378 - -- IDLE didn't start correctly when Python was installed in "Program Files" on -  W2K and XP.  Python Bugs 780451, 784183 - -- config-main.def documentation incorrectly referred to idle- instead of -  config-  filenames.  SF 782759  Also added note about .idlerc location. - - -What's New in IDLE 1.0? -======================= -*Release date: 29-Jul-2003* - -- Added a banner to the shell discussing warnings possibly raised by personal -  firewall software.  Added same comment to README.txt. - -- Calltip error when docstring was None  Python Bug 775541 - -- Updated extend.txt, help.txt, and config-extensions.def to correctly -  reflect the current status of the configuration system.  Python Bug 768469 - -- Fixed: Call Tip Trimming May Loop Forever. Python Patch 769142 (Daniels) - -- Replaced apply(f, args, kwds) with f(*args, **kwargs) to improve performance -  Python Patch 768187 - -- Break or continue statements outside a loop were causing IDLE crash -  Python Bug 767794 - -- Convert Unicode strings from readline to IOBinding.encoding.  Also set -  sys.std{in|out|err}.encoding, for both the local and the subprocess case. -  SF IDLEfork patch 682347. - -- Extend AboutDialog.ViewFile() to support file encodings.  Make the CREDITS -  file Latin-1. - -- Updated the About dialog to reflect re-integration into Python.  Provide -  buttons to display Python's NEWS, License, and Credits, plus additional -  buttons for IDLE's README and NEWS. - -- TextViewer() now has a third parameter which allows inserting text into the -  viewer instead of reading from a file. - -- (Created the .../Lib/idlelib directory in the Python CVS, which is a clone of -  IDLEfork modified to install in the Python environment.  The code in the -  interrupt module has been moved to thread.interrupt_main(). ) - -- Printing the Shell window was failing if it was not saved first SF 748975 - -- When using the Search in Files dialog, if the user had a selection -  highlighted in his Editor window, insert it into the dialog search field. - -- The Python Shell entry was disappearing from the Windows menu. - -- Update the Windows file list when a file name change occurs - -- Change to File / Open Module: always pop up the dialog, using the current -  selection as the default value.  This is easier to use habitually. - -- Avoided a problem with starting the subprocess when 'localhost' doesn't -  resolve to the user's loopback interface.  SF 747772 - -- Fixed an issue with highlighted errors never de-colorizing.  SF 747677.  Also -  improved notification of Tabnanny Token Error. - -- File / New will by default save in the directory of the Edit window from -  which it was initiated.  SF 748973 Guido van Rossum patch. - - -What's New in IDLEfork 0.9b1? -============================= -*Release date: 02-Jun-2003* - -- The current working directory of the execution environment (and shell -  following completion of execution) is now that of the module being run. - -- Added the delete-exitfunc option to config-main.def.  (This option is not -  included in the Options dialog.)  Setting this to True (the default) will -  cause IDLE to not run sys.exitfunc/atexit when the subprocess exits. - -- IDLE now preserves the line ending codes when editing a file produced on -  a different platform. SF 661759,  SF 538584 - -- Reduced default editor font size to 10 point and increased window height -  to provide a better initial impression on Windows. - -- Options / Fonts/Tabs / Set Base Editor Font: List box was not highlighting -  the default font when first installed on Windows.  SF 661676 - -- Added Autosave feature: when user runs code from edit window, if the file -  has been modified IDLE will silently save it if Autosave is enabled.  The -  option is set in the Options dialog, and the default is to prompt the -  user to save the file.   SF 661318 Bruce Sherwood patch. - -- Improved the RESTART annotation in the shell window when the user restarts -  the shell while it is generating output.  Also improved annotation when user -  repeatedly hammers the Ctrl-F6 restart. - -- Allow IDLE to run when not installed and cwd is not the IDLE directory -  SF Patch 686254 "Run IDLEfork from any directory without set-up" - Raphael - -- When a module is run from an EditorWindow: if its directory is not in -  sys.path, prepend it.  This allows the module to import other modules in -  the same directory.  Do the same for a script run from the command line. - -- Correctly restart the subprocess if it is running user code and the user -  attempts to run some other module or restarts the shell.  Do the same if -  the link is broken and it is possible to restart the subprocess and re- -  connect to the GUI.   SF RFE 661321. - -- Improved exception reporting when running commands or scripts from the -  command line. - -- Added a -n command line switch to start IDLE without the subprocess. -  Removed the Shell menu when running in that mode.  Updated help messages. - -- Added a comment to the shell startup header to indicate when IDLE is not -  using the subprocess. - -- Restore the ability to run without the subprocess.  This can be important for -  some platforms or configurations.  (Running without the subprocess allows the -  debugger to trace through parts of IDLE itself, which may or may not be -  desirable, depending on your point of view.  In addition, the traditional -  reload/import tricks must be use if user source code is changed.)  This is -  helpful for developing IDLE using IDLE, because one instance can be used to -  edit the code and a separate instance run to test changes.  (Multiple -  concurrent IDLE instances with subprocesses is a future feature) - -- Improve the error message a user gets when saving a file with non-ASCII -  characters and no source encoding is specified.  Done by adding a dialog -  'EncodingMessage', which contains the line to add in a fixed-font entry -  widget, and which has a button to add that line to the file automatically. -  Also, add a configuration option 'EditorWindow/encoding', which has three -  possible values: none, utf-8, and locale. None is the default: IDLE will show -  this dialog when non-ASCII characters are encountered. utf-8 means that files -  with non-ASCII characters are saved as utf-8-with-bom. locale means that -  files are saved in the locale's encoding; the dialog is only displayed if the -  source contains characters outside the locale's charset.  SF 710733 - Loewis - -- Improved I/O response by tweaking the wait parameter in various -  calls to signal.signal(). - -- Implemented a threaded subprocess which allows interrupting a pass -  loop in user code using the 'interrupt' extension.  User code runs -  in MainThread, while the RPCServer is handled by SockThread.  This is -  necessary because Windows doesn't support signals. - -- Implemented the 'interrupt' extension module, which allows a subthread -  to raise a KeyboardInterrupt in the main thread. - -- Attempting to save the shell raised an error related to saving -  breakpoints, which are not implemented in the shell - -- Provide a correct message when 'exit' or 'quit' are entered at the -  IDLE command prompt  SF 695861 - -- Eliminate extra blank line in shell output caused by not flushing -  stdout when user code ends with an unterminated print. SF 695861 - -- Moved responsibility for exception formatting (i.e. pruning IDLE internal -  calls) out of rpc.py into the client and server. - -- Exit IDLE cleanly even when doing subprocess I/O - -- Handle subprocess interrupt with an RPC message. - -- Restart the subprocess if it terminates itself. (VPython programs do that) - -- Support subclassing of exceptions, including in the shell, by moving the -  exception formatting to the subprocess. - - -What's New in IDLEfork 0.9 Alpha 2? -=================================== -*Release date: 27-Jan-2003* - -- Updated INSTALL.txt to claify use of the python2 rpm. - -- Improved formatting in IDLE Help. - -- Run menu: Replace "Run Script" with "Run Module". - -- Code encountering an unhandled exception under the debugger now shows -  the correct traceback, with IDLE internal levels pruned out. - -- If an exception occurs entirely in IDLE, don't prune the IDLE internal -  modules from the traceback displayed. - -- Class Browser and Path Browser now use Alt-Key-2 for vertical zoom. - -- IDLE icons will now install correctly even when setup.py is run from the -  build directory - -- Class Browser now compatible with Python2.3 version of pyclbr.py - -- Left cursor move in presence of selected text now moves from left end -  of the selection. - -- Add Meta keybindings to "IDLE Classic Windows" to handle reversed -  Alt/Meta on some Linux distros. - -- Change default: IDLE now starts with Python Shell. - -- Removed the File Path from the Additional Help Sources scrolled list. - -- Add capability to access Additional Help Sources on the web if the -  Help File Path begins with //http or www.  (Otherwise local path is -  validated, as before.) - -- Additional Help Sources were not being posted on the Help menu in the -  order entered.  Implement sorting the list by [HelpFiles] 'option' -  number. - -- Add Browse button to New Help Source dialog.  Arrange to start in -  Python/Doc if platform is Windows, otherwise start in current directory. - -- Put the Additional Help Sources directly on the Help menu instead of in -  an Extra Help cascade menu.  Rearrange the Help menu so the Additional -  Help Sources come last.  Update help.txt appropriately. - -- Fix Tk root pop-ups in configSectionNameDialog.py  and configDialog.py - -- Uniform capitalization in General tab of ConfigDialog, update the doc string. - -- Fix bug in ConfigDialog where SaveAllChangedConfig() was unexpectedly -  deleting Additional Help Sources from the user's config file. - -- Make configHelpSourceEdit OK button the default and bind <Return> - -- Fix Tk root pop-ups in configHelpSourceEdit: error dialogs not attached -  to parents. - -- Use os.startfile() to open both Additional Help and Python Help on the -  Windows platform.  The application associated with the file type will act as -  the viewer.  Windows help files (.chm) are now supported via the -  Settings/General/Additional Help facility. - -- If Python Help files are installed locally on Linux, use them instead of -  accessing python.org. - -- Make the methods for finding the Python help docs more robust, and make -  them work in the installed configuration, also. - -- On the Save Before Run dialog, make the OK button the default.  One -  less mouse action! - -- Add a method: EditorWindow.get_geometry() for future use in implementing -  window location persistence. - -- Removed the "Help/Advice" menu entry.  Thanks, David!  We'll remember! - -- Change the "Classic Windows" theme's paste key to be <ctrl-v>. - -- Rearrange the Shell menu to put Stack Viewer entries adjacent. - -- Add the ability to restart the subprocess interpreter from the shell window; -  add an associated menu entry "Shell/Restart" with binding Control-F6.  Update -  IDLE help. - -- Upon a restart, annotate the shell window with a "restart boundary".  Add a -  shell window menu "Shell/View Restart" with binding F6 to jump to the most -  recent restart boundary. - -- Add Shell menu to Python Shell; change "Settings" to "Options". - -- Remove incorrect comment in setup.py: IDLEfork is now installed as a package. - -- Add INSTALL.txt, HISTORY.txt, NEWS.txt to installed configuration. - -- In installer text, fix reference to Visual Python, should be VPython. -  Properly credit David Scherer. - -- Modified idle, idle.py, idle.pyw to improve exception handling. - - -What's New in IDLEfork 0.9 Alpha 1? -=================================== -*Release date: 31-Dec-2002* - -- First release of major new functionality.  For further details refer to -  Idle-dev and/or the Sourceforge CVS. - -- Adapted to the Mac platform. - -- Overhauled the IDLE startup options and revised the idle -h help message, -  which provides details of command line usage. - -- Multiple bug fixes and usability enhancements. - -- Introduced the new RPC implementation, which includes a debugger.  The output -  of user code is to the shell, and the shell may be used to inspect the -  environment after the run has finished.  (In version 0.8.1 the shell -  environment was separate from the environment of the user code.) - -- Introduced the configuration GUI and a new About dialog. - -- Removed David Scherer's Remote Procedure Call code and replaced with Guido -  van Rossum's.  GvR code has support for the IDLE debugger and uses the shell -  to inspect the environment of code Run from an Edit window.  Files removed: -  ExecBinding.py, loader.py, protocol.py, Remote.py, spawn.py - --------------------------------------------------------------------- -Refer to HISTORY.txt for additional information on earlier releases. --------------------------------------------------------------------- +------------------------------------------------------------------------ +Refer to NEWS2x.txt and HISTORY.txt for information on earlier releases. +------------------------------------------------------------------------ diff --git a/Lib/idlelib/NEWS2x.txt b/Lib/idlelib/NEWS2x.txt new file mode 100644 index 0000000000..6751ca5f11 --- /dev/null +++ b/Lib/idlelib/NEWS2x.txt @@ -0,0 +1,660 @@ +What's New in IDLE 2.7? (Merged into 3.1 before 2.7 release.) +======================= +*Release date: XX-XXX-2010* + +- idle.py modified and simplified to better support developing experimental +  versions of IDLE which are not installed in the standard location. + +- 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 + +- 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. + +- 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 + +- IDLE would print a "Unhandled server exception!" message when internal +  debugging is enabled. + +- Issue #4455: IDLE failed to display the windows list when two windows have +  the same title. + +- Issue #4383: When IDLE cannot make the connection to its subprocess, it would +  fail to properly display the error message. + +- help() was not paging to the shell.  Issue1650. + +- CodeContext was not importing. + +- Corrected two 3.0 compatibility errors reported by Mark Summerfield: +  http://mail.python.org/pipermail/python-3000/2007-December/011491.html + +- Shell was not colorizing due to bug introduced at r57998,  Bug 1586. + +- Issue #1585: IDLE uses non-existent xrange() function. + +- Windows EOL sequence not converted correctly, encoding error. +  Caused file save to fail. Bug 1130. + +- IDLE converted to Python 3000 syntax. + +- Strings became Unicode. + +- CallTips module now uses the inspect module to produce the argspec. + +- IDLE modules now use absolute import instead of implied relative import. + +- atexit call replaces sys.exitfunc.  The functionality of delete-exitfunc flag +  in config-main.cfg remains unchanged: if set, registered exit functions will +  be cleared before IDLE exits. + + +What's New in IDLE 2.6 +====================== +*Release date: 01-Oct-2008*, merged into 3.0 releases detailed above (3.0rc2) + +- Issue #2665: On Windows, an IDLE installation upgraded from an old version +  would not start if a custom theme was defined. + +- Home / Control-A toggles between left margin and end of leading white +  space.  issue1196903, patch by Jeff Shute. + +- Improved AutoCompleteWindow logic.  issue2062, patch by Tal Einat. + +- Autocompletion of filenames now support alternate separators, e.g. the +  '/' char on Windows.  issue2061 Patch by Tal Einat. + +- Configured selection highlighting colors were ignored; updating highlighting +  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 + +- There was an error on exit if no sys.exitfunc was defined. Issue 1647. + +- Could not open files in .idlerc directory if latter was hidden on Windows. +  Issue 1743, Issue 1862. + +- Configure Dialog: improved layout for keybinding.  Patch 1457 Tal Einat. + +- tabpage.py updated: tabbedPages.py now supports multiple dynamic rows +  of tabs.  Patch 1612746 Tal Einat. + +- Add confirmation dialog before printing.  Patch 1717170 Tal Einat. + +- Show paste position if > 80 col.  Patch 1659326 Tal Einat. + +- Update cursor color without restarting.  Patch 1725576 Tal Einat. + +- Allow keyboard interrupt only when user code is executing in subprocess. +  Patch 1225 Tal Einat (reworked from IDLE-Spoon). + +- configDialog cleanup. Patch 1730217 Tal Einat. + +- textView cleanup. Patch 1718043 Tal Einat. + +- Clean up EditorWindow close. + +- Patch 1693258: Fix for duplicate "preferences" menu-OS X. Backport of r56204. + +- OSX: Avoid crash for those versions of Tcl/Tk which don't have a console + +- Bug in idlelib.MultiCall: Options dialog was crashing IDLE if there was an +  option in config-extensions w/o a value. Patch #1672481, Tal Einat + +- Corrected some bugs in AutoComplete.  Also, Page Up/Down in ACW implemented; +  mouse and cursor selection in ACWindow implemented; double Tab inserts +  current selection and closes ACW (similar to double-click and Return); scroll +  wheel now works in ACW.  Added AutoComplete instructions to IDLE Help. + +- AutoCompleteWindow moved below input line, will move above if there +  isn't enough space.  Patch 1621265 Tal Einat + +- Calltips now 'handle' tuples in the argument list (display '<tuple>' :) +  Suggested solution by Christos Georgiou, Bug 791968. + +- Add 'raw' support to configHandler. Patch 1650174 Tal Einat. + +- Avoid hang when encountering a duplicate in a completion list. Bug 1571112. + +- Patch #1362975: Rework CodeContext indentation algorithm to +  avoid hard-coding pixel widths. + +- Bug #813342: Start the IDLE subprocess with -Qnew if the parent +  is started with that option. + +- Honor the "Cancel" action in the save dialog (Debian bug #299092) + +- Some syntax errors were being caught by tokenize during the tabnanny +  check, resulting in obscure error messages.  Do the syntax check +  first.  Bug 1562716, 1562719 + +- IDLE's version number takes a big jump to match the version number of +  the Python release of which it's a part. + + +What's New in IDLE 1.2? +======================= +*Release date: 19-SEP-2006* + +- File menu hotkeys: there were three 'p' assignments.  Reassign the +  'Save Copy As' and 'Print' hotkeys to 'y' and 't'.  Change the +  Shell hotkey from 's' to 'l'. + +- IDLE honors new quit() and exit() commands from site.py Quitter() object. +  Patch 1540892, Jim Jewett + +- The 'with' statement is now a Code Context block opener. +  Patch 1540851, Jim Jewett + +- Retrieval of previous shell command was not always preserving indentation +  (since 1.2a1) Patch 1528468 Tal Einat. + +- Changing tokenize (39046) to detect dedent broke tabnanny check (since 1.2a1) + +- ToggleTab dialog was setting indent to 8 even if cancelled (since 1.2a1). + +- When used w/o subprocess, all exceptions were preceded by an error +  message claiming they were IDLE internal errors (since 1.2a1). + +- Bug #1525817: Don't truncate short lines in IDLE's tool tips. + +- Bug #1517990: IDLE keybindings on MacOS X now work correctly + +- Bug #1517996: IDLE now longer shows the default Tk menu when a +  path browser, class browser or debugger is the frontmost window on MacOS X + +- EditorWindow.test() was failing.  Bug 1417598 + +- EditorWindow failed when used stand-alone if sys.ps1 not set. +  Bug 1010370 Dave Florek + +- Tooltips failed on new-syle class __init__ args.  Bug 1027566 Loren Guthrie + +- Avoid occasional failure to detect closing paren properly. +  Patch 1407280 Tal Einat + +- Rebinding Tab key was inserting 'tab' instead of 'Tab'.  Bug 1179168. + +- Colorizer now handles #<builtin> correctly, also unicode strings and +  'as' keyword in comment directly following import command. Closes 1325071. +  Patch 1479219 Tal Einat + +- Patch #1162825: Support non-ASCII characters in IDLE window titles. + +- Source file f.flush() after writing; trying to avoid lossage if user +  kills GUI. + +- Options / Keys / Advanced dialog made functional.  Also, allow binding +  of 'movement' keys. + +- 'syntax' patch adds improved calltips and a new class attribute listbox. +  MultiCall module allows binding multiple actions to an event. +  Patch 906702 Noam Raphael + +- Better indentation after first line of string continuation. +  IDLEfork Patch 681992, Noam Raphael + +- Fixed CodeContext alignment problem, following suggestion from Tal Einat. + +- Increased performance in CodeContext extension  Patch 936169 Noam Raphael + +- Mac line endings were incorrect when pasting code from some browsers +  when using X11 and the Fink distribution.  Python Bug 1263656. + +- <Enter> when cursor is on a previous command retrieves that command.  Instead +  of replacing the input line, the previous command is now appended to the +  input line. Indentation is preserved, and undo is enabled. +  Patch 1196917  Jeff Shute + +- Clarify "tab/space" Error Dialog and "Tab Width" Dialog associated with +  the Untabify command. + +- Corrected "tab/space" Error Dialog to show correct menu for Untabify. +  Patch 1196980 Jeff Shute + +- New files are colorized by default, and colorizing is removed when +  saving as non-Python files. Patch 1196895 Jeff Shute +  Closes Python Bugs 775012 and 800432, partial fix IDLEfork 763524 + +- Improve subprocess link error notification. + +- run.py: use Queue's blocking feature instead of sleeping in the main +  loop.  Patch # 1190163 Michiel de Hoon + +- Add config-main option to make the 'history' feature non-cyclic. +  Default remains cyclic.  Python Patch 914546 Noam Raphael. + +- Removed ability to configure tabs indent from Options dialog.  This 'feature' +  has never worked and no one has complained.  It is still possible to set a +  default tabs (v. spaces) indent 'manually' via config-main.def (or to turn on +  tabs for the current EditorWindow via the Format menu) but IDLE will +  encourage indentation via spaces. + +- Enable setting the indentation width using the Options dialog. +  Bug # 783877 + +- Add keybindings for del-word-left and del-word-right. + +- Discourage using an indent width other than 8 when using tabs to indent +  Python code. + +- Restore use of EditorWindow.set_indentation_params(), was dead code since +  Autoindent was merged into EditorWindow.  This allows IDLE to conform to the +  indentation width of a loaded file.  (But it still will not switch to tabs +  even if the file uses tabs.)  Any change in indent width is local to that +  window. + +- Add Tabnanny check before Run/F5, not just when Checking module. + +- If an extension can't be loaded, print warning and skip it instead of +  erroring out. + +- Improve error handling when .idlerc can't be created (warn and exit). + +- The GUI was hanging if the shell window was closed while a raw_input() +  was pending.  Restored the quit() of the readline() mainloop(). +  http://mail.python.org/pipermail/idle-dev/2004-December/002307.html + +- The remote procedure call module rpc.py can now access data attributes of +  remote registered objects.  Changes to these attributes are local, however. + + +What's New in IDLE 1.1? +======================= +*Release date: 30-NOV-2004* + +- On OpenBSD, terminating IDLE with ctrl-c from the command line caused a +  stuck subprocess MainThread because only the SocketThread was exiting. + +- Saving a Keyset w/o making changes (by using the "Save as New Custom Key Set" +  button) caused IDLE to fail on restart (no new keyset was created in +  config-keys.cfg).  Also true for Theme/highlights.  Python Bug 1064535. + +- A change to the linecache.py API caused IDLE to exit when an exception was +  raised while running without the subprocess (-n switch).  Python Bug 1063840. + +- When paragraph reformat width was made configurable, a bug was +  introduced that caused reformatting of comment blocks to ignore how +  far the block was indented, effectively adding the indentation width +  to the reformat width.  This has been repaired, and the reformat +  width is again a bound on the total width of reformatted lines. + +- Improve keyboard focus binding, especially in Windows menu.  Improve +  window raising, especially in the Windows menu and in the debugger. +  IDLEfork 763524. + +- If user passes a non-existent filename on the commandline, just +  open a new file, don't raise a dialog.  IDLEfork 854928. + +- EditorWindow.py was not finding the .chm help file on Windows.  Typo +  at Rev 1.54.  Python Bug 990954 + +- checking sys.platform for substring 'win' was breaking IDLE docs on Mac +  (darwin).  Also, Mac Safari browser requires full file:// URIs.  SF 900580. + +- Redirect the warning stream to the shell during the ScriptBinding check of +  user code and format the warning similarly to an exception for both that +  check and for runtime warnings raised in the subprocess. + +- CodeContext hint pane visibility state is now persistent across sessions. +  The pane no longer appears in the shell window.  Added capability to limit +  extensions to shell window or editor windows.  Noam Raphael addition +  to Patch 936169. + +- Paragraph reformat width is now a configurable parameter in the +  Options GUI. + +- New Extension: CodeContext.  Provides block structuring hints for code +  which has scrolled above an edit window. Patch 936169 Noam Raphael. + +- If nulls somehow got into the strings in recent-files.lst +  EditorWindow.update_recent_files_list() was failing.  Python Bug 931336. + +- If the normal background is changed via Configure/Highlighting, it will +  update immediately, thanks to the previously mentioned patch by Nigel Rowe. + +- Add a highlight theme for builtin keywords.  Python Patch 805830 Nigel Rowe +  This also fixed IDLEfork bug [ 693418 ] Normal text background color not +  refreshed and Python bug [897872 ] Unknown color name on HP-UX + +- rpc.py:SocketIO - Large modules were generating large pickles when downloaded +  to the execution server.  The return of the OK response from the subprocess +  initialization was interfering and causing the sending socket to be not +  ready.  Add an IO ready test to fix this.  Moved the polling IO ready test +  into pollpacket(). + +- Fix typo in rpc.py, s/b "pickle.PicklingError" not "pickle.UnpicklingError". + +- Added a Tk error dialog to run.py inform the user if the subprocess can't +  connect to the user GUI process.  Added a timeout to the GUI's listening +  socket.  Added Tk error dialogs to PyShell.py to announce a failure to bind +  the port or connect to the subprocess.  Clean up error handling during +  connection initiation phase.  This is an update of Python Patch 778323. + +- Print correct exception even if source file changed since shell was +  restarted.  IDLEfork Patch 869012 Noam Raphael + +- Keybindings with the Shift modifier now work correctly.  So do bindings which +  use the Space key.  Limit unmodified user keybindings to the function keys. +  Python Bug 775353, IDLEfork Bugs 755647, 761557 + +- After an exception, run.py was not setting the exception vector. Noam +  Raphael suggested correcting this so pdb's postmortem pm() would work. +  IDLEfork Patch 844675 + +- IDLE now does not fail to save the file anymore if the Tk buffer is not a +  Unicode string, yet eol_convention is.  Python Bugs 774680, 788378 + +- IDLE didn't start correctly when Python was installed in "Program Files" on +  W2K and XP.  Python Bugs 780451, 784183 + +- config-main.def documentation incorrectly referred to idle- instead of +  config-  filenames.  SF 782759  Also added note about .idlerc location. + + +What's New in IDLE 1.0? +======================= +*Release date: 29-Jul-2003* + +- Added a banner to the shell discussing warnings possibly raised by personal +  firewall software.  Added same comment to README.txt. + +- Calltip error when docstring was None  Python Bug 775541 + +- Updated extend.txt, help.txt, and config-extensions.def to correctly +  reflect the current status of the configuration system.  Python Bug 768469 + +- Fixed: Call Tip Trimming May Loop Forever. Python Patch 769142 (Daniels) + +- Replaced apply(f, args, kwds) with f(*args, **kwargs) to improve performance +  Python Patch 768187 + +- Break or continue statements outside a loop were causing IDLE crash +  Python Bug 767794 + +- Convert Unicode strings from readline to IOBinding.encoding.  Also set +  sys.std{in|out|err}.encoding, for both the local and the subprocess case. +  SF IDLEfork patch 682347. + +- Extend AboutDialog.ViewFile() to support file encodings.  Make the CREDITS +  file Latin-1. + +- Updated the About dialog to reflect re-integration into Python.  Provide +  buttons to display Python's NEWS, License, and Credits, plus additional +  buttons for IDLE's README and NEWS. + +- TextViewer() now has a third parameter which allows inserting text into the +  viewer instead of reading from a file. + +- (Created the .../Lib/idlelib directory in the Python CVS, which is a clone of +  IDLEfork modified to install in the Python environment.  The code in the +  interrupt module has been moved to thread.interrupt_main(). ) + +- Printing the Shell window was failing if it was not saved first SF 748975 + +- When using the Search in Files dialog, if the user had a selection +  highlighted in his Editor window, insert it into the dialog search field. + +- The Python Shell entry was disappearing from the Windows menu. + +- Update the Windows file list when a file name change occurs + +- Change to File / Open Module: always pop up the dialog, using the current +  selection as the default value.  This is easier to use habitually. + +- Avoided a problem with starting the subprocess when 'localhost' doesn't +  resolve to the user's loopback interface.  SF 747772 + +- Fixed an issue with highlighted errors never de-colorizing.  SF 747677.  Also +  improved notification of Tabnanny Token Error. + +- File / New will by default save in the directory of the Edit window from +  which it was initiated.  SF 748973 Guido van Rossum patch. + + +What's New in IDLEfork 0.9b1? +============================= +*Release date: 02-Jun-2003* + +- The current working directory of the execution environment (and shell +  following completion of execution) is now that of the module being run. + +- Added the delete-exitfunc option to config-main.def.  (This option is not +  included in the Options dialog.)  Setting this to True (the default) will +  cause IDLE to not run sys.exitfunc/atexit when the subprocess exits. + +- IDLE now preserves the line ending codes when editing a file produced on +  a different platform. SF 661759,  SF 538584 + +- Reduced default editor font size to 10 point and increased window height +  to provide a better initial impression on Windows. + +- Options / Fonts/Tabs / Set Base Editor Font: List box was not highlighting +  the default font when first installed on Windows.  SF 661676 + +- Added Autosave feature: when user runs code from edit window, if the file +  has been modified IDLE will silently save it if Autosave is enabled.  The +  option is set in the Options dialog, and the default is to prompt the +  user to save the file.   SF 661318 Bruce Sherwood patch. + +- Improved the RESTART annotation in the shell window when the user restarts +  the shell while it is generating output.  Also improved annotation when user +  repeatedly hammers the Ctrl-F6 restart. + +- Allow IDLE to run when not installed and cwd is not the IDLE directory +  SF Patch 686254 "Run IDLEfork from any directory without set-up" - Raphael + +- When a module is run from an EditorWindow: if its directory is not in +  sys.path, prepend it.  This allows the module to import other modules in +  the same directory.  Do the same for a script run from the command line. + +- Correctly restart the subprocess if it is running user code and the user +  attempts to run some other module or restarts the shell.  Do the same if +  the link is broken and it is possible to restart the subprocess and re- +  connect to the GUI.   SF RFE 661321. + +- Improved exception reporting when running commands or scripts from the +  command line. + +- Added a -n command line switch to start IDLE without the subprocess. +  Removed the Shell menu when running in that mode.  Updated help messages. + +- Added a comment to the shell startup header to indicate when IDLE is not +  using the subprocess. + +- Restore the ability to run without the subprocess.  This can be important for +  some platforms or configurations.  (Running without the subprocess allows the +  debugger to trace through parts of IDLE itself, which may or may not be +  desirable, depending on your point of view.  In addition, the traditional +  reload/import tricks must be use if user source code is changed.)  This is +  helpful for developing IDLE using IDLE, because one instance can be used to +  edit the code and a separate instance run to test changes.  (Multiple +  concurrent IDLE instances with subprocesses is a future feature) + +- Improve the error message a user gets when saving a file with non-ASCII +  characters and no source encoding is specified.  Done by adding a dialog +  'EncodingMessage', which contains the line to add in a fixed-font entry +  widget, and which has a button to add that line to the file automatically. +  Also, add a configuration option 'EditorWindow/encoding', which has three +  possible values: none, utf-8, and locale. None is the default: IDLE will show +  this dialog when non-ASCII characters are encountered. utf-8 means that files +  with non-ASCII characters are saved as utf-8-with-bom. locale means that +  files are saved in the locale's encoding; the dialog is only displayed if the +  source contains characters outside the locale's charset.  SF 710733 - Loewis + +- Improved I/O response by tweaking the wait parameter in various +  calls to signal.signal(). + +- Implemented a threaded subprocess which allows interrupting a pass +  loop in user code using the 'interrupt' extension.  User code runs +  in MainThread, while the RPCServer is handled by SockThread.  This is +  necessary because Windows doesn't support signals. + +- Implemented the 'interrupt' extension module, which allows a subthread +  to raise a KeyboardInterrupt in the main thread. + +- Attempting to save the shell raised an error related to saving +  breakpoints, which are not implemented in the shell + +- Provide a correct message when 'exit' or 'quit' are entered at the +  IDLE command prompt  SF 695861 + +- Eliminate extra blank line in shell output caused by not flushing +  stdout when user code ends with an unterminated print. SF 695861 + +- Moved responsibility for exception formatting (i.e. pruning IDLE internal +  calls) out of rpc.py into the client and server. + +- Exit IDLE cleanly even when doing subprocess I/O + +- Handle subprocess interrupt with an RPC message. + +- Restart the subprocess if it terminates itself. (VPython programs do that) + +- Support subclassing of exceptions, including in the shell, by moving the +  exception formatting to the subprocess. + + +What's New in IDLEfork 0.9 Alpha 2? +=================================== +*Release date: 27-Jan-2003* + +- Updated INSTALL.txt to claify use of the python2 rpm. + +- Improved formatting in IDLE Help. + +- Run menu: Replace "Run Script" with "Run Module". + +- Code encountering an unhandled exception under the debugger now shows +  the correct traceback, with IDLE internal levels pruned out. + +- If an exception occurs entirely in IDLE, don't prune the IDLE internal +  modules from the traceback displayed. + +- Class Browser and Path Browser now use Alt-Key-2 for vertical zoom. + +- IDLE icons will now install correctly even when setup.py is run from the +  build directory + +- Class Browser now compatible with Python2.3 version of pyclbr.py + +- Left cursor move in presence of selected text now moves from left end +  of the selection. + +- Add Meta keybindings to "IDLE Classic Windows" to handle reversed +  Alt/Meta on some Linux distros. + +- Change default: IDLE now starts with Python Shell. + +- Removed the File Path from the Additional Help Sources scrolled list. + +- Add capability to access Additional Help Sources on the web if the +  Help File Path begins with //http or www.  (Otherwise local path is +  validated, as before.) + +- Additional Help Sources were not being posted on the Help menu in the +  order entered.  Implement sorting the list by [HelpFiles] 'option' +  number. + +- Add Browse button to New Help Source dialog.  Arrange to start in +  Python/Doc if platform is Windows, otherwise start in current directory. + +- Put the Additional Help Sources directly on the Help menu instead of in +  an Extra Help cascade menu.  Rearrange the Help menu so the Additional +  Help Sources come last.  Update help.txt appropriately. + +- Fix Tk root pop-ups in configSectionNameDialog.py  and configDialog.py + +- Uniform capitalization in General tab of ConfigDialog, update the doc string. + +- Fix bug in ConfigDialog where SaveAllChangedConfig() was unexpectedly +  deleting Additional Help Sources from the user's config file. + +- Make configHelpSourceEdit OK button the default and bind <Return> + +- Fix Tk root pop-ups in configHelpSourceEdit: error dialogs not attached +  to parents. + +- Use os.startfile() to open both Additional Help and Python Help on the +  Windows platform.  The application associated with the file type will act as +  the viewer.  Windows help files (.chm) are now supported via the +  Settings/General/Additional Help facility. + +- If Python Help files are installed locally on Linux, use them instead of +  accessing python.org. + +- Make the methods for finding the Python help docs more robust, and make +  them work in the installed configuration, also. + +- On the Save Before Run dialog, make the OK button the default.  One +  less mouse action! + +- Add a method: EditorWindow.get_geometry() for future use in implementing +  window location persistence. + +- Removed the "Help/Advice" menu entry.  Thanks, David!  We'll remember! + +- Change the "Classic Windows" theme's paste key to be <ctrl-v>. + +- Rearrange the Shell menu to put Stack Viewer entries adjacent. + +- Add the ability to restart the subprocess interpreter from the shell window; +  add an associated menu entry "Shell/Restart" with binding Control-F6.  Update +  IDLE help. + +- Upon a restart, annotate the shell window with a "restart boundary".  Add a +  shell window menu "Shell/View Restart" with binding F6 to jump to the most +  recent restart boundary. + +- Add Shell menu to Python Shell; change "Settings" to "Options". + +- Remove incorrect comment in setup.py: IDLEfork is now installed as a package. + +- Add INSTALL.txt, HISTORY.txt, NEWS.txt to installed configuration. + +- In installer text, fix reference to Visual Python, should be VPython. +  Properly credit David Scherer. + +- Modified idle, idle.py, idle.pyw to improve exception handling. + + +What's New in IDLEfork 0.9 Alpha 1? +=================================== +*Release date: 31-Dec-2002* + +- First release of major new functionality.  For further details refer to +  Idle-dev and/or the Sourceforge CVS. + +- Adapted to the Mac platform. + +- Overhauled the IDLE startup options and revised the idle -h help message, +  which provides details of command line usage. + +- Multiple bug fixes and usability enhancements. + +- Introduced the new RPC implementation, which includes a debugger.  The output +  of user code is to the shell, and the shell may be used to inspect the +  environment after the run has finished.  (In version 0.8.1 the shell +  environment was separate from the environment of the user code.) + +- Introduced the configuration GUI and a new About dialog. + +- Removed David Scherer's Remote Procedure Call code and replaced with Guido +  van Rossum's.  GvR code has support for the IDLE debugger and uses the shell +  to inspect the environment of code Run from an Edit window.  Files removed: +  ExecBinding.py, loader.py, protocol.py, Remote.py, spawn.py + +-------------------------------------------------------------------- +Refer to HISTORY.txt for additional information on earlier releases. +-------------------------------------------------------------------- diff --git a/Lib/idlelib/ParenMatch.py b/Lib/idlelib/ParenMatch.py index 19bad8ce38..47e10f3517 100644 --- a/Lib/idlelib/ParenMatch.py +++ b/Lib/idlelib/ParenMatch.py @@ -9,7 +9,7 @@ from idlelib.HyperParser import HyperParser  from idlelib.configHandler import idleConf  _openers = {')':'(',']':'[','}':'{'} -CHECK_DELAY = 100 # miliseconds +CHECK_DELAY = 100 # milliseconds  class ParenMatch:      """Highlight matching parentheses diff --git a/Lib/idlelib/Percolator.py b/Lib/idlelib/Percolator.py index 9e9331940f..b8be2aa746 100644 --- a/Lib/idlelib/Percolator.py +++ b/Lib/idlelib/Percolator.py @@ -1,6 +1,7 @@  from idlelib.WidgetRedirector import WidgetRedirector  from idlelib.Delegator import Delegator +  class Percolator:      def __init__(self, text): @@ -16,8 +17,10 @@ class Percolator:          while self.top is not self.bottom:              self.removefilter(self.top)          self.top = None -        self.bottom.setdelegate(None); self.bottom = None -        self.redir.close(); self.redir = None +        self.bottom.setdelegate(None) +        self.bottom = None +        self.redir.close() +        self.redir = None          self.text = None      def insert(self, index, chars, tags=None): @@ -51,54 +54,52 @@ class Percolator:              f.setdelegate(filter.delegate)              filter.setdelegate(None) -def _percolator(parent): + +def _percolator(parent):  # htest #      import tkinter as tk      import re +      class Tracer(Delegator):          def __init__(self, name):              self.name = name              Delegator.__init__(self, None) +          def insert(self, *args):              print(self.name, ": insert", args)              self.delegate.insert(*args) +          def delete(self, *args):              print(self.name, ": delete", args)              self.delegate.delete(*args) -    root = tk.Tk() -    root.title("Test Percolator") + +    box = tk.Toplevel(parent) +    box.title("Test Percolator")      width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) -    root.geometry("+%d+%d"%(x, y + 150)) -    text = tk.Text(root) +    box.geometry("+%d+%d" % (x, y + 150)) +    text = tk.Text(box)      p = Percolator(text) +    pin = p.insertfilter +    pout = p.removefilter      t1 = Tracer("t1")      t2 = Tracer("t2")      def toggle1(): -        if var1.get() == 0: -            var1.set(1) -            p.insertfilter(t1) -        elif var1.get() == 1: -            var1.set(0) -            p.removefilter(t1) - +        (pin if var1.get() else pout)(t1)      def toggle2(): -        if var2.get() == 0: -            var2.set(1) -            p.insertfilter(t2) -        elif var2.get() == 1: -            var2.set(0) -            p.removefilter(t2) +        (pin if var2.get() else pout)(t2)      text.pack()      var1 = tk.IntVar() -    cb1 = tk.Checkbutton(root, text="Tracer1", command=toggle1, variable=var1) +    cb1 = tk.Checkbutton(box, text="Tracer1", command=toggle1, variable=var1)      cb1.pack()      var2 = tk.IntVar() -    cb2 = tk.Checkbutton(root, text="Tracer2", command=toggle2, variable=var2) +    cb2 = tk.Checkbutton(box, text="Tracer2", command=toggle2, variable=var2)      cb2.pack() -    root.mainloop() -  if __name__ == "__main__": +    import unittest +    unittest.main('idlelib.idle_test.test_percolator', verbosity=2, +                  exit=False) +      from idlelib.idle_test.htest import run      run(_percolator) diff --git a/Lib/idlelib/PyShell.py b/Lib/idlelib/PyShell.py index 1bcc9b6814..5dec68e580 100755 --- a/Lib/idlelib/PyShell.py +++ b/Lib/idlelib/PyShell.py @@ -1396,6 +1396,17 @@ class PseudoInputFile(PseudoFile):          self.shell.close() +def fix_x11_paste(root): +    "Make paste replace selection on x11.  See issue #5124." +    if root._windowingsystem == 'x11': +        for cls in 'Text', 'Entry', 'Spinbox': +            root.bind_class( +                cls, +                '<<Paste>>', +                'catch {%W delete sel.first sel.last}\n' + +                        root.bind_class(cls, '<<Paste>>')) + +  usage_msg = """\  USAGE: idle  [-deins] [-t title] [file]* @@ -1528,8 +1539,10 @@ def main():                                      'editor-on-startup', type='bool')      enable_edit = enable_edit or edit_start      enable_shell = enable_shell or not enable_edit +      # start editor and/or shell windows:      root = Tk(className="Idle") +    root.withdraw()      # set application icon      icondir = os.path.join(os.path.dirname(__file__), 'Icons') @@ -1544,7 +1557,7 @@ def main():          root.wm_iconphoto(True, *icons)      fixwordbreaks(root) -    root.withdraw() +    fix_x11_paste(root)      flist = PyShellFileList(root)      macosxSupport.setupApp(root, flist) diff --git a/Lib/idlelib/README.txt b/Lib/idlelib/README.txt index 7bf74c0fc4..ff4450495a 100644 --- a/Lib/idlelib/README.txt +++ b/Lib/idlelib/README.txt @@ -16,7 +16,7 @@ and omissions and lag behind changes in idlelib.  IDLELIB FILES -Implemetation files not in IDLE MENU are marked (nim). +Implementation files not in IDLE MENU are marked (nim).  Deprecated files and objects are listed separately as the end.  Startup @@ -161,14 +161,15 @@ Edit    Show surrounding parens  # ParenMatch (& Hyperparser)  Shell  # PyShell -  View Last Restart  # PyShell.? -  Restart Shell  # PyShell.? +  View Last Restart    # PyShell.PyShell.view_restart_mark +  Restart Shell        # PyShell.PyShell.restart_shell +  Interrupt Execution  # pyshell.PyShell.cancel_callback  Debug (Shell only)    Go to File/Line -  Debugger  # Debugger, RemoteDebugger -  Stack Viewer  # StackViewer -  Auto-open Stack Viewer  # StackViewer +  Debugger               # Debugger, RemoteDebugger, PyShell.toggle_debuger +  Stack Viewer           # StackViewer, PyShell.open_stack_viewer +  Auto-open Stack Viewer # StackViewer  Format (Editor only)    Indent Region diff --git a/Lib/idlelib/ReplaceDialog.py b/Lib/idlelib/ReplaceDialog.py index 2665a1c630..f2ea22e7f7 100644 --- a/Lib/idlelib/ReplaceDialog.py +++ b/Lib/idlelib/ReplaceDialog.py @@ -1,3 +1,8 @@ +"""Replace dialog for IDLE. Inherits SearchDialogBase for GUI. +Uses idlelib.SearchEngine for search capability. +Defines various replace related functions like replace, replace all, +replace+find. +"""  from tkinter import *  from idlelib import SearchEngine @@ -6,6 +11,8 @@ import re  def replace(text): +    """Returns a singleton ReplaceDialog instance.The single dialog +     saves user entries and preferences across instances."""      root = text._root()      engine = SearchEngine.get(root)      if not hasattr(engine, "_replacedialog"): @@ -24,6 +31,7 @@ class ReplaceDialog(SearchDialogBase):          self.replvar = StringVar(root)      def open(self, text): +        """Display the replace dialog"""          SearchDialogBase.open(self, text)          try:              first = text.index("sel.first") @@ -39,6 +47,7 @@ class ReplaceDialog(SearchDialogBase):          self.ok = 1      def create_entries(self): +        """Create label and text entry widgets"""          SearchDialogBase.create_entries(self)          self.replent = self.make_entry("Replace with:", self.replvar)[0] @@ -57,9 +66,10 @@ class ReplaceDialog(SearchDialogBase):              self.do_replace()      def default_command(self, event=None): +        "Replace and find next."          if self.do_find(self.ok): -            if self.do_replace():   # Only find next match if replace succeeded. -                                    # A bad re can cause it to fail. +            if self.do_replace():  # Only find next match if replace succeeded. +                                   # A bad re can cause it to fail.                  self.do_find(0)      def _replace_expand(self, m, repl): @@ -77,6 +87,7 @@ class ReplaceDialog(SearchDialogBase):          return new      def replace_all(self, event=None): +        """Replace all instances of patvar with replvar in text"""          prog = self.engine.getprog()          if not prog:              return @@ -173,6 +184,8 @@ class ReplaceDialog(SearchDialogBase):          return True      def show_hit(self, first, last): +        """Highlight text from 'first' to 'last'. +        'first', 'last' - Text indices"""          text = self.text          text.mark_set("insert", first)          text.tag_remove("sel", "1.0", "end") @@ -189,11 +202,13 @@ class ReplaceDialog(SearchDialogBase):          SearchDialogBase.close(self, event)          self.text.tag_remove("hit", "1.0", "end") -def _replace_dialog(parent): -    root = Tk() -    root.title("Test ReplaceDialog") + +def _replace_dialog(parent):  # htest # +    """htest wrapper function""" +    box = Toplevel(parent) +    box.title("Test ReplaceDialog")      width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) -    root.geometry("+%d+%d"%(x, y + 150)) +    box.geometry("+%d+%d"%(x, y + 150))      # mock undo delegator methods      def undo_block_start(): @@ -202,20 +217,25 @@ def _replace_dialog(parent):      def undo_block_stop():          pass -    text = Text(root) +    text = Text(box, inactiveselectbackground='gray')      text.undo_block_start = undo_block_start      text.undo_block_stop = undo_block_stop      text.pack() -    text.insert("insert","This is a sample string.\n"*10) +    text.insert("insert","This is a sample sTring\nPlus MORE.") +    text.focus_set()      def show_replace():          text.tag_add(SEL, "1.0", END)          replace(text)          text.tag_remove(SEL, "1.0", END) -    button = Button(root, text="Replace", command=show_replace) +    button = Button(box, text="Replace", command=show_replace)      button.pack()  if __name__ == '__main__': +    import unittest +    unittest.main('idlelib.idle_test.test_replacedialog', +                verbosity=2, exit=False) +      from idlelib.idle_test.htest import run      run(_replace_dialog) diff --git a/Lib/idlelib/SearchDialog.py b/Lib/idlelib/SearchDialog.py index 77ef7b9a82..765d53fe92 100644 --- a/Lib/idlelib/SearchDialog.py +++ b/Lib/idlelib/SearchDialog.py @@ -4,6 +4,7 @@ from idlelib import SearchEngine  from idlelib.SearchDialogBase import SearchDialogBase  def _setup(text): +    "Create or find the singleton SearchDialog instance."      root = text._root()      engine = SearchEngine.get(root)      if not hasattr(engine, "_searchdialog"): @@ -11,13 +12,16 @@ def _setup(text):      return engine._searchdialog  def find(text): +    "Handle the editor edit menu item and corresponding event."      pat = text.get("sel.first", "sel.last") -    return _setup(text).open(text,pat) +    return _setup(text).open(text, pat)  # Open is inherited from SDBase.  def find_again(text): +    "Handle the editor edit menu item and corresponding event."      return _setup(text).find_again(text)  def find_selection(text): +    "Handle the editor edit menu item and corresponding event."      return _setup(text).find_selection(text)  class SearchDialog(SearchDialogBase): @@ -66,24 +70,28 @@ class SearchDialog(SearchDialogBase):              self.engine.setcookedpat(pat)          return self.find_again(text) -def _search_dialog(parent): -    root = Tk() -    root.title("Test SearchDialog") + +def _search_dialog(parent):  # htest # +    '''Display search test box.''' +    box = Toplevel(parent) +    box.title("Test SearchDialog")      width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) -    root.geometry("+%d+%d"%(x, y + 150)) -    text = Text(root) +    box.geometry("+%d+%d"%(x, y + 150)) +    text = Text(box, inactiveselectbackground='gray')      text.pack() -    text.insert("insert","This is a sample string.\n"*10) +    text.insert("insert","This is a sample string.\n"*5)      def show_find():          text.tag_add(SEL, "1.0", END) -        s = _setup(text) -        s.open(text) +        _setup(text).open(text)          text.tag_remove(SEL, "1.0", END) -    button = Button(root, text="Search", command=show_find) +    button = Button(box, text="Search (selection ignored)", command=show_find)      button.pack()  if __name__ == '__main__': +    import unittest +    unittest.main('idlelib.idle_test.test_searchdialog', +                  verbosity=2, exit=False)      from idlelib.idle_test.htest import run      run(_search_dialog) diff --git a/Lib/idlelib/UndoDelegator.py b/Lib/idlelib/UndoDelegator.py index 04c1cf5a27..1c2502d818 100644 --- a/Lib/idlelib/UndoDelegator.py +++ b/Lib/idlelib/UndoDelegator.py @@ -336,30 +336,33 @@ class CommandSequence(Command):          self.depth = self.depth + incr          return self.depth -def _undo_delegator(parent): + +def _undo_delegator(parent):  # htest # +    import re +    import tkinter as tk      from idlelib.Percolator import Percolator -    root = Tk() -    root.title("Test UndoDelegator") +    undowin = tk.Toplevel() +    undowin.title("Test UndoDelegator")      width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) -    root.geometry("+%d+%d"%(x, y + 150)) +    undowin.geometry("+%d+%d"%(x, y + 150)) -    text = Text(root) -    text.config(height=10) +    text = Text(undowin, height=10)      text.pack()      text.focus_set()      p = Percolator(text)      d = UndoDelegator()      p.insertfilter(d) -    undo = Button(root, text="Undo", command=lambda:d.undo_event(None)) +    undo = Button(undowin, text="Undo", command=lambda:d.undo_event(None))      undo.pack(side='left') -    redo = Button(root, text="Redo", command=lambda:d.redo_event(None)) +    redo = Button(undowin, text="Redo", command=lambda:d.redo_event(None))      redo.pack(side='left') -    dump = Button(root, text="Dump", command=lambda:d.dump_event(None)) +    dump = Button(undowin, text="Dump", command=lambda:d.dump_event(None))      dump.pack(side='left') -    root.mainloop() -  if __name__ == "__main__": +    import unittest +    unittest.main('idlelib.idle_test.test_undodelegator', verbosity=2, +                  exit=False)      from idlelib.idle_test.htest import run      run(_undo_delegator) diff --git a/Lib/idlelib/WidgetRedirector.py b/Lib/idlelib/WidgetRedirector.py index b3d7bfa3c4..b66be9e721 100644 --- a/Lib/idlelib/WidgetRedirector.py +++ b/Lib/idlelib/WidgetRedirector.py @@ -47,8 +47,9 @@ class WidgetRedirector:          tk.createcommand(w, self.dispatch)      def __repr__(self): -        return "WidgetRedirector(%s<%s>)" % (self.widget.__class__.__name__, -                                             self.widget._w) +        return "%s(%s<%s>)" % (self.__class__.__name__, +                               self.widget.__class__.__name__, +                               self.widget._w)      def close(self):          "Unregister operations and revert redirection created by .__init__." @@ -67,7 +68,7 @@ class WidgetRedirector:          '''Return OriginalCommand(operation) after registering function.          Registration adds an operation: function pair to ._operations. -        It also adds an widget function attribute that masks the tkinter +        It also adds a widget function attribute that masks the tkinter          class instance method.  Method masking operates independently          from command dispatch. @@ -142,7 +143,8 @@ class OriginalCommand:          self.orig_and_operation = (redir.orig, operation)      def __repr__(self): -        return "OriginalCommand(%r, %r)" % (self.redir, self.operation) +        return "%s(%r, %r)" % (self.__class__.__name__, +                               self.redir, self.operation)      def __call__(self, *args):          return self.tk_call(self.orig_and_operation + args) diff --git a/Lib/idlelib/aboutDialog.py b/Lib/idlelib/aboutDialog.py index d876a97115..a8f75d2537 100644 --- a/Lib/idlelib/aboutDialog.py +++ b/Lib/idlelib/aboutDialog.py @@ -111,6 +111,7 @@ class AboutDialog(Toplevel):                                  command=self.ShowIDLECredits)          idle_credits_b.pack(side=LEFT, padx=10, pady=10) +    # License, et all, are of type _sitebuiltins._Printer      def ShowLicense(self):          self.display_printer_text('About - License', license) @@ -120,14 +121,16 @@ class AboutDialog(Toplevel):      def ShowPythonCredits(self):          self.display_printer_text('About - Python Credits', credits) +    # Encode CREDITS.txt to utf-8 for proper version of Loewis. +    # Specify others as ascii until need utf-8, so catch errors.      def ShowIDLECredits(self): -        self.display_file_text('About - Credits', 'CREDITS.txt', 'iso-8859-1') +        self.display_file_text('About - Credits', 'CREDITS.txt', 'utf-8')      def ShowIDLEAbout(self): -        self.display_file_text('About - Readme', 'README.txt') +        self.display_file_text('About - Readme', 'README.txt', 'ascii')      def ShowIDLENEWS(self): -        self.display_file_text('About - NEWS', 'NEWS.txt') +        self.display_file_text('About - NEWS', 'NEWS.txt', 'utf-8')      def display_printer_text(self, title, printer):          printer._Printer__setup() @@ -142,5 +145,7 @@ class AboutDialog(Toplevel):          self.destroy()  if __name__ == '__main__': +    import unittest +    unittest.main('idlelib.idle_test.test_helpabout', verbosity=2, exit=False)      from idlelib.idle_test.htest import run      run(AboutDialog) diff --git a/Lib/idlelib/configDialog.py b/Lib/idlelib/configDialog.py index 9b16459d54..5f5bd36f8a 100644 --- a/Lib/idlelib/configDialog.py +++ b/Lib/idlelib/configDialog.py @@ -483,6 +483,17 @@ class ConfigDialog(Toplevel):          self.autoSave.trace_variable('w', self.VarChanged_autoSave)          self.encoding.trace_variable('w', self.VarChanged_encoding) +    def remove_var_callbacks(self): +        "Remove callbacks to prevent memory leaks." +        for var in ( +                self.fontSize, self.fontName, self.fontBold, +                self.spaceNum, self.colour, self.builtinTheme, +                self.customTheme, self.themeIsBuiltin, self.highlightTarget, +                self.keyBinding, self.builtinKeys, self.customKeys, +                self.keysAreBuiltin, self.winWidth, self.winHeight, +                self.startupEdit, self.autoSave, self.encoding,): +            var.trace_vdelete('w', var.trace_vinfo()[0][1]) +      def VarChanged_font(self, *params):          '''When one font attribute changes, save them all, as they are          not independent from each other. In particular, when we are @@ -740,6 +751,7 @@ class ConfigDialog(Toplevel):          if not tkMessageBox.askyesno(                  'Delete Key Set',  delmsg % keySetName, parent=self):              return +        self.DeactivateCurrentConfig()          #remove key set from config          idleConf.userCfg['keys'].remove_section(keySetName)          if keySetName in self.changedItems['keys']: @@ -758,7 +770,8 @@ class ConfigDialog(Toplevel):          self.keysAreBuiltin.set(idleConf.defaultCfg['main'].Get('Keys', 'default'))          self.builtinKeys.set(idleConf.defaultCfg['main'].Get('Keys', 'name'))          #user can't back out of these changes, they must be applied now -        self.Apply() +        self.SaveAllChangedConfigs() +        self.ActivateConfigChanges()          self.SetKeysType()      def DeleteCustomTheme(self): @@ -767,6 +780,7 @@ class ConfigDialog(Toplevel):          if not tkMessageBox.askyesno(                  'Delete Theme',  delmsg % themeName, parent=self):              return +        self.DeactivateCurrentConfig()          #remove theme from config          idleConf.userCfg['highlight'].remove_section(themeName)          if themeName in self.changedItems['highlight']: @@ -785,7 +799,8 @@ class ConfigDialog(Toplevel):          self.themeIsBuiltin.set(idleConf.defaultCfg['main'].Get('Theme', 'default'))          self.builtinTheme.set(idleConf.defaultCfg['main'].Get('Theme', 'name'))          #user can't back out of these changes, they must be applied now -        self.Apply() +        self.SaveAllChangedConfigs() +        self.ActivateConfigChanges()          self.SetThemeType()      def GetColour(self): @@ -1196,7 +1211,7 @@ class ConfigDialog(Toplevel):          All values are treated as text, and it is up to the user to supply          reasonable values. The only exception to this are the 'enable*' options, -        which are boolean, and can be toggled with an True/False button. +        which are boolean, and can be toggled with a True/False button.          """          parent = self.parent          frame = self.tabPages.pages['Extensions'].frame diff --git a/Lib/idlelib/configHandler.py b/Lib/idlelib/configHandler.py index 531efb4b3e..8954488fd6 100644 --- a/Lib/idlelib/configHandler.py +++ b/Lib/idlelib/configHandler.py @@ -720,7 +720,7 @@ class IdleConf:                  actualFont = Font.actual(f)                  family = actualFont['family']                  size = actualFont['size'] -                if size < 0: +                if size <= 0:                      size = 10  # if font in pixels, ignore actual size                  bold = actualFont['weight']=='bold'          return (family, size, 'bold' if bold else 'normal') @@ -740,21 +740,32 @@ class IdleConf:  idleConf = IdleConf()  # TODO Revise test output, write expanded unittest -### module test +#  if __name__ == '__main__': +    from zlib import crc32 +    line, crc = 0, 0 + +    def sprint(obj): +        global line, crc +        txt = str(obj) +        line += 1 +        crc = crc32(txt.encode(encoding='utf-8'), crc) +        print(txt) +        #print('***', line, crc, '***')  # uncomment for diagnosis +      def dumpCfg(cfg): -        print('\n', cfg, '\n') -        for key in cfg: +        print('\n', cfg, '\n')  # has variable '0xnnnnnnnn' addresses +        for key in sorted(cfg.keys()):              sections = cfg[key].sections() -            print(key) -            print(sections) +            sprint(key) +            sprint(sections)              for section in sections:                  options = cfg[key].options(section) -                print(section) -                print(options) +                sprint(section) +                sprint(options)                  for option in options: -                    print(option, '=', cfg[key].Get(section, option)) +                    sprint(option + ' = ' + cfg[key].Get(section, option)) +      dumpCfg(idleConf.defaultCfg)      dumpCfg(idleConf.userCfg) -    print(idleConf.userCfg['main'].Get('Theme', 'name')) -    #print idleConf.userCfg['highlight'].GetDefHighlight('Foo','normal') +    print('\nlines = ', line, ', crc = ', crc, sep='') diff --git a/Lib/idlelib/configHelpSourceEdit.py b/Lib/idlelib/configHelpSourceEdit.py index 242b08db56..cde8118fe6 100644 --- a/Lib/idlelib/configHelpSourceEdit.py +++ b/Lib/idlelib/configHelpSourceEdit.py @@ -23,10 +23,10 @@ class GetHelpSourceDialog(Toplevel):          self.title(title)          self.transient(parent)          self.grab_set() -        self.protocol("WM_DELETE_WINDOW", self.Cancel) +        self.protocol("WM_DELETE_WINDOW", self.cancel)          self.parent = parent          self.result = None -        self.CreateWidgets() +        self.create_widgets()          self.menu.set(menuItem)          self.path.set(filePath)          self.withdraw() #hide while setting geometry @@ -41,10 +41,10 @@ class GetHelpSourceDialog(Toplevel):                      ((parent.winfo_height()/2 - self.winfo_reqheight()/2)                      if not _htest else 150)))          self.deiconify() #geometry set, unhide -        self.bind('<Return>', self.Ok) +        self.bind('<Return>', self.ok)          self.wait_window() -    def CreateWidgets(self): +    def create_widgets(self):          self.menu = StringVar(self)          self.path = StringVar(self)          self.fontSize = StringVar(self) @@ -65,18 +65,18 @@ class GetHelpSourceDialog(Toplevel):          labelPath.pack(anchor=W, padx=5, pady=3)          self.entryPath.pack(anchor=W, padx=5, pady=3)          browseButton = Button(self.frameMain, text='Browse', width=8, -                              command=self.browseFile) +                              command=self.browse_file)          browseButton.pack(pady=3)          frameButtons = Frame(self)          frameButtons.pack(side=BOTTOM, fill=X)          self.buttonOk = Button(frameButtons, text='OK', -                               width=8, default=ACTIVE,  command=self.Ok) +                               width=8, default=ACTIVE,  command=self.ok)          self.buttonOk.grid(row=0, column=0, padx=5,pady=5)          self.buttonCancel = Button(frameButtons, text='Cancel', -                                   width=8, command=self.Cancel) +                                   width=8, command=self.cancel)          self.buttonCancel.grid(row=0, column=1, padx=5, pady=5) -    def browseFile(self): +    def browse_file(self):          filetypes = [              ("HTML Files", "*.htm *.html", "TEXT"),              ("PDF Files", "*.pdf", "TEXT"), @@ -99,9 +99,9 @@ class GetHelpSourceDialog(Toplevel):          if file:              self.path.set(file) -    def MenuOk(self): +    def menu_ok(self):          "Simple validity check for a sensible menu item name" -        menuOk = True +        menu_ok = True          menu = self.menu.get()          menu.strip()          if not menu: @@ -109,19 +109,19 @@ class GetHelpSourceDialog(Toplevel):                                     message='No menu item specified',                                     parent=self)              self.entryMenu.focus_set() -            menuOk = False +            menu_ok = False          elif len(menu) > 30:              tkMessageBox.showerror(title='Menu Item Error',                                     message='Menu item too long:'                                             '\nLimit 30 characters.',                                     parent=self)              self.entryMenu.focus_set() -            menuOk = False -        return menuOk +            menu_ok = False +        return menu_ok -    def PathOk(self): +    def path_ok(self):          "Simple validity check for menu file path" -        pathOk = True +        path_ok = True          path = self.path.get()          path.strip()          if not path: #no path specified @@ -129,7 +129,7 @@ class GetHelpSourceDialog(Toplevel):                                     message='No help file path specified.',                                     parent=self)              self.entryPath.focus_set() -            pathOk = False +            path_ok = False          elif path.startswith(('www.', 'http')):              pass          else: @@ -140,16 +140,16 @@ class GetHelpSourceDialog(Toplevel):                                         message='Help file path does not exist.',                                         parent=self)                  self.entryPath.focus_set() -                pathOk = False -        return pathOk +                path_ok = False +        return path_ok -    def Ok(self, event=None): -        if self.MenuOk() and self.PathOk(): +    def ok(self, event=None): +        if self.menu_ok() and self.path_ok():              self.result = (self.menu.get().strip(),                             self.path.get().strip())              if sys.platform == 'darwin':                  path = self.result[1] -                if path.startswith(('www', 'file:', 'http:')): +                if path.startswith(('www', 'file:', 'http:', 'https:')):                      pass                  else:                      # Mac Safari insists on using the URI form for local files @@ -157,10 +157,14 @@ class GetHelpSourceDialog(Toplevel):                      self.result[1] = "file://" + path              self.destroy() -    def Cancel(self, event=None): +    def cancel(self, event=None):          self.result = None          self.destroy()  if __name__ == '__main__': +    import unittest +    unittest.main('idlelib.idle_test.test_config_help', +                   verbosity=2, exit=False) +      from idlelib.idle_test.htest import run      run(GetHelpSourceDialog) diff --git a/Lib/idlelib/help.html b/Lib/idlelib/help.html index 2189fd4cf0..ffc03c4112 100644 --- a/Lib/idlelib/help.html +++ b/Lib/idlelib/help.html @@ -6,7 +6,7 @@    <head>      <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -    <title>25.5. IDLE — Python 3.4.3 documentation</title> +    <title>25.5. IDLE — Python 3.5.2 documentation</title>      <link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />      <link rel="stylesheet" href="../_static/pygments.css" type="text/css" /> @@ -14,7 +14,7 @@      <script type="text/javascript">        var DOCUMENTATION_OPTIONS = {          URL_ROOT:    '../', -        VERSION:     '3.4.3', +        VERSION:     '3.5.2',          COLLAPSE_INDEX: false,          FILE_SUFFIX: '.html',          HAS_SOURCE:  true @@ -25,11 +25,11 @@      <script type="text/javascript" src="../_static/doctools.js"></script>      <script type="text/javascript" src="../_static/sidebar.js"></script>      <link rel="search" type="application/opensearchdescription+xml" -          title="Search within Python 3.4.3 documentation" +          title="Search within Python 3.5.2 documentation"            href="../_static/opensearch.xml"/>      <link rel="author" title="About these documents" href="../about.html" />      <link rel="copyright" title="Copyright" href="../copyright.html" /> -    <link rel="top" title="Python 3.4.3 documentation" href="../index.html" /> +    <link rel="top" title="Python 3.5.2 documentation" href="../contents.html" />      <link rel="up" title="25. Graphical User Interfaces with Tk" href="tk.html" />      <link rel="next" title="25.6. Other Graphical User Interface Packages" href="othergui.html" />      <link rel="prev" title="25.4. tkinter.scrolledtext — Scrolled Text Widget" href="tkinter.scrolledtext.html" /> @@ -40,8 +40,8 @@    </head> -  <body> -    <div class="related"> +  <body role="document"> +    <div class="related" role="navigation" aria-label="related navigation">        <h3>Navigation</h3>        <ul>          <li class="right" style="margin-right: 10px"> @@ -60,25 +60,42 @@                   style="vertical-align: middle; margin-top: -1px"/></li>          <li><a href="https://www.python.org/">Python</a> »</li>          <li> -          <a href="../index.html">3.4.3 Documentation</a> » +          <a href="../index.html">3.5.2 Documentation</a> »          </li> -          <li><a href="index.html" >The Python Standard Library</a> »</li> -          <li><a href="tk.html" accesskey="U">25. Graphical User Interfaces with Tk</a> »</li> +          <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li> +          <li class="nav-item nav-item-2"><a href="tk.html" accesskey="U">25. Graphical User Interfaces with Tk</a> »</li> +    <li class="right"> + + +    <div class="inline-search" style="display: none" role="search"> +        <form class="inline-search" action="../search.html" method="get"> +          <input placeholder="Quick search" type="text" name="q" /> +          <input type="submit" value="Go" /> +          <input type="hidden" name="check_keywords" value="yes" /> +          <input type="hidden" name="area" value="default" /> +        </form> +    </div> +    <script type="text/javascript">$('.inline-search').show(0);</script> +         | +    </li> +        </ul>      </div>      <div class="document">        <div class="documentwrapper">          <div class="bodywrapper"> -          <div class="body"> +          <div class="body" role="main">    <div class="section" id="idle">  <span id="id1"></span><h1>25.5. IDLE<a class="headerlink" href="#idle" title="Permalink to this headline">¶</a></h1> -<p id="index-0">IDLE is Python’s Integrated Development and Learning Environment.</p> +<p><strong>Source code:</strong> <a class="reference external" href="https://hg.python.org/cpython/file/3.5/Lib/idlelib/">Lib/idlelib/</a></p> +<hr class="docutils" id="index-0" /> +<p>IDLE is Python’s Integrated Development and Learning Environment.</p>  <p>IDLE has the following features:</p>  <ul class="simple"> -<li>coded in 100% pure Python, using the <a class="reference internal" href="tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><tt class="xref py py-mod docutils literal"><span class="pre">tkinter</span></tt></a> GUI toolkit</li> +<li>coded in 100% pure Python, using the <a class="reference internal" href="tkinter.html#module-tkinter" title="tkinter: Interface to Tcl/Tk for graphical user interfaces"><code class="xref py py-mod docutils literal"><span class="pre">tkinter</span></code></a> GUI toolkit</li>  <li>cross-platform: works mostly the same on Windows, Unix, and Mac OS X</li>  <li>Python shell window (interactive interpreter) with colorizing  of code input, output, and error messages</li> @@ -163,7 +180,7 @@ be undone.</dd>  <dt>Find Selection</dt>  <dd>Search for the currently selected string, if there is one.</dd>  <dt>Find in Files...</dt> -<dd>Open a file search dialog.  Put results in an new output window.</dd> +<dd>Open a file search dialog.  Put results in a new output window.</dd>  <dt>Replace...</dt>  <dd>Open a search-and-replace dialog.</dd>  <dt>Go to Line</dt> @@ -224,10 +241,10 @@ Editor window.</dd>  <dt>Run Module</dt>  <dd>Do Check Module (above).  If no error, restart the shell to clean the  environment, then execute the module.  Output is displayed in the Shell -window.  Note that output requires use of <tt class="docutils literal"><span class="pre">print</span></tt> or <tt class="docutils literal"><span class="pre">write</span></tt>. +window.  Note that output requires use of <code class="docutils literal"><span class="pre">print</span></code> or <code class="docutils literal"><span class="pre">write</span></code>.  When execution is complete, the Shell retains focus and displays a prompt.  At this point, one may interactively explore the result of execution. -This is similar to executing a file with <tt class="docutils literal"><span class="pre">python</span> <span class="pre">-i</span> <span class="pre">file</span></tt> at a command +This is similar to executing a file with <code class="docutils literal"><span class="pre">python</span> <span class="pre">-i</span> <span class="pre">file</span></code> at a command  line.</dd>  </dl>  </div> @@ -238,6 +255,8 @@ line.</dd>  <dd>Scroll the shell window to the last Shell restart.</dd>  <dt>Restart Shell</dt>  <dd>Restart the shell to clean the environment.</dd> +<dt>Interrupt Execution</dt> +<dd>Stop a running program.</dd>  </dl>  </div>  <div class="section" id="debug-menu-shell-window-only"> @@ -339,47 +358,47 @@ debugger.  Breakpoints for a file are saved in the user’s .idlerc director  </div>  <div class="section" id="editing-and-navigation">  <h2>25.5.2. Editing and navigation<a class="headerlink" href="#editing-and-navigation" title="Permalink to this headline">¶</a></h2> -<p>In this section, ‘C’ refers to the <tt class="kbd docutils literal"><span class="pre">Control</span></tt> key on Windows and Unix and -the <tt class="kbd docutils literal"><span class="pre">Command</span></tt> key on Mac OSX.</p> +<p>In this section, ‘C’ refers to the <code class="kbd docutils literal"><span class="pre">Control</span></code> key on Windows and Unix and +the <code class="kbd docutils literal"><span class="pre">Command</span></code> key on Mac OSX.</p>  <ul> -<li><p class="first"><tt class="kbd docutils literal"><span class="pre">Backspace</span></tt> deletes to the left; <tt class="kbd docutils literal"><span class="pre">Del</span></tt> deletes to the right</p> +<li><p class="first"><code class="kbd docutils literal"><span class="pre">Backspace</span></code> deletes to the left; <code class="kbd docutils literal"><span class="pre">Del</span></code> deletes to the right</p>  </li> -<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-Backspace</span></tt> delete word left; <tt class="kbd docutils literal"><span class="pre">C-Del</span></tt> delete word to the right</p> +<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-Backspace</span></code> delete word left; <code class="kbd docutils literal"><span class="pre">C-Del</span></code> delete word to the right</p>  </li> -<li><p class="first">Arrow keys and <tt class="kbd docutils literal"><span class="pre">Page</span> <span class="pre">Up</span></tt>/<tt class="kbd docutils literal"><span class="pre">Page</span> <span class="pre">Down</span></tt> to move around</p> +<li><p class="first">Arrow keys and <code class="kbd docutils literal"><span class="pre">Page</span> <span class="pre">Up</span></code>/<code class="kbd docutils literal"><span class="pre">Page</span> <span class="pre">Down</span></code> to move around</p>  </li> -<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-LeftArrow</span></tt> and <tt class="kbd docutils literal"><span class="pre">C-RightArrow</span></tt> moves by words</p> +<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-LeftArrow</span></code> and <code class="kbd docutils literal"><span class="pre">C-RightArrow</span></code> moves by words</p>  </li> -<li><p class="first"><tt class="kbd docutils literal"><span class="pre">Home</span></tt>/<tt class="kbd docutils literal"><span class="pre">End</span></tt> go to begin/end of line</p> +<li><p class="first"><code class="kbd docutils literal"><span class="pre">Home</span></code>/<code class="kbd docutils literal"><span class="pre">End</span></code> go to begin/end of line</p>  </li> -<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-Home</span></tt>/<tt class="kbd docutils literal"><span class="pre">C-End</span></tt> go to begin/end of file</p> +<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-Home</span></code>/<code class="kbd docutils literal"><span class="pre">C-End</span></code> go to begin/end of file</p>  </li>  <li><p class="first">Some useful Emacs bindings are inherited from Tcl/Tk:</p>  <blockquote>  <div><ul class="simple"> -<li><tt class="kbd docutils literal"><span class="pre">C-a</span></tt> beginning of line</li> -<li><tt class="kbd docutils literal"><span class="pre">C-e</span></tt> end of line</li> -<li><tt class="kbd docutils literal"><span class="pre">C-k</span></tt> kill line (but doesn’t put it in clipboard)</li> -<li><tt class="kbd docutils literal"><span class="pre">C-l</span></tt> center window around the insertion point</li> -<li><tt class="kbd docutils literal"><span class="pre">C-b</span></tt> go backwards one character without deleting (usually you can +<li><code class="kbd docutils literal"><span class="pre">C-a</span></code> beginning of line</li> +<li><code class="kbd docutils literal"><span class="pre">C-e</span></code> end of line</li> +<li><code class="kbd docutils literal"><span class="pre">C-k</span></code> kill line (but doesn’t put it in clipboard)</li> +<li><code class="kbd docutils literal"><span class="pre">C-l</span></code> center window around the insertion point</li> +<li><code class="kbd docutils literal"><span class="pre">C-b</span></code> go backwards one character without deleting (usually you can  also use the cursor key for this)</li> -<li><tt class="kbd docutils literal"><span class="pre">C-f</span></tt> go forward one character without deleting (usually you can +<li><code class="kbd docutils literal"><span class="pre">C-f</span></code> go forward one character without deleting (usually you can  also use the cursor key for this)</li> -<li><tt class="kbd docutils literal"><span class="pre">C-p</span></tt> go up one line (usually you can also use the cursor key for +<li><code class="kbd docutils literal"><span class="pre">C-p</span></code> go up one line (usually you can also use the cursor key for  this)</li> -<li><tt class="kbd docutils literal"><span class="pre">C-d</span></tt> delete next character</li> +<li><code class="kbd docutils literal"><span class="pre">C-d</span></code> delete next character</li>  </ul>  </div></blockquote>  </li>  </ul> -<p>Standard keybindings (like <tt class="kbd docutils literal"><span class="pre">C-c</span></tt> to copy and <tt class="kbd docutils literal"><span class="pre">C-v</span></tt> to paste) +<p>Standard keybindings (like <code class="kbd docutils literal"><span class="pre">C-c</span></code> to copy and <code class="kbd docutils literal"><span class="pre">C-v</span></code> to paste)  may work.  Keybindings are selected in the Configure IDLE dialog.</p>  <div class="section" id="automatic-indentation">  <h3>25.5.2.1. Automatic indentation<a class="headerlink" href="#automatic-indentation" title="Permalink to this headline">¶</a></h3>  <p>After a block-opening statement, the next line is indented by 4 spaces (in the  Python Shell window by one tab).  After certain keywords (break, return etc.) -the next line is dedented.  In leading indentation, <tt class="kbd docutils literal"><span class="pre">Backspace</span></tt> deletes up -to 4 spaces if they are there. <tt class="kbd docutils literal"><span class="pre">Tab</span></tt> inserts spaces (in the Python +the next line is dedented.  In leading indentation, <code class="kbd docutils literal"><span class="pre">Backspace</span></code> deletes up +to 4 spaces if they are there. <code class="kbd docutils literal"><span class="pre">Tab</span></code> inserts spaces (in the Python  Shell window one tab), number depends on Indent width. Currently tabs  are restricted to four spaces due to Tcl/Tk limitations.</p>  <p>See also the indent/dedent region commands in the edit menu.</p> @@ -394,25 +413,25 @@ two seconds) after a ‘.’ or (in a string) an os.sep is typed. If aft  of those characters (plus zero or more other characters) a tab is typed  the ACW will open immediately if a possible continuation is found.</p>  <p>If there is only one possible completion for the characters entered, a -<tt class="kbd docutils literal"><span class="pre">Tab</span></tt> will supply that completion without opening the ACW.</p> +<code class="kbd docutils literal"><span class="pre">Tab</span></code> will supply that completion without opening the ACW.</p>  <p>‘Show Completions’ will force open a completions window, by default the -<tt class="kbd docutils literal"><span class="pre">C-space</span></tt> will open a completions window. In an empty +<code class="kbd docutils literal"><span class="pre">C-space</span></code> will open a completions window. In an empty  string, this will contain the files in the current directory. On a  blank line, it will contain the built-in and user-defined functions and  classes in the current name spaces, plus any modules imported. If some  characters have been entered, the ACW will attempt to be more specific.</p>  <p>If a string of characters is typed, the ACW selection will jump to the -entry most closely matching those characters.  Entering a <tt class="kbd docutils literal"><span class="pre">tab</span></tt> will +entry most closely matching those characters.  Entering a <code class="kbd docutils literal"><span class="pre">tab</span></code> will  cause the longest non-ambiguous match to be entered in the Editor window or -Shell.  Two <tt class="kbd docutils literal"><span class="pre">tab</span></tt> in a row will supply the current ACW selection, as +Shell.  Two <code class="kbd docutils literal"><span class="pre">tab</span></code> in a row will supply the current ACW selection, as  will return or a double click.  Cursor keys, Page Up/Down, mouse selection,  and the scroll wheel all operate on the ACW.</p>  <p>“Hidden” attributes can be accessed by typing the beginning of hidden  name after a ‘.’, e.g. ‘_’. This allows access to modules with -<tt class="docutils literal"><span class="pre">__all__</span></tt> set, or to class-private attributes.</p> +<code class="docutils literal"><span class="pre">__all__</span></code> set, or to class-private attributes.</p>  <p>Completions and the ‘Expand Word’ facility can save a lot of typing!</p>  <p>Completions are currently limited to those in the namespaces. Names in -an Editor window which are not via <tt class="docutils literal"><span class="pre">__main__</span></tt> and <a class="reference internal" href="sys.html#sys.modules" title="sys.modules"><tt class="xref py py-data docutils literal"><span class="pre">sys.modules</span></tt></a> will +an Editor window which are not via <code class="docutils literal"><span class="pre">__main__</span></code> and <a class="reference internal" href="sys.html#sys.modules" title="sys.modules"><code class="xref py py-data docutils literal"><span class="pre">sys.modules</span></code></a> will  not be found.  Run the module once with your imports to correct this situation.  Note that IDLE itself places quite a few modules in sys.modules, so  much can be found by default, e.g. the re module.</p> @@ -421,10 +440,10 @@ longer or disable the extension.</p>  </div>  <div class="section" id="calltips">  <h3>25.5.2.3. Calltips<a class="headerlink" href="#calltips" title="Permalink to this headline">¶</a></h3> -<p>A calltip is shown when one types <tt class="kbd docutils literal"><span class="pre">(</span></tt> after the name of an <em>acccessible</em> +<p>A calltip is shown when one types <code class="kbd docutils literal"><span class="pre">(</span></code> after the name of an <em>acccessible</em>  function.  A name expression may include dots and subscripts.  A calltip  remains until it is clicked, the cursor is moved out of the argument area, -or <tt class="kbd docutils literal"><span class="pre">)</span></tt> is typed.  When the cursor is in the argument part of a definition, +or <code class="kbd docutils literal"><span class="pre">)</span></code> is typed.  When the cursor is in the argument part of a definition,  the menu or shortcut display a calltip.</p>  <p>A calltip consists of the function signature and the first line of the  docstring.  For builtins without an accessible signature, the calltip @@ -433,11 +452,11 @@ details may change.</p>  <p>The set of <em>accessible</em> functions depends on what modules have been imported  into the user process, including those imported by Idle itself,  and what definitions have been run, all since the last restart.</p> -<p>For example, restart the Shell and enter <tt class="docutils literal"><span class="pre">itertools.count(</span></tt>.  A calltip +<p>For example, restart the Shell and enter <code class="docutils literal"><span class="pre">itertools.count(</span></code>.  A calltip  appears because Idle imports itertools into the user process for its own use. -(This could change.)  Enter <tt class="docutils literal"><span class="pre">turtle.write(</span></tt> and nothing appears.  Idle does +(This could change.)  Enter <code class="docutils literal"><span class="pre">turtle.write(</span></code> and nothing appears.  Idle does  not import turtle.  The menu or shortcut do nothing either.  Enter -<tt class="docutils literal"><span class="pre">import</span> <span class="pre">turtle</span></tt> and then <tt class="docutils literal"><span class="pre">turtle.write(</span></tt> will work.</p> +<code class="docutils literal"><span class="pre">import</span> <span class="pre">turtle</span></code> and then <code class="docutils literal"><span class="pre">turtle.write(</span></code> will work.</p>  <p>In an editor, import statements have no effect until one runs the file.  One  might want to run a file after writing the import statements at the top,  or immediately run an existing file before editing.</p> @@ -445,17 +464,17 @@ or immediately run an existing file before editing.</p>  <div class="section" id="python-shell-window">  <h3>25.5.2.4. Python Shell window<a class="headerlink" href="#python-shell-window" title="Permalink to this headline">¶</a></h3>  <ul> -<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-c</span></tt> interrupts executing command</p> +<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-c</span></code> interrupts executing command</p>  </li> -<li><p class="first"><tt class="kbd docutils literal"><span class="pre">C-d</span></tt> sends end-of-file; closes window if typed at a <tt class="docutils literal"><span class="pre">>>></span></tt> prompt</p> +<li><p class="first"><code class="kbd docutils literal"><span class="pre">C-d</span></code> sends end-of-file; closes window if typed at a <code class="docutils literal"><span class="pre">>>></span></code> prompt</p>  </li> -<li><p class="first"><tt class="kbd docutils literal"><span class="pre">Alt-/</span></tt> (Expand word) is also useful to reduce typing</p> +<li><p class="first"><code class="kbd docutils literal"><span class="pre">Alt-/</span></code> (Expand word) is also useful to reduce typing</p>  <p>Command history</p>  <ul class="simple"> -<li><tt class="kbd docutils literal"><span class="pre">Alt-p</span></tt> retrieves previous command matching what you have typed. On -OS X use <tt class="kbd docutils literal"><span class="pre">C-p</span></tt>.</li> -<li><tt class="kbd docutils literal"><span class="pre">Alt-n</span></tt> retrieves next. On OS X use <tt class="kbd docutils literal"><span class="pre">C-n</span></tt>.</li> -<li><tt class="kbd docutils literal"><span class="pre">Return</span></tt> while on any previous command retrieves that command</li> +<li><code class="kbd docutils literal"><span class="pre">Alt-p</span></code> retrieves previous command matching what you have typed. On +OS X use <code class="kbd docutils literal"><span class="pre">C-p</span></code>.</li> +<li><code class="kbd docutils literal"><span class="pre">Alt-n</span></code> retrieves next. On OS X use <code class="kbd docutils literal"><span class="pre">C-n</span></code>.</li> +<li><code class="kbd docutils literal"><span class="pre">Return</span></code> while on any previous command retrieves that command</li>  </ul>  </li>  </ul> @@ -465,8 +484,8 @@ OS X use <tt class="kbd docutils literal"><span class="pre">C-p</span></tt>.</li  <p>Idle defaults to black on white text, but colors text with special meanings.  For the shell, these are shell output, shell error, user output, and  user error.  For Python code, at the shell prompt or in an editor, these are -keywords, builtin class and function names, names following <tt class="docutils literal"><span class="pre">class</span></tt> and -<tt class="docutils literal"><span class="pre">def</span></tt>, strings, and comments. For any text window, these are the cursor (when +keywords, builtin class and function names, names following <code class="docutils literal"><span class="pre">class</span></code> and +<code class="docutils literal"><span class="pre">def</span></code>, strings, and comments. For any text window, these are the cursor (when  present), found text (when possible), and selected text.</p>  <p>Text coloring is done in the background, so uncolorized text is occasionally  visible.  To change the color scheme, use the Configure IDLE dialog @@ -476,26 +495,26 @@ text in popups and dialogs is not user-configurable.</p>  </div>  <div class="section" id="startup-and-code-execution">  <h2>25.5.3. Startup and code execution<a class="headerlink" href="#startup-and-code-execution" title="Permalink to this headline">¶</a></h2> -<p>Upon startup with the <tt class="docutils literal"><span class="pre">-s</span></tt> option, IDLE will execute the file referenced by -the environment variables <span class="target" id="index-5"></span><tt class="xref std std-envvar docutils literal"><span class="pre">IDLESTARTUP</span></tt> or <span class="target" id="index-6"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONSTARTUP"><tt class="xref std std-envvar docutils literal"><span class="pre">PYTHONSTARTUP</span></tt></a>. -IDLE first checks for <tt class="docutils literal"><span class="pre">IDLESTARTUP</span></tt>; if <tt class="docutils literal"><span class="pre">IDLESTARTUP</span></tt> is present the file -referenced is run.  If <tt class="docutils literal"><span class="pre">IDLESTARTUP</span></tt> is not present, IDLE checks for -<tt class="docutils literal"><span class="pre">PYTHONSTARTUP</span></tt>.  Files referenced by these environment variables are +<p>Upon startup with the <code class="docutils literal"><span class="pre">-s</span></code> option, IDLE will execute the file referenced by +the environment variables <span class="target" id="index-5"></span><code class="xref std std-envvar docutils literal"><span class="pre">IDLESTARTUP</span></code> or <span class="target" id="index-6"></span><a class="reference internal" href="../using/cmdline.html#envvar-PYTHONSTARTUP"><code class="xref std std-envvar docutils literal"><span class="pre">PYTHONSTARTUP</span></code></a>. +IDLE first checks for <code class="docutils literal"><span class="pre">IDLESTARTUP</span></code>; if <code class="docutils literal"><span class="pre">IDLESTARTUP</span></code> is present the file +referenced is run.  If <code class="docutils literal"><span class="pre">IDLESTARTUP</span></code> is not present, IDLE checks for +<code class="docutils literal"><span class="pre">PYTHONSTARTUP</span></code>.  Files referenced by these environment variables are  convenient places to store functions that are used frequently from the IDLE  shell, or for executing import statements to import common modules.</p> -<p>In addition, <tt class="docutils literal"><span class="pre">Tk</span></tt> also loads a startup file if it is present.  Note that the -Tk file is loaded unconditionally.  This additional file is <tt class="docutils literal"><span class="pre">.Idle.py</span></tt> and is +<p>In addition, <code class="docutils literal"><span class="pre">Tk</span></code> also loads a startup file if it is present.  Note that the +Tk file is loaded unconditionally.  This additional file is <code class="docutils literal"><span class="pre">.Idle.py</span></code> and is  looked for in the user’s home directory.  Statements in this file will be  executed in the Tk namespace, so this file is not useful for importing  functions to be used from IDLE’s Python shell.</p>  <div class="section" id="command-line-usage">  <h3>25.5.3.1. Command line usage<a class="headerlink" href="#command-line-usage" title="Permalink to this headline">¶</a></h3> -<div class="highlight-python3"><div class="highlight"><pre>idle.py [-c command] [-d] [-e] [-h] [-i] [-r file] [-s] [-t title] [-] [arg] ... +<div class="highlight-none"><div class="highlight"><pre><span></span>idle.py [-c command] [-d] [-e] [-h] [-i] [-r file] [-s] [-t title] [-] [arg] ...  -c command  run command in the shell window  -d          enable debugger and open shell window  -e          open editor window --h          print help message with legal combinatios and exit +-h          print help message with legal combinations and exit  -i          open shell window  -r file     run file in shell window  -s          run $IDLESTARTUP or $PYTHONSTARTUP first, in shell window @@ -505,27 +524,31 @@ functions to be used from IDLE’s Python shell.</p>  </div>  <p>If there are arguments:</p>  <ul class="simple"> -<li>If <tt class="docutils literal"><span class="pre">-</span></tt>, <tt class="docutils literal"><span class="pre">-c</span></tt>, or <tt class="docutils literal"><span class="pre">r</span></tt> is used, all arguments are placed in -<tt class="docutils literal"><span class="pre">sys.argv[1:...]</span></tt> and <tt class="docutils literal"><span class="pre">sys.argv[0]</span></tt> is set to <tt class="docutils literal"><span class="pre">''</span></tt>, <tt class="docutils literal"><span class="pre">'-c'</span></tt>, -or <tt class="docutils literal"><span class="pre">'-r'</span></tt>.  No editor window is opened, even if that is the default +<li>If <code class="docutils literal"><span class="pre">-</span></code>, <code class="docutils literal"><span class="pre">-c</span></code>, or <code class="docutils literal"><span class="pre">r</span></code> is used, all arguments are placed in +<code class="docutils literal"><span class="pre">sys.argv[1:...]</span></code> and <code class="docutils literal"><span class="pre">sys.argv[0]</span></code> is set to <code class="docutils literal"><span class="pre">''</span></code>, <code class="docutils literal"><span class="pre">'-c'</span></code>, +or <code class="docutils literal"><span class="pre">'-r'</span></code>.  No editor window is opened, even if that is the default  set in the Options dialog.</li>  <li>Otherwise, arguments are files opened for editing and -<tt class="docutils literal"><span class="pre">sys.argv</span></tt> reflects the arguments passed to IDLE itself.</li> +<code class="docutils literal"><span class="pre">sys.argv</span></code> reflects the arguments passed to IDLE itself.</li>  </ul>  </div>  <div class="section" id="idle-console-differences">  <h3>25.5.3.2. IDLE-console differences<a class="headerlink" href="#idle-console-differences" title="Permalink to this headline">¶</a></h3>  <p>As much as possible, the result of executing Python code with IDLE is the  same as executing the same code in a console window.  However, the different -interface and operation occasionally affects results.</p> -<p>For instance, IDLE normally executes user code in a separate process from -the IDLE GUI itself.  The IDLE versions of sys.stdin, .stdout, and .stderr in the -execution process get input from and send output to the GUI process, -which keeps control of the keyboard and screen.  This is normally transparent, -but code that access these object will see different attribute values. -Also, functions that directly access the keyboard and screen will not work.</p> +interface and operation occasionally affects visible results.  For instance, +<code class="docutils literal"><span class="pre">sys.modules</span></code> starts with more entries.</p> +<p>IDLE also replaces <code class="docutils literal"><span class="pre">sys.stdin</span></code>, <code class="docutils literal"><span class="pre">sys.stdout</span></code>, and <code class="docutils literal"><span class="pre">sys.stderr</span></code> with +objects that get input from and send output to the Shell window. +When this window has the focus, it controls the keyboard and screen. +This is normally transparent, but functions that directly access the keyboard +and screen will not work.  If <code class="docutils literal"><span class="pre">sys</span></code> is reset with <code class="docutils literal"><span class="pre">importlib.reload(sys)</span></code>, +IDLE’s changes are lost and things like <code class="docutils literal"><span class="pre">input</span></code>, <code class="docutils literal"><span class="pre">raw_input</span></code>, and +<code class="docutils literal"><span class="pre">print</span></code> will not work correctly.</p>  <p>With IDLE’s Shell, one enters, edits, and recalls complete statements. -Some consoles only work with a single physical line at a time.</p> +Some consoles only work with a single physical line at a time.  IDLE uses +<code class="docutils literal"><span class="pre">exec</span></code> to run each statement.  As a result, <code class="docutils literal"><span class="pre">'__builtins__'</span></code> is always +defined for each statement.</p>  </div>  <div class="section" id="running-without-a-subprocess">  <h3>25.5.3.3. Running without a subprocess<a class="headerlink" href="#running-without-a-subprocess" title="Permalink to this headline">¶</a></h3> @@ -595,7 +618,7 @@ are currently:</p>            </div>          </div>        </div> -      <div class="sphinxsidebar"> +      <div class="sphinxsidebar" role="navigation" aria-label="main navigation">          <div class="sphinxsidebarwrapper">    <h3><a href="../contents.html">Table Of Contents</a></h3>    <ul> @@ -639,35 +662,23 @@ are currently:</p>    <h4>Previous topic</h4>    <p class="topless"><a href="tkinter.scrolledtext.html" -                        title="previous chapter">25.4. <tt class="docutils literal"><span class="pre">tkinter.scrolledtext</span></tt> — Scrolled Text Widget</a></p> +                        title="previous chapter">25.4. <code class="docutils literal"><span class="pre">tkinter.scrolledtext</span></code> — Scrolled Text Widget</a></p>    <h4>Next topic</h4>    <p class="topless"><a href="othergui.html"                          title="next chapter">25.6. Other Graphical User Interface Packages</a></p> -<h3>This Page</h3> -<ul class="this-page-menu"> -  <li><a href="../bugs.html">Report a Bug</a></li> -  <li><a href="../_sources/library/idle.txt" -         rel="nofollow">Show Source</a></li> -</ul> - -<div id="searchbox" style="display: none"> -  <h3>Quick search</h3> -    <form class="search" action="../search.html" method="get"> -      <input type="text" name="q" /> -      <input type="submit" value="Go" /> -      <input type="hidden" name="check_keywords" value="yes" /> -      <input type="hidden" name="area" value="default" /> -    </form> -    <p class="searchtip" style="font-size: 90%"> -    Enter search terms or a module, class or function name. -    </p> -</div> -<script type="text/javascript">$('#searchbox').show(0);</script> +  <div role="note" aria-label="source link"> +    <h3>This Page</h3> +    <ul class="this-page-menu"> +      <li><a href="../bugs.html">Report a Bug</a></li> +      <li><a href="../_sources/library/idle.txt" +            rel="nofollow">Show Source</a></li> +    </ul> +  </div>          </div>        </div>        <div class="clearer"></div>      </div> -    <div class="related"> +    <div class="related" role="navigation" aria-label="related navigation">        <h3>Navigation</h3>        <ul>          <li class="right" style="margin-right: 10px"> @@ -686,23 +697,38 @@ are currently:</p>                   style="vertical-align: middle; margin-top: -1px"/></li>          <li><a href="https://www.python.org/">Python</a> »</li>          <li> -          <a href="../index.html">3.4.3 Documentation</a> » +          <a href="../index.html">3.5.2 Documentation</a> »          </li> -          <li><a href="index.html" >The Python Standard Library</a> »</li> -          <li><a href="tk.html" >25. Graphical User Interfaces with Tk</a> »</li> +          <li class="nav-item nav-item-1"><a href="index.html" >The Python Standard Library</a> »</li> +          <li class="nav-item nav-item-2"><a href="tk.html" >25. Graphical User Interfaces with Tk</a> »</li> +    <li class="right"> + + +    <div class="inline-search" style="display: none" role="search"> +        <form class="inline-search" action="../search.html" method="get"> +          <input placeholder="Quick search" type="text" name="q" /> +          <input type="submit" value="Go" /> +          <input type="hidden" name="check_keywords" value="yes" /> +          <input type="hidden" name="area" value="default" /> +        </form> +    </div> +    <script type="text/javascript">$('.inline-search').show(0);</script> +         | +    </li> +        </ul>      </div>      <div class="footer"> -    © <a href="../copyright.html">Copyright</a> 1990-2015, Python Software Foundation. +    © <a href="../copyright.html">Copyright</a> 2001-2016, Python Software Foundation.      <br />      The Python Software Foundation is a non-profit corporation.      <a href="https://www.python.org/psf/donations/">Please donate.</a>      <br /> -    Last updated on Oct 13, 2015. +    Last updated on Sep 12, 2016.      <a href="../bugs.html">Found a bug</a>?      <br /> -    Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.2.3. +    Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.3.6.      </div>    </body> diff --git a/Lib/idlelib/help.py b/Lib/idlelib/help.py index b31596c2eb..a7008e94ed 100644 --- a/Lib/idlelib/help.py +++ b/Lib/idlelib/help.py @@ -11,7 +11,7 @@ Help => IDLE Help: Display help.html with proper formatting.  Doc/library/idle.rst (Sphinx)=> Doc/build/html/library/idle.html  (help.copy_strip)=> Lib/idlelib/help.html -HelpParser - Parse help.html and and render to tk Text. +HelpParser - Parse help.html and render to tk Text.  HelpText - Display formatted help.html. @@ -26,6 +26,7 @@ show_idlehelp - Create HelpWindow.  Called in EditorWindow.help_dialog.  """  from html.parser import HTMLParser  from os.path import abspath, dirname, isdir, isfile, join +from platform import python_version  from tkinter import Tk, Toplevel, Frame, Text, Scrollbar, Menu, Menubutton  from tkinter import font as tkfont  from idlelib.configHandler import idleConf @@ -45,6 +46,8 @@ class HelpParser(HTMLParser):      The overridden handle_xyz methods handle a subset of html tags.      The supplied text should have the needed tag configurations.      The behavior for unsupported tags, such as table, is undefined. +    If the tags generated by Sphinx change, this class, especially +    the handle_starttag and handle_endtags methods, might have to also.      """      def __init__(self, text):          HTMLParser.__init__(self, convert_charrefs=True) @@ -226,7 +229,28 @@ class HelpWindow(Toplevel):  def copy_strip(): -    "Copy idle.html to idlelib/help.html, stripping trailing whitespace." +    """Copy idle.html to idlelib/help.html, stripping trailing whitespace. + +    Files with trailing whitespace cannot be pushed to the hg cpython +    repository.  For 3.x (on Windows), help.html is generated, after +    editing idle.rst in the earliest maintenance version, with +      sphinx-build -bhtml . build/html +      python_d.exe -c "from idlelib.help import copy_strip; copy_strip()" +    After refreshing TortoiseHG workshop to generate a diff, +    check  both the diff and displayed text.  Push the diff along with +    the idle.rst change and merge both into default (or an intermediate +    maintenance version). + +    When the 'earlist' version gets its final maintenance release, +    do an update as described above, without editing idle.rst, to +    rebase help.html on the next version of idle.rst.  Do not worry +    about version changes as version is not displayed.  Examine other +    changes and the result of Help -> IDLE Help. + +    If maintenance and default versions of idle.rst diverge, and +    merging does not go smoothly, then consider generating +    separate help.html files from separate idle.htmls. +    """      src = join(abspath(dirname(dirname(dirname(__file__)))),                 'Doc', 'build', 'html', 'library', 'idle.html')      dst = join(abspath(dirname(__file__)), 'help.html') @@ -242,7 +266,7 @@ def show_idlehelp(parent):      if not isfile(filename):          # try copy_strip, present message          return -    HelpWindow(parent, filename, 'IDLE Help') +    HelpWindow(parent, filename, 'IDLE Help (%s)' % python_version())  if __name__ == '__main__':      from idlelib.idle_test.htest import run diff --git a/Lib/idlelib/idle.py b/Lib/idlelib/idle.py index a249557dd1..141534dfe1 100644 --- a/Lib/idlelib/idle.py +++ b/Lib/idlelib/idle.py @@ -1,11 +1,13 @@  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: +# Enable running IDLE with idlelib in a non-standard location. +# This was once used to run development versions of IDLE. +# Because PEP 434 declared idle.py a public interface, +# removal should require deprecation.  idlelib_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -sys.path.insert(0, idlelib_dir) +if idlelib_dir not in sys.path: +    sys.path.insert(0, idlelib_dir) -import idlelib.PyShell -idlelib.PyShell.main() +from idlelib.PyShell import main  # This is subject to change +main() diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt index 2339926ef3..dc7a28697c 100644 --- a/Lib/idlelib/idle_test/README.txt +++ b/Lib/idlelib/idle_test/README.txt @@ -2,12 +2,12 @@ README FOR IDLE TESTS IN IDLELIB.IDLE_TEST  0. Quick Start -Automated unit tests were added in 2.7 for Python 2.x and 3.3 for Python 3.x. +Automated unit tests were added in 3.3 for Python 3.x.  To run the tests from a command line:  python -m test.test_idle -Human-mediated tests were added later in 2.7 and in 3.4. +Human-mediated tests were added later in 3.4.  python -m idlelib.idle_test.htest @@ -15,9 +15,9 @@ python -m idlelib.idle_test.htest  1. Test Files  The idle directory, idlelib, has over 60 xyz.py files. The idle_test -subdirectory should contain a test_xyz.py for each, where 'xyz' is lowercased -even if xyz.py is not. Here is a possible template, with the blanks after after -'.' and 'as', and before and after '_' to be filled in. +subdirectory should contain a test_xyz.py for each, where 'xyz' is +lowercased even if xyz.py is not. Here is a possible template, with the +blanks after '.' and 'as', and before and after '_' to be filled in.  import unittest  from test.support import requires @@ -30,9 +30,9 @@ class _Test(unittest.TestCase):  if __name__ == '__main__':      unittest.main(verbosity=2) -Add the following at the end of xyy.py, with the appropriate name added after -'test_'. Some files already have something like this for htest.  If so, insert -the import and unittest.main lines before the htest lines. +Add the following at the end of xyy.py, with the appropriate name added +after 'test_'. Some files already have something like this for htest. +If so, insert the import and unittest.main lines before the htest lines.  if __name__ == "__main__":      import unittest @@ -42,64 +42,82 @@ if __name__ == "__main__":  2. GUI Tests -When run as part of the Python test suite, Idle gui tests need to run -test.support.requires('gui') (test.test_support in 2.7).  A test is a gui test -if it creates a Tk root or master object either directly or indirectly by -instantiating a tkinter or idle class.  For the benefit of test processes that -either have no graphical environment available or are not allowed to use it, gui -tests must be 'guarded' by "requires('gui')" in a setUp function or method. -This will typically be setUpClass. +When run as part of the Python test suite, Idle GUI tests need to run +test.support.requires('gui').  A test is a GUI test if it creates a +tkinter.Tk root or master object either directly or indirectly by +instantiating a tkinter or idle class.  GUI tests cannot run in test +processes that either have no graphical environment available or are not +allowed to use it. -To avoid interfering with other gui tests, all gui objects must be destroyed and -deleted by the end of the test.  Widgets, such as a Tk root, created in a setUpX -function, should be destroyed in the corresponding tearDownX.  Module and class -widget attributes should also be deleted.. +To guard a module consisting entirely of GUI tests, start with + +from test.support import requires +requires('gui') + +To guard a test class, put "requires('gui')" in its setUpClass function. + +To avoid interfering with other GUI tests, all GUI objects must be destroyed and +deleted by the end of the test.  The Tk root created in a setUpX function should +be destroyed in the corresponding tearDownX and the module or class attribute +deleted.  Others widgets should descend from the single root and the attributes +deleted BEFORE root is destroyed.  See https://bugs.python.org/issue20567.      @classmethod      def setUpClass(cls):          requires('gui')          cls.root = tk.Tk() +        cls.text = tk.Text(root)      @classmethod      def tearDownClass(cls): +        del cls.text +        cls.root.update_idletasks()          cls.root.destroy()          del cls.root +The update_idletasks call is sometimes needed to prevent the following warning +either when running a test alone or as part of the test suite (#27196). +  can't invoke "event" command: application has been destroyed +  ... +  "ttk::ThemeChanged"  Requires('gui') causes the test(s) it guards to be skipped if any of -a few conditions are met: -     - - The tests are being run by regrtest.py, and it was started without enabling -   the "gui" resource with the "-u" command line option. -    - - The tests are being run on Windows by a service that is not allowed to -   interact with the graphical environment. -    - - The tests are being run on Mac OSX in a process that cannot make a window -   manager connection. -    +these conditions are met: + + - The tests are being run by regrtest.py, and it was started without +   enabling the "gui" resource with the "-u" command line option. + + - The tests are being run on Windows by a service that is not allowed +   to interact with the graphical environment. + + - The tests are being run on Linux and X Windows is not available. + + - The tests are being run on Mac OSX in a process that cannot make a +   window manager connection. +   - tkinter.Tk cannot be successfully instantiated for some reason. -  +   - test.support.use_resources has been set by something other than     regrtest.py and does not contain "gui". -    -Tests of non-gui operations should avoid creating tk widgets. Incidental uses of -tk variables and messageboxes can be replaced by the mock classes in -idle_test/mock_tk.py. The mock text handles some uses of the tk Text widget. + +Tests of non-GUI operations should avoid creating tk widgets. Incidental +uses of tk variables and messageboxes can be replaced by the mock +classes in idle_test/mock_tk.py. The mock text handles some uses of the +tk Text widget.  3. Running Unit Tests  Assume that xyz.py and test_xyz.py both end with a unittest.main() call. -Running either from an Idle editor runs all tests in the test_xyz file with the -version of Python running Idle.  Test output appears in the Shell window.  The -'verbosity=2' option lists all test methods in the file, which is appropriate -when developing tests. The 'exit=False' option is needed in xyx.py files when an -htest follows. +Running either from an Idle editor runs all tests in the test_xyz file +with the version of Python running Idle.  Test output appears in the +Shell window.  The 'verbosity=2' option lists all test methods in the +file, which is appropriate when developing tests. The 'exit=False' +option is needed in xyx.py files when an htest follows.  The following command lines also run all test methods, including -gui tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle' start -Idle and so cannot run tests.) +GUI tests, in test_xyz.py. (Both '-m idlelib' and '-m idlelib.idle' +start Idle and so cannot run tests.)  python -m idlelib.xyz  python -m idlelib.idle_test.test_xyz @@ -109,35 +127,35 @@ The following runs all idle_test/test_*.py tests interactively.  >>> import unittest  >>> unittest.main('idlelib.idle_test', verbosity=2) -The following run all Idle tests at a command line.  Option '-v' is the same as -'verbosity=2'.  (For 2.7, replace 'test' in the second line with -'test.regrtest'.) +The following run all Idle tests at a command line.  Option '-v' is the +same as 'verbosity=2'.  python -m unittest -v idlelib.idle_test  python -m test -v -ugui test_idle  python -m test.test_idle -The idle tests are 'discovered' by idlelib.idle_test.__init__.load_tests, -which is also imported into test.test_idle. Normally, neither file should be -changed when working on individual test modules. The third command runs -unittest indirectly through regrtest. The same happens when the entire test -suite is run with 'python -m test'. So that command must work for buildbots -to stay green. Idle tests must not disturb the environment in a way that -makes other tests fail (issue 18081). +The idle tests are 'discovered' by +idlelib.idle_test.__init__.load_tests, which is also imported into +test.test_idle. Normally, neither file should be changed when working on +individual test modules. The third command runs unittest indirectly +through regrtest. The same happens when the entire test suite is run +with 'python -m test'. So that command must work for buildbots to stay +green. Idle tests must not disturb the environment in a way that makes +other tests fail (issue 18081). -To run an individual Testcase or test method, extend the dotted name given to -unittest on the command line. +To run an individual Testcase or test method, extend the dotted name +given to unittest on the command line.  python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth  4. Human-mediated Tests -Human-mediated tests are widget tests that cannot be automated but need human -verification. They are contained in idlelib/idle_test/htest.py, which has -instructions.  (Some modules need an auxiliary function, identified with # htest -# on the header line.)  The set is about complete, though some tests need -improvement. To run all htests, run the htest file from an editor or from the -command line with: +Human-mediated tests are widget tests that cannot be automated but need +human verification. They are contained in idlelib/idle_test/htest.py, +which has instructions.  (Some modules need an auxiliary function, +identified with "# htest # on the header line.)  The set is about +complete, though some tests need improvement. To run all htests, run the +htest file from an editor or from the command line with:  python -m idlelib.idle_test.htest diff --git a/Lib/idlelib/idle_test/__init__.py b/Lib/idlelib/idle_test/__init__.py index 1bc953643e..845c92d372 100644 --- a/Lib/idlelib/idle_test/__init__.py +++ b/Lib/idlelib/idle_test/__init__.py @@ -1,3 +1,9 @@ +'''idlelib.idle_test is a private implementation of test.test_idle, +which tests the IDLE application as part of the stdlib test suite. +Run IDLE tests alone with "python -m test.test_idle". +This package and its contained modules are subject to change and +any direct use is at your own risk. +'''  from os.path import dirname  def load_tests(loader, standard_tests, pattern): diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py index 3e24518a0f..58e62cb4e2 100644 --- a/Lib/idlelib/idle_test/htest.py +++ b/Lib/idlelib/idle_test/htest.py @@ -192,7 +192,10 @@ _io_binding_spec = {      'msg': "Test the following bindings.\n"             "<Control-o> to open file from dialog.\n"             "Edit the file.\n" +           "<Control-p> to print the file.\n"             "<Control-s> to save the file.\n" +           "<Alt-s> to save-as another file.\n" +           "<Control-c> to save-copy-as another file.\n"             "Check that changes were saved by opening the file elsewhere."      } diff --git a/Lib/idlelib/idle_test/mock_tk.py b/Lib/idlelib/idle_test/mock_tk.py index 86fe84884f..6e351297d7 100644 --- a/Lib/idlelib/idle_test/mock_tk.py +++ b/Lib/idlelib/idle_test/mock_tk.py @@ -296,3 +296,8 @@ class Text:      def bind(sequence=None, func=None, add=None):          "Bind to this widget at event sequence a call to function func."          pass + +class Entry: +    "Mock for tkinter.Entry." +    def focus_set(self): +        pass diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py index 3a2192e8af..5fc899dcd4 100644 --- a/Lib/idlelib/idle_test/test_autocomplete.py +++ b/Lib/idlelib/idle_test/test_autocomplete.py @@ -4,7 +4,6 @@ from tkinter import Tk, Text  import idlelib.AutoComplete as ac  import idlelib.AutoCompleteWindow as acw -import idlelib.macosxSupport as mac  from idlelib.idle_test.mock_idle import Func  from idlelib.idle_test.mock_tk import Event @@ -27,15 +26,13 @@ class AutoCompleteTest(unittest.TestCase):      def setUpClass(cls):          requires('gui')          cls.root = Tk() -        mac.setupApp(cls.root, None)          cls.text = Text(cls.root)          cls.editor = DummyEditwin(cls.root, cls.text)      @classmethod      def tearDownClass(cls): +        del cls.editor, cls.text          cls.root.destroy() -        del cls.text -        del cls.editor          del cls.root      def setUp(self): diff --git a/Lib/idlelib/idle_test/test_autoexpand.py b/Lib/idlelib/idle_test/test_autoexpand.py index 7ca941ec29..d2a3156dca 100644 --- a/Lib/idlelib/idle_test/test_autoexpand.py +++ b/Lib/idlelib/idle_test/test_autoexpand.py @@ -25,10 +25,10 @@ class AutoExpandTest(unittest.TestCase):      @classmethod      def tearDownClass(cls): +        del cls.text, cls.auto_expand          if hasattr(cls, 'tk'):              cls.tk.destroy()              del cls.tk -        del cls.text, cls.auto_expand      def tearDown(self):          self.text.delete('1.0', 'end') diff --git a/Lib/idlelib/idle_test/test_config_help.py b/Lib/idlelib/idle_test/test_config_help.py new file mode 100644 index 0000000000..664f8edc62 --- /dev/null +++ b/Lib/idlelib/idle_test/test_config_help.py @@ -0,0 +1,106 @@ +"""Unittests for idlelib.configHelpSourceEdit""" +import unittest +from idlelib.idle_test.mock_tk import Var, Mbox, Entry +from idlelib import configHelpSourceEdit as help_dialog_module + +help_dialog = help_dialog_module.GetHelpSourceDialog + + +class Dummy_help_dialog: +    # Mock for testing the following methods of help_dialog +    menu_ok = help_dialog.menu_ok +    path_ok = help_dialog.path_ok +    ok = help_dialog.ok +    cancel = help_dialog.cancel +    # Attributes, constant or variable, needed for tests +    menu = Var() +    entryMenu = Entry() +    path = Var() +    entryPath = Entry() +    result = None +    destroyed = False + +    def destroy(self): +        self.destroyed = True + + +# menu_ok and path_ok call Mbox.showerror if menu and path are not ok. +orig_mbox = help_dialog_module.tkMessageBox +showerror = Mbox.showerror + + +class ConfigHelpTest(unittest.TestCase): +    dialog = Dummy_help_dialog() + +    @classmethod +    def setUpClass(cls): +        help_dialog_module.tkMessageBox = Mbox + +    @classmethod +    def tearDownClass(cls): +        help_dialog_module.tkMessageBox = orig_mbox + +    def test_blank_menu(self): +        self.dialog.menu.set('') +        self.assertFalse(self.dialog.menu_ok()) +        self.assertEqual(showerror.title, 'Menu Item Error') +        self.assertIn('No', showerror.message) + +    def test_long_menu(self): +        self.dialog.menu.set('hello' * 10) +        self.assertFalse(self.dialog.menu_ok()) +        self.assertEqual(showerror.title, 'Menu Item Error') +        self.assertIn('long', showerror.message) + +    def test_good_menu(self): +        self.dialog.menu.set('help') +        showerror.title = 'No Error'  # should not be called +        self.assertTrue(self.dialog.menu_ok()) +        self.assertEqual(showerror.title, 'No Error') + +    def test_blank_path(self): +        self.dialog.path.set('') +        self.assertFalse(self.dialog.path_ok()) +        self.assertEqual(showerror.title, 'File Path Error') +        self.assertIn('No', showerror.message) + +    def test_invalid_file_path(self): +        self.dialog.path.set('foobar' * 100) +        self.assertFalse(self.dialog.path_ok()) +        self.assertEqual(showerror.title, 'File Path Error') +        self.assertIn('not exist', showerror.message) + +    def test_invalid_url_path(self): +        self.dialog.path.set('ww.foobar.com') +        self.assertFalse(self.dialog.path_ok()) +        self.assertEqual(showerror.title, 'File Path Error') +        self.assertIn('not exist', showerror.message) + +        self.dialog.path.set('htt.foobar.com') +        self.assertFalse(self.dialog.path_ok()) +        self.assertEqual(showerror.title, 'File Path Error') +        self.assertIn('not exist', showerror.message) + +    def test_good_path(self): +        self.dialog.path.set('https://docs.python.org') +        showerror.title = 'No Error'  # should not be called +        self.assertTrue(self.dialog.path_ok()) +        self.assertEqual(showerror.title, 'No Error') + +    def test_ok(self): +        self.dialog.destroyed = False +        self.dialog.menu.set('help') +        self.dialog.path.set('https://docs.python.org') +        self.dialog.ok() +        self.assertEqual(self.dialog.result, ('help', +                                              'https://docs.python.org')) +        self.assertTrue(self.dialog.destroyed) + +    def test_cancel(self): +        self.dialog.destroyed = False +        self.dialog.cancel() +        self.assertEqual(self.dialog.result, None) +        self.assertTrue(self.dialog.destroyed) + +if __name__ == '__main__': +    unittest.main(verbosity=2, exit=False) diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py index 68831236b7..5c09790c64 100644 --- a/Lib/idlelib/idle_test/test_configdialog.py +++ b/Lib/idlelib/idle_test/test_configdialog.py @@ -1,31 +1,32 @@ -'''Unittests for idlelib/configHandler.py - -Coverage: 46% just by creating dialog. The other half is change code. +'''Test idlelib.configDialog. +Coverage: 46% just by creating dialog. +The other half is code for working with user customizations.  ''' -import unittest +from idlelib.configDialog import ConfigDialog  # always test import  from test.support import requires +requires('gui')  from tkinter import Tk -from idlelib.configDialog import ConfigDialog -from idlelib.macosxSupport import _initializeTkVariantTests - +import unittest +from idlelib import macosxSupport as macosx  class ConfigDialogTest(unittest.TestCase):      @classmethod      def setUpClass(cls): -        requires('gui')          cls.root = Tk() -        _initializeTkVariantTests(cls.root) +        cls.root.withdraw() +        macosx._initializeTkVariantTests(cls.root)      @classmethod      def tearDownClass(cls): +        cls.root.update_idletasks()          cls.root.destroy()          del cls.root      def test_dialog(self): -        d=ConfigDialog(self.root, 'Test', _utest=True) -        d.destroy() +        d = ConfigDialog(self.root, 'Test', _utest=True) +        d.remove_var_callbacks()  if __name__ == '__main__': diff --git a/Lib/idlelib/idle_test/test_delegator.py b/Lib/idlelib/idle_test/test_delegator.py index b8ae5eeefe..1f0baa9c0d 100644 --- a/Lib/idlelib/idle_test/test_delegator.py +++ b/Lib/idlelib/idle_test/test_delegator.py @@ -4,34 +4,37 @@ from idlelib.Delegator import Delegator  class DelegatorTest(unittest.TestCase):      def test_mydel(self): -        # test a simple use scenario +        # Test a simple use scenario. -        # initialize +        # Initialize an int delegator.          mydel = Delegator(int)          self.assertIs(mydel.delegate, int)          self.assertEqual(mydel._Delegator__cache, set()) - -        # add an attribute: +        # Trying to access a non-attribute of int fails.          self.assertRaises(AttributeError, mydel.__getattr__, 'xyz') + +        # Add real int attribute 'bit_length' by accessing it.          bl = mydel.bit_length          self.assertIs(bl, int.bit_length)          self.assertIs(mydel.__dict__['bit_length'], int.bit_length)          self.assertEqual(mydel._Delegator__cache, {'bit_length'}) -        # add a second attribute +        # Add attribute 'numerator'.          mydel.numerator          self.assertEqual(mydel._Delegator__cache, {'bit_length', 'numerator'}) -        # delete the second (which, however, leaves it in the name cache) +        # Delete 'numerator'.          del mydel.numerator          self.assertNotIn('numerator', mydel.__dict__) -        self.assertIn('numerator', mydel._Delegator__cache) +        # The current implementation leaves  it in the name cache. +        # self.assertIn('numerator', mydel._Delegator__cache) +        # However, this is not required and not part of the specification -        # reset by calling .setdelegate, which calls .resetcache -        mydel.setdelegate(float) -        self.assertIs(mydel.delegate, float) +        # Change delegate to float, first resetting the attributes. +        mydel.setdelegate(float)  # calls resetcache          self.assertNotIn('bit_length', mydel.__dict__)          self.assertEqual(mydel._Delegator__cache, set()) +        self.assertIs(mydel.delegate, float)  if __name__ == '__main__':      unittest.main(verbosity=2, exit=2) diff --git a/Lib/idlelib/idle_test/test_editmenu.py b/Lib/idlelib/idle_test/test_editmenu.py new file mode 100644 index 0000000000..a258e29e0f --- /dev/null +++ b/Lib/idlelib/idle_test/test_editmenu.py @@ -0,0 +1,72 @@ +'''Test (selected) IDLE Edit menu items. + +Edit modules have their own test files files +''' +from test.support import requires +requires('gui') +import tkinter as tk +import unittest +from idlelib import PyShell + +class PasteTest(unittest.TestCase): +    '''Test pasting into widgets that allow pasting. + +    On X11, replacing selections requires tk fix. +    ''' +    @classmethod +    def setUpClass(cls): +        cls.root = root = tk.Tk() +        root.withdraw() +        PyShell.fix_x11_paste(root) +        cls.text = tk.Text(root) +        cls.entry = tk.Entry(root) +        cls.spin = tk.Spinbox(root) +        root.clipboard_clear() +        root.clipboard_append('two') + +    @classmethod +    def tearDownClass(cls): +        del cls.text, cls.entry, cls.spin +        cls.root.clipboard_clear() +        cls.root.update_idletasks() +        cls.root.destroy() +        del cls.root + +    def test_paste_text(self): +        "Test pasting into text with and without a selection." +        text = self.text +        for tag, ans in ('', 'onetwo\n'), ('sel', 'two\n'): +            with self.subTest(tag=tag, ans=ans): +                text.delete('1.0', 'end') +                text.insert('1.0', 'one', tag) +                text.event_generate('<<Paste>>') +                self.assertEqual(text.get('1.0', 'end'), ans) + +    def test_paste_entry(self): +        "Test pasting into an entry with and without a selection." +        # On 3.6, generated <<Paste>> fails without empty select range +        # for 'no selection'.  Live widget works fine. +        entry = self.entry +        for end, ans in (0, 'onetwo'), ('end', 'two'): +            with self.subTest(entry=entry, end=end, ans=ans): +                entry.delete(0, 'end') +                entry.insert(0, 'one') +                entry.select_range(0, end)  # see note +                entry.event_generate('<<Paste>>') +                self.assertEqual(entry.get(), ans) + +    def test_paste_spin(self): +        "Test pasting into a spinbox with and without a selection." +        # See note above for entry. +        spin = self.spin +        for end, ans in (0, 'onetwo'), ('end', 'two'): +            with self.subTest(end=end, ans=ans): +                spin.delete(0, 'end') +                spin.insert(0, 'one') +                spin.selection('range', 0, end)  # see note +                spin.event_generate('<<Paste>>') +                self.assertEqual(spin.get(), ans) + + +if __name__ == '__main__': +    unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_formatparagraph.py b/Lib/idlelib/idle_test/test_formatparagraph.py index f6039e6ab4..b6eb2f31e4 100644 --- a/Lib/idlelib/idle_test/test_formatparagraph.py +++ b/Lib/idlelib/idle_test/test_formatparagraph.py @@ -159,7 +159,7 @@ class FindTest(unittest.TestCase):  class ReformatFunctionTest(unittest.TestCase):      """Test the reformat_paragraph function without the editor window.""" -    def test_reformat_paragrah(self): +    def test_reformat_paragraph(self):          Equal = self.assertEqual          reform = fp.reformat_paragraph          hw = "O hello world" @@ -276,10 +276,9 @@ class FormatEventTest(unittest.TestCase):      @classmethod      def tearDownClass(cls): +        del cls.text, cls.formatter          cls.root.destroy()          del cls.root -        del cls.text -        del cls.formatter      def test_short_line(self):          self.text.insert('1.0', "Short line\n") diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py new file mode 100644 index 0000000000..d0a012767a --- /dev/null +++ b/Lib/idlelib/idle_test/test_help_about.py @@ -0,0 +1,52 @@ +'''Test idlelib.help_about. + +Coverage: +''' +from idlelib import aboutDialog as help_about +from idlelib import textView as textview +from idlelib.idle_test.mock_idle import Func +from idlelib.idle_test.mock_tk import Mbox +import unittest + +About = help_about.AboutDialog +class Dummy_about_dialog(): +    # Dummy class for testing file display functions. +    idle_credits = About.ShowIDLECredits +    idle_readme = About.ShowIDLEAbout +    idle_news = About.ShowIDLENEWS +    # Called by the above +    display_file_text = About.display_file_text + + +class DisplayFileTest(unittest.TestCase): +    "Test that .txt files are found and properly decoded." +    dialog = Dummy_about_dialog() + +    @classmethod +    def setUpClass(cls): +        cls.orig_mbox = textview.tkMessageBox +        cls.orig_view = textview.view_text +        cls.mbox = Mbox() +        cls.view = Func() +        textview.tkMessageBox = cls.mbox +        textview.view_text = cls.view +        cls.About = Dummy_about_dialog() + +    @classmethod +    def tearDownClass(cls): +        textview.tkMessageBox = cls.orig_mbox +        textview.view_text = cls.orig_view + +    def test_file_isplay(self): +        for handler in (self.dialog.idle_credits, +                        self.dialog.idle_readme, +                        self.dialog.idle_news): +            self.mbox.showerror.message = '' +            self.view.called = False +            handler() +            self.assertEqual(self.mbox.showerror.message, '') +            self.assertEqual(self.view.called, True) + + +if __name__ == '__main__': +    unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_hyperparser.py b/Lib/idlelib/idle_test/test_hyperparser.py index edfc783fe8..9ce3f2c67f 100644 --- a/Lib/idlelib/idle_test/test_hyperparser.py +++ b/Lib/idlelib/idle_test/test_hyperparser.py @@ -37,6 +37,7 @@ class HyperParserTest(unittest.TestCase):      def setUpClass(cls):          requires('gui')          cls.root = Tk() +        cls.root.withdraw()          cls.text = Text(cls.root)          cls.editwin = DummyEditwin(cls.text) diff --git a/Lib/idlelib/idle_test/test_idlehistory.py b/Lib/idlelib/idle_test/test_idlehistory.py index d7c3d70393..6e7c6c3bff 100644 --- a/Lib/idlelib/idle_test/test_idlehistory.py +++ b/Lib/idlelib/idle_test/test_idlehistory.py @@ -68,6 +68,7 @@ class FetchTest(unittest.TestCase):      def setUpClass(cls):          requires('gui')          cls.root = tk.Tk() +        cls.root.withdraw()      def setUp(self):          self.text = text = TextWrapper(self.root) diff --git a/Lib/idlelib/idle_test/test_parenmatch.py b/Lib/idlelib/idle_test/test_parenmatch.py index 9aba4bec93..95cc22cf68 100644 --- a/Lib/idlelib/idle_test/test_parenmatch.py +++ b/Lib/idlelib/idle_test/test_parenmatch.py @@ -1,10 +1,13 @@ -"""Test idlelib.ParenMatch.""" -# This must currently be a gui test because ParenMatch methods use -# several text methods not defined on idlelib.idle_test.mock_tk.Text. +'''Test idlelib.ParenMatch. + +This must currently be a gui test because ParenMatch methods use +several text methods not defined on idlelib.idle_test.mock_tk.Text. +''' +from test.support import requires +requires('gui')  import unittest  from unittest.mock import Mock -from test.support import requires  from tkinter import Tk, Text  from idlelib.ParenMatch import ParenMatch @@ -20,7 +23,6 @@ class ParenMatchTest(unittest.TestCase):      @classmethod      def setUpClass(cls): -        requires('gui')          cls.root = Tk()          cls.text = Text(cls.root)          cls.editwin = DummyEditwin(cls.text) @@ -29,6 +31,7 @@ class ParenMatchTest(unittest.TestCase):      @classmethod      def tearDownClass(cls):          del cls.text, cls.editwin +        cls.root.update_idletasks()          cls.root.destroy()          del cls.root diff --git a/Lib/idlelib/idle_test/test_percolator.py b/Lib/idlelib/idle_test/test_percolator.py new file mode 100644 index 0000000000..4c0a7ad2bd --- /dev/null +++ b/Lib/idlelib/idle_test/test_percolator.py @@ -0,0 +1,118 @@ +'''Test Percolator''' +from test.support import requires +requires('gui') + +import unittest +from tkinter import Text, Tk, END +from idlelib.Percolator import Percolator, Delegator + + +class MyFilter(Delegator): +    def __init__(self): +        Delegator.__init__(self, None) + +    def insert(self, *args): +        self.insert_called_with = args +        self.delegate.insert(*args) + +    def delete(self, *args): +        self.delete_called_with = args +        self.delegate.delete(*args) + +    def uppercase_insert(self, index, chars, tags=None): +        chars = chars.upper() +        self.delegate.insert(index, chars) + +    def lowercase_insert(self, index, chars, tags=None): +        chars = chars.lower() +        self.delegate.insert(index, chars) + +    def dont_insert(self, index, chars, tags=None): +        pass + + +class PercolatorTest(unittest.TestCase): + +    @classmethod +    def setUpClass(cls): +        cls.root = Tk() +        cls.text = Text(cls.root) + +    @classmethod +    def tearDownClass(cls): +        del cls.text +        cls.root.destroy() +        del cls.root + +    def setUp(self): +        self.percolator = Percolator(self.text) +        self.filter_one = MyFilter() +        self.filter_two = MyFilter() +        self.percolator.insertfilter(self.filter_one) +        self.percolator.insertfilter(self.filter_two) + +    def tearDown(self): +        self.percolator.close() +        self.text.delete('1.0', END) + +    def test_insertfilter(self): +        self.assertIsNotNone(self.filter_one.delegate) +        self.assertEqual(self.percolator.top, self.filter_two) +        self.assertEqual(self.filter_two.delegate, self.filter_one) +        self.assertEqual(self.filter_one.delegate, self.percolator.bottom) + +    def test_removefilter(self): +        filter_three = MyFilter() +        self.percolator.removefilter(self.filter_two) +        self.assertEqual(self.percolator.top, self.filter_one) +        self.assertIsNone(self.filter_two.delegate) + +        filter_three = MyFilter() +        self.percolator.insertfilter(self.filter_two) +        self.percolator.insertfilter(filter_three) +        self.percolator.removefilter(self.filter_one) +        self.assertEqual(self.percolator.top, filter_three) +        self.assertEqual(filter_three.delegate, self.filter_two) +        self.assertEqual(self.filter_two.delegate, self.percolator.bottom) +        self.assertIsNone(self.filter_one.delegate) + +    def test_insert(self): +        self.text.insert('insert', 'foo') +        self.assertEqual(self.text.get('1.0', END), 'foo\n') +        self.assertTupleEqual(self.filter_one.insert_called_with, +                              ('insert', 'foo', None)) + +    def test_modify_insert(self): +        self.filter_one.insert = self.filter_one.uppercase_insert +        self.text.insert('insert', 'bAr') +        self.assertEqual(self.text.get('1.0', END), 'BAR\n') + +    def test_modify_chain_insert(self): +        filter_three = MyFilter() +        self.percolator.insertfilter(filter_three) +        self.filter_two.insert = self.filter_two.uppercase_insert +        self.filter_one.insert = self.filter_one.lowercase_insert +        self.text.insert('insert', 'BaR') +        self.assertEqual(self.text.get('1.0', END), 'bar\n') + +    def test_dont_insert(self): +        self.filter_one.insert = self.filter_one.dont_insert +        self.text.insert('insert', 'foo bar') +        self.assertEqual(self.text.get('1.0', END), '\n') +        self.filter_one.insert = self.filter_one.dont_insert +        self.text.insert('insert', 'foo bar') +        self.assertEqual(self.text.get('1.0', END), '\n') + +    def test_without_filter(self): +        self.text.insert('insert', 'hello') +        self.assertEqual(self.text.get('1.0', 'end'), 'hello\n') + +    def test_delete(self): +        self.text.insert('insert', 'foo') +        self.text.delete('1.0', '1.2') +        self.assertEqual(self.text.get('1.0', END), 'o\n') +        self.assertTupleEqual(self.filter_one.delete_called_with, +                              ('1.0', '1.2')) + +if __name__ == '__main__': +    unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_replacedialog.py b/Lib/idlelib/idle_test/test_replacedialog.py new file mode 100644 index 0000000000..ff44820809 --- /dev/null +++ b/Lib/idlelib/idle_test/test_replacedialog.py @@ -0,0 +1,293 @@ +"""Unittest for idlelib.ReplaceDialog""" +from test.support import requires +requires('gui') + +import unittest +from unittest.mock import Mock +from tkinter import Tk, Text +from idlelib.idle_test.mock_tk import Mbox +import idlelib.SearchEngine as se +import idlelib.ReplaceDialog as rd + +orig_mbox = se.tkMessageBox +showerror = Mbox.showerror + + +class ReplaceDialogTest(unittest.TestCase): + +    @classmethod +    def setUpClass(cls): +        cls.root = Tk() +        cls.root.withdraw() +        se.tkMessageBox = Mbox +        cls.engine = se.SearchEngine(cls.root) +        cls.dialog = rd.ReplaceDialog(cls.root, cls.engine) +        cls.dialog.ok = Mock() +        cls.text = Text(cls.root) +        cls.text.undo_block_start = Mock() +        cls.text.undo_block_stop = Mock() +        cls.dialog.text = cls.text + +    @classmethod +    def tearDownClass(cls): +        se.tkMessageBox = orig_mbox +        del cls.text, cls.dialog, cls.engine +        cls.root.destroy() +        del cls.root + +    def setUp(self): +        self.text.insert('insert', 'This is a sample sTring') + +    def tearDown(self): +        self.engine.patvar.set('') +        self.dialog.replvar.set('') +        self.engine.wordvar.set(False) +        self.engine.casevar.set(False) +        self.engine.revar.set(False) +        self.engine.wrapvar.set(True) +        self.engine.backvar.set(False) +        showerror.title = '' +        showerror.message = '' +        self.text.delete('1.0', 'end') + +    def test_replace_simple(self): +        # Test replace function with all options at default setting. +        # Wrap around - True +        # Regular Expression - False +        # Match case - False +        # Match word - False +        # Direction - Forwards +        text = self.text +        equal = self.assertEqual +        pv = self.engine.patvar +        rv = self.dialog.replvar +        replace = self.dialog.replace_it + +        # test accessor method +        self.engine.setpat('asdf') +        equal(self.engine.getpat(), pv.get()) + +        # text found and replaced +        pv.set('a') +        rv.set('asdf') +        self.dialog.open(self.text) +        replace() +        equal(text.get('1.8', '1.12'), 'asdf') + +        # dont "match word" case +        text.mark_set('insert', '1.0') +        pv.set('is') +        rv.set('hello') +        replace() +        equal(text.get('1.2', '1.7'), 'hello') + +        # dont "match case" case +        pv.set('string') +        rv.set('world') +        replace() +        equal(text.get('1.23', '1.28'), 'world') + +        # without "regular expression" case +        text.mark_set('insert', 'end') +        text.insert('insert', '\nline42:') +        before_text = text.get('1.0', 'end') +        pv.set('[a-z][\d]+') +        replace() +        after_text = text.get('1.0', 'end') +        equal(before_text, after_text) + +        # test with wrap around selected and complete a cycle +        text.mark_set('insert', '1.9') +        pv.set('i') +        rv.set('j') +        replace() +        equal(text.get('1.8'), 'i') +        equal(text.get('2.1'), 'j') +        replace() +        equal(text.get('2.1'), 'j') +        equal(text.get('1.8'), 'j') +        before_text = text.get('1.0', 'end') +        replace() +        after_text = text.get('1.0', 'end') +        equal(before_text, after_text) + +        # text not found +        before_text = text.get('1.0', 'end') +        pv.set('foobar') +        replace() +        after_text = text.get('1.0', 'end') +        equal(before_text, after_text) + +        # test access method +        self.dialog.find_it(0) + +    def test_replace_wrap_around(self): +        text = self.text +        equal = self.assertEqual +        pv = self.engine.patvar +        rv = self.dialog.replvar +        replace = self.dialog.replace_it +        self.engine.wrapvar.set(False) + +        # replace candidate found both after and before 'insert' +        text.mark_set('insert', '1.4') +        pv.set('i') +        rv.set('j') +        replace() +        equal(text.get('1.2'), 'i') +        equal(text.get('1.5'), 'j') +        replace() +        equal(text.get('1.2'), 'i') +        equal(text.get('1.20'), 'j') +        replace() +        equal(text.get('1.2'), 'i') + +        # replace candidate found only before 'insert' +        text.mark_set('insert', '1.8') +        pv.set('is') +        before_text = text.get('1.0', 'end') +        replace() +        after_text = text.get('1.0', 'end') +        equal(before_text, after_text) + +    def test_replace_whole_word(self): +        text = self.text +        equal = self.assertEqual +        pv = self.engine.patvar +        rv = self.dialog.replvar +        replace = self.dialog.replace_it +        self.engine.wordvar.set(True) + +        pv.set('is') +        rv.set('hello') +        replace() +        equal(text.get('1.0', '1.4'), 'This') +        equal(text.get('1.5', '1.10'), 'hello') + +    def test_replace_match_case(self): +        equal = self.assertEqual +        text = self.text +        pv = self.engine.patvar +        rv = self.dialog.replvar +        replace = self.dialog.replace_it +        self.engine.casevar.set(True) + +        before_text = self.text.get('1.0', 'end') +        pv.set('this') +        rv.set('that') +        replace() +        after_text = self.text.get('1.0', 'end') +        equal(before_text, after_text) + +        pv.set('This') +        replace() +        equal(text.get('1.0', '1.4'), 'that') + +    def test_replace_regex(self): +        equal = self.assertEqual +        text = self.text +        pv = self.engine.patvar +        rv = self.dialog.replvar +        replace = self.dialog.replace_it +        self.engine.revar.set(True) + +        before_text = text.get('1.0', 'end') +        pv.set('[a-z][\d]+') +        rv.set('hello') +        replace() +        after_text = text.get('1.0', 'end') +        equal(before_text, after_text) + +        text.insert('insert', '\nline42') +        replace() +        equal(text.get('2.0', '2.8'), 'linhello') + +        pv.set('') +        replace() +        self.assertIn('error', showerror.title) +        self.assertIn('Empty', showerror.message) + +        pv.set('[\d') +        replace() +        self.assertIn('error', showerror.title) +        self.assertIn('Pattern', showerror.message) + +        showerror.title = '' +        showerror.message = '' +        pv.set('[a]') +        rv.set('test\\') +        replace() +        self.assertIn('error', showerror.title) +        self.assertIn('Invalid Replace Expression', showerror.message) + +        # test access method +        self.engine.setcookedpat("\'") +        equal(pv.get(), "\\'") + +    def test_replace_backwards(self): +        equal = self.assertEqual +        text = self.text +        pv = self.engine.patvar +        rv = self.dialog.replvar +        replace = self.dialog.replace_it +        self.engine.backvar.set(True) + +        text.insert('insert', '\nis as ') + +        pv.set('is') +        rv.set('was') +        replace() +        equal(text.get('1.2', '1.4'), 'is') +        equal(text.get('2.0', '2.3'), 'was') +        replace() +        equal(text.get('1.5', '1.8'), 'was') +        replace() +        equal(text.get('1.2', '1.5'), 'was') + +    def test_replace_all(self): +        text = self.text +        pv = self.engine.patvar +        rv = self.dialog.replvar +        replace_all = self.dialog.replace_all + +        text.insert('insert', '\n') +        text.insert('insert', text.get('1.0', 'end')*100) +        pv.set('is') +        rv.set('was') +        replace_all() +        self.assertNotIn('is', text.get('1.0', 'end')) + +        self.engine.revar.set(True) +        pv.set('') +        replace_all() +        self.assertIn('error', showerror.title) +        self.assertIn('Empty', showerror.message) + +        pv.set('[s][T]') +        rv.set('\\') +        replace_all() + +        self.engine.revar.set(False) +        pv.set('text which is not present') +        rv.set('foobar') +        replace_all() + +    def test_default_command(self): +        text = self.text +        pv = self.engine.patvar +        rv = self.dialog.replvar +        replace_find = self.dialog.default_command +        equal = self.assertEqual + +        pv.set('This') +        rv.set('was') +        replace_find() +        equal(text.get('sel.first', 'sel.last'), 'was') + +        self.engine.revar.set(True) +        pv.set('') +        replace_find() + + +if __name__ == '__main__': +    unittest.main(verbosity=2) diff --git a/Lib/idlelib/idle_test/test_searchdialog.py b/Lib/idlelib/idle_test/test_searchdialog.py new file mode 100644 index 0000000000..190c866a18 --- /dev/null +++ b/Lib/idlelib/idle_test/test_searchdialog.py @@ -0,0 +1,80 @@ +"""Test SearchDialog class in SearchDialogue.py""" + +# Does not currently test the event handler wrappers. +# A usage test should simulate clicks and check hilighting. +# Tests need to be coordinated with SearchDialogBase tests +# to avoid duplication. + +from test.support import requires +requires('gui') + +import unittest +import tkinter as tk +from tkinter import BooleanVar +import idlelib.SearchEngine as se +import idlelib.SearchDialog as sd + + +class SearchDialogTest(unittest.TestCase): + +    @classmethod +    def setUpClass(cls): +        cls.root = tk.Tk() + +    @classmethod +    def tearDownClass(cls): +        cls.root.destroy() +        del cls.root + +    def setUp(self): +        self.engine = se.SearchEngine(self.root) +        self.dialog = sd.SearchDialog(self.root, self.engine) +        self.text = tk.Text(self.root) +        self.text.insert('1.0', 'Hello World!') + +    def test_find_again(self): +        # Search for various expressions +        text = self.text + +        self.engine.setpat('') +        self.assertFalse(self.dialog.find_again(text)) + +        self.engine.setpat('Hello') +        self.assertTrue(self.dialog.find_again(text)) + +        self.engine.setpat('Goodbye') +        self.assertFalse(self.dialog.find_again(text)) + +        self.engine.setpat('World!') +        self.assertTrue(self.dialog.find_again(text)) + +        self.engine.setpat('Hello World!') +        self.assertTrue(self.dialog.find_again(text)) + +        # Regular expression +        self.engine.revar = BooleanVar(self.root, True) +        self.engine.setpat('W[aeiouy]r') +        self.assertTrue(self.dialog.find_again(text)) + +    def test_find_selection(self): +        # Select some text and make sure it's found +        text = self.text +        # Add additional line to find +        self.text.insert('2.0', 'Hello World!') + +        text.tag_add('sel', '1.0', '1.4')       # Select 'Hello' +        self.assertTrue(self.dialog.find_selection(text)) + +        text.tag_remove('sel', '1.0', 'end') +        text.tag_add('sel', '1.6', '1.11')      # Select 'World!' +        self.assertTrue(self.dialog.find_selection(text)) + +        text.tag_remove('sel', '1.0', 'end') +        text.tag_add('sel', '1.0', '1.11')      # Select 'Hello World!' +        self.assertTrue(self.dialog.find_selection(text)) + +        # Remove additional line +        text.delete('2.0', 'end') + +if __name__ == '__main__': +    unittest.main(verbosity=2, exit=2) diff --git a/Lib/idlelib/idle_test/test_searchengine.py b/Lib/idlelib/idle_test/test_searchengine.py index c7792fb188..edbd558133 100644 --- a/Lib/idlelib/idle_test/test_searchengine.py +++ b/Lib/idlelib/idle_test/test_searchengine.py @@ -178,7 +178,7 @@ class SearchEngineTest(unittest.TestCase):          engine.revar.set(1)          Equal(engine.getprog(), None)          self.assertEqual(Mbox.showerror.message, -                          'Error: nothing to repeat\nPattern: +') +                         'Error: nothing to repeat at position 0\nPattern: +')      def test_report_error(self):          showerror = Mbox.showerror diff --git a/Lib/idlelib/idle_test/test_textview.py b/Lib/idlelib/idle_test/test_textview.py index 68e5b82ad9..5d2e60019d 100644 --- a/Lib/idlelib/idle_test/test_textview.py +++ b/Lib/idlelib/idle_test/test_textview.py @@ -1,4 +1,4 @@ -'''Test the functions and main class method of textView.py. +'''Test idlelib.textView.  Since all methods and functions create (or destroy) a TextViewer, which  is a widget containing multiple widgets, all tests must be gui tests. @@ -20,14 +20,16 @@ from idlelib.idle_test.mock_tk import Mbox  def setUpModule():      global root      root = Tk() +    root.withdraw()  def tearDownModule():      global root -    root.destroy()  # pyflakes falsely sees root as undefined +    root.update_idletasks() +    root.destroy()  # Pyflakes falsely sees root as undefined.      del root -class TV(tv.TextViewer):  # used by TextViewTest +class TV(tv.TextViewer):  # Used in TextViewTest.      transient = Func()      grab_set = Func()      wait_window = Func() @@ -58,8 +60,8 @@ class TextViewTest(unittest.TestCase):          view.destroy = Func()          view.Ok()          self.assertTrue(view.destroy.called) -        del view.destroy  # unmask real function -        view.destroy +        del view.destroy  # Unmask real function. +        view.destroy()  class textviewTest(unittest.TestCase): @@ -75,9 +77,10 @@ class textviewTest(unittest.TestCase):          del cls.orig_mbox      def test_view_text(self): -        # If modal True, tkinter will error with 'can't invoke "event" command' +        # If modal True, get tk error 'can't invoke "event" command'.          view = tv.view_text(root, 'Title', 'test text', modal=False)          self.assertIsInstance(view, tv.TextViewer) +        view.Ok()      def test_view_file(self):          test_dir = os.path.dirname(__file__) diff --git a/Lib/idlelib/idle_test/test_undodelegator.py b/Lib/idlelib/idle_test/test_undodelegator.py new file mode 100644 index 0000000000..2b83c991e2 --- /dev/null +++ b/Lib/idlelib/idle_test/test_undodelegator.py @@ -0,0 +1,135 @@ +"""Unittest for UndoDelegator in idlelib.UndoDelegator. + +Coverage about 80% (retest). +""" +from test.support import requires +requires('gui') + +import unittest +from unittest.mock import Mock +from tkinter import Text, Tk +from idlelib.UndoDelegator import UndoDelegator +from idlelib.Percolator import Percolator + + +class UndoDelegatorTest(unittest.TestCase): + +    @classmethod +    def setUpClass(cls): +        cls.root = Tk() +        cls.text = Text(cls.root) +        cls.percolator = Percolator(cls.text) + +    @classmethod +    def tearDownClass(cls): +        cls.percolator.redir.close() +        del cls.percolator, cls.text +        cls.root.destroy() +        del cls.root + +    def setUp(self): +        self.delegator = UndoDelegator() +        self.percolator.insertfilter(self.delegator) +        self.delegator.bell = Mock(wraps=self.delegator.bell) + +    def tearDown(self): +        self.percolator.removefilter(self.delegator) +        self.text.delete('1.0', 'end') +        self.delegator.resetcache() + +    def test_undo_event(self): +        text = self.text + +        text.insert('insert', 'foobar') +        text.insert('insert', 'h') +        text.event_generate('<<undo>>') +        self.assertEqual(text.get('1.0', 'end'), '\n') + +        text.insert('insert', 'foo') +        text.insert('insert', 'bar') +        text.delete('1.2', '1.4') +        text.insert('insert', 'hello') +        text.event_generate('<<undo>>') +        self.assertEqual(text.get('1.0', '1.4'), 'foar') +        text.event_generate('<<undo>>') +        self.assertEqual(text.get('1.0', '1.6'), 'foobar') +        text.event_generate('<<undo>>') +        self.assertEqual(text.get('1.0', '1.3'), 'foo') +        text.event_generate('<<undo>>') +        self.delegator.undo_event('event') +        self.assertTrue(self.delegator.bell.called) + +    def test_redo_event(self): +        text = self.text + +        text.insert('insert', 'foo') +        text.insert('insert', 'bar') +        text.delete('1.0', '1.3') +        text.event_generate('<<undo>>') +        text.event_generate('<<redo>>') +        self.assertEqual(text.get('1.0', '1.3'), 'bar') +        text.event_generate('<<redo>>') +        self.assertTrue(self.delegator.bell.called) + +    def test_dump_event(self): +        """ +        Dump_event cannot be tested directly without changing +        environment variables. So, test statements in dump_event +        indirectly +        """ +        text = self.text +        d = self.delegator + +        text.insert('insert', 'foo') +        text.insert('insert', 'bar') +        text.delete('1.2', '1.4') +        self.assertTupleEqual((d.pointer, d.can_merge), (3, True)) +        text.event_generate('<<undo>>') +        self.assertTupleEqual((d.pointer, d.can_merge), (2, False)) + +    def test_get_set_saved(self): +        # test the getter method get_saved +        # test the setter method set_saved +        # indirectly test check_saved +        d = self.delegator + +        self.assertTrue(d.get_saved()) +        self.text.insert('insert', 'a') +        self.assertFalse(d.get_saved()) +        d.saved_change_hook = Mock() + +        d.set_saved(True) +        self.assertEqual(d.pointer, d.saved) +        self.assertTrue(d.saved_change_hook.called) + +        d.set_saved(False) +        self.assertEqual(d.saved, -1) +        self.assertTrue(d.saved_change_hook.called) + +    def test_undo_start_stop(self): +        # test the undo_block_start and undo_block_stop methods +        text = self.text + +        text.insert('insert', 'foo') +        self.delegator.undo_block_start() +        text.insert('insert', 'bar') +        text.insert('insert', 'bar') +        self.delegator.undo_block_stop() +        self.assertEqual(text.get('1.0', '1.3'), 'foo') + +        # test another code path +        self.delegator.undo_block_start() +        text.insert('insert', 'bar') +        self.delegator.undo_block_stop() +        self.assertEqual(text.get('1.0', '1.3'), 'foo') + +    def test_addcmd(self): +        text = self.text +        # when number of undo operations exceeds max_undo +        self.delegator.max_undo = max_undo = 10 +        for i in range(max_undo + 10): +            text.insert('insert', 'foo') +            self.assertLessEqual(len(self.delegator.undolist), max_undo) + +if __name__ == '__main__': +    unittest.main(verbosity=2, exit=False) diff --git a/Lib/idlelib/idle_test/test_warning.py b/Lib/idlelib/idle_test/test_warning.py index 54ac993e88..18627ddd23 100644 --- a/Lib/idlelib/idle_test/test_warning.py +++ b/Lib/idlelib/idle_test/test_warning.py @@ -68,15 +68,6 @@ class ShellWarnTest(unittest.TestCase):                      'Test', UserWarning, 'test_warning.py', 99, f, 'Line of code')              self.assertEqual(shellmsg.splitlines(), f.getvalue().splitlines()) -class ImportWarnTest(unittest.TestCase): -    def test_idlever(self): -        with warnings.catch_warnings(record=True) as w: -            warnings.simplefilter("always") -            import idlelib.idlever -            self.assertEqual(len(w), 1) -            self.assertTrue(issubclass(w[-1].category, DeprecationWarning)) -            self.assertIn("version", str(w[-1].message)) -  if __name__ == '__main__':      unittest.main(verbosity=2, exit=False) diff --git a/Lib/idlelib/idle_test/test_widgetredir.py b/Lib/idlelib/idle_test/test_widgetredir.py index 64405615a0..baa975db35 100644 --- a/Lib/idlelib/idle_test/test_widgetredir.py +++ b/Lib/idlelib/idle_test/test_widgetredir.py @@ -1,7 +1,7 @@ -"""Unittest for idlelib.WidgetRedirector +'''Test idlelib.WidgetRedirector.  100% coverage -""" +'''  from test.support import requires  import unittest  from idlelib.idle_test.mock_idle import Func @@ -14,14 +14,15 @@ class InitCloseTest(unittest.TestCase):      @classmethod      def setUpClass(cls):          requires('gui') -        cls.tk = Tk() -        cls.text = Text(cls.tk) +        cls.root = Tk() +        cls.root.withdraw() +        cls.text = Text(cls.root)      @classmethod      def tearDownClass(cls): -        cls.text.destroy() -        cls.tk.destroy() -        del cls.text, cls.tk +        del cls.text +        cls.root.destroy() +        del cls.root      def test_init(self):          redir = WidgetRedirector(self.text) @@ -43,14 +44,16 @@ class WidgetRedirectorTest(unittest.TestCase):      @classmethod      def setUpClass(cls):          requires('gui') -        cls.tk = Tk() -        cls.text = Text(cls.tk) +        cls.root = Tk() +        cls.root.withdraw() +        cls.text = Text(cls.root)      @classmethod      def tearDownClass(cls): -        cls.text.destroy() -        cls.tk.destroy() -        del cls.text, cls.tk +        del cls.text +        cls.root.update_idletasks() +        cls.root.destroy() +        del cls.root      def setUp(self):          self.redir = WidgetRedirector(self.text) @@ -108,13 +111,13 @@ class WidgetRedirectorTest(unittest.TestCase):      def test_command_dispatch(self):          # Test that .__init__ causes redirection of tk calls          # through redir.dispatch -        self.tk.call(self.text._w, 'insert', 'hello') +        self.root.call(self.text._w, 'insert', 'hello')          self.assertEqual(self.func.args, ('hello',))          self.assertEqual(self.text.get('1.0', 'end'), '\n')          # Ensure that called through redir .dispatch and not through          # self.text.insert by having mock raise TclError.          self.func.__init__(TclError()) -        self.assertEqual(self.tk.call(self.text._w, 'insert', 'boo'), '') +        self.assertEqual(self.root.call(self.text._w, 'insert', 'boo'), '') diff --git a/Lib/idlelib/rpc.py b/Lib/idlelib/rpc.py index aa33041e7b..48105f2aa1 100644 --- a/Lib/idlelib/rpc.py +++ b/Lib/idlelib/rpc.py @@ -1,4 +1,4 @@ -"""RPC Implemention, originally written for the Python Idle IDE +"""RPC Implementation, originally written for the Python Idle IDE  For security reasons, GvR requested that Idle's Python execution server process  connect to the Idle process, which listens for the connection.  Since Idle has diff --git a/Lib/idlelib/run.py b/Lib/idlelib/run.py index 595e7bc3aa..28ce4200a9 100644 --- a/Lib/idlelib/run.py +++ b/Lib/idlelib/run.py @@ -19,6 +19,12 @@ from idlelib import IOBinding  import __main__ +for mod in ('simpledialog', 'messagebox', 'font', +            'dialog', 'filedialog', 'commondialog', +            'colorchooser'): +    delattr(tkinter, mod) +    del sys.modules['tkinter.' + mod] +  LOCALHOST = '127.0.0.1'  import warnings diff --git a/Lib/idlelib/textView.py b/Lib/idlelib/textView.py index 01b2d8f4ab..12ac31962d 100644 --- a/Lib/idlelib/textView.py +++ b/Lib/idlelib/textView.py @@ -76,6 +76,10 @@ def view_file(parent, title, filename, encoding=None, modal=True):          tkMessageBox.showerror(title='File Load Error',                                 message='Unable to load file %r .' % filename,                                 parent=parent) +    except UnicodeDecodeError as err: +        tkMessageBox.showerror(title='Unicode Decode Error', +                               message=str(err), +                               parent=parent)      else:          return view_text(parent, title, contents, modal)  | 
