summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/idlelib/config-main.def68
-rw-r--r--Lib/idlelib/config.py27
-rw-r--r--Lib/idlelib/configdialog.py32
-rw-r--r--Lib/idlelib/idle_test/test_configdialog.py129
4 files changed, 181 insertions, 75 deletions
diff --git a/Lib/idlelib/config-main.def b/Lib/idlelib/config-main.def
index a61bba7..330c015 100644
--- 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.
+#
+# 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
#
-# 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
# <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/
+#
+# 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.
#
-# 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
+# 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
index 10fe3ba..358bee4 100644
--- a/Lib/idlelib/config.py
+++ b/Lib/idlelib/config.py
@@ -1,13 +1,20 @@
-"""Provides access to stored 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 contents of the user files may be altered using the Options/Configure IDLE
-menu to access the configuration GUI (configdialog.py), or manually.
+"""idlelib.config -- Manage IDLE configuration information.
+
+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 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
index fa47aaa..8184582 100644
--- a/Lib/idlelib/configdialog.py
+++ b/Lib/idlelib/configdialog.py
@@ -392,28 +392,28 @@ class ConfigDialog(Toplevel):
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 @@ class ConfigDialog(Toplevel):
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
index 70bd14e..81c57e8 100644
--- 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__':