[Python-checkins] cpython (merge 3.6 -> default): Merge with 3.6

terry.reedy python-checkins at python.org
Mon Nov 7 17:15:31 EST 2016


https://hg.python.org/cpython/rev/d0e4440a68b3
changeset:   104958:d0e4440a68b3
parent:      104956:38c806f0943b
parent:      104957:d6440718eb30
user:        Terry Jan Reedy <tjreedy at udel.edu>
date:        Mon Nov 07 17:15:16 2016 -0500
summary:
  Merge with 3.6

files:
  Lib/idlelib/config-main.def                |   68 ++--
  Lib/idlelib/config.py                      |   23 +-
  Lib/idlelib/configdialog.py                |   32 +-
  Lib/idlelib/idle_test/test_configdialog.py |  129 ++++++++-
  4 files changed, 179 insertions(+), 73 deletions(-)


diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def
--- a/Lib/idlelib/config-main.def
+++ b/Lib/idlelib/config-main.def
@@ -4,44 +4,50 @@
 # When IDLE starts, it will look in
 # the following two sets of files, in order:
 #
-#     default configuration
-#     ---------------------
-#     config-main.def         the default general config file
-#     config-extensions.def   the default extension config file
-#     config-highlight.def    the default highlighting config file
-#     config-keys.def         the default keybinding config file
+#     default configuration files in idlelib
+#     --------------------------------------
+#     config-main.def         default general config file
+#     config-extensions.def   default extension config file
+#     config-highlight.def    default highlighting config file
+#     config-keys.def         default keybinding config file
 #
-#     user configuration
-#     -------------------
-#     ~/.idlerc/config-main.cfg            the user general config file
-#     ~/.idlerc/config-extensions.cfg      the user extension config file
-#     ~/.idlerc/config-highlight.cfg       the user highlighting config file
-#     ~/.idlerc/config-keys.cfg            the user keybinding config file
+#     user configuration files in ~/.idlerc
+#     -------------------------------------
+#     config-main.cfg         user general config file
+#     config-extensions.cfg   user extension config file
+#     config-highlight.cfg    user highlighting config file
+#     config-keys.cfg         user keybinding config file
 #
-# On Windows2000 and Windows XP the .idlerc directory is at
-#     Documents and Settings\<username>\.idlerc
-#
-# On Windows98 it is at c:\.idlerc
+# On Windows, the default location of the home directory ('~' above)
+# depends on the version.  For Windows 10, it is C:\Users\<username>.
 #
 # Any options the user saves through the config dialog will be saved to
-# the relevant user config file. Reverting any general setting to the
-# default causes that entry to be wiped from the user file and re-read
-# from the default file. User highlighting themes or keybinding sets are
-# retained unless specifically deleted within the config dialog. Choosing
-# one of the default themes or keysets just applies the relevant settings
-# from the default file.
+# the relevant user config file. Reverting any general or extension
+# setting to the default causes that entry to be wiped from the user
+# file and re-read from the default file.  This rule applies to each
+# item, except that the three editor font items are saved as a group.
 #
-# Additional help sources are listed in the [HelpFiles] section and must be
-# viewable by a web browser (or the Windows Help viewer in the case of .chm
-# files). These sources will be listed on the Help menu.  The pattern is
+# User highlighting themes and keybinding sets must have (section) names
+# distinct from the default names.  All items are added and saved as a
+# group. They are retained unless specifically deleted within the config
+# dialog. Choosing one of the default themes or keysets just applies the
+# relevant settings from the default file.
+#
+# Additional help sources are listed in the [HelpFiles] section below
+# and should be viewable by a web browser (or the Windows Help viewer in
+# the case of .chm files). These sources will be listed on the Help
+# menu.  The pattern, and two examples, are
+#
 # <sequence_number = menu item;/path/to/help/source>
-# You can't use a semi-colon in a menu item or path.  The path will be platform
-# specific because of path separators, drive specs etc.
+# 1 = IDLE;C:/Programs/Python36/Lib/idlelib/help.html
+# 2 = Pillow;https://pillow.readthedocs.io/en/latest/
 #
-# It is best to use the Configuration GUI to set up additional help sources!
-# Example:
-#1 = My Extra Help Source;/usr/share/doc/foo/index.html
-#2 = Another Help Source;/path/to/another.pdf
+# You can't use a semi-colon in a menu item or path.  The path will be
+# platform specific because of path separators, drive specs etc.
+#
+# The default files should not be edited except to add new sections to
+# config-extensions.def for added extensions .  The user files should be
+# modified through the Settings dialog.
 
 [General]
 editor-on-startup= 0
diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py
--- a/Lib/idlelib/config.py
+++ b/Lib/idlelib/config.py
@@ -1,13 +1,20 @@
-"""Provides access to stored IDLE configuration information.
+"""idlelib.config -- Manage IDLE configuration information.
 
