Issue #28572: Add 10% to coverage of IDLE's test_configdialog.
Update and augment description of the configuration system.
This commit is contained in:
parent
f5df73025d
commit
f46b7823e6
|
@ -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/
|
||||
#
|
||||
# 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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__':
|
||||
|
|
Loading…
Reference in New Issue