-Refer to the comments at the beginning of config-main.def for a description of
-the available configuration files and the design implemented to update user
-configuration information.  In particular, user configuration choices which
-duplicate the defaults will be removed from the user's configuration files,
-and if a file becomes empty, it will be deleted.
+The comments at the beginning of config-main.def describe the
+configuration files and the design implemented to update user
+configuration information.  In particular, user configuration choices
+which duplicate the defaults will be removed from the user's
+configuration files, and if a user file becomes empty, it will be
+deleted.
 
-The contents of the user files may be altered using the Options/Configure IDLE
-menu to access the configuration GUI (configdialog.py), or manually.
+The configuration database maps options to values.  Comceptually, the
+database keys are tuples (config-type, section, item).  As implemented,
+there are  separate dicts for default and user values.  Each has
+config-type keys 'main', 'extensions', 'highlight', and 'keys'.  The
+value for each key is a ConfigParser instance that maps section and item
+to values.  For 'main' and 'extenstons', user values override
+default values.  For 'highlight' and 'keys', user sections augment the
+default sections (and must, therefore, have distinct names).
 
 Throughout this module there is an emphasis on returning useable defaults
 when a problem occurs in returning a requested configuration value back to
diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py
--- a/Lib/idlelib/configdialog.py
+++ b/Lib/idlelib/configdialog.py
@@ -392,28 +392,28 @@
                                text=' Additional Help Sources ')
         #frameRun
         labelRunChoiceTitle = Label(frameRun, text='At Startup')
-        radioStartupEdit = Radiobutton(
+        self.radioStartupEdit = Radiobutton(
                 frameRun, variable=self.startupEdit, value=1,
-                command=self.SetKeysType, text="Open Edit Window")
-        radioStartupShell = Radiobutton(
+                text="Open Edit Window")
+        self.radioStartupShell = Radiobutton(
                 frameRun, variable=self.startupEdit, value=0,
-                command=self.SetKeysType, text='Open Shell Window')
+                text='Open Shell Window')
         #frameSave
         labelRunSaveTitle = Label(frameSave, text='At Start of Run (F5)  ')
-        radioSaveAsk = Radiobutton(
+        self.radioSaveAsk = Radiobutton(
                 frameSave, variable=self.autoSave, value=0,
-                command=self.SetKeysType, text="Prompt to Save")
-        radioSaveAuto = Radiobutton(
+                text="Prompt to Save")
+        self.radioSaveAuto = Radiobutton(
                 frameSave, variable=self.autoSave, value=1,
-                command=self.SetKeysType, text='No Prompt')
+                text='No Prompt')
         #frameWinSize
         labelWinSizeTitle = Label(
                 frameWinSize, text='Initial Window Size  (in characters)')
         labelWinWidthTitle = Label(frameWinSize, text='Width')
-        entryWinWidth = Entry(
+        self.entryWinWidth = Entry(
                 frameWinSize, textvariable=self.winWidth, width=3)
         labelWinHeightTitle = Label(frameWinSize, text='Height')
-        entryWinHeight = Entry(
+        self.entryWinHeight = Entry(
                 frameWinSize, textvariable=self.winHeight, width=3)
         #frameHelp
         frameHelpList = Frame(frameHelp)
@@ -443,17 +443,17 @@
         frameHelp.pack(side=TOP, padx=5, pady=5, expand=TRUE, fill=BOTH)
         #frameRun
         labelRunChoiceTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
-        radioStartupShell.pack(side=RIGHT, anchor=W, padx=5, pady=5)
-        radioStartupEdit.pack(side=RIGHT, anchor=W, padx=5, pady=5)
+        self.radioStartupShell.pack(side=RIGHT, anchor=W, padx=5, pady=5)
+        self.radioStartupEdit.pack(side=RIGHT, anchor=W, padx=5, pady=5)
         #frameSave
         labelRunSaveTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
-        radioSaveAuto.pack(side=RIGHT, anchor=W, padx=5, pady=5)
-        radioSaveAsk.pack(side=RIGHT, anchor=W, padx=5, pady=5)
+        self.radioSaveAuto.pack(side=RIGHT, anchor=W, padx=5, pady=5)
+        self.radioSaveAsk.pack(side=RIGHT, anchor=W, padx=5, pady=5)
         #frameWinSize
         labelWinSizeTitle.pack(side=LEFT, anchor=W, padx=5, pady=5)
-        entryWinHeight.pack(side=RIGHT, anchor=E, padx=10, pady=5)
+        self.entryWinHeight.pack(side=RIGHT, anchor=E, padx=10, pady=5)
         labelWinHeightTitle.pack(side=RIGHT, anchor=E, pady=5)
-        entryWinWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5)
+        self.entryWinWidth.pack(side=RIGHT, anchor=E, padx=10, pady=5)
         labelWinWidthTitle.pack(side=RIGHT, anchor=E, pady=5)
         #frameHelp
         frameHelpListButtons.pack(side=RIGHT, padx=5, pady=5, fill=Y)
diff --git a/Lib/idlelib/idle_test/test_configdialog.py b/Lib/idlelib/idle_test/test_configdialog.py
--- a/Lib/idlelib/idle_test/test_configdialog.py
+++ b/Lib/idlelib/idle_test/test_configdialog.py
@@ -1,30 +1,123 @@
-'''Test idlelib.configdialog.
+"""Test idlelib.configdialog.
 
-Coverage: 46% just by creating dialog.
-The other half is code for working with user customizations.
-'''
-from idlelib.configdialog import ConfigDialog  # always test import
+Half the class creates dialog, half works with user customizations.
+Coverage: 46% just by creating dialog, 56% with current tests.
+"""
+from idlelib.configdialog import ConfigDialog, idleConf  # test import
 from test.support import requires
 requires('gui')
 from tkinter import Tk
 import unittest
+import idlelib.config as config
 
-class ConfigDialogTest(unittest.TestCase):
+# Tests should not depend on fortuitous user configurations.
+# They must not affect actual user .cfg files.
+# Use solution from test_config: empty parsers with no filename.
+usercfg = idleConf.userCfg
+testcfg = {
+    'main': config.IdleUserConfParser(''),
+    'highlight': config.IdleUserConfParser(''),
+    'keys': config.IdleUserConfParser(''),
+    'extensions': config.IdleUserConfParser(''),
+}
 
-    @classmethod
-    def setUpClass(cls):
-        cls.root = Tk()
-        cls.root.withdraw()
+# ConfigDialog.changedItems is a 3-level hierarchical dictionary of
+# pending changes that mirrors the multilevel user config dict.
+# For testing, record args in a list for comparison with expected.
+changes = []
+class TestDialog(ConfigDialog):
+    def AddChangedItem(self, *args):
+        changes.append(args)
 
-    @classmethod
-    def tearDownClass(cls):
-        cls.root.update_idletasks()
-        cls.root.destroy()
-        del cls.root
+def setUpModule():
+    global root, configure
+    idleConf.userCfg = testcfg
+    root = Tk()
+    root.withdraw()
+    configure = TestDialog(root, 'Test', _utest=True)
 
-    def test_configdialog(self):
-        d = ConfigDialog(self.root, 'Test', _utest=True)
-        d.remove_var_callbacks()
+
+def tearDownModule():
+    global root, configure
+    idleConf.userCfg = testcfg
+    configure.remove_var_callbacks()
+    del configure
+    root.update_idletasks()
+    root.destroy()
+    del root
+
+
+class FontTabTest(unittest.TestCase):
+
+
+    def setUp(self):
+        changes.clear()
+
+    def test_font(self):
+        configure.fontName.set('Test Font')
+        expected = [
+            ('main', 'EditorWindow', 'font', 'Test Font'),
+            ('main', 'EditorWindow', 'font-size', '10'),
+            ('main', 'EditorWindow', 'font-bold', False)]
+        self.assertEqual(changes, expected)
+        changes.clear()
+        configure.fontSize.set(12)
+        expected = [
+            ('main', 'EditorWindow', 'font', 'Test Font'),
+            ('main', 'EditorWindow', 'font-size', '12'),
+            ('main', 'EditorWindow', 'font-bold', False)]
+        self.assertEqual(changes, expected)
+        changes.clear()
+        configure.fontBold.set(True)
+        expected = [
+            ('main', 'EditorWindow', 'font', 'Test Font'),
+            ('main', 'EditorWindow', 'font-size', '12'),
+            ('main', 'EditorWindow', 'font-bold', True)]
+        self.assertEqual(changes, expected)
+
+    #def test_sample(self): pass  # TODO
+
+    def test_tabspace(self):
+        configure.spaceNum.set(6)
+        self.assertEqual(changes, [('main', 'Indent', 'num-spaces', 6)])
+
+
+class HighlightTest(unittest.TestCase):
+
+    def setUp(self):
+        changes.clear()
+
+    #def test_colorchoose(self): pass  # TODO
+
+
+class KeysTest(unittest.TestCase):
+
+    def setUp(self):
+        changes.clear()
+
+
+class GeneralTest(unittest.TestCase):
+
+    def setUp(self):
+        changes.clear()
+
+    def test_startup(self):
+        configure.radioStartupEdit.invoke()
+        self.assertEqual(changes,
+                         [('main', 'General', 'editor-on-startup', 1)])
+
+    def test_autosave(self):
+        configure.radioSaveAuto.invoke()
+        self.assertEqual(changes, [('main', 'General', 'autosave', 1)])
+
+    def test_editor_size(self):
+        configure.entryWinHeight.insert(0, '1')
+        self.assertEqual(changes, [('main', 'EditorWindow', 'height', '140')])
+        changes.clear()
+        configure.entryWinWidth.insert(0, '1')
+        self.assertEqual(changes, [('main', 'EditorWindow', 'width', '180')])
+
+    #def test_help_sources(self): pass  # TODO
 
 
 if __name__ == '__main__':

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list