summaryrefslogtreecommitdiffstats
path: root/Lib/idlelib/idle_test
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/idlelib/idle_test')
-rw-r--r--Lib/idlelib/idle_test/README.txt224
-rw-r--r--Lib/idlelib/idle_test/__init__.py2
-rw-r--r--Lib/idlelib/idle_test/htest.py234
-rw-r--r--Lib/idlelib/idle_test/mock_idle.py44
-rw-r--r--Lib/idlelib/idle_test/mock_tk.py21
-rw-r--r--Lib/idlelib/idle_test/template.py30
-rw-r--r--Lib/idlelib/idle_test/test_autocomplete.py299
-rw-r--r--Lib/idlelib/idle_test/test_autocomplete_w.py32
-rw-r--r--Lib/idlelib/idle_test/test_autoexpand.py42
-rw-r--r--Lib/idlelib/idle_test/test_browser.py248
-rw-r--r--Lib/idlelib/idle_test/test_calltip.py253
-rw-r--r--Lib/idlelib/idle_test/test_calltip_w.py29
-rw-r--r--Lib/idlelib/idle_test/test_calltips.py185
-rw-r--r--Lib/idlelib/idle_test/test_codecontext.py447
-rw-r--r--Lib/idlelib/idle_test/test_colorizer.py423
-rw-r--r--Lib/idlelib/idle_test/test_config.py805
-rw-r--r--Lib/idlelib/idle_test/test_config_key.py291
-rw-r--r--Lib/idlelib/idle_test/test_config_name.py77
-rw-r--r--Lib/idlelib/idle_test/test_configdialog.py1420
-rw-r--r--Lib/idlelib/idle_test/test_debugger.py29
-rw-r--r--Lib/idlelib/idle_test/test_debugger_r.py29
-rw-r--r--Lib/idlelib/idle_test/test_debugobj.py57
-rw-r--r--Lib/idlelib/idle_test/test_debugobj_r.py22
-rw-r--r--Lib/idlelib/idle_test/test_delegator.py29
-rw-r--r--Lib/idlelib/idle_test/test_editmenu.py105
-rw-r--r--Lib/idlelib/idle_test/test_editor.py95
-rw-r--r--Lib/idlelib/idle_test/test_filelist.py33
-rw-r--r--Lib/idlelib/idle_test/test_formatparagraph.py (renamed from Lib/idlelib/idle_test/test_format.py)342
-rw-r--r--Lib/idlelib/idle_test/test_grep.py108
-rw-r--r--Lib/idlelib/idle_test/test_help.py34
-rw-r--r--Lib/idlelib/idle_test/test_help_about.py182
-rw-r--r--Lib/idlelib/idle_test/test_helpabout.py52
-rw-r--r--Lib/idlelib/idle_test/test_hyperparser.py104
-rw-r--r--Lib/idlelib/idle_test/test_idlehistory.py (renamed from Lib/idlelib/idle_test/test_history.py)16
-rw-r--r--Lib/idlelib/idle_test/test_io.py (renamed from Lib/idlelib/idle_test/test_run.py)342
-rw-r--r--Lib/idlelib/idle_test/test_iomenu.py49
-rw-r--r--Lib/idlelib/idle_test/test_macosx.py104
-rw-r--r--Lib/idlelib/idle_test/test_mainmenu.py21
-rw-r--r--Lib/idlelib/idle_test/test_multicall.py48
-rw-r--r--Lib/idlelib/idle_test/test_outwin.py171
-rw-r--r--Lib/idlelib/idle_test/test_parenmatch.py113
-rw-r--r--Lib/idlelib/idle_test/test_pathbrowser.py74
-rw-r--r--Lib/idlelib/idle_test/test_percolator.py118
-rw-r--r--Lib/idlelib/idle_test/test_pyparse.py466
-rw-r--r--Lib/idlelib/idle_test/test_pyshell.py64
-rw-r--r--Lib/idlelib/idle_test/test_query.py405
-rw-r--r--Lib/idlelib/idle_test/test_replace.py294
-rw-r--r--Lib/idlelib/idle_test/test_rpc.py29
-rw-r--r--Lib/idlelib/idle_test/test_rstrip.py49
-rw-r--r--Lib/idlelib/idle_test/test_runscript.py33
-rw-r--r--Lib/idlelib/idle_test/test_scrolledlist.py27
-rw-r--r--Lib/idlelib/idle_test/test_search.py80
-rw-r--r--Lib/idlelib/idle_test/test_searchdialogbase.py (renamed from Lib/idlelib/idle_test/test_searchbase.py)51
-rw-r--r--Lib/idlelib/idle_test/test_searchengine.py37
-rw-r--r--Lib/idlelib/idle_test/test_sidebar.py375
-rw-r--r--Lib/idlelib/idle_test/test_squeezer.py476
-rw-r--r--Lib/idlelib/idle_test/test_stackviewer.py47
-rw-r--r--Lib/idlelib/idle_test/test_statusbar.py41
-rw-r--r--Lib/idlelib/idle_test/test_text.py25
-rw-r--r--Lib/idlelib/idle_test/test_textview.py249
-rw-r--r--Lib/idlelib/idle_test/test_tooltip.py161
-rw-r--r--Lib/idlelib/idle_test/test_tree.py60
-rw-r--r--Lib/idlelib/idle_test/test_undo.py135
-rw-r--r--Lib/idlelib/idle_test/test_warning.py18
-rw-r--r--Lib/idlelib/idle_test/test_widgetredir.py (renamed from Lib/idlelib/idle_test/test_redirector.py)12
-rw-r--r--Lib/idlelib/idle_test/test_window.py45
-rw-r--r--Lib/idlelib/idle_test/test_zoomheight.py39
67 files changed, 1129 insertions, 9472 deletions
diff --git a/Lib/idlelib/idle_test/README.txt b/Lib/idlelib/idle_test/README.txt
index 566bfd1..6967d70 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 3.3 for Python 3.x.
+Automated unit tests were added in 2.7 for Python 2.x and 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 3.4.
+Human-mediated tests were added later in 2.7 and in 3.4.
python -m idlelib.idle_test.htest
@@ -15,53 +15,46 @@ python -m idlelib.idle_test.htest
1. Test Files
The idle directory, idlelib, has over 60 xyz.py files. The idle_test
-subdirectory contains test_xyz.py for each implementation file xyz.py.
-To add a test for abc.py, open idle_test/template.py and immediately
-Save As test_abc.py. Insert 'abc' on the first line, and replace
-'zzdummy' with 'abc.
+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.
-Remove the imports of requires and tkinter if not needed. Otherwise,
-add to the tkinter imports as needed.
+import unittest
+from test.support import requires
+import idlelib. as
-Add a prefix to 'Test' for the initial test class. The template class
-contains code needed or possibly needed for gui tests. See the next
-section if doing gui tests. If not, and not needed for further classes,
-this code can be removed.
+class _Test(unittest.TestCase):
-Add the following at the end of abc.py. If an htest was added first,
-insert the import and main lines before the htest lines.
+ def test_(self):
-if __name__ == "__main__":
- from unittest import main
- main('idlelib.idle_test.test_abc', verbosity=2, exit=False)
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
-The ', exit=False' is only needed if an htest follows.
+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
+ unittest.main('idlelib.idle_test.test_', verbosity=2, exit=False)
2. GUI Tests
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 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.
-The template.py file does this.
-
-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.
+test.test_support.requires('gui') (test.support in 3.x). 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.
+
+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):
@@ -72,64 +65,48 @@ destroyed. See https://bugs.python.org/issue20567.
@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). It should not hurt if not needed.
-
- can't invoke "event" command: application has been destroyed
- ...
- "ttk::ThemeChanged"
-
-If a test creates instance 'e' of EditorWindow, call 'e._close()' before
-or as the first part of teardown. The effect of omitting this depends
-on the later shutdown. Then enable the after_cancel loop in the
-template. This prevents messages like the following.
-
-bgerror failed to handle background error.
- Original error: invalid command name "106096696timer_event"
- Error in bgerror: can't invoke "tk" command: application has been destroyed
+WARNING: In 2.7, "requires('gui') MUST NOT be called at module scope.
+See https://bugs.python.org/issue18910
Requires('gui') causes the test(s) it guards to be skipped if any of
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 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 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.
+ - 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
@@ -139,100 +116,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'.
+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'.)
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).
-
-To run an individual Testcase or test method, extend the dotted name
-given to unittest on the command line or use the test -m option. The
-latter allows use of other regrtest options. When using the latter,
-all components of the pattern must be present, but any can be replaced
-by '*'.
+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).
-python -m unittest -v idlelib.idle_test.test_xyz.Test_case.test_meth
-python -m test -m idlelib.idle_test.text_xyz.Test_case.test_meth test_idle
+To run an individual Testcase or test method, extend the dotted name given to
+unittest on the command line.
-The test suite can be run in an IDLE user process from Shell.
->>> import test.autotest # Issue 25588, 2017/10/13, 3.6.4, 3.7.0a2.
-There are currently failures not usually present, and this does not
-work when run from the editor.
+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
-
-
-5. Test Coverage
-
-Install the coverage package into your Python 3.6 site-packages
-directory. (Its exact location depends on the OS).
-> python3 -m pip install coverage
-(On Windows, replace 'python3 with 'py -3.6' or perhaps just 'python'.)
-
-The problem with running coverage with repository python is that
-coverage uses absolute imports for its submodules, hence it needs to be
-in a directory in sys.path. One solution: copy the package to the
-directory containing the cpython repository. Call it 'dev'. Then run
-coverage either directly or from a script in that directory so that
-'dev' is prepended to sys.path.
-
-Either edit or add dev/.coveragerc so it looks something like this.
----
-# .coveragerc sets coverage options.
-[run]
-branch = True
-
-[report]
-# Regexes for lines to exclude from consideration
-exclude_lines =
- # Don't complain if non-runnable code isn't run:
- if 0:
- if __name__ == .__main__.:
-
- .*# htest #
- if not _utest:
- if _htest:
----
-The additions for IDLE are 'branch = True', to test coverage both ways,
-and the last three exclude lines, to exclude things peculiar to IDLE
-that are not executed during tests.
-
-A script like the following cover.bat (for Windows) is very handy.
----
-@echo off
-rem Usage: cover filename [test_ suffix] # proper case required by coverage
-rem filename without .py, 2nd parameter if test is not test_filename
-setlocal
-set py=f:\dev\3x\pcbuild\win32\python_d.exe
-set src=idlelib.%1
-if "%2" EQU "" set tst=f:/dev/3x/Lib/idlelib/idle_test/test_%1.py
-if "%2" NEQ "" set tst=f:/dev/ex/Lib/idlelib/idle_test/test_%2.py
-
-%py% -m coverage run --pylib --source=%src% %tst%
-%py% -m coverage report --show-missing
-%py% -m coverage html
-start htmlcov\3x_Lib_idlelib_%1_py.html
-rem Above opens new report; htmlcov\index.html displays report index
----
-The second parameter was added for tests of module x not named test_x.
-(There were several before modules were renamed, now only one is left.)
diff --git a/Lib/idlelib/idle_test/__init__.py b/Lib/idlelib/idle_test/__init__.py
index ad067b4..845c92d 100644
--- a/Lib/idlelib/idle_test/__init__.py
+++ b/Lib/idlelib/idle_test/__init__.py
@@ -1,8 +1,6 @@
'''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".
-Starting with Python 3.6, IDLE requires tcl/tk 8.5 or later.
-
This package and its contained modules are subject to change and
any direct use is at your own risk.
'''
diff --git a/Lib/idlelib/idle_test/htest.py b/Lib/idlelib/idle_test/htest.py
index 1373b76..9e2ddd2 100644
--- a/Lib/idlelib/idle_test/htest.py
+++ b/Lib/idlelib/idle_test/htest.py
@@ -8,11 +8,11 @@ callable in the module named in the spec. Close the window to skip or
end the test.
In a tested module, let X be a global name bound to a callable (class
-or function) whose .__name__ attribute is also X (the usual situation).
+or function) whose .__name__ attrubute is also X (the usual situation).
The first parameter of X must be 'parent'. When called, the parent
argument will be the root window. X must create a child Toplevel
window (or subclass thereof). The Toplevel may be a test widget or
-dialog, in which case the callable is the corresponding class. Or the
+dialog, in which case the callable is the corresonding class. Or the
Toplevel may contain the widget to be tested or set up a context in
which a test widget is invoked. In this latter case, the callable is a
wrapper function that sets up the Toplevel and other objects. Wrapper
@@ -59,40 +59,34 @@ msg: master window hints about testing the widget.
Modules and classes not being tested at the moment:
-pyshell.PyShellEditorWindow
-debugger.Debugger
-autocomplete_w.AutoCompleteWindow
-outwin.OutputWindow (indirectly being tested with grep test)
+PyShell.PyShellEditorWindow
+Debugger.Debugger
+AutoCompleteWindow.AutoCompleteWindow
+OutputWindow.OutputWindow (indirectly being tested with grep test)
'''
-import idlelib.pyshell # Set Windows DPI awareness before Tk().
from importlib import import_module
-import textwrap
-import tkinter as tk
-from tkinter.ttk import Scrollbar
-tk.NoDefaultRoot()
+from idlelib.macosxSupport import _initializeTkVariantTests
+import Tkinter as tk
AboutDialog_spec = {
- 'file': 'help_about',
- 'kwds': {'title': 'help_about test',
+ 'file': 'aboutDialog',
+ 'kwds': {'title': 'aboutDialog test',
'_htest': True,
},
'msg': "Test every button. Ensure Python, TK and IDLE versions "
"are correctly displayed.\n [Close] to exit.",
}
-# TODO implement ^\; adding '<Control-Key-\\>' to function does not work.
_calltip_window_spec = {
- 'file': 'calltip_w',
+ 'file': 'CallTipWindow',
'kwds': {},
'msg': "Typing '(' should display a calltip.\n"
"Typing ') should hide the calltip.\n"
- "So should moving cursor out of argument area.\n"
- "Force-open-calltip does not work here.\n"
}
-_module_browser_spec = {
- 'file': 'browser',
+_class_browser_spec = {
+ 'file': 'ClassBrowser',
'kwds': {},
'msg': "Inspect names of module, class(with superclass if "
"applicable), methods and functions.\nToggle nested items.\n"
@@ -101,7 +95,7 @@ _module_browser_spec = {
}
_color_delegator_spec = {
- 'file': 'colorizer',
+ 'file': 'ColorDelegator',
'kwds': {},
'msg': "The text is sample Python code.\n"
"Ensure components like comments, keywords, builtins,\n"
@@ -109,18 +103,8 @@ _color_delegator_spec = {
"The default color scheme is in idlelib/config-highlight.def"
}
-CustomRun_spec = {
- 'file': 'query',
- 'kwds': {'title': 'Customize query.py Run',
- '_htest': True},
- 'msg': "Enter with <Return> or [Run]. Print valid entry to Shell\n"
- "Arguments are parsed into a list\n"
- "Mode is currently restart True or False\n"
- "Close dialog with valid entry, <Escape>, [Cancel], [X]"
- }
-
ConfigDialog_spec = {
- 'file': 'configdialog',
+ 'file': 'configDialog',
'kwds': {'title': 'ConfigDialogTest',
'_htest': True,},
'msg': "IDLE preferences dialog.\n"
@@ -137,7 +121,7 @@ ConfigDialog_spec = {
# TODO Improve message
_dyn_option_menu_spec = {
- 'file': 'dynoption',
+ 'file': 'dynOptionMenuWidget',
'kwds': {},
'msg': "Select one of the many options in the 'old option set'.\n"
"Click the button to change the option set.\n"
@@ -146,55 +130,64 @@ _dyn_option_menu_spec = {
# TODO edit wrapper
_editor_window_spec = {
- 'file': 'editor',
+ 'file': 'EditorWindow',
'kwds': {},
'msg': "Test editor functions of interest.\n"
"Best to close editor first."
}
+GetCfgSectionNameDialog_spec = {
+ 'file': 'configSectionNameDialog',
+ 'kwds': {'title':'Get Name',
+ 'message':'Enter something',
+ 'used_names': {'abc'},
+ '_htest': True},
+ 'msg': "After the text entered with [Ok] is stripped, <nothing>, "
+ "'abc', or more that 30 chars are errors.\n"
+ "Close 'Get Name' with a valid entry (printed to Shell), "
+ "[Cancel], or [X]",
+ }
+
+GetHelpSourceDialog_spec = {
+ 'file': 'configHelpSourceEdit',
+ 'kwds': {'title': 'Get helpsource',
+ '_htest': True},
+ 'msg': "Enter menu item name and help file path\n "
+ "<nothing> and more than 30 chars are invalid menu item names.\n"
+ "<nothing>, file does not exist are invalid path items.\n"
+ "Test for incomplete web address for help file path.\n"
+ "A valid entry will be printed to shell with [0k].\n"
+ "[Cancel] will print None to shell",
+ }
+
+# Update once issue21519 is resolved.
GetKeysDialog_spec = {
- 'file': 'config_key',
+ 'file': 'keybindingDialog',
'kwds': {'title': 'Test keybindings',
'action': 'find-again',
- 'current_key_sequences': [['<Control-Key-g>', '<Key-F3>', '<Control-Key-G>']],
+ 'currentKeySequences': [''] ,
'_htest': True,
},
'msg': "Test for different key modifier sequences.\n"
"<nothing> is invalid.\n"
"No modifier key is invalid.\n"
"Shift key with [a-z],[0-9], function key, move key, tab, space "
- "is invalid.\nNo validity checking if advanced key binding "
+ "is invalid.\nNo validitity checking if advanced key binding "
"entry is used."
}
_grep_dialog_spec = {
- 'file': 'grep',
+ 'file': 'GrepDialog',
'kwds': {},
'msg': "Click the 'Show GrepDialog' button.\n"
"Test the various 'Find-in-files' functions.\n"
"The results should be displayed in a new '*Output*' window.\n"
- "'Right-click'->'Go to file/line' anywhere in the search results "
+ "'Right-click'->'Goto file/line' anywhere in the search results "
"should open that file \nin a new EditorWindow."
}
-HelpSource_spec = {
- 'file': 'query',
- 'kwds': {'title': 'Help name and source',
- 'menuitem': 'test',
- 'filepath': __file__,
- 'used_names': {'abc'},
- '_htest': True},
- 'msg': "Enter menu item name and help file path\n"
- "'', > than 30 chars, and 'abc' are invalid menu item names.\n"
- "'' and file does not exist are invalid path items.\n"
- "Any url ('www...', 'http...') is accepted.\n"
- "Test Browse with and without path, as cannot unittest.\n"
- "[Ok] or <Return> prints valid entry to shell\n"
- "[Cancel] or <Escape> prints None to shell"
- }
-
_io_binding_spec = {
- 'file': 'iomenu',
+ 'file': 'IOBinding',
'kwds': {},
'msg': "Test the following bindings.\n"
"<Control-o> to open file from dialog.\n"
@@ -206,28 +199,8 @@ _io_binding_spec = {
"Check that changes were saved by opening the file elsewhere."
}
-_linenumbers_drag_scrolling_spec = {
- 'file': 'sidebar',
- 'kwds': {},
- 'msg': textwrap.dedent("""\
- 1. Click on the line numbers and drag down below the edge of the
- window, moving the mouse a bit and then leaving it there for a while.
- The text and line numbers should gradually scroll down, with the
- selection updated continuously.
-
- 2. With the lines still selected, click on a line number above the
- selected lines. Only the line whose number was clicked should be
- selected.
-
- 3. Repeat step #1, dragging to above the window. The text and line
- numbers should gradually scroll up, with the selection updated
- continuously.
-
- 4. Repeat step #2, clicking a line number below the selection."""),
- }
-
_multi_call_spec = {
- 'file': 'multicall',
+ 'file': 'MultiCall',
'kwds': {},
'msg': "The following actions should trigger a print to console or IDLE"
" Shell.\nEntering and leaving the text area, key entry, "
@@ -237,14 +210,14 @@ _multi_call_spec = {
}
_multistatus_bar_spec = {
- 'file': 'statusbar',
+ 'file': 'MultiStatusBar',
'kwds': {},
'msg': "Ensure presence of multi-status bar below text area.\n"
"Click 'Update Status' to change the multi-status text"
}
_object_browser_spec = {
- 'file': 'debugobj',
+ 'file': 'ObjectBrowser',
'kwds': {},
'msg': "Double click on items upto the lowest level.\n"
"Attributes of the objects and related information "
@@ -252,7 +225,7 @@ _object_browser_spec = {
}
_path_browser_spec = {
- 'file': 'pathbrowser',
+ 'file': 'PathBrowser',
'kwds': {},
'msg': "Test for correct display of all paths in sys.path.\n"
"Toggle nested items upto the lowest level.\n"
@@ -261,7 +234,7 @@ _path_browser_spec = {
}
_percolator_spec = {
- 'file': 'percolator',
+ 'file': 'Percolator',
'kwds': {},
'msg': "There are two tracers which can be toggled using a checkbox.\n"
"Toggling a tracer 'on' by checking it should print tracer "
@@ -271,20 +244,8 @@ _percolator_spec = {
"Test for actions like text entry, and removal."
}
-Query_spec = {
- 'file': 'query',
- 'kwds': {'title': 'Query',
- 'message': 'Enter something',
- 'text0': 'Go',
- '_htest': True},
- 'msg': "Enter with <Return> or [Ok]. Print valid entry to Shell\n"
- "Blank line, after stripping, is ignored\n"
- "Close dialog with valid entry, <Escape>, [Cancel], [X]"
- }
-
-
_replace_dialog_spec = {
- 'file': 'replace',
+ 'file': 'ReplaceDialog',
'kwds': {},
'msg': "Click the 'Replace' button.\n"
"Test various replace options in the 'Replace dialog'.\n"
@@ -292,22 +253,15 @@ _replace_dialog_spec = {
}
_search_dialog_spec = {
- 'file': 'search',
+ 'file': 'SearchDialog',
'kwds': {},
'msg': "Click the 'Search' button.\n"
"Test various search options in the 'Search dialog'.\n"
"Click [Close] or [X] to close the 'Search Dialog'."
}
-_searchbase_spec = {
- 'file': 'searchbase',
- 'kwds': {},
- 'msg': "Check the appearance of the base search dialog\n"
- "Its only action is to close."
- }
-
_scrolled_list_spec = {
- 'file': 'scrolledlist',
+ 'file': 'ScrolledList',
'kwds': {},
'msg': "You should see a scrollable list of items\n"
"Selecting (clicking) or double clicking an item "
@@ -323,29 +277,48 @@ show_idlehelp_spec = {
}
_stack_viewer_spec = {
- 'file': 'stackviewer',
+ 'file': 'StackViewer',
'kwds': {},
'msg': "A stacktrace for a NameError exception.\n"
"Expand 'idlelib ...' and '<locals>'.\n"
"Check that exc_value, exc_tb, and exc_type are correct.\n"
}
+_tabbed_pages_spec = {
+ 'file': 'tabbedpages',
+ 'kwds': {},
+ 'msg': "Toggle between the two tabs 'foo' and 'bar'\n"
+ "Add a tab by entering a suitable name for it.\n"
+ "Remove an existing tab by entering its name.\n"
+ "Remove all existing tabs.\n"
+ "<nothing> is an invalid add page and remove page name.\n"
+ }
+
+TextViewer_spec = {
+ 'file': 'textView',
+ 'kwds': {'title': 'Test textView',
+ 'text':'The quick brown fox jumps over the lazy dog.\n'*35,
+ '_htest': True},
+ 'msg': "Test for read-only property of text.\n"
+ "Text is selectable. Window is scrollable.",
+ }
+
_tooltip_spec = {
- 'file': 'tooltip',
+ 'file': 'ToolTip',
'kwds': {},
'msg': "Place mouse cursor over both the buttons\n"
"A tooltip should appear with some text."
}
_tree_widget_spec = {
- 'file': 'tree',
+ 'file': 'TreeWidget',
'kwds': {},
'msg': "The canvas is scrollable.\n"
"Click on folders upto to the lowest level."
}
_undo_delegator_spec = {
- 'file': 'undo',
+ 'file': 'UndoDelegator',
'kwds': {},
'msg': "Click [Undo] to undo any action.\n"
"Click [Redo] to redo any action.\n"
@@ -353,17 +326,8 @@ _undo_delegator_spec = {
"by printing to the console or the IDLE shell.\n"
}
-ViewWindow_spec = {
- 'file': 'textview',
- 'kwds': {'title': 'Test textview',
- 'contents': 'The quick brown fox jumps over the lazy dog.\n'*35,
- '_htest': True},
- 'msg': "Test for read-only property of text.\n"
- "Select text, scroll window, close"
- }
-
_widget_redirector_spec = {
- 'file': 'redirector',
+ 'file': 'WidgetRedirector',
'kwds': {},
'msg': "Every text insert should be printed to the console "
"or the IDLE shell."
@@ -373,13 +337,14 @@ def run(*tests):
root = tk.Tk()
root.title('IDLE htest')
root.resizable(0, 0)
+ _initializeTkVariantTests(root)
# a scrollable Label like constant width text widget.
frameLabel = tk.Frame(root, padx=10)
frameLabel.pack()
text = tk.Text(frameLabel, wrap='word')
text.configure(bg=root.cget('bg'), relief='flat', height=4, width=70)
- scrollbar = Scrollbar(frameLabel, command=text.yview)
+ scrollbar = tk.Scrollbar(frameLabel, command=text.yview)
text.config(yscrollcommand=scrollbar.set)
scrollbar.pack(side='right', fill='y', expand=False)
text.pack(side='left', fill='both', expand=True)
@@ -400,45 +365,38 @@ def run(*tests):
test = getattr(mod, test_name)
test_list.append((test_spec, test))
- test_name = tk.StringVar(root)
- callable_object = None
- test_kwds = None
+ test_name = [tk.StringVar('')]
+ callable_object = [None]
+ test_kwds = [None]
- def next_test():
- nonlocal test_name, callable_object, test_kwds
+ def next():
if len(test_list) == 1:
next_button.pack_forget()
- test_spec, callable_object = test_list.pop()
- test_kwds = test_spec['kwds']
- test_kwds['parent'] = root
- test_name.set('Test ' + test_spec['name'])
+ test_spec, callable_object[0] = test_list.pop()
+ test_kwds[0] = test_spec['kwds']
+ test_kwds[0]['parent'] = root
+ test_name[0].set('Test ' + test_spec['name'])
text.configure(state='normal') # enable text editing
text.delete('1.0','end')
text.insert("1.0",test_spec['msg'])
text.configure(state='disabled') # preserve read-only property
- def run_test(_=None):
- widget = callable_object(**test_kwds)
+ def run_test():
+ widget = callable_object[0](**test_kwds[0])
try:
print(widget.result)
except AttributeError:
pass
- def close(_=None):
- root.destroy()
-
- button = tk.Button(root, textvariable=test_name,
- default='active', command=run_test)
- next_button = tk.Button(root, text="Next", command=next_test)
+ button = tk.Button(root, textvariable=test_name[0], command=run_test)
button.pack()
+ next_button = tk.Button(root, text="Next", command=next)
next_button.pack()
- next_button.focus_set()
- root.bind('<Key-Return>', run_test)
- root.bind('<Key-Escape>', close)
- next_test()
+ next()
+
root.mainloop()
if __name__ == '__main__':
diff --git a/Lib/idlelib/idle_test/mock_idle.py b/Lib/idlelib/idle_test/mock_idle.py
index 71fa480..7b09f83 100644
--- a/Lib/idlelib/idle_test/mock_idle.py
+++ b/Lib/idlelib/idle_test/mock_idle.py
@@ -5,44 +5,38 @@ Attributes and methods will be added as needed for tests.
from idlelib.idle_test.mock_tk import Text
-class Func:
- '''Record call, capture args, return/raise result set by test.
-
- When mock function is called, set or use attributes:
- self.called - increment call number even if no args, kwds passed.
- self.args - capture positional arguments.
- self.kwds - capture keyword arguments.
- self.result - return or raise value set in __init__.
- self.return_self - return self instead, to mock query class return.
-
- Most common use will probably be to mock instance methods.
- Given class instance, can set and delete as instance attribute.
+class Func(object):
+ '''Mock function captures args and returns result set by test.
+
+ Attributes:
+ self.called - records call even if no args, kwds passed.
+ self.result - set by init, returned by call.
+ self.args - captures positional arguments.
+ self.kwds - captures keyword arguments.
+
+ Most common use will probably be to mock methods.
Mock_tk.Var and Mbox_func are special variants of this.
'''
- def __init__(self, result=None, return_self=False):
- self.called = 0
+ def __init__(self, result=None):
+ self.called = False
self.result = result
- self.return_self = return_self
self.args = None
self.kwds = None
def __call__(self, *args, **kwds):
- self.called += 1
+ self.called = True
self.args = args
self.kwds = kwds
if isinstance(self.result, BaseException):
raise self.result
- elif self.return_self:
- return self
else:
return self.result
-class Editor:
- '''Minimally imitate editor.EditorWindow class.
+class Editor(object):
+ '''Minimally imitate EditorWindow.EditorWindow class.
'''
- def __init__(self, flist=None, filename=None, key=None, root=None,
- text=None): # Allow real Text with mock Editor.
- self.text = text or Text()
+ def __init__(self, flist=None, filename=None, key=None, root=None):
+ self.text = Text()
self.undo = UndoDelegator()
def get_selection_indices(self):
@@ -51,8 +45,8 @@ class Editor:
return first, last
-class UndoDelegator:
- '''Minimally imitate undo.UndoDelegator class.
+class UndoDelegator(object):
+ '''Minimally imitate UndoDelegator,UndoDelegator class.
'''
# A real undo block is only needed for user interaction.
def undo_block_start(*args):
diff --git a/Lib/idlelib/idle_test/mock_tk.py b/Lib/idlelib/idle_test/mock_tk.py
index 576f7d5..56ca876 100644
--- a/Lib/idlelib/idle_test/mock_tk.py
+++ b/Lib/idlelib/idle_test/mock_tk.py
@@ -4,7 +4,7 @@ A gui object is anything with a master or parent parameter, which is
typically required in spite of what the doc strings say.
"""
-class Event:
+class Event(object):
'''Minimal mock with attributes for testing event handlers.
This is not a gui object, but is used as an argument for callbacks
@@ -22,7 +22,7 @@ class Event:
"Create event with attributes needed for test"
self.__dict__.update(kwds)
-class Var:
+class Var(object):
"Use for String/Int/BooleanVar: incomplete"
def __init__(self, master=None, value=None, name=None):
self.master = master
@@ -33,11 +33,11 @@ class Var:
def get(self):
return self.value
-class Mbox_func:
+class Mbox_func(object):
"""Generic mock for messagebox functions, which all have the same signature.
Instead of displaying a message box, the mock's call method saves the
- arguments as instance attributes, which test functions can then examine.
+ arguments as instance attributes, which test functions can then examime.
The test can set the result returned to ask function
"""
def __init__(self, result=None):
@@ -50,7 +50,7 @@ class Mbox_func:
self.kwds = kwds
return self.result # Set by tester for ask functions
-class Mbox:
+class Mbox(object):
"""Mock for tkinter.messagebox with an Mbox_func for each function.
This module was 'tkMessageBox' in 2.x; hence the 'import as' in 3.x.
@@ -87,7 +87,7 @@ class Test(unittest.TestCase):
from _tkinter import TclError
-class Text:
+class Text(object):
"""A semi-functional non-gui replacement for tkinter.Text text editors.
The mock's data model is that a text is a list of \n-terminated lines.
@@ -116,7 +116,7 @@ class Text:
"""Return a (line, char) tuple of int indexes into self.data.
This implements .index without converting the result back to a string.
- The result is constrained by the number of lines and linelengths of
+ The result is contrained by the number of lines and linelengths of
self.data. For many indexes, the result is initially (1, 0).
The input index may have any of several possible forms:
@@ -133,7 +133,7 @@ class Text:
try:
index=index.lower()
except AttributeError:
- raise TclError('bad text index "%s"' % index) from None
+ raise TclError('bad text index "%s"' % index)
lastline = len(self.data) - 1 # same as number of text lines
if index == 'insert':
@@ -296,8 +296,3 @@ 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/template.py b/Lib/idlelib/idle_test/template.py
deleted file mode 100644
index 725a55b..0000000
--- a/Lib/idlelib/idle_test/template.py
+++ /dev/null
@@ -1,30 +0,0 @@
-"Test , coverage %."
-
-from idlelib import zzdummy
-import unittest
-from test.support import requires
-from tkinter import Tk
-
-
-class Test(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.update_idletasks()
-## for id in cls.root.tk.call('after', 'info'):
-## cls.root.after_cancel(id) # Need for EditorWindow.
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- self.assertTrue(True)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_autocomplete.py b/Lib/idlelib/idle_test/test_autocomplete.py
index 2c478cd..002751e 100644
--- a/Lib/idlelib/idle_test/test_autocomplete.py
+++ b/Lib/idlelib/idle_test/test_autocomplete.py
@@ -1,17 +1,15 @@
-"Test autocomplete, coverage 93%."
-
import unittest
-from unittest.mock import Mock, patch
-from test.support import requires
-from tkinter import Tk, Text
-import os
-import __main__
+from test.test_support import requires
+from Tkinter import Tk, Text
-import idlelib.autocomplete as ac
-import idlelib.autocomplete_w as acw
+import idlelib.AutoComplete as ac
+import idlelib.AutoCompleteWindow as acw
from idlelib.idle_test.mock_idle import Func
from idlelib.idle_test.mock_tk import Event
+class AutoCompleteWindow:
+ def complete():
+ return
class DummyEditwin:
def __init__(self, root, text):
@@ -19,7 +17,7 @@ class DummyEditwin:
self.text = text
self.indentwidth = 8
self.tabwidth = 8
- self.prompt_last_line = '>>>' # Currently not used by autocomplete.
+ self.context_use_ps1 = True
class AutoCompleteTest(unittest.TestCase):
@@ -28,269 +26,114 @@ class AutoCompleteTest(unittest.TestCase):
def setUpClass(cls):
requires('gui')
cls.root = Tk()
- cls.root.withdraw()
cls.text = Text(cls.root)
cls.editor = DummyEditwin(cls.root, cls.text)
@classmethod
def tearDownClass(cls):
del cls.editor, cls.text
- cls.root.update_idletasks()
cls.root.destroy()
del cls.root
def setUp(self):
- self.text.delete('1.0', 'end')
+ self.editor.text.delete('1.0', 'end')
self.autocomplete = ac.AutoComplete(self.editor)
def test_init(self):
self.assertEqual(self.autocomplete.editwin, self.editor)
- self.assertEqual(self.autocomplete.text, self.text)
def test_make_autocomplete_window(self):
testwin = self.autocomplete._make_autocomplete_window()
self.assertIsInstance(testwin, acw.AutoCompleteWindow)
def test_remove_autocomplete_window(self):
- acp = self.autocomplete
- acp.autocompletewindow = m = Mock()
- acp._remove_autocomplete_window()
- m.hide_window.assert_called_once()
- self.assertIsNone(acp.autocompletewindow)
+ self.autocomplete.autocompletewindow = (
+ self.autocomplete._make_autocomplete_window())
+ self.autocomplete._remove_autocomplete_window()
+ self.assertIsNone(self.autocomplete.autocompletewindow)
def test_force_open_completions_event(self):
- # Call _open_completions and break.
- acp = self.autocomplete
- open_c = Func()
- acp.open_completions = open_c
- self.assertEqual(acp.force_open_completions_event('event'), 'break')
- self.assertEqual(open_c.args[0], ac.FORCE)
+ # Test that force_open_completions_event calls _open_completions
+ o_cs = Func()
+ self.autocomplete.open_completions = o_cs
+ self.autocomplete.force_open_completions_event('event')
+ self.assertEqual(o_cs.args, (True, False, True))
- def test_autocomplete_event(self):
+ def test_try_open_completions_event(self):
Equal = self.assertEqual
- acp = self.autocomplete
+ autocomplete = self.autocomplete
+ trycompletions = self.autocomplete.try_open_completions_event
+ o_c_l = Func()
+ autocomplete._open_completions_later = o_c_l
- # Result of autocomplete event: If modified tab, None.
- ev = Event(mc_state=True)
- self.assertIsNone(acp.autocomplete_event(ev))
- del ev.mc_state
+ # _open_completions_later should not be called with no text in editor
+ trycompletions('event')
+ Equal(o_c_l.args, None)
- # If tab after whitespace, None.
- self.text.insert('1.0', ' """Docstring.\n ')
- self.assertIsNone(acp.autocomplete_event(ev))
- self.text.delete('1.0', 'end')
-
- # If active autocomplete window, complete() and 'break'.
+ # _open_completions_later should be called with COMPLETE_ATTRIBUTES (1)
self.text.insert('1.0', 're.')
- acp.autocompletewindow = mock = Mock()
- mock.is_active = Mock(return_value=True)
- Equal(acp.autocomplete_event(ev), 'break')
- mock.complete.assert_called_once()
- acp.autocompletewindow = None
+ trycompletions('event')
+ Equal(o_c_l.args, (False, False, False, 1))
- # If no active autocomplete window, open_completions(), None/break.
- open_c = Func(result=False)
- acp.open_completions = open_c
- Equal(acp.autocomplete_event(ev), None)
- Equal(open_c.args[0], ac.TAB)
- open_c.result = True
- Equal(acp.autocomplete_event(ev), 'break')
- Equal(open_c.args[0], ac.TAB)
+ # _open_completions_later should be called with COMPLETE_FILES (2)
+ self.text.delete('1.0', 'end')
+ self.text.insert('1.0', '"./Lib/')
+ trycompletions('event')
+ Equal(o_c_l.args, (False, False, False, 2))
- def test_try_open_completions_event(self):
+ def test_autocomplete_event(self):
Equal = self.assertEqual
- text = self.text
- acp = self.autocomplete
- trycompletions = acp.try_open_completions_event
- after = Func(result='after1')
- acp.text.after = after
+ autocomplete = self.autocomplete
- # If no text or trigger, after not called.
- trycompletions()
- Equal(after.called, 0)
- text.insert('1.0', 're')
- trycompletions()
- Equal(after.called, 0)
-
- # Attribute needed, no existing callback.
- text.insert('insert', ' re.')
- acp._delayed_completion_id = None
- trycompletions()
- Equal(acp._delayed_completion_index, text.index('insert'))
- Equal(after.args,
- (acp.popupwait, acp._delayed_open_completions, ac.TRY_A))
- cb1 = acp._delayed_completion_id
- Equal(cb1, 'after1')
+ # Test that the autocomplete event is ignored if user is pressing a
+ # modifier key in addition to the tab key
+ ev = Event(mc_state=True)
+ self.assertIsNone(autocomplete.autocomplete_event(ev))
+ del ev.mc_state
- # File needed, existing callback cancelled.
- text.insert('insert', ' "./Lib/')
- after.result = 'after2'
- cancel = Func()
- acp.text.after_cancel = cancel
- trycompletions()
- Equal(acp._delayed_completion_index, text.index('insert'))
- Equal(cancel.args, (cb1,))
- Equal(after.args,
- (acp.popupwait, acp._delayed_open_completions, ac.TRY_F))
- Equal(acp._delayed_completion_id, 'after2')
+ # If autocomplete window is open, complete() method is called
+ self.text.insert('1.0', 're.')
+ # This must call autocomplete._make_autocomplete_window()
+ Equal(self.autocomplete.autocomplete_event(ev), 'break')
+
+ # If autocomplete window is not active or does not exist,
+ # open_completions is called. Return depends on its return.
+ autocomplete._remove_autocomplete_window()
+ o_cs = Func() # .result = None
+ autocomplete.open_completions = o_cs
+ Equal(self.autocomplete.autocomplete_event(ev), None)
+ Equal(o_cs.args, (False, True, True))
+ o_cs.result = True
+ Equal(self.autocomplete.autocomplete_event(ev), 'break')
+ Equal(o_cs.args, (False, True, True))
+
+ def test_open_completions_later(self):
+ # Test that autocomplete._delayed_completion_id is set
+ pass
def test_delayed_open_completions(self):
- Equal = self.assertEqual
- acp = self.autocomplete
- open_c = Func()
- acp.open_completions = open_c
- self.text.insert('1.0', '"dict.')
-
- # Set autocomplete._delayed_completion_id to None.
- # Text index changed, don't call open_completions.
- acp._delayed_completion_id = 'after'
- acp._delayed_completion_index = self.text.index('insert+1c')
- acp._delayed_open_completions('dummy')
- self.assertIsNone(acp._delayed_completion_id)
- Equal(open_c.called, 0)
-
- # Text index unchanged, call open_completions.
- acp._delayed_completion_index = self.text.index('insert')
- acp._delayed_open_completions((1, 2, 3, ac.FILES))
- self.assertEqual(open_c.args[0], (1, 2, 3, ac.FILES))
-
- def test_oc_cancel_comment(self):
- none = self.assertIsNone
- acp = self.autocomplete
-
- # Comment is in neither code or string.
- acp._delayed_completion_id = 'after'
- after = Func(result='after')
- acp.text.after_cancel = after
- self.text.insert(1.0, '# comment')
- none(acp.open_completions(ac.TAB)) # From 'else' after 'elif'.
- none(acp._delayed_completion_id)
-
- def test_oc_no_list(self):
- acp = self.autocomplete
- fetch = Func(result=([],[]))
- acp.fetch_completions = fetch
- self.text.insert('1.0', 'object')
- self.assertIsNone(acp.open_completions(ac.TAB))
- self.text.insert('insert', '.')
- self.assertIsNone(acp.open_completions(ac.TAB))
- self.assertEqual(fetch.called, 2)
-
-
- def test_open_completions_none(self):
- # Test other two None returns.
- none = self.assertIsNone
- acp = self.autocomplete
-
- # No object for attributes or need call not allowed.
- self.text.insert(1.0, '.')
- none(acp.open_completions(ac.TAB))
- self.text.insert('insert', ' int().')
- none(acp.open_completions(ac.TAB))
-
- # Blank or quote trigger 'if complete ...'.
- self.text.delete(1.0, 'end')
- self.assertFalse(acp.open_completions(ac.TAB))
- self.text.insert('1.0', '"')
- self.assertFalse(acp.open_completions(ac.TAB))
- self.text.delete('1.0', 'end')
-
- class dummy_acw():
- __init__ = Func()
- show_window = Func(result=False)
- hide_window = Func()
+ # Test that autocomplete._delayed_completion_id set to None and that
+ # open_completions only called if insertion index is the same as
+ # _delayed_completion_index
+ pass
def test_open_completions(self):
- # Test completions of files and attributes.
- acp = self.autocomplete
- fetch = Func(result=(['tem'],['tem', '_tem']))
- acp.fetch_completions = fetch
- def make_acw(): return self.dummy_acw()
- acp._make_autocomplete_window = make_acw
-
- self.text.insert('1.0', 'int.')
- acp.open_completions(ac.TAB)
- self.assertIsInstance(acp.autocompletewindow, self.dummy_acw)
- self.text.delete('1.0', 'end')
-
- # Test files.
- self.text.insert('1.0', '"t')
- self.assertTrue(acp.open_completions(ac.TAB))
- self.text.delete('1.0', 'end')
+ # Test completions of files and attributes as well as non-completion
+ # of errors
+ pass
def test_fetch_completions(self):
# Test that fetch_completions returns 2 lists:
# For attribute completion, a large list containing all variables, and
# a small list containing non-private variables.
# For file completion, a large list containing all files in the path,
- # and a small list containing files that do not start with '.'.
- acp = self.autocomplete
- small, large = acp.fetch_completions(
- '', ac.ATTRS)
- if __main__.__file__ != ac.__file__:
- self.assertNotIn('AutoComplete', small) # See issue 36405.
-
- # Test attributes
- s, b = acp.fetch_completions('', ac.ATTRS)
- self.assertLess(len(small), len(large))
- self.assertTrue(all(filter(lambda x: x.startswith('_'), s)))
- self.assertTrue(any(filter(lambda x: x.startswith('_'), b)))
-
- # Test smalll should respect to __all__.
- with patch.dict('__main__.__dict__', {'__all__': ['a', 'b']}):
- s, b = acp.fetch_completions('', ac.ATTRS)
- self.assertEqual(s, ['a', 'b'])
- self.assertIn('__name__', b) # From __main__.__dict__
- self.assertIn('sum', b) # From __main__.__builtins__.__dict__
-
- # Test attributes with name entity.
- mock = Mock()
- mock._private = Mock()
- with patch.dict('__main__.__dict__', {'foo': mock}):
- s, b = acp.fetch_completions('foo', ac.ATTRS)
- self.assertNotIn('_private', s)
- self.assertIn('_private', b)
- self.assertEqual(s, [i for i in sorted(dir(mock)) if i[:1] != '_'])
- self.assertEqual(b, sorted(dir(mock)))
-
- # Test files
- def _listdir(path):
- # This will be patch and used in fetch_completions.
- if path == '.':
- return ['foo', 'bar', '.hidden']
- return ['monty', 'python', '.hidden']
-
- with patch.object(os, 'listdir', _listdir):
- s, b = acp.fetch_completions('', ac.FILES)
- self.assertEqual(s, ['bar', 'foo'])
- self.assertEqual(b, ['.hidden', 'bar', 'foo'])
-
- s, b = acp.fetch_completions('~', ac.FILES)
- self.assertEqual(s, ['monty', 'python'])
- self.assertEqual(b, ['.hidden', 'monty', 'python'])
+ # and a small list containing files that do not start with '.'
+ pass
def test_get_entity(self):
# Test that a name is in the namespace of sys.modules and
- # __main__.__dict__.
- acp = self.autocomplete
- Equal = self.assertEqual
-
- Equal(acp.get_entity('int'), int)
-
- # Test name from sys.modules.
- mock = Mock()
- with patch.dict('sys.modules', {'tempfile': mock}):
- Equal(acp.get_entity('tempfile'), mock)
-
- # Test name from __main__.__dict__.
- di = {'foo': 10, 'bar': 20}
- with patch.dict('__main__.__dict__', {'d': di}):
- Equal(acp.get_entity('d'), di)
-
- # Test name not in namespace.
- with patch.dict('__main__.__dict__', {}):
- with self.assertRaises(NameError):
- acp.get_entity('not_exist')
+ # __main__.__dict__
+ pass
if __name__ == '__main__':
diff --git a/Lib/idlelib/idle_test/test_autocomplete_w.py b/Lib/idlelib/idle_test/test_autocomplete_w.py
deleted file mode 100644
index b1bdc6c..0000000
--- a/Lib/idlelib/idle_test/test_autocomplete_w.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"Test autocomplete_w, coverage 11%."
-
-import unittest
-from test.support import requires
-from tkinter import Tk, Text
-
-import idlelib.autocomplete_w as acw
-
-
-class AutoCompleteWindowTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.text = Text(cls.root)
- cls.acw = acw.AutoCompleteWindow(cls.text)
-
- @classmethod
- def tearDownClass(cls):
- del cls.text, cls.acw
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- self.assertEqual(self.acw.widget, self.text)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_autoexpand.py b/Lib/idlelib/idle_test/test_autoexpand.py
index e734a8b..6be4fbf 100644
--- a/Lib/idlelib/idle_test/test_autoexpand.py
+++ b/Lib/idlelib/idle_test/test_autoexpand.py
@@ -1,12 +1,12 @@
-"Test autoexpand, coverage 100%."
-
-from idlelib.autoexpand import AutoExpand
+"""Unit tests for idlelib.AutoExpand"""
import unittest
-from test.support import requires
-from tkinter import Text, Tk
+from test.test_support import requires
+from Tkinter import Text, Tk
+#from idlelib.idle_test.mock_tk import Text
+from idlelib.AutoExpand import AutoExpand
-class DummyEditwin:
+class Dummy_Editwin:
# AutoExpand.__init__ only needs .text
def __init__(self, text):
self.text = text
@@ -15,26 +15,13 @@ class AutoExpandTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
- requires('gui')
- cls.tk = Tk()
- cls.text = Text(cls.tk)
- cls.auto_expand = AutoExpand(DummyEditwin(cls.text))
- cls.auto_expand.bell = lambda: None
-
-# If mock_tk.Text._decode understood indexes 'insert' with suffixed 'linestart',
-# 'wordstart', and 'lineend', used by autoexpand, we could use the following
-# to run these test on non-gui machines (but check bell).
-## try:
-## requires('gui')
-## #raise ResourceDenied() # Uncomment to test mock.
-## except ResourceDenied:
-## from idlelib.idle_test.mock_tk import Text
-## cls.text = Text()
-## cls.text.bell = lambda: None
-## else:
-## from tkinter import Tk, Text
-## cls.tk = Tk()
-## cls.text = Text(cls.tk)
+ if 'Tkinter' in str(Text):
+ requires('gui')
+ cls.tk = Tk()
+ cls.text = Text(cls.tk)
+ else:
+ cls.text = Text()
+ cls.auto_expand = AutoExpand(Dummy_Editwin(cls.text))
@classmethod
def tearDownClass(cls):
@@ -91,7 +78,7 @@ class AutoExpandTest(unittest.TestCase):
equal(previous(), 'a')
def test_after_only(self):
- # Also add punctuation 'noise' that should be ignored.
+ # Also add punctuation 'noise' that shoud be ignored.
text = self.text
previous = self.auto_expand.getprevword
expand = self.auto_expand.expand_word_event
@@ -150,6 +137,5 @@ class AutoExpandTest(unittest.TestCase):
new_state = self.auto_expand.state
self.assertNotEqual(initial_state, new_state)
-
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_browser.py b/Lib/idlelib/idle_test/test_browser.py
deleted file mode 100644
index 25d6dc6..0000000
--- a/Lib/idlelib/idle_test/test_browser.py
+++ /dev/null
@@ -1,248 +0,0 @@
-"Test browser, coverage 90%."
-
-from idlelib import browser
-from test.support import requires
-import unittest
-from unittest import mock
-from idlelib.idle_test.mock_idle import Func
-
-from collections import deque
-import os.path
-import pyclbr
-from tkinter import Tk
-
-from idlelib.tree import TreeNode
-
-
-class ModuleBrowserTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.mb = browser.ModuleBrowser(cls.root, __file__, _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- cls.mb.close()
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root, cls.mb
-
- def test_init(self):
- mb = self.mb
- eq = self.assertEqual
- eq(mb.path, __file__)
- eq(pyclbr._modules, {})
- self.assertIsInstance(mb.node, TreeNode)
- self.assertIsNotNone(browser.file_open)
-
- def test_settitle(self):
- mb = self.mb
- self.assertIn(os.path.basename(__file__), mb.top.title())
- self.assertEqual(mb.top.iconname(), 'Module Browser')
-
- def test_rootnode(self):
- mb = self.mb
- rn = mb.rootnode()
- self.assertIsInstance(rn, browser.ModuleBrowserTreeItem)
-
- def test_close(self):
- mb = self.mb
- mb.top.destroy = Func()
- mb.node.destroy = Func()
- mb.close()
- self.assertTrue(mb.top.destroy.called)
- self.assertTrue(mb.node.destroy.called)
- del mb.top.destroy, mb.node.destroy
-
-
-# Nested tree same as in test_pyclbr.py except for supers on C0. C1.
-mb = pyclbr
-module, fname = 'test', 'test.py'
-C0 = mb.Class(module, 'C0', ['base'], fname, 1)
-F1 = mb._nest_function(C0, 'F1', 3)
-C1 = mb._nest_class(C0, 'C1', 6, [''])
-C2 = mb._nest_class(C1, 'C2', 7)
-F3 = mb._nest_function(C2, 'F3', 9)
-f0 = mb.Function(module, 'f0', fname, 11)
-f1 = mb._nest_function(f0, 'f1', 12)
-f2 = mb._nest_function(f1, 'f2', 13)
-c1 = mb._nest_class(f0, 'c1', 15)
-mock_pyclbr_tree = {'C0': C0, 'f0': f0}
-
-# Adjust C0.name, C1.name so tests do not depend on order.
-browser.transform_children(mock_pyclbr_tree, 'test') # C0(base)
-browser.transform_children(C0.children) # C1()
-
-# The class below checks that the calls above are correct
-# and that duplicate calls have no effect.
-
-
-class TransformChildrenTest(unittest.TestCase):
-
- def test_transform_module_children(self):
- eq = self.assertEqual
- transform = browser.transform_children
- # Parameter matches tree module.
- tcl = list(transform(mock_pyclbr_tree, 'test'))
- eq(tcl, [C0, f0])
- eq(tcl[0].name, 'C0(base)')
- eq(tcl[1].name, 'f0')
- # Check that second call does not change suffix.
- tcl = list(transform(mock_pyclbr_tree, 'test'))
- eq(tcl[0].name, 'C0(base)')
- # Nothing to traverse if parameter name isn't same as tree module.
- tcl = list(transform(mock_pyclbr_tree, 'different name'))
- eq(tcl, [])
-
- def test_transform_node_children(self):
- eq = self.assertEqual
- transform = browser.transform_children
- # Class with two children, one name altered.
- tcl = list(transform(C0.children))
- eq(tcl, [F1, C1])
- eq(tcl[0].name, 'F1')
- eq(tcl[1].name, 'C1()')
- tcl = list(transform(C0.children))
- eq(tcl[1].name, 'C1()')
- # Function with two children.
- eq(list(transform(f0.children)), [f1, c1])
-
-
-class ModuleBrowserTreeItemTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.mbt = browser.ModuleBrowserTreeItem(fname)
-
- def test_init(self):
- self.assertEqual(self.mbt.file, fname)
-
- def test_gettext(self):
- self.assertEqual(self.mbt.GetText(), fname)
-
- def test_geticonname(self):
- self.assertEqual(self.mbt.GetIconName(), 'python')
-
- def test_isexpandable(self):
- self.assertTrue(self.mbt.IsExpandable())
-
- def test_listchildren(self):
- save_rex = browser.pyclbr.readmodule_ex
- save_tc = browser.transform_children
- browser.pyclbr.readmodule_ex = Func(result=mock_pyclbr_tree)
- browser.transform_children = Func(result=[f0, C0])
- try:
- self.assertEqual(self.mbt.listchildren(), [f0, C0])
- finally:
- browser.pyclbr.readmodule_ex = save_rex
- browser.transform_children = save_tc
-
- def test_getsublist(self):
- mbt = self.mbt
- mbt.listchildren = Func(result=[f0, C0])
- sub0, sub1 = mbt.GetSubList()
- del mbt.listchildren
- self.assertIsInstance(sub0, browser.ChildBrowserTreeItem)
- self.assertIsInstance(sub1, browser.ChildBrowserTreeItem)
- self.assertEqual(sub0.name, 'f0')
- self.assertEqual(sub1.name, 'C0(base)')
-
- @mock.patch('idlelib.browser.file_open')
- def test_ondoubleclick(self, fopen):
- mbt = self.mbt
-
- with mock.patch('os.path.exists', return_value=False):
- mbt.OnDoubleClick()
- fopen.assert_not_called()
-
- with mock.patch('os.path.exists', return_value=True):
- mbt.OnDoubleClick()
- fopen.assert_called()
- fopen.called_with(fname)
-
-
-class ChildBrowserTreeItemTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- CBT = browser.ChildBrowserTreeItem
- cls.cbt_f1 = CBT(f1)
- cls.cbt_C1 = CBT(C1)
- cls.cbt_F1 = CBT(F1)
-
- @classmethod
- def tearDownClass(cls):
- del cls.cbt_C1, cls.cbt_f1, cls.cbt_F1
-
- def test_init(self):
- eq = self.assertEqual
- eq(self.cbt_C1.name, 'C1()')
- self.assertFalse(self.cbt_C1.isfunction)
- eq(self.cbt_f1.name, 'f1')
- self.assertTrue(self.cbt_f1.isfunction)
-
- def test_gettext(self):
- self.assertEqual(self.cbt_C1.GetText(), 'class C1()')
- self.assertEqual(self.cbt_f1.GetText(), 'def f1(...)')
-
- def test_geticonname(self):
- self.assertEqual(self.cbt_C1.GetIconName(), 'folder')
- self.assertEqual(self.cbt_f1.GetIconName(), 'python')
-
- def test_isexpandable(self):
- self.assertTrue(self.cbt_C1.IsExpandable())
- self.assertTrue(self.cbt_f1.IsExpandable())
- self.assertFalse(self.cbt_F1.IsExpandable())
-
- def test_getsublist(self):
- eq = self.assertEqual
- CBT = browser.ChildBrowserTreeItem
-
- f1sublist = self.cbt_f1.GetSubList()
- self.assertIsInstance(f1sublist[0], CBT)
- eq(len(f1sublist), 1)
- eq(f1sublist[0].name, 'f2')
-
- eq(self.cbt_F1.GetSubList(), [])
-
- @mock.patch('idlelib.browser.file_open')
- def test_ondoubleclick(self, fopen):
- goto = fopen.return_value.gotoline = mock.Mock()
- self.cbt_F1.OnDoubleClick()
- fopen.assert_called()
- goto.assert_called()
- goto.assert_called_with(self.cbt_F1.obj.lineno)
- # Failure test would have to raise OSError or AttributeError.
-
-
-class NestedChildrenTest(unittest.TestCase):
- "Test that all the nodes in a nested tree are added to the BrowserTree."
-
- def test_nested(self):
- queue = deque()
- actual_names = []
- # The tree items are processed in breadth first order.
- # Verify that processing each sublist hits every node and
- # in the right order.
- expected_names = ['f0', 'C0(base)',
- 'f1', 'c1', 'F1', 'C1()',
- 'f2', 'C2',
- 'F3']
- CBT = browser.ChildBrowserTreeItem
- queue.extend((CBT(f0), CBT(C0)))
- while queue:
- cb = queue.popleft()
- sublist = cb.GetSubList()
- queue.extend(sublist)
- self.assertIn(cb.name, cb.GetText())
- self.assertIn(cb.GetIconName(), ('python', 'folder'))
- self.assertIs(cb.IsExpandable(), sublist != [])
- actual_names.append(cb.name)
- self.assertEqual(actual_names, expected_names)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_calltip.py b/Lib/idlelib/idle_test/test_calltip.py
deleted file mode 100644
index 886959b..0000000
--- a/Lib/idlelib/idle_test/test_calltip.py
+++ /dev/null
@@ -1,253 +0,0 @@
-"Test calltip, coverage 60%"
-
-from idlelib import calltip
-import unittest
-import textwrap
-import types
-import re
-
-
-# Test Class TC is used in multiple get_argspec test methods
-class TC():
- 'doc'
- tip = "(ai=None, *b)"
- def __init__(self, ai=None, *b): 'doc'
- __init__.tip = "(self, ai=None, *b)"
- def t1(self): 'doc'
- t1.tip = "(self)"
- def t2(self, ai, b=None): 'doc'
- t2.tip = "(self, ai, b=None)"
- def t3(self, ai, *args): 'doc'
- t3.tip = "(self, ai, *args)"
- def t4(self, *args): 'doc'
- t4.tip = "(self, *args)"
- def t5(self, ai, b=None, *args, **kw): 'doc'
- t5.tip = "(self, ai, b=None, *args, **kw)"
- def t6(no, self): 'doc'
- t6.tip = "(no, self)"
- def __call__(self, ci): 'doc'
- __call__.tip = "(self, ci)"
- def nd(self): pass # No doc.
- # attaching .tip to wrapped methods does not work
- @classmethod
- def cm(cls, a): 'doc'
- @staticmethod
- def sm(b): 'doc'
-
-
-tc = TC()
-default_tip = calltip._default_callable_argspec
-get_spec = calltip.get_argspec
-
-
-class Get_argspecTest(unittest.TestCase):
- # The get_spec function must return a string, even if blank.
- # Test a variety of objects to be sure that none cause it to raise
- # (quite aside from getting as correct an answer as possible).
- # The tests of builtins may break if inspect or the docstrings change,
- # but a red buildbot is better than a user crash (as has happened).
- # For a simple mismatch, change the expected output to the actual.
-
- def test_builtins(self):
-
- def tiptest(obj, out):
- self.assertEqual(get_spec(obj), out)
-
- # Python class that inherits builtin methods
- class List(list): "List() doc"
-
- # Simulate builtin with no docstring for default tip test
- class SB: __call__ = None
-
- if List.__doc__ is not None:
- tiptest(List,
- f'(iterable=(), /){calltip._argument_positional}'
- f'\n{List.__doc__}')
- tiptest(list.__new__,
- '(*args, **kwargs)\n'
- 'Create and return a new object. '
- 'See help(type) for accurate signature.')
- tiptest(list.__init__,
- '(self, /, *args, **kwargs)'
- + calltip._argument_positional + '\n' +
- 'Initialize self. See help(type(self)) for accurate signature.')
- append_doc = (calltip._argument_positional
- + "\nAppend object to the end of the list.")
- tiptest(list.append, '(self, object, /)' + append_doc)
- tiptest(List.append, '(self, object, /)' + append_doc)
- tiptest([].append, '(object, /)' + append_doc)
-
- tiptest(types.MethodType, "method(function, instance)")
- tiptest(SB(), default_tip)
-
- p = re.compile('')
- tiptest(re.sub, '''\
-(pattern, repl, string, count=0, flags=0)
-Return the string obtained by replacing the leftmost
-non-overlapping occurrences of the pattern in string by the
-replacement repl. repl can be either a string or a callable;
-if a string, backslash escapes in it are processed. If it is
-a callable, it's passed the Match object and must return''')
- tiptest(p.sub, '''\
-(repl, string, count=0)
-Return the string obtained by replacing the leftmost \
-non-overlapping occurrences o...''')
-
- def test_signature_wrap(self):
- if textwrap.TextWrapper.__doc__ is not None:
- self.assertEqual(get_spec(textwrap.TextWrapper), '''\
-(width=70, initial_indent='', subsequent_indent='', expand_tabs=True,
- replace_whitespace=True, fix_sentence_endings=False, break_long_words=True,
- drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None,
- placeholder=' [...]')''')
-
- def test_properly_formated(self):
-
- def foo(s='a'*100):
- pass
-
- def bar(s='a'*100):
- """Hello Guido"""
- pass
-
- def baz(s='a'*100, z='b'*100):
- pass
-
- indent = calltip._INDENT
-
- sfoo = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\
- "aaaaaaaaaa')"
- sbar = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\
- "aaaaaaaaaa')\nHello Guido"
- sbaz = "(s='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"\
- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + indent + "aaaaaaaaa"\
- "aaaaaaaaaa', z='bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"\
- "bbbbbbbbbbbbbbbbb\n" + indent + "bbbbbbbbbbbbbbbbbbbbbb"\
- "bbbbbbbbbbbbbbbbbbbbbb')"
-
- for func,doc in [(foo, sfoo), (bar, sbar), (baz, sbaz)]:
- with self.subTest(func=func, doc=doc):
- self.assertEqual(get_spec(func), doc)
-
- def test_docline_truncation(self):
- def f(): pass
- f.__doc__ = 'a'*300
- self.assertEqual(get_spec(f), f"()\n{'a'*(calltip._MAX_COLS-3) + '...'}")
-
- def test_multiline_docstring(self):
- # Test fewer lines than max.
- self.assertEqual(get_spec(range),
- "range(stop) -> range object\n"
- "range(start, stop[, step]) -> range object")
-
- # Test max lines
- self.assertEqual(get_spec(bytes), '''\
-bytes(iterable_of_ints) -> bytes
-bytes(string, encoding[, errors]) -> bytes
-bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer
-bytes(int) -> bytes object of size given by the parameter initialized with null bytes
-bytes() -> empty bytes object''')
-
- # Test more than max lines
- def f(): pass
- f.__doc__ = 'a\n' * 15
- self.assertEqual(get_spec(f), '()' + '\na' * calltip._MAX_LINES)
-
- def test_functions(self):
- def t1(): 'doc'
- t1.tip = "()"
- def t2(a, b=None): 'doc'
- t2.tip = "(a, b=None)"
- def t3(a, *args): 'doc'
- t3.tip = "(a, *args)"
- def t4(*args): 'doc'
- t4.tip = "(*args)"
- def t5(a, b=None, *args, **kw): 'doc'
- t5.tip = "(a, b=None, *args, **kw)"
-
- doc = '\ndoc' if t1.__doc__ is not None else ''
- for func in (t1, t2, t3, t4, t5, TC):
- with self.subTest(func=func):
- self.assertEqual(get_spec(func), func.tip + doc)
-
- def test_methods(self):
- doc = '\ndoc' if TC.__doc__ is not None else ''
- for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__):
- with self.subTest(meth=meth):
- self.assertEqual(get_spec(meth), meth.tip + doc)
- self.assertEqual(get_spec(TC.cm), "(a)" + doc)
- self.assertEqual(get_spec(TC.sm), "(b)" + doc)
-
- def test_bound_methods(self):
- # test that first parameter is correctly removed from argspec
- doc = '\ndoc' if TC.__doc__ is not None else ''
- for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"),
- (tc.t6, "(self)"), (tc.__call__, '(ci)'),
- (tc, '(ci)'), (TC.cm, "(a)"),):
- with self.subTest(meth=meth, mtip=mtip):
- self.assertEqual(get_spec(meth), mtip + doc)
-
- def test_starred_parameter(self):
- # test that starred first parameter is *not* removed from argspec
- class C:
- def m1(*args): pass
- c = C()
- for meth, mtip in ((C.m1, '(*args)'), (c.m1, "(*args)"),):
- with self.subTest(meth=meth, mtip=mtip):
- self.assertEqual(get_spec(meth), mtip)
-
- def test_invalid_method_get_spec(self):
- class C:
- def m2(**kwargs): pass
- class Test:
- def __call__(*, a): pass
-
- mtip = calltip._invalid_method
- self.assertEqual(get_spec(C().m2), mtip)
- self.assertEqual(get_spec(Test()), mtip)
-
- def test_non_ascii_name(self):
- # test that re works to delete a first parameter name that
- # includes non-ascii chars, such as various forms of A.
- uni = "(A\u0391\u0410\u05d0\u0627\u0905\u1e00\u3042, a)"
- assert calltip._first_param.sub('', uni) == '(a)'
-
- def test_no_docstring(self):
- for meth, mtip in ((TC.nd, "(self)"), (tc.nd, "()")):
- with self.subTest(meth=meth, mtip=mtip):
- self.assertEqual(get_spec(meth), mtip)
-
- def test_attribute_exception(self):
- class NoCall:
- def __getattr__(self, name):
- raise BaseException
- class CallA(NoCall):
- def __call__(oui, a, b, c):
- pass
- class CallB(NoCall):
- def __call__(self, ci):
- pass
-
- for meth, mtip in ((NoCall, default_tip), (CallA, default_tip),
- (NoCall(), ''), (CallA(), '(a, b, c)'),
- (CallB(), '(ci)')):
- with self.subTest(meth=meth, mtip=mtip):
- self.assertEqual(get_spec(meth), mtip)
-
- def test_non_callables(self):
- for obj in (0, 0.0, '0', b'0', [], {}):
- with self.subTest(obj=obj):
- self.assertEqual(get_spec(obj), '')
-
-
-class Get_entityTest(unittest.TestCase):
- def test_bad_entity(self):
- self.assertIsNone(calltip.get_entity('1/0'))
- def test_good_entity(self):
- self.assertIs(calltip.get_entity('int'), int)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_calltip_w.py b/Lib/idlelib/idle_test/test_calltip_w.py
deleted file mode 100644
index a5ec76e..0000000
--- a/Lib/idlelib/idle_test/test_calltip_w.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"Test calltip_w, coverage 18%."
-
-from idlelib import calltip_w
-import unittest
-from test.support import requires
-from tkinter import Tk, Text
-
-
-class CallTipWindowTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.text = Text(cls.root)
- cls.calltip = calltip_w.CalltipWindow(cls.text)
-
- @classmethod
- def tearDownClass(cls):
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.text, cls.root
-
- def test_init(self):
- self.assertEqual(self.calltip.anchor_widget, self.text)
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py
new file mode 100644
index 0000000..147119c
--- /dev/null
+++ b/Lib/idlelib/idle_test/test_calltips.py
@@ -0,0 +1,185 @@
+import unittest
+import idlelib.CallTips as ct
+CTi = ct.CallTips() # needed for get_entity test in 2.7
+import textwrap
+import types
+import warnings
+
+default_tip = ''
+
+# Test Class TC is used in multiple get_argspec test methods
+class TC(object):
+ 'doc'
+ tip = "(ai=None, *args)"
+ def __init__(self, ai=None, *b): 'doc'
+ __init__.tip = "(self, ai=None, *args)"
+ def t1(self): 'doc'
+ t1.tip = "(self)"
+ def t2(self, ai, b=None): 'doc'
+ t2.tip = "(self, ai, b=None)"
+ def t3(self, ai, *args): 'doc'
+ t3.tip = "(self, ai, *args)"
+ def t4(self, *args): 'doc'
+ t4.tip = "(self, *args)"
+ def t5(self, ai, b=None, *args, **kw): 'doc'
+ t5.tip = "(self, ai, b=None, *args, **kwargs)"
+ def t6(no, self): 'doc'
+ t6.tip = "(no, self)"
+ def __call__(self, ci): 'doc'
+ __call__.tip = "(self, ci)"
+ # attaching .tip to wrapped methods does not work
+ @classmethod
+ def cm(cls, a): 'doc'
+ @staticmethod
+ def sm(b): 'doc'
+
+tc = TC()
+
+signature = ct.get_arg_text # 2.7 and 3.x use different functions
+class Get_signatureTest(unittest.TestCase):
+ # The signature function must return a string, even if blank.
+ # Test a variety of objects to be sure that none cause it to raise
+ # (quite aside from getting as correct an answer as possible).
+ # The tests of builtins may break if the docstrings change,
+ # but a red buildbot is better than a user crash (as has happened).
+ # For a simple mismatch, change the expected output to the actual.
+
+ def test_builtins(self):
+ # 2.7 puts '()\n' where 3.x does not, other minor differences
+
+ # Python class that inherits builtin methods
+ class List(list): "List() doc"
+ # Simulate builtin with no docstring for default argspec test
+ class SB: __call__ = None
+
+ def gtest(obj, out):
+ self.assertEqual(signature(obj), out)
+
+ if List.__doc__ is not None:
+ gtest(List, '()\n' + List.__doc__)
+ gtest(list.__new__,
+ 'T.__new__(S, ...) -> a new object with type S, a subtype of T')
+ gtest(list.__init__,
+ 'x.__init__(...) initializes x; see help(type(x)) for signature')
+ append_doc = "L.append(object) -- append object to end"
+ gtest(list.append, append_doc)
+ gtest([].append, append_doc)
+ gtest(List.append, append_doc)
+
+ gtest(types.MethodType, '()\ninstancemethod(function, instance, class)')
+ gtest(SB(), default_tip)
+
+ def test_signature_wrap(self):
+ # This is also a test of an old-style class
+ if textwrap.TextWrapper.__doc__ is not None:
+ self.assertEqual(signature(textwrap.TextWrapper), '''\
+(width=70, initial_indent='', subsequent_indent='', expand_tabs=True,
+ replace_whitespace=True, fix_sentence_endings=False, break_long_words=True,
+ drop_whitespace=True, break_on_hyphens=True)''')
+
+ def test_docline_truncation(self):
+ def f(): pass
+ f.__doc__ = 'a'*300
+ self.assertEqual(signature(f), '()\n' + 'a' * (ct._MAX_COLS-3) + '...')
+
+ def test_multiline_docstring(self):
+ # Test fewer lines than max.
+ self.assertEqual(signature(list),
+ "()\nlist() -> new empty list\n"
+ "list(iterable) -> new list initialized from iterable's items")
+
+ # Test max lines and line (currently) too long.
+ def f():
+ pass
+ s = 'a\nb\nc\nd\n'
+ f.__doc__ = s + 300 * 'e' + 'f'
+ self.assertEqual(signature(f),
+ '()\n' + s + (ct._MAX_COLS - 3) * 'e' + '...')
+
+ def test_functions(self):
+ def t1(): 'doc'
+ t1.tip = "()"
+ def t2(a, b=None): 'doc'
+ t2.tip = "(a, b=None)"
+ def t3(a, *args): 'doc'
+ t3.tip = "(a, *args)"
+ def t4(*args): 'doc'
+ t4.tip = "(*args)"
+ def t5(a, b=None, *args, **kwds): 'doc'
+ t5.tip = "(a, b=None, *args, **kwargs)"
+
+ doc = '\ndoc' if t1.__doc__ is not None else ''
+ for func in (t1, t2, t3, t4, t5, TC):
+ self.assertEqual(signature(func), func.tip + doc)
+
+ def test_methods(self):
+ doc = '\ndoc' if TC.__doc__ is not None else ''
+ for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__):
+ self.assertEqual(signature(meth), meth.tip + doc)
+ self.assertEqual(signature(TC.cm), "(a)" + doc)
+ self.assertEqual(signature(TC.sm), "(b)" + doc)
+
+ def test_bound_methods(self):
+ # test that first parameter is correctly removed from argspec
+ doc = '\ndoc' if TC.__doc__ is not None else ''
+ for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"), (tc.t6, "(self)"),
+ (tc.__call__, '(ci)'), (tc, '(ci)'), (TC.cm, "(a)"),):
+ self.assertEqual(signature(meth), mtip + doc)
+
+ def test_starred_parameter(self):
+ # test that starred first parameter is *not* removed from argspec
+ class C:
+ def m1(*args): pass
+ def m2(**kwds): pass
+ def f1(args, kwargs, *a, **k): pass
+ def f2(args, kwargs, args1, kwargs1, *a, **k): pass
+ c = C()
+ self.assertEqual(signature(C.m1), '(*args)')
+ self.assertEqual(signature(c.m1), '(*args)')
+ self.assertEqual(signature(C.m2), '(**kwargs)')
+ self.assertEqual(signature(c.m2), '(**kwargs)')
+ self.assertEqual(signature(f1), '(args, kwargs, *args1, **kwargs1)')
+ self.assertEqual(signature(f2),
+ '(args, kwargs, args1, kwargs1, *args2, **kwargs2)')
+
+ def test_no_docstring(self):
+ def nd(s): pass
+ TC.nd = nd
+ self.assertEqual(signature(nd), "(s)")
+ self.assertEqual(signature(TC.nd), "(s)")
+ self.assertEqual(signature(tc.nd), "()")
+
+ def test_attribute_exception(self):
+ class NoCall(object):
+ def __getattr__(self, name):
+ raise BaseException
+ class Call(NoCall):
+ def __call__(self, ci):
+ pass
+ for meth, mtip in ((NoCall, '()'), (Call, '()'),
+ (NoCall(), ''), (Call(), '(ci)')):
+ self.assertEqual(signature(meth), mtip)
+
+ def test_non_callables(self):
+ for obj in (0, 0.0, '0', b'0', [], {}):
+ self.assertEqual(signature(obj), '')
+
+class Get_entityTest(unittest.TestCase):
+ # In 3.x, get_entity changed from 'instance method' to module function
+ # since 'self' not used. Use dummy instance until change 2.7 also.
+ def test_bad_entity(self):
+ self.assertIsNone(CTi.get_entity('1//0'))
+ def test_good_entity(self):
+ self.assertIs(CTi.get_entity('int'), int)
+
+class Py2Test(unittest.TestCase):
+ def test_paramtuple_float(self):
+ # 18539: (a,b) becomes '.0' in code object; change that but not 0.0
+ with warnings.catch_warnings():
+ # Suppess message of py3 deprecation of parameter unpacking
+ warnings.simplefilter("ignore")
+ exec "def f((a,b), c=0.0): pass"
+ self.assertEqual(signature(f), '(<tuple>, c=0.0)')
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, exit=False)
diff --git a/Lib/idlelib/idle_test/test_codecontext.py b/Lib/idlelib/idle_test/test_codecontext.py
deleted file mode 100644
index 3ec49e9..0000000
--- a/Lib/idlelib/idle_test/test_codecontext.py
+++ /dev/null
@@ -1,447 +0,0 @@
-"Test codecontext, coverage 100%"
-
-from idlelib import codecontext
-import unittest
-import unittest.mock
-from test.support import requires
-from tkinter import NSEW, Tk, Frame, Text, TclError
-
-from unittest import mock
-import re
-from idlelib import config
-
-
-usercfg = codecontext.idleConf.userCfg
-testcfg = {
- 'main': config.IdleUserConfParser(''),
- 'highlight': config.IdleUserConfParser(''),
- 'keys': config.IdleUserConfParser(''),
- 'extensions': config.IdleUserConfParser(''),
-}
-code_sample = """\
-
-class C1():
- # Class comment.
- def __init__(self, a, b):
- self.a = a
- self.b = b
- def compare(self):
- if a > b:
- return a
- elif a < b:
- return b
- else:
- return None
-"""
-
-
-class DummyEditwin:
- def __init__(self, root, frame, text):
- self.root = root
- self.top = root
- self.text_frame = frame
- self.text = text
- self.label = ''
-
- def getlineno(self, index):
- return int(float(self.text.index(index)))
-
- def update_menu_label(self, **kwargs):
- self.label = kwargs['label']
-
-
-class CodeContextTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- root = cls.root = Tk()
- root.withdraw()
- frame = cls.frame = Frame(root)
- text = cls.text = Text(frame)
- text.insert('1.0', code_sample)
- # Need to pack for creation of code context text widget.
- frame.pack(side='left', fill='both', expand=1)
- text.grid(row=1, column=1, sticky=NSEW)
- cls.editor = DummyEditwin(root, frame, text)
- codecontext.idleConf.userCfg = testcfg
-
- @classmethod
- def tearDownClass(cls):
- codecontext.idleConf.userCfg = usercfg
- cls.editor.text.delete('1.0', 'end')
- del cls.editor, cls.frame, cls.text
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def setUp(self):
- self.text.yview(0)
- self.text['font'] = 'TkFixedFont'
- self.cc = codecontext.CodeContext(self.editor)
-
- self.highlight_cfg = {"background": '#abcdef',
- "foreground": '#123456'}
- orig_idleConf_GetHighlight = codecontext.idleConf.GetHighlight
- def mock_idleconf_GetHighlight(theme, element):
- if element == 'context':
- return self.highlight_cfg
- return orig_idleConf_GetHighlight(theme, element)
- GetHighlight_patcher = unittest.mock.patch.object(
- codecontext.idleConf, 'GetHighlight', mock_idleconf_GetHighlight)
- GetHighlight_patcher.start()
- self.addCleanup(GetHighlight_patcher.stop)
-
- self.font_override = 'TkFixedFont'
- def mock_idleconf_GetFont(root, configType, section):
- return self.font_override
- GetFont_patcher = unittest.mock.patch.object(
- codecontext.idleConf, 'GetFont', mock_idleconf_GetFont)
- GetFont_patcher.start()
- self.addCleanup(GetFont_patcher.stop)
-
- def tearDown(self):
- if self.cc.context:
- self.cc.context.destroy()
- # Explicitly call __del__ to remove scheduled scripts.
- self.cc.__del__()
- del self.cc.context, self.cc
-
- def test_init(self):
- eq = self.assertEqual
- ed = self.editor
- cc = self.cc
-
- eq(cc.editwin, ed)
- eq(cc.text, ed.text)
- eq(cc.text['font'], ed.text['font'])
- self.assertIsNone(cc.context)
- eq(cc.info, [(0, -1, '', False)])
- eq(cc.topvisible, 1)
- self.assertIsNone(self.cc.t1)
-
- def test_del(self):
- self.cc.__del__()
-
- def test_del_with_timer(self):
- timer = self.cc.t1 = self.text.after(10000, lambda: None)
- self.cc.__del__()
- with self.assertRaises(TclError) as cm:
- self.root.tk.call('after', 'info', timer)
- self.assertIn("doesn't exist", str(cm.exception))
-
- def test_reload(self):
- codecontext.CodeContext.reload()
- self.assertEqual(self.cc.context_depth, 15)
-
- def test_toggle_code_context_event(self):
- eq = self.assertEqual
- cc = self.cc
- toggle = cc.toggle_code_context_event
-
- # Make sure code context is off.
- if cc.context:
- toggle()
-
- # Toggle on.
- toggle()
- self.assertIsNotNone(cc.context)
- eq(cc.context['font'], self.text['font'])
- eq(cc.context['fg'], self.highlight_cfg['foreground'])
- eq(cc.context['bg'], self.highlight_cfg['background'])
- eq(cc.context.get('1.0', 'end-1c'), '')
- eq(cc.editwin.label, 'Hide Code Context')
- eq(self.root.tk.call('after', 'info', self.cc.t1)[1], 'timer')
-
- # Toggle off.
- toggle()
- self.assertIsNone(cc.context)
- eq(cc.editwin.label, 'Show Code Context')
- self.assertIsNone(self.cc.t1)
-
- # Scroll down and toggle back on.
- line11_context = '\n'.join(x[2] for x in cc.get_context(11)[0])
- cc.text.yview(11)
- toggle()
- eq(cc.context.get('1.0', 'end-1c'), line11_context)
-
- # Toggle off and on again.
- toggle()
- toggle()
- eq(cc.context.get('1.0', 'end-1c'), line11_context)
-
- def test_get_context(self):
- eq = self.assertEqual
- gc = self.cc.get_context
-
- # stopline must be greater than 0.
- with self.assertRaises(AssertionError):
- gc(1, stopline=0)
-
- eq(gc(3), ([(2, 0, 'class C1():', 'class')], 0))
-
- # Don't return comment.
- eq(gc(4), ([(2, 0, 'class C1():', 'class')], 0))
-
- # Two indentation levels and no comment.
- eq(gc(5), ([(2, 0, 'class C1():', 'class'),
- (4, 4, ' def __init__(self, a, b):', 'def')], 0))
-
- # Only one 'def' is returned, not both at the same indent level.
- eq(gc(10), ([(2, 0, 'class C1():', 'class'),
- (7, 4, ' def compare(self):', 'def'),
- (8, 8, ' if a > b:', 'if')], 0))
-
- # With 'elif', also show the 'if' even though it's at the same level.
- eq(gc(11), ([(2, 0, 'class C1():', 'class'),
- (7, 4, ' def compare(self):', 'def'),
- (8, 8, ' if a > b:', 'if'),
- (10, 8, ' elif a < b:', 'elif')], 0))
-
- # Set stop_line to not go back to first line in source code.
- # Return includes stop_line.
- eq(gc(11, stopline=2), ([(2, 0, 'class C1():', 'class'),
- (7, 4, ' def compare(self):', 'def'),
- (8, 8, ' if a > b:', 'if'),
- (10, 8, ' elif a < b:', 'elif')], 0))
- eq(gc(11, stopline=3), ([(7, 4, ' def compare(self):', 'def'),
- (8, 8, ' if a > b:', 'if'),
- (10, 8, ' elif a < b:', 'elif')], 4))
- eq(gc(11, stopline=8), ([(8, 8, ' if a > b:', 'if'),
- (10, 8, ' elif a < b:', 'elif')], 8))
-
- # Set stop_indent to test indent level to stop at.
- eq(gc(11, stopindent=4), ([(7, 4, ' def compare(self):', 'def'),
- (8, 8, ' if a > b:', 'if'),
- (10, 8, ' elif a < b:', 'elif')], 4))
- # Check that the 'if' is included.
- eq(gc(11, stopindent=8), ([(8, 8, ' if a > b:', 'if'),
- (10, 8, ' elif a < b:', 'elif')], 8))
-
- def test_update_code_context(self):
- eq = self.assertEqual
- cc = self.cc
- # Ensure code context is active.
- if not cc.context:
- cc.toggle_code_context_event()
-
- # Invoke update_code_context without scrolling - nothing happens.
- self.assertIsNone(cc.update_code_context())
- eq(cc.info, [(0, -1, '', False)])
- eq(cc.topvisible, 1)
-
- # Scroll down to line 1.
- cc.text.yview(1)
- cc.update_code_context()
- eq(cc.info, [(0, -1, '', False)])
- eq(cc.topvisible, 2)
- eq(cc.context.get('1.0', 'end-1c'), '')
-
- # Scroll down to line 2.
- cc.text.yview(2)
- cc.update_code_context()
- eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')])
- eq(cc.topvisible, 3)
- eq(cc.context.get('1.0', 'end-1c'), 'class C1():')
-
- # Scroll down to line 3. Since it's a comment, nothing changes.
- cc.text.yview(3)
- cc.update_code_context()
- eq(cc.info, [(0, -1, '', False), (2, 0, 'class C1():', 'class')])
- eq(cc.topvisible, 4)
- eq(cc.context.get('1.0', 'end-1c'), 'class C1():')
-
- # Scroll down to line 4.
- cc.text.yview(4)
- cc.update_code_context()
- eq(cc.info, [(0, -1, '', False),
- (2, 0, 'class C1():', 'class'),
- (4, 4, ' def __init__(self, a, b):', 'def')])
- eq(cc.topvisible, 5)
- eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
- ' def __init__(self, a, b):')
-
- # Scroll down to line 11. Last 'def' is removed.
- cc.text.yview(11)
- cc.update_code_context()
- eq(cc.info, [(0, -1, '', False),
- (2, 0, 'class C1():', 'class'),
- (7, 4, ' def compare(self):', 'def'),
- (8, 8, ' if a > b:', 'if'),
- (10, 8, ' elif a < b:', 'elif')])
- eq(cc.topvisible, 12)
- eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
- ' def compare(self):\n'
- ' if a > b:\n'
- ' elif a < b:')
-
- # No scroll. No update, even though context_depth changed.
- cc.update_code_context()
- cc.context_depth = 1
- eq(cc.info, [(0, -1, '', False),
- (2, 0, 'class C1():', 'class'),
- (7, 4, ' def compare(self):', 'def'),
- (8, 8, ' if a > b:', 'if'),
- (10, 8, ' elif a < b:', 'elif')])
- eq(cc.topvisible, 12)
- eq(cc.context.get('1.0', 'end-1c'), 'class C1():\n'
- ' def compare(self):\n'
- ' if a > b:\n'
- ' elif a < b:')
-
- # Scroll up.
- cc.text.yview(5)
- cc.update_code_context()
- eq(cc.info, [(0, -1, '', False),
- (2, 0, 'class C1():', 'class'),
- (4, 4, ' def __init__(self, a, b):', 'def')])
- eq(cc.topvisible, 6)
- # context_depth is 1.
- eq(cc.context.get('1.0', 'end-1c'), ' def __init__(self, a, b):')
-
- def test_jumptoline(self):
- eq = self.assertEqual
- cc = self.cc
- jump = cc.jumptoline
-
- if not cc.context:
- cc.toggle_code_context_event()
-
- # Empty context.
- cc.text.yview('2.0')
- cc.update_code_context()
- eq(cc.topvisible, 2)
- cc.context.mark_set('insert', '1.5')
- jump()
- eq(cc.topvisible, 1)
-
- # 4 lines of context showing.
- cc.text.yview('12.0')
- cc.update_code_context()
- eq(cc.topvisible, 12)
- cc.context.mark_set('insert', '3.0')
- jump()
- eq(cc.topvisible, 8)
-
- # More context lines than limit.
- cc.context_depth = 2
- cc.text.yview('12.0')
- cc.update_code_context()
- eq(cc.topvisible, 12)
- cc.context.mark_set('insert', '1.0')
- jump()
- eq(cc.topvisible, 8)
-
- @mock.patch.object(codecontext.CodeContext, 'update_code_context')
- def test_timer_event(self, mock_update):
- # Ensure code context is not active.
- if self.cc.context:
- self.cc.toggle_code_context_event()
- self.cc.timer_event()
- mock_update.assert_not_called()
-
- # Activate code context.
- self.cc.toggle_code_context_event()
- self.cc.timer_event()
- mock_update.assert_called()
-
- def test_font(self):
- eq = self.assertEqual
- cc = self.cc
-
- orig_font = cc.text['font']
- test_font = 'TkTextFont'
- self.assertNotEqual(orig_font, test_font)
-
- # Ensure code context is not active.
- if cc.context is not None:
- cc.toggle_code_context_event()
-
- self.font_override = test_font
- # Nothing breaks or changes with inactive code context.
- cc.update_font()
-
- # Activate code context, previous font change is immediately effective.
- cc.toggle_code_context_event()
- eq(cc.context['font'], test_font)
-
- # Call the font update, change is picked up.
- self.font_override = orig_font
- cc.update_font()
- eq(cc.context['font'], orig_font)
-
- def test_highlight_colors(self):
- eq = self.assertEqual
- cc = self.cc
-
- orig_colors = dict(self.highlight_cfg)
- test_colors = {'background': '#222222', 'foreground': '#ffff00'}
-
- def assert_colors_are_equal(colors):
- eq(cc.context['background'], colors['background'])
- eq(cc.context['foreground'], colors['foreground'])
-
- # Ensure code context is not active.
- if cc.context:
- cc.toggle_code_context_event()
-
- self.highlight_cfg = test_colors
- # Nothing breaks with inactive code context.
- cc.update_highlight_colors()
-
- # Activate code context, previous colors change is immediately effective.
- cc.toggle_code_context_event()
- assert_colors_are_equal(test_colors)
-
- # Call colors update with no change to the configured colors.
- cc.update_highlight_colors()
- assert_colors_are_equal(test_colors)
-
- # Call the colors update with code context active, change is picked up.
- self.highlight_cfg = orig_colors
- cc.update_highlight_colors()
- assert_colors_are_equal(orig_colors)
-
-
-class HelperFunctionText(unittest.TestCase):
-
- def test_get_spaces_firstword(self):
- get = codecontext.get_spaces_firstword
- test_lines = (
- (' first word', (' ', 'first')),
- ('\tfirst word', ('\t', 'first')),
- (' \u19D4\u19D2: ', (' ', '\u19D4\u19D2')),
- ('no spaces', ('', 'no')),
- ('', ('', '')),
- ('# TEST COMMENT', ('', '')),
- (' (continuation)', (' ', ''))
- )
- for line, expected_output in test_lines:
- self.assertEqual(get(line), expected_output)
-
- # Send the pattern in the call.
- self.assertEqual(get(' (continuation)',
- c=re.compile(r'^(\s*)([^\s]*)')),
- (' ', '(continuation)'))
-
- def test_get_line_info(self):
- eq = self.assertEqual
- gli = codecontext.get_line_info
- lines = code_sample.splitlines()
-
- # Line 1 is not a BLOCKOPENER.
- eq(gli(lines[0]), (codecontext.INFINITY, '', False))
- # Line 2 is a BLOCKOPENER without an indent.
- eq(gli(lines[1]), (0, 'class C1():', 'class'))
- # Line 3 is not a BLOCKOPENER and does not return the indent level.
- eq(gli(lines[2]), (codecontext.INFINITY, ' # Class comment.', False))
- # Line 4 is a BLOCKOPENER and is indented.
- eq(gli(lines[3]), (4, ' def __init__(self, a, b):', 'def'))
- # Line 8 is a different BLOCKOPENER and is indented.
- eq(gli(lines[7]), (8, ' if a > b:', 'if'))
- # Test tab.
- eq(gli('\tif a == b:'), (1, '\tif a == b:', 'if'))
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_colorizer.py b/Lib/idlelib/idle_test/test_colorizer.py
deleted file mode 100644
index c31c492..0000000
--- a/Lib/idlelib/idle_test/test_colorizer.py
+++ /dev/null
@@ -1,423 +0,0 @@
-"Test colorizer, coverage 93%."
-
-from idlelib import colorizer
-from test.support import requires
-import unittest
-from unittest import mock
-
-from functools import partial
-from tkinter import Tk, Text
-from idlelib import config
-from idlelib.percolator import Percolator
-
-
-usercfg = colorizer.idleConf.userCfg
-testcfg = {
- 'main': config.IdleUserConfParser(''),
- 'highlight': config.IdleUserConfParser(''),
- 'keys': config.IdleUserConfParser(''),
- 'extensions': config.IdleUserConfParser(''),
-}
-
-source = (
- "if True: int ('1') # keyword, builtin, string, comment\n"
- "elif False: print(0) # 'string' in comment\n"
- "else: float(None) # if in comment\n"
- "if iF + If + IF: 'keyword matching must respect case'\n"
- "if'': x or'' # valid string-keyword no-space combinations\n"
- "async def f(): await g()\n"
- "'x', '''x''', \"x\", \"\"\"x\"\"\"\n"
- )
-
-
-def setUpModule():
- colorizer.idleConf.userCfg = testcfg
-
-
-def tearDownModule():
- colorizer.idleConf.userCfg = usercfg
-
-
-class FunctionTest(unittest.TestCase):
-
- def test_any(self):
- self.assertEqual(colorizer.any('test', ('a', 'b', 'cd')),
- '(?P<test>a|b|cd)')
-
- def test_make_pat(self):
- # Tested in more detail by testing prog.
- self.assertTrue(colorizer.make_pat())
-
- def test_prog(self):
- prog = colorizer.prog
- eq = self.assertEqual
- line = 'def f():\n print("hello")\n'
- m = prog.search(line)
- eq(m.groupdict()['KEYWORD'], 'def')
- m = prog.search(line, m.end())
- eq(m.groupdict()['SYNC'], '\n')
- m = prog.search(line, m.end())
- eq(m.groupdict()['BUILTIN'], 'print')
- m = prog.search(line, m.end())
- eq(m.groupdict()['STRING'], '"hello"')
- m = prog.search(line, m.end())
- eq(m.groupdict()['SYNC'], '\n')
-
- def test_idprog(self):
- idprog = colorizer.idprog
- m = idprog.match('nospace')
- self.assertIsNone(m)
- m = idprog.match(' space')
- self.assertEqual(m.group(0), ' space')
-
-
-class ColorConfigTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- root = cls.root = Tk()
- root.withdraw()
- cls.text = Text(root)
-
- @classmethod
- def tearDownClass(cls):
- del cls.text
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def test_color_config(self):
- text = self.text
- eq = self.assertEqual
- colorizer.color_config(text)
- # Uses IDLE Classic theme as default.
- eq(text['background'], '#ffffff')
- eq(text['foreground'], '#000000')
- eq(text['selectbackground'], 'gray')
- eq(text['selectforeground'], '#000000')
- eq(text['insertbackground'], 'black')
- eq(text['inactiveselectbackground'], 'gray')
-
-
-class ColorDelegatorInstantiationTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- root = cls.root = Tk()
- root.withdraw()
- text = cls.text = Text(root)
-
- @classmethod
- def tearDownClass(cls):
- del cls.text
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def setUp(self):
- self.color = colorizer.ColorDelegator()
-
- def tearDown(self):
- self.color.close()
- self.text.delete('1.0', 'end')
- self.color.resetcache()
- del self.color
-
- def test_init(self):
- color = self.color
- self.assertIsInstance(color, colorizer.ColorDelegator)
-
- def test_init_state(self):
- # init_state() is called during the instantiation of
- # ColorDelegator in setUp().
- color = self.color
- self.assertIsNone(color.after_id)
- self.assertTrue(color.allow_colorizing)
- self.assertFalse(color.colorizing)
- self.assertFalse(color.stop_colorizing)
-
-
-class ColorDelegatorTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- root = cls.root = Tk()
- root.withdraw()
- text = cls.text = Text(root)
- cls.percolator = Percolator(text)
- # Delegator stack = [Delegator(text)]
-
- @classmethod
- def tearDownClass(cls):
- cls.percolator.redir.close()
- del cls.percolator, cls.text
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def setUp(self):
- self.color = colorizer.ColorDelegator()
- self.percolator.insertfilter(self.color)
- # Calls color.setdelegate(Delegator(text)).
-
- def tearDown(self):
- self.color.close()
- self.percolator.removefilter(self.color)
- self.text.delete('1.0', 'end')
- self.color.resetcache()
- del self.color
-
- def test_setdelegate(self):
- # Called in setUp when filter is attached to percolator.
- color = self.color
- self.assertIsInstance(color.delegate, colorizer.Delegator)
- # It is too late to mock notify_range, so test side effect.
- self.assertEqual(self.root.tk.call(
- 'after', 'info', color.after_id)[1], 'timer')
-
- def test_LoadTagDefs(self):
- highlight = partial(config.idleConf.GetHighlight, theme='IDLE Classic')
- for tag, colors in self.color.tagdefs.items():
- with self.subTest(tag=tag):
- self.assertIn('background', colors)
- self.assertIn('foreground', colors)
- if tag not in ('SYNC', 'TODO'):
- self.assertEqual(colors, highlight(element=tag.lower()))
-
- def test_config_colors(self):
- text = self.text
- highlight = partial(config.idleConf.GetHighlight, theme='IDLE Classic')
- for tag in self.color.tagdefs:
- for plane in ('background', 'foreground'):
- with self.subTest(tag=tag, plane=plane):
- if tag in ('SYNC', 'TODO'):
- self.assertEqual(text.tag_cget(tag, plane), '')
- else:
- self.assertEqual(text.tag_cget(tag, plane),
- highlight(element=tag.lower())[plane])
- # 'sel' is marked as the highest priority.
- self.assertEqual(text.tag_names()[-1], 'sel')
-
- @mock.patch.object(colorizer.ColorDelegator, 'notify_range')
- def test_insert(self, mock_notify):
- text = self.text
- # Initial text.
- text.insert('insert', 'foo')
- self.assertEqual(text.get('1.0', 'end'), 'foo\n')
- mock_notify.assert_called_with('1.0', '1.0+3c')
- # Additional text.
- text.insert('insert', 'barbaz')
- self.assertEqual(text.get('1.0', 'end'), 'foobarbaz\n')
- mock_notify.assert_called_with('1.3', '1.3+6c')
-
- @mock.patch.object(colorizer.ColorDelegator, 'notify_range')
- def test_delete(self, mock_notify):
- text = self.text
- # Initialize text.
- text.insert('insert', 'abcdefghi')
- self.assertEqual(text.get('1.0', 'end'), 'abcdefghi\n')
- # Delete single character.
- text.delete('1.7')
- self.assertEqual(text.get('1.0', 'end'), 'abcdefgi\n')
- mock_notify.assert_called_with('1.7')
- # Delete multiple characters.
- text.delete('1.3', '1.6')
- self.assertEqual(text.get('1.0', 'end'), 'abcgi\n')
- mock_notify.assert_called_with('1.3')
-
- def test_notify_range(self):
- text = self.text
- color = self.color
- eq = self.assertEqual
-
- # Colorizing already scheduled.
- save_id = color.after_id
- eq(self.root.tk.call('after', 'info', save_id)[1], 'timer')
- self.assertFalse(color.colorizing)
- self.assertFalse(color.stop_colorizing)
- self.assertTrue(color.allow_colorizing)
-
- # Coloring scheduled and colorizing in progress.
- color.colorizing = True
- color.notify_range('1.0', 'end')
- self.assertFalse(color.stop_colorizing)
- eq(color.after_id, save_id)
-
- # No colorizing scheduled and colorizing in progress.
- text.after_cancel(save_id)
- color.after_id = None
- color.notify_range('1.0', '1.0+3c')
- self.assertTrue(color.stop_colorizing)
- self.assertIsNotNone(color.after_id)
- eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
- # New event scheduled.
- self.assertNotEqual(color.after_id, save_id)
-
- # No colorizing scheduled and colorizing off.
- text.after_cancel(color.after_id)
- color.after_id = None
- color.allow_colorizing = False
- color.notify_range('1.4', '1.4+10c')
- # Nothing scheduled when colorizing is off.
- self.assertIsNone(color.after_id)
-
- def test_toggle_colorize_event(self):
- color = self.color
- eq = self.assertEqual
-
- # Starts with colorizing allowed and scheduled.
- self.assertFalse(color.colorizing)
- self.assertFalse(color.stop_colorizing)
- self.assertTrue(color.allow_colorizing)
- eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
-
- # Toggle colorizing off.
- color.toggle_colorize_event()
- self.assertIsNone(color.after_id)
- self.assertFalse(color.colorizing)
- self.assertFalse(color.stop_colorizing)
- self.assertFalse(color.allow_colorizing)
-
- # Toggle on while colorizing in progress (doesn't add timer).
- color.colorizing = True
- color.toggle_colorize_event()
- self.assertIsNone(color.after_id)
- self.assertTrue(color.colorizing)
- self.assertFalse(color.stop_colorizing)
- self.assertTrue(color.allow_colorizing)
-
- # Toggle off while colorizing in progress.
- color.toggle_colorize_event()
- self.assertIsNone(color.after_id)
- self.assertTrue(color.colorizing)
- self.assertTrue(color.stop_colorizing)
- self.assertFalse(color.allow_colorizing)
-
- # Toggle on while colorizing not in progress.
- color.colorizing = False
- color.toggle_colorize_event()
- eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
- self.assertFalse(color.colorizing)
- self.assertTrue(color.stop_colorizing)
- self.assertTrue(color.allow_colorizing)
-
- @mock.patch.object(colorizer.ColorDelegator, 'recolorize_main')
- def test_recolorize(self, mock_recmain):
- text = self.text
- color = self.color
- eq = self.assertEqual
- # Call recolorize manually and not scheduled.
- text.after_cancel(color.after_id)
-
- # No delegate.
- save_delegate = color.delegate
- color.delegate = None
- color.recolorize()
- mock_recmain.assert_not_called()
- color.delegate = save_delegate
-
- # Toggle off colorizing.
- color.allow_colorizing = False
- color.recolorize()
- mock_recmain.assert_not_called()
- color.allow_colorizing = True
-
- # Colorizing in progress.
- color.colorizing = True
- color.recolorize()
- mock_recmain.assert_not_called()
- color.colorizing = False
-
- # Colorizing is done, but not completed, so rescheduled.
- color.recolorize()
- self.assertFalse(color.stop_colorizing)
- self.assertFalse(color.colorizing)
- mock_recmain.assert_called()
- eq(mock_recmain.call_count, 1)
- # Rescheduled when TODO tag still exists.
- eq(self.root.tk.call('after', 'info', color.after_id)[1], 'timer')
-
- # No changes to text, so no scheduling added.
- text.tag_remove('TODO', '1.0', 'end')
- color.recolorize()
- self.assertFalse(color.stop_colorizing)
- self.assertFalse(color.colorizing)
- mock_recmain.assert_called()
- eq(mock_recmain.call_count, 2)
- self.assertIsNone(color.after_id)
-
- @mock.patch.object(colorizer.ColorDelegator, 'notify_range')
- def test_recolorize_main(self, mock_notify):
- text = self.text
- color = self.color
- eq = self.assertEqual
-
- text.insert('insert', source)
- expected = (('1.0', ('KEYWORD',)), ('1.2', ()), ('1.3', ('KEYWORD',)),
- ('1.7', ()), ('1.9', ('BUILTIN',)), ('1.14', ('STRING',)),
- ('1.19', ('COMMENT',)),
- ('2.1', ('KEYWORD',)), ('2.18', ()), ('2.25', ('COMMENT',)),
- ('3.6', ('BUILTIN',)), ('3.12', ('KEYWORD',)), ('3.21', ('COMMENT',)),
- ('4.0', ('KEYWORD',)), ('4.3', ()), ('4.6', ()),
- ('5.2', ('STRING',)), ('5.8', ('KEYWORD',)), ('5.10', ('STRING',)),
- ('6.0', ('KEYWORD',)), ('6.10', ('DEFINITION',)), ('6.11', ()),
- ('7.0', ('STRING',)), ('7.4', ()), ('7.5', ('STRING',)),
- ('7.12', ()), ('7.14', ('STRING',)),
- # SYNC at the end of every line.
- ('1.55', ('SYNC',)), ('2.50', ('SYNC',)), ('3.34', ('SYNC',)),
- )
-
- # Nothing marked to do therefore no tags in text.
- text.tag_remove('TODO', '1.0', 'end')
- color.recolorize_main()
- for tag in text.tag_names():
- with self.subTest(tag=tag):
- eq(text.tag_ranges(tag), ())
-
- # Source marked for processing.
- text.tag_add('TODO', '1.0', 'end')
- # Check some indexes.
- color.recolorize_main()
- for index, expected_tags in expected:
- with self.subTest(index=index):
- eq(text.tag_names(index), expected_tags)
-
- # Check for some tags for ranges.
- eq(text.tag_nextrange('TODO', '1.0'), ())
- eq(text.tag_nextrange('KEYWORD', '1.0'), ('1.0', '1.2'))
- eq(text.tag_nextrange('COMMENT', '2.0'), ('2.22', '2.43'))
- eq(text.tag_nextrange('SYNC', '2.0'), ('2.43', '3.0'))
- eq(text.tag_nextrange('STRING', '2.0'), ('4.17', '4.53'))
- eq(text.tag_nextrange('STRING', '7.0'), ('7.0', '7.3'))
- eq(text.tag_nextrange('STRING', '7.3'), ('7.5', '7.12'))
- eq(text.tag_nextrange('STRING', '7.12'), ('7.14', '7.17'))
- eq(text.tag_nextrange('STRING', '7.17'), ('7.19', '7.26'))
- eq(text.tag_nextrange('SYNC', '7.0'), ('7.26', '9.0'))
-
- @mock.patch.object(colorizer.ColorDelegator, 'recolorize')
- @mock.patch.object(colorizer.ColorDelegator, 'notify_range')
- def test_removecolors(self, mock_notify, mock_recolorize):
- text = self.text
- color = self.color
- text.insert('insert', source)
-
- color.recolorize_main()
- # recolorize_main doesn't add these tags.
- text.tag_add("ERROR", "1.0")
- text.tag_add("TODO", "1.0")
- text.tag_add("hit", "1.0")
- for tag in color.tagdefs:
- with self.subTest(tag=tag):
- self.assertNotEqual(text.tag_ranges(tag), ())
-
- color.removecolors()
- for tag in color.tagdefs:
- with self.subTest(tag=tag):
- self.assertEqual(text.tag_ranges(tag), ())
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_config.py b/Lib/idlelib/idle_test/test_config.py
deleted file mode 100644
index 697fda5..0000000
--- a/Lib/idlelib/idle_test/test_config.py
+++ /dev/null
@@ -1,805 +0,0 @@
-"""Test config, coverage 93%.
-(100% for IdleConfParser, IdleUserConfParser*, ConfigChanges).
-* Exception is OSError clause in Save method.
-Much of IdleConf is also exercised by ConfigDialog and test_configdialog.
-"""
-from idlelib import config
-import sys
-import os
-import tempfile
-from test.support import captured_stderr, findfile
-import unittest
-from unittest import mock
-import idlelib
-from idlelib.idle_test.mock_idle import Func
-
-# Tests should not depend on fortuitous user configurations.
-# They must not affect actual user .cfg files.
-# Replace user parsers with empty parsers that cannot be saved
-# due to getting '' as the filename when created.
-
-idleConf = config.idleConf
-usercfg = idleConf.userCfg
-testcfg = {}
-usermain = testcfg['main'] = config.IdleUserConfParser('')
-userhigh = testcfg['highlight'] = config.IdleUserConfParser('')
-userkeys = testcfg['keys'] = config.IdleUserConfParser('')
-userextn = testcfg['extensions'] = config.IdleUserConfParser('')
-
-def setUpModule():
- idleConf.userCfg = testcfg
- idlelib.testing = True
-
-def tearDownModule():
- idleConf.userCfg = usercfg
- idlelib.testing = False
-
-
-class IdleConfParserTest(unittest.TestCase):
- """Test that IdleConfParser works"""
-
- config = """
- [one]
- one = false
- two = true
- three = 10
-
- [two]
- one = a string
- two = true
- three = false
- """
-
- def test_get(self):
- parser = config.IdleConfParser('')
- parser.read_string(self.config)
- eq = self.assertEqual
-
- # Test with type argument.
- self.assertIs(parser.Get('one', 'one', type='bool'), False)
- self.assertIs(parser.Get('one', 'two', type='bool'), True)
- eq(parser.Get('one', 'three', type='int'), 10)
- eq(parser.Get('two', 'one'), 'a string')
- self.assertIs(parser.Get('two', 'two', type='bool'), True)
- self.assertIs(parser.Get('two', 'three', type='bool'), False)
-
- # Test without type should fallback to string.
- eq(parser.Get('two', 'two'), 'true')
- eq(parser.Get('two', 'three'), 'false')
-
- # If option not exist, should return None, or default.
- self.assertIsNone(parser.Get('not', 'exist'))
- eq(parser.Get('not', 'exist', default='DEFAULT'), 'DEFAULT')
-
- def test_get_option_list(self):
- parser = config.IdleConfParser('')
- parser.read_string(self.config)
- get_list = parser.GetOptionList
- self.assertCountEqual(get_list('one'), ['one', 'two', 'three'])
- self.assertCountEqual(get_list('two'), ['one', 'two', 'three'])
- self.assertEqual(get_list('not exist'), [])
-
- def test_load_nothing(self):
- parser = config.IdleConfParser('')
- parser.Load()
- self.assertEqual(parser.sections(), [])
-
- def test_load_file(self):
- # Borrow test/cfgparser.1 from test_configparser.
- config_path = findfile('cfgparser.1')
- parser = config.IdleConfParser(config_path)
- parser.Load()
-
- self.assertEqual(parser.Get('Foo Bar', 'foo'), 'newbar')
- self.assertEqual(parser.GetOptionList('Foo Bar'), ['foo'])
-
-
-class IdleUserConfParserTest(unittest.TestCase):
- """Test that IdleUserConfParser works"""
-
- def new_parser(self, path=''):
- return config.IdleUserConfParser(path)
-
- def test_set_option(self):
- parser = self.new_parser()
- parser.add_section('Foo')
- # Setting new option in existing section should return True.
- self.assertTrue(parser.SetOption('Foo', 'bar', 'true'))
- # Setting existing option with same value should return False.
- self.assertFalse(parser.SetOption('Foo', 'bar', 'true'))
- # Setting exiting option with new value should return True.
- self.assertTrue(parser.SetOption('Foo', 'bar', 'false'))
- self.assertEqual(parser.Get('Foo', 'bar'), 'false')
-
- # Setting option in new section should create section and return True.
- self.assertTrue(parser.SetOption('Bar', 'bar', 'true'))
- self.assertCountEqual(parser.sections(), ['Bar', 'Foo'])
- self.assertEqual(parser.Get('Bar', 'bar'), 'true')
-
- def test_remove_option(self):
- parser = self.new_parser()
- parser.AddSection('Foo')
- parser.SetOption('Foo', 'bar', 'true')
-
- self.assertTrue(parser.RemoveOption('Foo', 'bar'))
- self.assertFalse(parser.RemoveOption('Foo', 'bar'))
- self.assertFalse(parser.RemoveOption('Not', 'Exist'))
-
- def test_add_section(self):
- parser = self.new_parser()
- self.assertEqual(parser.sections(), [])
-
- # Should not add duplicate section.
- # Configparser raises DuplicateError, IdleParser not.
- parser.AddSection('Foo')
- parser.AddSection('Foo')
- parser.AddSection('Bar')
- self.assertCountEqual(parser.sections(), ['Bar', 'Foo'])
-
- def test_remove_empty_sections(self):
- parser = self.new_parser()
-
- parser.AddSection('Foo')
- parser.AddSection('Bar')
- parser.SetOption('Idle', 'name', 'val')
- self.assertCountEqual(parser.sections(), ['Bar', 'Foo', 'Idle'])
- parser.RemoveEmptySections()
- self.assertEqual(parser.sections(), ['Idle'])
-
- def test_is_empty(self):
- parser = self.new_parser()
-
- parser.AddSection('Foo')
- parser.AddSection('Bar')
- self.assertTrue(parser.IsEmpty())
- self.assertEqual(parser.sections(), [])
-
- parser.SetOption('Foo', 'bar', 'false')
- parser.AddSection('Bar')
- self.assertFalse(parser.IsEmpty())
- self.assertCountEqual(parser.sections(), ['Foo'])
-
- def test_save(self):
- with tempfile.TemporaryDirectory() as tdir:
- path = os.path.join(tdir, 'test.cfg')
- parser = self.new_parser(path)
- parser.AddSection('Foo')
- parser.SetOption('Foo', 'bar', 'true')
-
- # Should save to path when config is not empty.
- self.assertFalse(os.path.exists(path))
- parser.Save()
- self.assertTrue(os.path.exists(path))
-
- # Should remove the file from disk when config is empty.
- parser.remove_section('Foo')
- parser.Save()
- self.assertFalse(os.path.exists(path))
-
-
-class IdleConfTest(unittest.TestCase):
- """Test for idleConf"""
-
- @classmethod
- def setUpClass(cls):
- cls.config_string = {}
-
- conf = config.IdleConf(_utest=True)
- if __name__ != '__main__':
- idle_dir = os.path.dirname(__file__)
- else:
- idle_dir = os.path.abspath(sys.path[0])
- for ctype in conf.config_types:
- config_path = os.path.join(idle_dir, '../config-%s.def' % ctype)
- with open(config_path, 'r') as f:
- cls.config_string[ctype] = f.read()
-
- cls.orig_warn = config._warn
- config._warn = Func()
-
- @classmethod
- def tearDownClass(cls):
- config._warn = cls.orig_warn
-
- def new_config(self, _utest=False):
- return config.IdleConf(_utest=_utest)
-
- def mock_config(self):
- """Return a mocked idleConf
-
- Both default and user config used the same config-*.def
- """
- conf = config.IdleConf(_utest=True)
- for ctype in conf.config_types:
- conf.defaultCfg[ctype] = config.IdleConfParser('')
- conf.defaultCfg[ctype].read_string(self.config_string[ctype])
- conf.userCfg[ctype] = config.IdleUserConfParser('')
- conf.userCfg[ctype].read_string(self.config_string[ctype])
-
- return conf
-
- @unittest.skipIf(sys.platform.startswith('win'), 'this is test for unix system')
- def test_get_user_cfg_dir_unix(self):
- # Test to get user config directory under unix.
- conf = self.new_config(_utest=True)
-
- # Check normal way should success
- with mock.patch('os.path.expanduser', return_value='/home/foo'):
- with mock.patch('os.path.exists', return_value=True):
- self.assertEqual(conf.GetUserCfgDir(), '/home/foo/.idlerc')
-
- # Check os.getcwd should success
- with mock.patch('os.path.expanduser', return_value='~'):
- with mock.patch('os.getcwd', return_value='/home/foo/cpython'):
- with mock.patch('os.mkdir'):
- self.assertEqual(conf.GetUserCfgDir(),
- '/home/foo/cpython/.idlerc')
-
- # Check user dir not exists and created failed should raise SystemExit
- with mock.patch('os.path.join', return_value='/path/not/exists'):
- with self.assertRaises(SystemExit):
- with self.assertRaises(FileNotFoundError):
- conf.GetUserCfgDir()
-
- @unittest.skipIf(not sys.platform.startswith('win'), 'this is test for Windows system')
- def test_get_user_cfg_dir_windows(self):
- # Test to get user config directory under Windows.
- conf = self.new_config(_utest=True)
-
- # Check normal way should success
- with mock.patch('os.path.expanduser', return_value='C:\\foo'):
- with mock.patch('os.path.exists', return_value=True):
- self.assertEqual(conf.GetUserCfgDir(), 'C:\\foo\\.idlerc')
-
- # Check os.getcwd should success
- with mock.patch('os.path.expanduser', return_value='~'):
- with mock.patch('os.getcwd', return_value='C:\\foo\\cpython'):
- with mock.patch('os.mkdir'):
- self.assertEqual(conf.GetUserCfgDir(),
- 'C:\\foo\\cpython\\.idlerc')
-
- # Check user dir not exists and created failed should raise SystemExit
- with mock.patch('os.path.join', return_value='/path/not/exists'):
- with self.assertRaises(SystemExit):
- with self.assertRaises(FileNotFoundError):
- conf.GetUserCfgDir()
-
- def test_create_config_handlers(self):
- conf = self.new_config(_utest=True)
-
- # Mock out idle_dir
- idle_dir = '/home/foo'
- with mock.patch.dict({'__name__': '__foo__'}):
- with mock.patch('os.path.dirname', return_value=idle_dir):
- conf.CreateConfigHandlers()
-
- # Check keys are equal
- self.assertCountEqual(conf.defaultCfg.keys(), conf.config_types)
- self.assertCountEqual(conf.userCfg.keys(), conf.config_types)
-
- # Check conf parser are correct type
- for default_parser in conf.defaultCfg.values():
- self.assertIsInstance(default_parser, config.IdleConfParser)
- for user_parser in conf.userCfg.values():
- self.assertIsInstance(user_parser, config.IdleUserConfParser)
-
- # Check config path are correct
- for cfg_type, parser in conf.defaultCfg.items():
- self.assertEqual(parser.file,
- os.path.join(idle_dir, f'config-{cfg_type}.def'))
- for cfg_type, parser in conf.userCfg.items():
- self.assertEqual(parser.file,
- os.path.join(conf.userdir or '#', f'config-{cfg_type}.cfg'))
-
- def test_load_cfg_files(self):
- conf = self.new_config(_utest=True)
-
- # Borrow test/cfgparser.1 from test_configparser.
- config_path = findfile('cfgparser.1')
- conf.defaultCfg['foo'] = config.IdleConfParser(config_path)
- conf.userCfg['foo'] = config.IdleUserConfParser(config_path)
-
- # Load all config from path
- conf.LoadCfgFiles()
-
- eq = self.assertEqual
-
- # Check defaultCfg is loaded
- eq(conf.defaultCfg['foo'].Get('Foo Bar', 'foo'), 'newbar')
- eq(conf.defaultCfg['foo'].GetOptionList('Foo Bar'), ['foo'])
-
- # Check userCfg is loaded
- eq(conf.userCfg['foo'].Get('Foo Bar', 'foo'), 'newbar')
- eq(conf.userCfg['foo'].GetOptionList('Foo Bar'), ['foo'])
-
- def test_save_user_cfg_files(self):
- conf = self.mock_config()
-
- with mock.patch('idlelib.config.IdleUserConfParser.Save') as m:
- conf.SaveUserCfgFiles()
- self.assertEqual(m.call_count, len(conf.userCfg))
-
- def test_get_option(self):
- conf = self.mock_config()
-
- eq = self.assertEqual
- eq(conf.GetOption('main', 'EditorWindow', 'width'), '80')
- eq(conf.GetOption('main', 'EditorWindow', 'width', type='int'), 80)
- with mock.patch('idlelib.config._warn') as _warn:
- eq(conf.GetOption('main', 'EditorWindow', 'font', type='int'), None)
- eq(conf.GetOption('main', 'EditorWindow', 'NotExists'), None)
- eq(conf.GetOption('main', 'EditorWindow', 'NotExists', default='NE'), 'NE')
- eq(_warn.call_count, 4)
-
- def test_set_option(self):
- conf = self.mock_config()
-
- conf.SetOption('main', 'Foo', 'bar', 'newbar')
- self.assertEqual(conf.GetOption('main', 'Foo', 'bar'), 'newbar')
-
- def test_get_section_list(self):
- conf = self.mock_config()
-
- self.assertCountEqual(
- conf.GetSectionList('default', 'main'),
- ['General', 'EditorWindow', 'PyShell', 'Indent', 'Theme',
- 'Keys', 'History', 'HelpFiles'])
- self.assertCountEqual(
- conf.GetSectionList('user', 'main'),
- ['General', 'EditorWindow', 'PyShell', 'Indent', 'Theme',
- 'Keys', 'History', 'HelpFiles'])
-
- with self.assertRaises(config.InvalidConfigSet):
- conf.GetSectionList('foobar', 'main')
- with self.assertRaises(config.InvalidConfigType):
- conf.GetSectionList('default', 'notexists')
-
- def test_get_highlight(self):
- conf = self.mock_config()
-
- eq = self.assertEqual
- eq(conf.GetHighlight('IDLE Classic', 'normal'), {'foreground': '#000000',
- 'background': '#ffffff'})
-
- # Test cursor (this background should be normal-background)
- eq(conf.GetHighlight('IDLE Classic', 'cursor'), {'foreground': 'black',
- 'background': '#ffffff'})
-
- # Test get user themes
- conf.SetOption('highlight', 'Foobar', 'normal-foreground', '#747474')
- conf.SetOption('highlight', 'Foobar', 'normal-background', '#171717')
- with mock.patch('idlelib.config._warn'):
- eq(conf.GetHighlight('Foobar', 'normal'), {'foreground': '#747474',
- 'background': '#171717'})
-
- def test_get_theme_dict(self):
- # TODO: finish.
- conf = self.mock_config()
-
- # These two should be the same
- self.assertEqual(
- conf.GetThemeDict('default', 'IDLE Classic'),
- conf.GetThemeDict('user', 'IDLE Classic'))
-
- with self.assertRaises(config.InvalidTheme):
- conf.GetThemeDict('bad', 'IDLE Classic')
-
- def test_get_current_theme_and_keys(self):
- conf = self.mock_config()
-
- self.assertEqual(conf.CurrentTheme(), conf.current_colors_and_keys('Theme'))
- self.assertEqual(conf.CurrentKeys(), conf.current_colors_and_keys('Keys'))
-
- def test_current_colors_and_keys(self):
- conf = self.mock_config()
-
- self.assertEqual(conf.current_colors_and_keys('Theme'), 'IDLE Classic')
-
- def test_default_keys(self):
- current_platform = sys.platform
- conf = self.new_config(_utest=True)
-
- sys.platform = 'win32'
- self.assertEqual(conf.default_keys(), 'IDLE Classic Windows')
-
- sys.platform = 'darwin'
- self.assertEqual(conf.default_keys(), 'IDLE Classic OSX')
-
- sys.platform = 'some-linux'
- self.assertEqual(conf.default_keys(), 'IDLE Modern Unix')
-
- # Restore platform
- sys.platform = current_platform
-
- def test_get_extensions(self):
- userextn.read_string('''
- [ZzDummy]
- enable = True
- [DISABLE]
- enable = False
- ''')
- eq = self.assertEqual
- iGE = idleConf.GetExtensions
- eq(iGE(shell_only=True), [])
- eq(iGE(), ['ZzDummy'])
- eq(iGE(editor_only=True), ['ZzDummy'])
- eq(iGE(active_only=False), ['ZzDummy', 'DISABLE'])
- eq(iGE(active_only=False, editor_only=True), ['ZzDummy', 'DISABLE'])
- userextn.remove_section('ZzDummy')
- userextn.remove_section('DISABLE')
-
-
- def test_remove_key_bind_names(self):
- conf = self.mock_config()
-
- self.assertCountEqual(
- conf.RemoveKeyBindNames(conf.GetSectionList('default', 'extensions')),
- ['AutoComplete', 'CodeContext', 'FormatParagraph', 'ParenMatch', 'ZzDummy'])
-
- def test_get_extn_name_for_event(self):
- userextn.read_string('''
- [ZzDummy]
- enable = True
- ''')
- eq = self.assertEqual
- eq(idleConf.GetExtnNameForEvent('z-in'), 'ZzDummy')
- eq(idleConf.GetExtnNameForEvent('z-out'), None)
- userextn.remove_section('ZzDummy')
-
- def test_get_extension_keys(self):
- userextn.read_string('''
- [ZzDummy]
- enable = True
- ''')
- self.assertEqual(idleConf.GetExtensionKeys('ZzDummy'),
- {'<<z-in>>': ['<Control-Shift-KeyRelease-Insert>']})
- userextn.remove_section('ZzDummy')
-# need option key test
-## key = ['<Option-Key-2>'] if sys.platform == 'darwin' else ['<Alt-Key-2>']
-## eq(conf.GetExtensionKeys('ZoomHeight'), {'<<zoom-height>>': key})
-
- def test_get_extension_bindings(self):
- userextn.read_string('''
- [ZzDummy]
- enable = True
- ''')
- eq = self.assertEqual
- iGEB = idleConf.GetExtensionBindings
- eq(iGEB('NotExists'), {})
- expect = {'<<z-in>>': ['<Control-Shift-KeyRelease-Insert>'],
- '<<z-out>>': ['<Control-Shift-KeyRelease-Delete>']}
- eq(iGEB('ZzDummy'), expect)
- userextn.remove_section('ZzDummy')
-
- def test_get_keybinding(self):
- conf = self.mock_config()
-
- eq = self.assertEqual
- eq(conf.GetKeyBinding('IDLE Modern Unix', '<<copy>>'),
- ['<Control-Shift-Key-C>', '<Control-Key-Insert>'])
- eq(conf.GetKeyBinding('IDLE Classic Unix', '<<copy>>'),
- ['<Alt-Key-w>', '<Meta-Key-w>'])
- eq(conf.GetKeyBinding('IDLE Classic Windows', '<<copy>>'),
- ['<Control-Key-c>', '<Control-Key-C>'])
- eq(conf.GetKeyBinding('IDLE Classic Mac', '<<copy>>'), ['<Command-Key-c>'])
- eq(conf.GetKeyBinding('IDLE Classic OSX', '<<copy>>'), ['<Command-Key-c>'])
-
- # Test keybinding not exists
- eq(conf.GetKeyBinding('NOT EXISTS', '<<copy>>'), [])
- eq(conf.GetKeyBinding('IDLE Modern Unix', 'NOT EXISTS'), [])
-
- def test_get_current_keyset(self):
- current_platform = sys.platform
- conf = self.mock_config()
-
- # Ensure that platform isn't darwin
- sys.platform = 'some-linux'
- self.assertEqual(conf.GetCurrentKeySet(), conf.GetKeySet(conf.CurrentKeys()))
-
- # This should not be the same, since replace <Alt- to <Option-.
- # Above depended on config-extensions.def having Alt keys,
- # which is no longer true.
- # sys.platform = 'darwin'
- # self.assertNotEqual(conf.GetCurrentKeySet(), conf.GetKeySet(conf.CurrentKeys()))
-
- # Restore platform
- sys.platform = current_platform
-
- def test_get_keyset(self):
- conf = self.mock_config()
-
- # Conflict with key set, should be disable to ''
- conf.defaultCfg['extensions'].add_section('Foobar')
- conf.defaultCfg['extensions'].add_section('Foobar_cfgBindings')
- conf.defaultCfg['extensions'].set('Foobar', 'enable', 'True')
- conf.defaultCfg['extensions'].set('Foobar_cfgBindings', 'newfoo', '<Key-F3>')
- self.assertEqual(conf.GetKeySet('IDLE Modern Unix')['<<newfoo>>'], '')
-
- def test_is_core_binding(self):
- # XXX: Should move out the core keys to config file or other place
- conf = self.mock_config()
-
- self.assertTrue(conf.IsCoreBinding('copy'))
- self.assertTrue(conf.IsCoreBinding('cut'))
- self.assertTrue(conf.IsCoreBinding('del-word-right'))
- self.assertFalse(conf.IsCoreBinding('not-exists'))
-
- def test_extra_help_source_list(self):
- # Test GetExtraHelpSourceList and GetAllExtraHelpSourcesList in same
- # place to prevent prepare input data twice.
- conf = self.mock_config()
-
- # Test default with no extra help source
- self.assertEqual(conf.GetExtraHelpSourceList('default'), [])
- self.assertEqual(conf.GetExtraHelpSourceList('user'), [])
- with self.assertRaises(config.InvalidConfigSet):
- self.assertEqual(conf.GetExtraHelpSourceList('bad'), [])
- self.assertCountEqual(
- conf.GetAllExtraHelpSourcesList(),
- conf.GetExtraHelpSourceList('default') + conf.GetExtraHelpSourceList('user'))
-
- # Add help source to user config
- conf.userCfg['main'].SetOption('HelpFiles', '4', 'Python;https://python.org') # This is bad input
- conf.userCfg['main'].SetOption('HelpFiles', '3', 'Python:https://python.org') # This is bad input
- conf.userCfg['main'].SetOption('HelpFiles', '2', 'Pillow;https://pillow.readthedocs.io/en/latest/')
- conf.userCfg['main'].SetOption('HelpFiles', '1', 'IDLE;C:/Programs/Python36/Lib/idlelib/help.html')
- self.assertEqual(conf.GetExtraHelpSourceList('user'),
- [('IDLE', 'C:/Programs/Python36/Lib/idlelib/help.html', '1'),
- ('Pillow', 'https://pillow.readthedocs.io/en/latest/', '2'),
- ('Python', 'https://python.org', '4')])
- self.assertCountEqual(
- conf.GetAllExtraHelpSourcesList(),
- conf.GetExtraHelpSourceList('default') + conf.GetExtraHelpSourceList('user'))
-
- def test_get_font(self):
- from test.support import requires
- from tkinter import Tk
- from tkinter.font import Font
- conf = self.mock_config()
-
- requires('gui')
- root = Tk()
- root.withdraw()
-
- f = Font.actual(Font(name='TkFixedFont', exists=True, root=root))
- self.assertEqual(
- conf.GetFont(root, 'main', 'EditorWindow'),
- (f['family'], 10 if f['size'] <= 0 else f['size'], f['weight']))
-
- # Cleanup root
- root.destroy()
- del root
-
- def test_get_core_keys(self):
- conf = self.mock_config()
-
- eq = self.assertEqual
- eq(conf.GetCoreKeys()['<<center-insert>>'], ['<Control-l>'])
- eq(conf.GetCoreKeys()['<<copy>>'], ['<Control-c>', '<Control-C>'])
- eq(conf.GetCoreKeys()['<<history-next>>'], ['<Alt-n>'])
- eq(conf.GetCoreKeys('IDLE Classic Windows')['<<center-insert>>'],
- ['<Control-Key-l>', '<Control-Key-L>'])
- eq(conf.GetCoreKeys('IDLE Classic OSX')['<<copy>>'], ['<Command-Key-c>'])
- eq(conf.GetCoreKeys('IDLE Classic Unix')['<<history-next>>'],
- ['<Alt-Key-n>', '<Meta-Key-n>'])
- eq(conf.GetCoreKeys('IDLE Modern Unix')['<<history-next>>'],
- ['<Alt-Key-n>', '<Meta-Key-n>'])
-
-
-class CurrentColorKeysTest(unittest.TestCase):
- """ Test colorkeys function with user config [Theme] and [Keys] patterns.
-
- colorkeys = config.IdleConf.current_colors_and_keys
- Test all patterns written by IDLE and some errors
- Item 'default' should really be 'builtin' (versus 'custom).
- """
- colorkeys = idleConf.current_colors_and_keys
- default_theme = 'IDLE Classic'
- default_keys = idleConf.default_keys()
-
- def test_old_builtin_theme(self):
- # On initial installation, user main is blank.
- self.assertEqual(self.colorkeys('Theme'), self.default_theme)
- # For old default, name2 must be blank.
- usermain.read_string('''
- [Theme]
- default = True
- ''')
- # IDLE omits 'name' for default old builtin theme.
- self.assertEqual(self.colorkeys('Theme'), self.default_theme)
- # IDLE adds 'name' for non-default old builtin theme.
- usermain['Theme']['name'] = 'IDLE New'
- self.assertEqual(self.colorkeys('Theme'), 'IDLE New')
- # Erroneous non-default old builtin reverts to default.
- usermain['Theme']['name'] = 'non-existent'
- self.assertEqual(self.colorkeys('Theme'), self.default_theme)
- usermain.remove_section('Theme')
-
- def test_new_builtin_theme(self):
- # IDLE writes name2 for new builtins.
- usermain.read_string('''
- [Theme]
- default = True
- name2 = IDLE Dark
- ''')
- self.assertEqual(self.colorkeys('Theme'), 'IDLE Dark')
- # Leftover 'name', not removed, is ignored.
- usermain['Theme']['name'] = 'IDLE New'
- self.assertEqual(self.colorkeys('Theme'), 'IDLE Dark')
- # Erroneous non-default new builtin reverts to default.
- usermain['Theme']['name2'] = 'non-existent'
- self.assertEqual(self.colorkeys('Theme'), self.default_theme)
- usermain.remove_section('Theme')
-
- def test_user_override_theme(self):
- # Erroneous custom name (no definition) reverts to default.
- usermain.read_string('''
- [Theme]
- default = False
- name = Custom Dark
- ''')
- self.assertEqual(self.colorkeys('Theme'), self.default_theme)
- # Custom name is valid with matching Section name.
- userhigh.read_string('[Custom Dark]\na=b')
- self.assertEqual(self.colorkeys('Theme'), 'Custom Dark')
- # Name2 is ignored.
- usermain['Theme']['name2'] = 'non-existent'
- self.assertEqual(self.colorkeys('Theme'), 'Custom Dark')
- usermain.remove_section('Theme')
- userhigh.remove_section('Custom Dark')
-
- def test_old_builtin_keys(self):
- # On initial installation, user main is blank.
- self.assertEqual(self.colorkeys('Keys'), self.default_keys)
- # For old default, name2 must be blank, name is always used.
- usermain.read_string('''
- [Keys]
- default = True
- name = IDLE Classic Unix
- ''')
- self.assertEqual(self.colorkeys('Keys'), 'IDLE Classic Unix')
- # Erroneous non-default old builtin reverts to default.
- usermain['Keys']['name'] = 'non-existent'
- self.assertEqual(self.colorkeys('Keys'), self.default_keys)
- usermain.remove_section('Keys')
-
- def test_new_builtin_keys(self):
- # IDLE writes name2 for new builtins.
- usermain.read_string('''
- [Keys]
- default = True
- name2 = IDLE Modern Unix
- ''')
- self.assertEqual(self.colorkeys('Keys'), 'IDLE Modern Unix')
- # Leftover 'name', not removed, is ignored.
- usermain['Keys']['name'] = 'IDLE Classic Unix'
- self.assertEqual(self.colorkeys('Keys'), 'IDLE Modern Unix')
- # Erroneous non-default new builtin reverts to default.
- usermain['Keys']['name2'] = 'non-existent'
- self.assertEqual(self.colorkeys('Keys'), self.default_keys)
- usermain.remove_section('Keys')
-
- def test_user_override_keys(self):
- # Erroneous custom name (no definition) reverts to default.
- usermain.read_string('''
- [Keys]
- default = False
- name = Custom Keys
- ''')
- self.assertEqual(self.colorkeys('Keys'), self.default_keys)
- # Custom name is valid with matching Section name.
- userkeys.read_string('[Custom Keys]\na=b')
- self.assertEqual(self.colorkeys('Keys'), 'Custom Keys')
- # Name2 is ignored.
- usermain['Keys']['name2'] = 'non-existent'
- self.assertEqual(self.colorkeys('Keys'), 'Custom Keys')
- usermain.remove_section('Keys')
- userkeys.remove_section('Custom Keys')
-
-
-class ChangesTest(unittest.TestCase):
-
- empty = {'main':{}, 'highlight':{}, 'keys':{}, 'extensions':{}}
-
- def load(self): # Test_add_option verifies that this works.
- changes = self.changes
- changes.add_option('main', 'Msec', 'mitem', 'mval')
- changes.add_option('highlight', 'Hsec', 'hitem', 'hval')
- changes.add_option('keys', 'Ksec', 'kitem', 'kval')
- return changes
-
- loaded = {'main': {'Msec': {'mitem': 'mval'}},
- 'highlight': {'Hsec': {'hitem': 'hval'}},
- 'keys': {'Ksec': {'kitem':'kval'}},
- 'extensions': {}}
-
- def setUp(self):
- self.changes = config.ConfigChanges()
-
- def test_init(self):
- self.assertEqual(self.changes, self.empty)
-
- def test_add_option(self):
- changes = self.load()
- self.assertEqual(changes, self.loaded)
- changes.add_option('main', 'Msec', 'mitem', 'mval')
- self.assertEqual(changes, self.loaded)
-
- def test_save_option(self): # Static function does not touch changes.
- save_option = self.changes.save_option
- self.assertTrue(save_option('main', 'Indent', 'what', '0'))
- self.assertFalse(save_option('main', 'Indent', 'what', '0'))
- self.assertEqual(usermain['Indent']['what'], '0')
-
- self.assertTrue(save_option('main', 'Indent', 'use-spaces', '0'))
- self.assertEqual(usermain['Indent']['use-spaces'], '0')
- self.assertTrue(save_option('main', 'Indent', 'use-spaces', '1'))
- self.assertFalse(usermain.has_option('Indent', 'use-spaces'))
- usermain.remove_section('Indent')
-
- def test_save_added(self):
- changes = self.load()
- self.assertTrue(changes.save_all())
- self.assertEqual(usermain['Msec']['mitem'], 'mval')
- self.assertEqual(userhigh['Hsec']['hitem'], 'hval')
- self.assertEqual(userkeys['Ksec']['kitem'], 'kval')
- changes.add_option('main', 'Msec', 'mitem', 'mval')
- self.assertFalse(changes.save_all())
- usermain.remove_section('Msec')
- userhigh.remove_section('Hsec')
- userkeys.remove_section('Ksec')
-
- def test_save_help(self):
- # Any change to HelpFiles overwrites entire section.
- changes = self.changes
- changes.save_option('main', 'HelpFiles', 'IDLE', 'idledoc')
- changes.add_option('main', 'HelpFiles', 'ELDI', 'codeldi')
- changes.save_all()
- self.assertFalse(usermain.has_option('HelpFiles', 'IDLE'))
- self.assertTrue(usermain.has_option('HelpFiles', 'ELDI'))
-
- def test_save_default(self): # Cover 2nd and 3rd false branches.
- changes = self.changes
- changes.add_option('main', 'Indent', 'use-spaces', '1')
- # save_option returns False; cfg_type_changed remains False.
-
- # TODO: test that save_all calls usercfg Saves.
-
- def test_delete_section(self):
- changes = self.load()
- changes.delete_section('main', 'fake') # Test no exception.
- self.assertEqual(changes, self.loaded) # Test nothing deleted.
- for cfgtype, section in (('main', 'Msec'), ('keys', 'Ksec')):
- testcfg[cfgtype].SetOption(section, 'name', 'value')
- changes.delete_section(cfgtype, section)
- with self.assertRaises(KeyError):
- changes[cfgtype][section] # Test section gone from changes
- testcfg[cfgtype][section] # and from mock userCfg.
- # TODO test for save call.
-
- def test_clear(self):
- changes = self.load()
- changes.clear()
- self.assertEqual(changes, self.empty)
-
-
-class WarningTest(unittest.TestCase):
-
- def test_warn(self):
- Equal = self.assertEqual
- config._warned = set()
- with captured_stderr() as stderr:
- config._warn('warning', 'key')
- Equal(config._warned, {('warning','key')})
- Equal(stderr.getvalue(), 'warning'+'\n')
- with captured_stderr() as stderr:
- config._warn('warning', 'key')
- Equal(stderr.getvalue(), '')
- with captured_stderr() as stderr:
- config._warn('warn2', 'yek')
- Equal(config._warned, {('warning','key'), ('warn2','yek')})
- Equal(stderr.getvalue(), 'warn2'+'\n')
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_config_key.py b/Lib/idlelib/idle_test/test_config_key.py
deleted file mode 100644
index b7fe7fd..0000000
--- a/Lib/idlelib/idle_test/test_config_key.py
+++ /dev/null
@@ -1,291 +0,0 @@
-"""Test config_key, coverage 98%.
-
-Coverage is effectively 100%. Tkinter dialog is mocked, Mac-only line
-may be skipped, and dummy function in bind test should not be called.
-Not tested: exit with 'self.advanced or self.keys_ok(keys)) ...' False.
-"""
-
-from idlelib import config_key
-from test.support import requires
-import unittest
-from unittest import mock
-from tkinter import Tk, TclError
-from idlelib.idle_test.mock_idle import Func
-from idlelib.idle_test.mock_tk import Mbox_func
-
-gkd = config_key.GetKeysDialog
-
-
-class ValidationTest(unittest.TestCase):
- "Test validation methods: ok, keys_ok, bind_ok."
-
- class Validator(gkd):
- def __init__(self, *args, **kwargs):
- config_key.GetKeysDialog.__init__(self, *args, **kwargs)
- class list_keys_final:
- get = Func()
- self.list_keys_final = list_keys_final
- get_modifiers = Func()
- showerror = Mbox_func()
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- keylist = [['<Key-F12>'], ['<Control-Key-x>', '<Control-Key-X>']]
- cls.dialog = cls.Validator(
- cls.root, 'Title', '<<Test>>', keylist, _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- cls.dialog.cancel()
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.dialog, cls.root
-
- def setUp(self):
- self.dialog.showerror.message = ''
- # A test that needs a particular final key value should set it.
- # A test that sets a non-blank modifier list should reset it to [].
-
- def test_ok_empty(self):
- self.dialog.key_string.set(' ')
- self.dialog.ok()
- self.assertEqual(self.dialog.result, '')
- self.assertEqual(self.dialog.showerror.message, 'No key specified.')
-
- def test_ok_good(self):
- self.dialog.key_string.set('<Key-F11>')
- self.dialog.list_keys_final.get.result = 'F11'
- self.dialog.ok()
- self.assertEqual(self.dialog.result, '<Key-F11>')
- self.assertEqual(self.dialog.showerror.message, '')
-
- def test_keys_no_ending(self):
- self.assertFalse(self.dialog.keys_ok('<Control-Shift'))
- self.assertIn('Missing the final', self.dialog.showerror.message)
-
- def test_keys_no_modifier_bad(self):
- self.dialog.list_keys_final.get.result = 'A'
- self.assertFalse(self.dialog.keys_ok('<Key-A>'))
- self.assertIn('No modifier', self.dialog.showerror.message)
-
- def test_keys_no_modifier_ok(self):
- self.dialog.list_keys_final.get.result = 'F11'
- self.assertTrue(self.dialog.keys_ok('<Key-F11>'))
- self.assertEqual(self.dialog.showerror.message, '')
-
- def test_keys_shift_bad(self):
- self.dialog.list_keys_final.get.result = 'a'
- self.dialog.get_modifiers.result = ['Shift']
- self.assertFalse(self.dialog.keys_ok('<a>'))
- self.assertIn('shift modifier', self.dialog.showerror.message)
- self.dialog.get_modifiers.result = []
-
- def test_keys_dup(self):
- for mods, final, seq in (([], 'F12', '<Key-F12>'),
- (['Control'], 'x', '<Control-Key-x>'),
- (['Control'], 'X', '<Control-Key-X>')):
- with self.subTest(m=mods, f=final, s=seq):
- self.dialog.list_keys_final.get.result = final
- self.dialog.get_modifiers.result = mods
- self.assertFalse(self.dialog.keys_ok(seq))
- self.assertIn('already in use', self.dialog.showerror.message)
- self.dialog.get_modifiers.result = []
-
- def test_bind_ok(self):
- self.assertTrue(self.dialog.bind_ok('<Control-Shift-Key-a>'))
- self.assertEqual(self.dialog.showerror.message, '')
-
- def test_bind_not_ok(self):
- self.assertFalse(self.dialog.bind_ok('<Control-Shift>'))
- self.assertIn('not accepted', self.dialog.showerror.message)
-
-
-class ToggleLevelTest(unittest.TestCase):
- "Test toggle between Basic and Advanced frames."
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.dialog = gkd(cls.root, 'Title', '<<Test>>', [], _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- cls.dialog.cancel()
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.dialog, cls.root
-
- def test_toggle_level(self):
- dialog = self.dialog
-
- def stackorder():
- """Get the stack order of the children of the frame.
-
- winfo_children() stores the children in stack order, so
- this can be used to check whether a frame is above or
- below another one.
- """
- for index, child in enumerate(dialog.frame.winfo_children()):
- if child._name == 'keyseq_basic':
- basic = index
- if child._name == 'keyseq_advanced':
- advanced = index
- return basic, advanced
-
- # New window starts at basic level.
- self.assertFalse(dialog.advanced)
- self.assertIn('Advanced', dialog.button_level['text'])
- basic, advanced = stackorder()
- self.assertGreater(basic, advanced)
-
- # Toggle to advanced.
- dialog.toggle_level()
- self.assertTrue(dialog.advanced)
- self.assertIn('Basic', dialog.button_level['text'])
- basic, advanced = stackorder()
- self.assertGreater(advanced, basic)
-
- # Toggle to basic.
- dialog.button_level.invoke()
- self.assertFalse(dialog.advanced)
- self.assertIn('Advanced', dialog.button_level['text'])
- basic, advanced = stackorder()
- self.assertGreater(basic, advanced)
-
-
-class KeySelectionTest(unittest.TestCase):
- "Test selecting key on Basic frames."
-
- class Basic(gkd):
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
- class list_keys_final:
- get = Func()
- select_clear = Func()
- yview = Func()
- self.list_keys_final = list_keys_final
- def set_modifiers_for_platform(self):
- self.modifiers = ['foo', 'bar', 'BAZ']
- self.modifier_label = {'BAZ': 'ZZZ'}
- showerror = Mbox_func()
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.dialog = cls.Basic(cls.root, 'Title', '<<Test>>', [], _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- cls.dialog.cancel()
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.dialog, cls.root
-
- def setUp(self):
- self.dialog.clear_key_seq()
-
- def test_get_modifiers(self):
- dialog = self.dialog
- gm = dialog.get_modifiers
- eq = self.assertEqual
-
- # Modifiers are set on/off by invoking the checkbutton.
- dialog.modifier_checkbuttons['foo'].invoke()
- eq(gm(), ['foo'])
-
- dialog.modifier_checkbuttons['BAZ'].invoke()
- eq(gm(), ['foo', 'BAZ'])
-
- dialog.modifier_checkbuttons['foo'].invoke()
- eq(gm(), ['BAZ'])
-
- @mock.patch.object(gkd, 'get_modifiers')
- def test_build_key_string(self, mock_modifiers):
- dialog = self.dialog
- key = dialog.list_keys_final
- string = dialog.key_string.get
- eq = self.assertEqual
-
- key.get.result = 'a'
- mock_modifiers.return_value = []
- dialog.build_key_string()
- eq(string(), '<Key-a>')
-
- mock_modifiers.return_value = ['mymod']
- dialog.build_key_string()
- eq(string(), '<mymod-Key-a>')
-
- key.get.result = ''
- mock_modifiers.return_value = ['mymod', 'test']
- dialog.build_key_string()
- eq(string(), '<mymod-test>')
-
- @mock.patch.object(gkd, 'get_modifiers')
- def test_final_key_selected(self, mock_modifiers):
- dialog = self.dialog
- key = dialog.list_keys_final
- string = dialog.key_string.get
- eq = self.assertEqual
-
- mock_modifiers.return_value = ['Shift']
- key.get.result = '{'
- dialog.final_key_selected()
- eq(string(), '<Shift-Key-braceleft>')
-
-
-class CancelTest(unittest.TestCase):
- "Simulate user clicking [Cancel] button."
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.dialog = gkd(cls.root, 'Title', '<<Test>>', [], _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- cls.dialog.cancel()
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.dialog, cls.root
-
- def test_cancel(self):
- self.assertEqual(self.dialog.winfo_class(), 'Toplevel')
- self.dialog.button_cancel.invoke()
- with self.assertRaises(TclError):
- self.dialog.winfo_class()
- self.assertEqual(self.dialog.result, '')
-
-
-class HelperTest(unittest.TestCase):
- "Test module level helper functions."
-
- def test_translate_key(self):
- tr = config_key.translate_key
- eq = self.assertEqual
-
- # Letters return unchanged with no 'Shift'.
- eq(tr('q', []), 'Key-q')
- eq(tr('q', ['Control', 'Alt']), 'Key-q')
-
- # 'Shift' uppercases single lowercase letters.
- eq(tr('q', ['Shift']), 'Key-Q')
- eq(tr('q', ['Control', 'Shift']), 'Key-Q')
- eq(tr('q', ['Control', 'Alt', 'Shift']), 'Key-Q')
-
- # Convert key name to keysym.
- eq(tr('Page Up', []), 'Key-Prior')
- # 'Shift' doesn't change case when it's not a single char.
- eq(tr('*', ['Shift']), 'Key-asterisk')
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_config_name.py b/Lib/idlelib/idle_test/test_config_name.py
new file mode 100644
index 0000000..2a4df6a
--- /dev/null
+++ b/Lib/idlelib/idle_test/test_config_name.py
@@ -0,0 +1,77 @@
+"""Unit tests for idlelib.configSectionNameDialog"""
+import unittest
+from idlelib.idle_test.mock_tk import Var, Mbox
+from idlelib import configSectionNameDialog as name_dialog_module
+
+name_dialog = name_dialog_module.GetCfgSectionNameDialog
+
+class Dummy_name_dialog(object):
+ # Mock for testing the following methods of name_dialog
+ name_ok = name_dialog.name_ok.im_func
+ Ok = name_dialog.Ok.im_func
+ Cancel = name_dialog.Cancel.im_func
+ # Attributes, constant or variable, needed for tests
+ used_names = ['used']
+ name = Var()
+ result = None
+ destroyed = False
+ def grab_release(self):
+ pass
+ def destroy(self):
+ self.destroyed = True
+
+# name_ok calls Mbox.showerror if name is not ok
+orig_mbox = name_dialog_module.tkMessageBox
+showerror = Mbox.showerror
+
+class ConfigNameTest(unittest.TestCase):
+ dialog = Dummy_name_dialog()
+
+ @classmethod
+ def setUpClass(cls):
+ name_dialog_module.tkMessageBox = Mbox
+
+ @classmethod
+ def tearDownClass(cls):
+ name_dialog_module.tkMessageBox = orig_mbox
+
+ def test_blank_name(self):
+ self.dialog.name.set(' ')
+ self.assertEqual(self.dialog.name_ok(), '')
+ self.assertEqual(showerror.title, 'Name Error')
+ self.assertIn('No', showerror.message)
+
+ def test_used_name(self):
+ self.dialog.name.set('used')
+ self.assertEqual(self.dialog.name_ok(), '')
+ self.assertEqual(showerror.title, 'Name Error')
+ self.assertIn('use', showerror.message)
+
+ def test_long_name(self):
+ self.dialog.name.set('good'*8)
+ self.assertEqual(self.dialog.name_ok(), '')
+ self.assertEqual(showerror.title, 'Name Error')
+ self.assertIn('too long', showerror.message)
+
+ def test_good_name(self):
+ self.dialog.name.set(' good ')
+ showerror.title = 'No Error' # should not be called
+ self.assertEqual(self.dialog.name_ok(), 'good')
+ self.assertEqual(showerror.title, 'No Error')
+
+ def test_ok(self):
+ self.dialog.destroyed = False
+ self.dialog.name.set('good')
+ self.dialog.Ok()
+ self.assertEqual(self.dialog.result, 'good')
+ self.assertTrue(self.dialog.destroyed)
+
+ def test_cancel(self):
+ self.dialog.destroyed = False
+ self.dialog.Cancel()
+ self.assertEqual(self.dialog.result, '')
+ 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 1f14ed1..ba65100 100644
--- a/Lib/idlelib/idle_test/test_configdialog.py
+++ b/Lib/idlelib/idle_test/test_configdialog.py
@@ -1,1416 +1,32 @@
-"""Test configdialog, coverage 94%.
+'''Unittests for idlelib/configHandler.py
-Half the class creates dialog, half works with user customizations.
-"""
-from idlelib import configdialog
-from test.support import requires
-requires('gui')
-import unittest
-from unittest import mock
-from idlelib.idle_test.mock_idle import Func
-from tkinter import Tk, StringVar, IntVar, BooleanVar, DISABLED, NORMAL
-from idlelib import config
-from idlelib.configdialog import idleConf, changes, tracers
-
-# 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(''),
-}
-
-root = None
-dialog = None
-mainpage = changes['main']
-highpage = changes['highlight']
-keyspage = changes['keys']
-extpage = changes['extensions']
-
-def setUpModule():
- global root, dialog
- idleConf.userCfg = testcfg
- root = Tk()
- # root.withdraw() # Comment out, see issue 30870
- dialog = configdialog.ConfigDialog(root, 'Test', _utest=True)
-
-def tearDownModule():
- global root, dialog
- idleConf.userCfg = usercfg
- tracers.detach()
- tracers.clear()
- changes.clear()
- root.update_idletasks()
- root.destroy()
- root = dialog = None
-
-
-class FontPageTest(unittest.TestCase):
- """Test that font widgets enable users to make font changes.
-
- Test that widget actions set vars, that var changes add three
- options to changes and call set_samples, and that set_samples
- changes the font of both sample boxes.
- """
- @classmethod
- def setUpClass(cls):
- page = cls.page = dialog.fontpage
- dialog.note.select(page)
- page.set_samples = Func() # Mask instance method.
- page.update()
-
- @classmethod
- def tearDownClass(cls):
- del cls.page.set_samples # Unmask instance method.
-
- def setUp(self):
- changes.clear()
-
- def test_load_font_cfg(self):
- # Leave widget load test to human visual check.
- # TODO Improve checks when add IdleConf.get_font_values.
- tracers.detach()
- d = self.page
- d.font_name.set('Fake')
- d.font_size.set('1')
- d.font_bold.set(True)
- d.set_samples.called = 0
- d.load_font_cfg()
- self.assertNotEqual(d.font_name.get(), 'Fake')
- self.assertNotEqual(d.font_size.get(), '1')
- self.assertFalse(d.font_bold.get())
- self.assertEqual(d.set_samples.called, 1)
- tracers.attach()
-
- def test_fontlist_key(self):
- # Up and Down keys should select a new font.
- d = self.page
- if d.fontlist.size() < 2:
- self.skipTest('need at least 2 fonts')
- fontlist = d.fontlist
- fontlist.activate(0)
- font = d.fontlist.get('active')
-
- # Test Down key.
- fontlist.focus_force()
- fontlist.update()
- fontlist.event_generate('<Key-Down>')
- fontlist.event_generate('<KeyRelease-Down>')
-
- down_font = fontlist.get('active')
- self.assertNotEqual(down_font, font)
- self.assertIn(d.font_name.get(), down_font.lower())
-
- # Test Up key.
- fontlist.focus_force()
- fontlist.update()
- fontlist.event_generate('<Key-Up>')
- fontlist.event_generate('<KeyRelease-Up>')
-
- up_font = fontlist.get('active')
- self.assertEqual(up_font, font)
- self.assertIn(d.font_name.get(), up_font.lower())
-
- def test_fontlist_mouse(self):
- # Click on item should select that item.
- d = self.page
- if d.fontlist.size() < 2:
- self.skipTest('need at least 2 fonts')
- fontlist = d.fontlist
- fontlist.activate(0)
-
- # Select next item in listbox
- fontlist.focus_force()
- fontlist.see(1)
- fontlist.update()
- x, y, dx, dy = fontlist.bbox(1)
- x += dx // 2
- y += dy // 2
- fontlist.event_generate('<Button-1>', x=x, y=y)
- fontlist.event_generate('<ButtonRelease-1>', x=x, y=y)
-
- font1 = fontlist.get(1)
- select_font = fontlist.get('anchor')
- self.assertEqual(select_font, font1)
- self.assertIn(d.font_name.get(), font1.lower())
-
- def test_sizelist(self):
- # Click on number should select that number
- d = self.page
- d.sizelist.variable.set(40)
- self.assertEqual(d.font_size.get(), '40')
-
- def test_bold_toggle(self):
- # Click on checkbutton should invert it.
- d = self.page
- d.font_bold.set(False)
- d.bold_toggle.invoke()
- self.assertTrue(d.font_bold.get())
- d.bold_toggle.invoke()
- self.assertFalse(d.font_bold.get())
-
- def test_font_set(self):
- # Test that setting a font Variable results in 3 provisional
- # change entries and a call to set_samples. Use values sure to
- # not be defaults.
-
- default_font = idleConf.GetFont(root, 'main', 'EditorWindow')
- default_size = str(default_font[1])
- default_bold = default_font[2] == 'bold'
- d = self.page
- d.font_size.set(default_size)
- d.font_bold.set(default_bold)
- d.set_samples.called = 0
-
- d.font_name.set('Test Font')
- expected = {'EditorWindow': {'font': 'Test Font',
- 'font-size': default_size,
- 'font-bold': str(default_bold)}}
- self.assertEqual(mainpage, expected)
- self.assertEqual(d.set_samples.called, 1)
- changes.clear()
-
- d.font_size.set('20')
- expected = {'EditorWindow': {'font': 'Test Font',
- 'font-size': '20',
- 'font-bold': str(default_bold)}}
- self.assertEqual(mainpage, expected)
- self.assertEqual(d.set_samples.called, 2)
- changes.clear()
-
- d.font_bold.set(not default_bold)
- expected = {'EditorWindow': {'font': 'Test Font',
- 'font-size': '20',
- 'font-bold': str(not default_bold)}}
- self.assertEqual(mainpage, expected)
- self.assertEqual(d.set_samples.called, 3)
-
- def test_set_samples(self):
- d = self.page
- del d.set_samples # Unmask method for test
- orig_samples = d.font_sample, d.highlight_sample
- d.font_sample, d.highlight_sample = {}, {}
- d.font_name.set('test')
- d.font_size.set('5')
- d.font_bold.set(1)
- expected = {'font': ('test', '5', 'bold')}
-
- # Test set_samples.
- d.set_samples()
- self.assertTrue(d.font_sample == d.highlight_sample == expected)
-
- d.font_sample, d.highlight_sample = orig_samples
- d.set_samples = Func() # Re-mask for other tests.
-
-
-class IndentTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.page = dialog.fontpage
- cls.page.update()
-
- def test_load_tab_cfg(self):
- d = self.page
- d.space_num.set(16)
- d.load_tab_cfg()
- self.assertEqual(d.space_num.get(), 4)
-
- def test_indent_scale(self):
- d = self.page
- changes.clear()
- d.indent_scale.set(20)
- self.assertEqual(d.space_num.get(), 16)
- self.assertEqual(mainpage, {'Indent': {'num-spaces': '16'}})
-
-
-class HighPageTest(unittest.TestCase):
- """Test that highlight tab widgets enable users to make changes.
-
- Test that widget actions set vars, that var changes add
- options to changes and that themes work correctly.
- """
-
- @classmethod
- def setUpClass(cls):
- page = cls.page = dialog.highpage
- dialog.note.select(page)
- page.set_theme_type = Func()
- page.paint_theme_sample = Func()
- page.set_highlight_target = Func()
- page.set_color_sample = Func()
- page.update()
-
- @classmethod
- def tearDownClass(cls):
- d = cls.page
- del d.set_theme_type, d.paint_theme_sample
- del d.set_highlight_target, d.set_color_sample
-
- def setUp(self):
- d = self.page
- # The following is needed for test_load_key_cfg, _delete_custom_keys.
- # This may indicate a defect in some test or function.
- for section in idleConf.GetSectionList('user', 'highlight'):
- idleConf.userCfg['highlight'].remove_section(section)
- changes.clear()
- d.set_theme_type.called = 0
- d.paint_theme_sample.called = 0
- d.set_highlight_target.called = 0
- d.set_color_sample.called = 0
-
- def test_load_theme_cfg(self):
- tracers.detach()
- d = self.page
- eq = self.assertEqual
-
- # Use builtin theme with no user themes created.
- idleConf.CurrentTheme = mock.Mock(return_value='IDLE Classic')
- d.load_theme_cfg()
- self.assertTrue(d.theme_source.get())
- # builtinlist sets variable builtin_name to the CurrentTheme default.
- eq(d.builtin_name.get(), 'IDLE Classic')
- eq(d.custom_name.get(), '- no custom themes -')
- eq(d.custom_theme_on.state(), ('disabled',))
- eq(d.set_theme_type.called, 1)
- eq(d.paint_theme_sample.called, 1)
- eq(d.set_highlight_target.called, 1)
-
- # Builtin theme with non-empty user theme list.
- idleConf.SetOption('highlight', 'test1', 'option', 'value')
- idleConf.SetOption('highlight', 'test2', 'option2', 'value2')
- d.load_theme_cfg()
- eq(d.builtin_name.get(), 'IDLE Classic')
- eq(d.custom_name.get(), 'test1')
- eq(d.set_theme_type.called, 2)
- eq(d.paint_theme_sample.called, 2)
- eq(d.set_highlight_target.called, 2)
-
- # Use custom theme.
- idleConf.CurrentTheme = mock.Mock(return_value='test2')
- idleConf.SetOption('main', 'Theme', 'default', '0')
- d.load_theme_cfg()
- self.assertFalse(d.theme_source.get())
- eq(d.builtin_name.get(), 'IDLE Classic')
- eq(d.custom_name.get(), 'test2')
- eq(d.set_theme_type.called, 3)
- eq(d.paint_theme_sample.called, 3)
- eq(d.set_highlight_target.called, 3)
-
- del idleConf.CurrentTheme
- tracers.attach()
-
- def test_theme_source(self):
- eq = self.assertEqual
- d = self.page
- # Test these separately.
- d.var_changed_builtin_name = Func()
- d.var_changed_custom_name = Func()
- # Builtin selected.
- d.builtin_theme_on.invoke()
- eq(mainpage, {'Theme': {'default': 'True'}})
- eq(d.var_changed_builtin_name.called, 1)
- eq(d.var_changed_custom_name.called, 0)
- changes.clear()
-
- # Custom selected.
- d.custom_theme_on.state(('!disabled',))
- d.custom_theme_on.invoke()
- self.assertEqual(mainpage, {'Theme': {'default': 'False'}})
- eq(d.var_changed_builtin_name.called, 1)
- eq(d.var_changed_custom_name.called, 1)
- del d.var_changed_builtin_name, d.var_changed_custom_name
-
- def test_builtin_name(self):
- eq = self.assertEqual
- d = self.page
- item_list = ['IDLE Classic', 'IDLE Dark', 'IDLE New']
-
- # Not in old_themes, defaults name to first item.
- idleConf.SetOption('main', 'Theme', 'name', 'spam')
- d.builtinlist.SetMenu(item_list, 'IDLE Dark')
- eq(mainpage, {'Theme': {'name': 'IDLE Classic',
- 'name2': 'IDLE Dark'}})
- eq(d.theme_message['text'], 'New theme, see Help')
- eq(d.paint_theme_sample.called, 1)
-
- # Not in old themes - uses name2.
- changes.clear()
- idleConf.SetOption('main', 'Theme', 'name', 'IDLE New')
- d.builtinlist.SetMenu(item_list, 'IDLE Dark')
- eq(mainpage, {'Theme': {'name2': 'IDLE Dark'}})
- eq(d.theme_message['text'], 'New theme, see Help')
- eq(d.paint_theme_sample.called, 2)
-
- # Builtin name in old_themes.
- changes.clear()
- d.builtinlist.SetMenu(item_list, 'IDLE Classic')
- eq(mainpage, {'Theme': {'name': 'IDLE Classic', 'name2': ''}})
- eq(d.theme_message['text'], '')
- eq(d.paint_theme_sample.called, 3)
-
- def test_custom_name(self):
- d = self.page
-
- # If no selections, doesn't get added.
- d.customlist.SetMenu([], '- no custom themes -')
- self.assertNotIn('Theme', mainpage)
- self.assertEqual(d.paint_theme_sample.called, 0)
-
- # Custom name selected.
- changes.clear()
- d.customlist.SetMenu(['a', 'b', 'c'], 'c')
- self.assertEqual(mainpage, {'Theme': {'name': 'c'}})
- self.assertEqual(d.paint_theme_sample.called, 1)
-
- def test_color(self):
- d = self.page
- d.on_new_color_set = Func()
- # self.color is only set in get_color through ColorChooser.
- d.color.set('green')
- self.assertEqual(d.on_new_color_set.called, 1)
- del d.on_new_color_set
-
- def test_highlight_target_list_mouse(self):
- # Set highlight_target through targetlist.
- eq = self.assertEqual
- d = self.page
-
- d.targetlist.SetMenu(['a', 'b', 'c'], 'c')
- eq(d.highlight_target.get(), 'c')
- eq(d.set_highlight_target.called, 1)
-
- def test_highlight_target_text_mouse(self):
- # Set highlight_target through clicking highlight_sample.
- eq = self.assertEqual
- d = self.page
-
- elem = {}
- count = 0
- hs = d.highlight_sample
- hs.focus_force()
- hs.see(1.0)
- hs.update_idletasks()
-
- def tag_to_element(elem):
- for element, tag in d.theme_elements.items():
- elem[tag[0]] = element
-
- def click_it(start):
- x, y, dx, dy = hs.bbox(start)
- x += dx // 2
- y += dy // 2
- hs.event_generate('<Enter>', x=0, y=0)
- hs.event_generate('<Motion>', x=x, y=y)
- hs.event_generate('<ButtonPress-1>', x=x, y=y)
- hs.event_generate('<ButtonRelease-1>', x=x, y=y)
-
- # Flip theme_elements to make the tag the key.
- tag_to_element(elem)
-
- # If highlight_sample has a tag that isn't in theme_elements, there
- # will be a KeyError in the test run.
- for tag in hs.tag_names():
- for start_index in hs.tag_ranges(tag)[0::2]:
- count += 1
- click_it(start_index)
- eq(d.highlight_target.get(), elem[tag])
- eq(d.set_highlight_target.called, count)
-
- def test_set_theme_type(self):
- eq = self.assertEqual
- d = self.page
- del d.set_theme_type
-
- # Builtin theme selected.
- d.theme_source.set(True)
- d.set_theme_type()
- eq(d.builtinlist['state'], NORMAL)
- eq(d.customlist['state'], DISABLED)
- eq(d.button_delete_custom.state(), ('disabled',))
-
- # Custom theme selected.
- d.theme_source.set(False)
- d.set_theme_type()
- eq(d.builtinlist['state'], DISABLED)
- eq(d.custom_theme_on.state(), ('selected',))
- eq(d.customlist['state'], NORMAL)
- eq(d.button_delete_custom.state(), ())
- d.set_theme_type = Func()
-
- def test_get_color(self):
- eq = self.assertEqual
- d = self.page
- orig_chooser = configdialog.tkColorChooser.askcolor
- chooser = configdialog.tkColorChooser.askcolor = Func()
- gntn = d.get_new_theme_name = Func()
-
- d.highlight_target.set('Editor Breakpoint')
- d.color.set('#ffffff')
-
- # Nothing selected.
- chooser.result = (None, None)
- d.button_set_color.invoke()
- eq(d.color.get(), '#ffffff')
-
- # Selection same as previous color.
- chooser.result = ('', d.style.lookup(d.frame_color_set['style'], 'background'))
- d.button_set_color.invoke()
- eq(d.color.get(), '#ffffff')
-
- # Select different color.
- chooser.result = ((222.8671875, 0.0, 0.0), '#de0000')
-
- # Default theme.
- d.color.set('#ffffff')
- d.theme_source.set(True)
-
- # No theme name selected therefore color not saved.
- gntn.result = ''
- d.button_set_color.invoke()
- eq(gntn.called, 1)
- eq(d.color.get(), '#ffffff')
- # Theme name selected.
- gntn.result = 'My New Theme'
- d.button_set_color.invoke()
- eq(d.custom_name.get(), gntn.result)
- eq(d.color.get(), '#de0000')
-
- # Custom theme.
- d.color.set('#ffffff')
- d.theme_source.set(False)
- d.button_set_color.invoke()
- eq(d.color.get(), '#de0000')
-
- del d.get_new_theme_name
- configdialog.tkColorChooser.askcolor = orig_chooser
-
- def test_on_new_color_set(self):
- d = self.page
- color = '#3f7cae'
- d.custom_name.set('Python')
- d.highlight_target.set('Selected Text')
- d.fg_bg_toggle.set(True)
-
- d.color.set(color)
- self.assertEqual(d.style.lookup(d.frame_color_set['style'], 'background'), color)
- self.assertEqual(d.highlight_sample.tag_cget('hilite', 'foreground'), color)
- self.assertEqual(highpage,
- {'Python': {'hilite-foreground': color}})
-
- def test_get_new_theme_name(self):
- orig_sectionname = configdialog.SectionName
- sn = configdialog.SectionName = Func(return_self=True)
- d = self.page
-
- sn.result = 'New Theme'
- self.assertEqual(d.get_new_theme_name(''), 'New Theme')
-
- configdialog.SectionName = orig_sectionname
-
- def test_save_as_new_theme(self):
- d = self.page
- gntn = d.get_new_theme_name = Func()
- d.theme_source.set(True)
-
- # No name entered.
- gntn.result = ''
- d.button_save_custom.invoke()
- self.assertNotIn(gntn.result, idleConf.userCfg['highlight'])
-
- # Name entered.
- gntn.result = 'my new theme'
- gntn.called = 0
- self.assertNotIn(gntn.result, idleConf.userCfg['highlight'])
- d.button_save_custom.invoke()
- self.assertIn(gntn.result, idleConf.userCfg['highlight'])
-
- del d.get_new_theme_name
-
- def test_create_new_and_save_new(self):
- eq = self.assertEqual
- d = self.page
-
- # Use default as previously active theme.
- d.theme_source.set(True)
- d.builtin_name.set('IDLE Classic')
- first_new = 'my new custom theme'
- second_new = 'my second custom theme'
-
- # No changes, so themes are an exact copy.
- self.assertNotIn(first_new, idleConf.userCfg)
- d.create_new(first_new)
- eq(idleConf.GetSectionList('user', 'highlight'), [first_new])
- eq(idleConf.GetThemeDict('default', 'IDLE Classic'),
- idleConf.GetThemeDict('user', first_new))
- eq(d.custom_name.get(), first_new)
- self.assertFalse(d.theme_source.get()) # Use custom set.
- eq(d.set_theme_type.called, 1)
-
- # Test that changed targets are in new theme.
- changes.add_option('highlight', first_new, 'hit-background', 'yellow')
- self.assertNotIn(second_new, idleConf.userCfg)
- d.create_new(second_new)
- eq(idleConf.GetSectionList('user', 'highlight'), [first_new, second_new])
- self.assertNotEqual(idleConf.GetThemeDict('user', first_new),
- idleConf.GetThemeDict('user', second_new))
- # Check that difference in themes was in `hit-background` from `changes`.
- idleConf.SetOption('highlight', first_new, 'hit-background', 'yellow')
- eq(idleConf.GetThemeDict('user', first_new),
- idleConf.GetThemeDict('user', second_new))
-
- def test_set_highlight_target(self):
- eq = self.assertEqual
- d = self.page
- del d.set_highlight_target
-
- # Target is cursor.
- d.highlight_target.set('Cursor')
- eq(d.fg_on.state(), ('disabled', 'selected'))
- eq(d.bg_on.state(), ('disabled',))
- self.assertTrue(d.fg_bg_toggle)
- eq(d.set_color_sample.called, 1)
-
- # Target is not cursor.
- d.highlight_target.set('Comment')
- eq(d.fg_on.state(), ('selected',))
- eq(d.bg_on.state(), ())
- self.assertTrue(d.fg_bg_toggle)
- eq(d.set_color_sample.called, 2)
-
- d.set_highlight_target = Func()
-
- def test_set_color_sample_binding(self):
- d = self.page
- scs = d.set_color_sample
-
- d.fg_on.invoke()
- self.assertEqual(scs.called, 1)
-
- d.bg_on.invoke()
- self.assertEqual(scs.called, 2)
-
- def test_set_color_sample(self):
- d = self.page
- del d.set_color_sample
- d.highlight_target.set('Selected Text')
- d.fg_bg_toggle.set(True)
- d.set_color_sample()
- self.assertEqual(
- d.style.lookup(d.frame_color_set['style'], 'background'),
- d.highlight_sample.tag_cget('hilite', 'foreground'))
- d.set_color_sample = Func()
-
- def test_paint_theme_sample(self):
- eq = self.assertEqual
- page = self.page
- del page.paint_theme_sample # Delete masking mock.
- hs_tag = page.highlight_sample.tag_cget
- gh = idleConf.GetHighlight
-
- # Create custom theme based on IDLE Dark.
- page.theme_source.set(True)
- page.builtin_name.set('IDLE Dark')
- theme = 'IDLE Test'
- page.create_new(theme)
- page.set_color_sample.called = 0
-
- # Base theme with nothing in `changes`.
- page.paint_theme_sample()
- new_console = {'foreground': 'blue',
- 'background': 'yellow',}
- for key, value in new_console.items():
- self.assertNotEqual(hs_tag('console', key), value)
- eq(page.set_color_sample.called, 1)
-
- # Apply changes.
- for key, value in new_console.items():
- changes.add_option('highlight', theme, 'console-'+key, value)
- page.paint_theme_sample()
- for key, value in new_console.items():
- eq(hs_tag('console', key), value)
- eq(page.set_color_sample.called, 2)
-
- page.paint_theme_sample = Func()
-
- def test_delete_custom(self):
- eq = self.assertEqual
- d = self.page
- d.button_delete_custom.state(('!disabled',))
- yesno = d.askyesno = Func()
- dialog.deactivate_current_config = Func()
- dialog.activate_config_changes = Func()
-
- theme_name = 'spam theme'
- idleConf.userCfg['highlight'].SetOption(theme_name, 'name', 'value')
- highpage[theme_name] = {'option': 'True'}
-
- # Force custom theme.
- d.theme_source.set(False)
- d.custom_name.set(theme_name)
+Coverage: 46% just by creating dialog. The other half is change code.
- # Cancel deletion.
- yesno.result = False
- d.button_delete_custom.invoke()
- eq(yesno.called, 1)
- eq(highpage[theme_name], {'option': 'True'})
- eq(idleConf.GetSectionList('user', 'highlight'), ['spam theme'])
- eq(dialog.deactivate_current_config.called, 0)
- eq(dialog.activate_config_changes.called, 0)
- eq(d.set_theme_type.called, 0)
-
- # Confirm deletion.
- yesno.result = True
- d.button_delete_custom.invoke()
- eq(yesno.called, 2)
- self.assertNotIn(theme_name, highpage)
- eq(idleConf.GetSectionList('user', 'highlight'), [])
- eq(d.custom_theme_on.state(), ('disabled',))
- eq(d.custom_name.get(), '- no custom themes -')
- eq(dialog.deactivate_current_config.called, 1)
- eq(dialog.activate_config_changes.called, 1)
- eq(d.set_theme_type.called, 1)
-
- del dialog.activate_config_changes, dialog.deactivate_current_config
- del d.askyesno
-
-
-class KeysPageTest(unittest.TestCase):
- """Test that keys tab widgets enable users to make changes.
-
- Test that widget actions set vars, that var changes add
- options to changes and that key sets works correctly.
- """
-
- @classmethod
- def setUpClass(cls):
- page = cls.page = dialog.keyspage
- dialog.note.select(page)
- page.set_keys_type = Func()
- page.load_keys_list = Func()
-
- @classmethod
- def tearDownClass(cls):
- page = cls.page
- del page.set_keys_type, page.load_keys_list
-
- def setUp(self):
- d = self.page
- # The following is needed for test_load_key_cfg, _delete_custom_keys.
- # This may indicate a defect in some test or function.
- for section in idleConf.GetSectionList('user', 'keys'):
- idleConf.userCfg['keys'].remove_section(section)
- changes.clear()
- d.set_keys_type.called = 0
- d.load_keys_list.called = 0
-
- def test_load_key_cfg(self):
- tracers.detach()
- d = self.page
- eq = self.assertEqual
-
- # Use builtin keyset with no user keysets created.
- idleConf.CurrentKeys = mock.Mock(return_value='IDLE Classic OSX')
- d.load_key_cfg()
- self.assertTrue(d.keyset_source.get())
- # builtinlist sets variable builtin_name to the CurrentKeys default.
- eq(d.builtin_name.get(), 'IDLE Classic OSX')
- eq(d.custom_name.get(), '- no custom keys -')
- eq(d.custom_keyset_on.state(), ('disabled',))
- eq(d.set_keys_type.called, 1)
- eq(d.load_keys_list.called, 1)
- eq(d.load_keys_list.args, ('IDLE Classic OSX', ))
-
- # Builtin keyset with non-empty user keyset list.
- idleConf.SetOption('keys', 'test1', 'option', 'value')
- idleConf.SetOption('keys', 'test2', 'option2', 'value2')
- d.load_key_cfg()
- eq(d.builtin_name.get(), 'IDLE Classic OSX')
- eq(d.custom_name.get(), 'test1')
- eq(d.set_keys_type.called, 2)
- eq(d.load_keys_list.called, 2)
- eq(d.load_keys_list.args, ('IDLE Classic OSX', ))
-
- # Use custom keyset.
- idleConf.CurrentKeys = mock.Mock(return_value='test2')
- idleConf.default_keys = mock.Mock(return_value='IDLE Modern Unix')
- idleConf.SetOption('main', 'Keys', 'default', '0')
- d.load_key_cfg()
- self.assertFalse(d.keyset_source.get())
- eq(d.builtin_name.get(), 'IDLE Modern Unix')
- eq(d.custom_name.get(), 'test2')
- eq(d.set_keys_type.called, 3)
- eq(d.load_keys_list.called, 3)
- eq(d.load_keys_list.args, ('test2', ))
-
- del idleConf.CurrentKeys, idleConf.default_keys
- tracers.attach()
-
- def test_keyset_source(self):
- eq = self.assertEqual
- d = self.page
- # Test these separately.
- d.var_changed_builtin_name = Func()
- d.var_changed_custom_name = Func()
- # Builtin selected.
- d.builtin_keyset_on.invoke()
- eq(mainpage, {'Keys': {'default': 'True'}})
- eq(d.var_changed_builtin_name.called, 1)
- eq(d.var_changed_custom_name.called, 0)
- changes.clear()
-
- # Custom selected.
- d.custom_keyset_on.state(('!disabled',))
- d.custom_keyset_on.invoke()
- self.assertEqual(mainpage, {'Keys': {'default': 'False'}})
- eq(d.var_changed_builtin_name.called, 1)
- eq(d.var_changed_custom_name.called, 1)
- del d.var_changed_builtin_name, d.var_changed_custom_name
-
- def test_builtin_name(self):
- eq = self.assertEqual
- d = self.page
- idleConf.userCfg['main'].remove_section('Keys')
- item_list = ['IDLE Classic Windows', 'IDLE Classic OSX',
- 'IDLE Modern UNIX']
-
- # Not in old_keys, defaults name to first item.
- d.builtinlist.SetMenu(item_list, 'IDLE Modern UNIX')
- eq(mainpage, {'Keys': {'name': 'IDLE Classic Windows',
- 'name2': 'IDLE Modern UNIX'}})
- eq(d.keys_message['text'], 'New key set, see Help')
- eq(d.load_keys_list.called, 1)
- eq(d.load_keys_list.args, ('IDLE Modern UNIX', ))
-
- # Not in old keys - uses name2.
- changes.clear()
- idleConf.SetOption('main', 'Keys', 'name', 'IDLE Classic Unix')
- d.builtinlist.SetMenu(item_list, 'IDLE Modern UNIX')
- eq(mainpage, {'Keys': {'name2': 'IDLE Modern UNIX'}})
- eq(d.keys_message['text'], 'New key set, see Help')
- eq(d.load_keys_list.called, 2)
- eq(d.load_keys_list.args, ('IDLE Modern UNIX', ))
-
- # Builtin name in old_keys.
- changes.clear()
- d.builtinlist.SetMenu(item_list, 'IDLE Classic OSX')
- eq(mainpage, {'Keys': {'name': 'IDLE Classic OSX', 'name2': ''}})
- eq(d.keys_message['text'], '')
- eq(d.load_keys_list.called, 3)
- eq(d.load_keys_list.args, ('IDLE Classic OSX', ))
-
- def test_custom_name(self):
- d = self.page
-
- # If no selections, doesn't get added.
- d.customlist.SetMenu([], '- no custom keys -')
- self.assertNotIn('Keys', mainpage)
- self.assertEqual(d.load_keys_list.called, 0)
-
- # Custom name selected.
- changes.clear()
- d.customlist.SetMenu(['a', 'b', 'c'], 'c')
- self.assertEqual(mainpage, {'Keys': {'name': 'c'}})
- self.assertEqual(d.load_keys_list.called, 1)
-
- def test_keybinding(self):
- idleConf.SetOption('extensions', 'ZzDummy', 'enable', 'True')
- d = self.page
- d.custom_name.set('my custom keys')
- d.bindingslist.delete(0, 'end')
- d.bindingslist.insert(0, 'copy')
- d.bindingslist.insert(1, 'z-in')
- d.bindingslist.selection_set(0)
- d.bindingslist.selection_anchor(0)
- # Core binding - adds to keys.
- d.keybinding.set('<Key-F11>')
- self.assertEqual(keyspage,
- {'my custom keys': {'copy': '<Key-F11>'}})
-
- # Not a core binding - adds to extensions.
- d.bindingslist.selection_set(1)
- d.bindingslist.selection_anchor(1)
- d.keybinding.set('<Key-F11>')
- self.assertEqual(extpage,
- {'ZzDummy_cfgBindings': {'z-in': '<Key-F11>'}})
-
- def test_set_keys_type(self):
- eq = self.assertEqual
- d = self.page
- del d.set_keys_type
-
- # Builtin keyset selected.
- d.keyset_source.set(True)
- d.set_keys_type()
- eq(d.builtinlist['state'], NORMAL)
- eq(d.customlist['state'], DISABLED)
- eq(d.button_delete_custom_keys.state(), ('disabled',))
-
- # Custom keyset selected.
- d.keyset_source.set(False)
- d.set_keys_type()
- eq(d.builtinlist['state'], DISABLED)
- eq(d.custom_keyset_on.state(), ('selected',))
- eq(d.customlist['state'], NORMAL)
- eq(d.button_delete_custom_keys.state(), ())
- d.set_keys_type = Func()
-
- def test_get_new_keys(self):
- eq = self.assertEqual
- d = self.page
- orig_getkeysdialog = configdialog.GetKeysDialog
- gkd = configdialog.GetKeysDialog = Func(return_self=True)
- gnkn = d.get_new_keys_name = Func()
-
- d.button_new_keys.state(('!disabled',))
- d.bindingslist.delete(0, 'end')
- d.bindingslist.insert(0, 'copy - <Control-Shift-Key-C>')
- d.bindingslist.selection_set(0)
- d.bindingslist.selection_anchor(0)
- d.keybinding.set('Key-a')
- d.keyset_source.set(True) # Default keyset.
-
- # Default keyset; no change to binding.
- gkd.result = ''
- d.button_new_keys.invoke()
- eq(d.bindingslist.get('anchor'), 'copy - <Control-Shift-Key-C>')
- # Keybinding isn't changed when there isn't a change entered.
- eq(d.keybinding.get(), 'Key-a')
-
- # Default keyset; binding changed.
- gkd.result = '<Key-F11>'
- # No keyset name selected therefore binding not saved.
- gnkn.result = ''
- d.button_new_keys.invoke()
- eq(gnkn.called, 1)
- eq(d.bindingslist.get('anchor'), 'copy - <Control-Shift-Key-C>')
- # Keyset name selected.
- gnkn.result = 'My New Key Set'
- d.button_new_keys.invoke()
- eq(d.custom_name.get(), gnkn.result)
- eq(d.bindingslist.get('anchor'), 'copy - <Key-F11>')
- eq(d.keybinding.get(), '<Key-F11>')
-
- # User keyset; binding changed.
- d.keyset_source.set(False) # Custom keyset.
- gnkn.called = 0
- gkd.result = '<Key-p>'
- d.button_new_keys.invoke()
- eq(gnkn.called, 0)
- eq(d.bindingslist.get('anchor'), 'copy - <Key-p>')
- eq(d.keybinding.get(), '<Key-p>')
-
- del d.get_new_keys_name
- configdialog.GetKeysDialog = orig_getkeysdialog
-
- def test_get_new_keys_name(self):
- orig_sectionname = configdialog.SectionName
- sn = configdialog.SectionName = Func(return_self=True)
- d = self.page
-
- sn.result = 'New Keys'
- self.assertEqual(d.get_new_keys_name(''), 'New Keys')
-
- configdialog.SectionName = orig_sectionname
-
- def test_save_as_new_key_set(self):
- d = self.page
- gnkn = d.get_new_keys_name = Func()
- d.keyset_source.set(True)
-
- # No name entered.
- gnkn.result = ''
- d.button_save_custom_keys.invoke()
-
- # Name entered.
- gnkn.result = 'my new key set'
- gnkn.called = 0
- self.assertNotIn(gnkn.result, idleConf.userCfg['keys'])
- d.button_save_custom_keys.invoke()
- self.assertIn(gnkn.result, idleConf.userCfg['keys'])
-
- del d.get_new_keys_name
-
- def test_on_bindingslist_select(self):
- d = self.page
- b = d.bindingslist
- b.delete(0, 'end')
- b.insert(0, 'copy')
- b.insert(1, 'find')
- b.activate(0)
-
- b.focus_force()
- b.see(1)
- b.update()
- x, y, dx, dy = b.bbox(1)
- x += dx // 2
- y += dy // 2
- b.event_generate('<Enter>', x=0, y=0)
- b.event_generate('<Motion>', x=x, y=y)
- b.event_generate('<Button-1>', x=x, y=y)
- b.event_generate('<ButtonRelease-1>', x=x, y=y)
- self.assertEqual(b.get('anchor'), 'find')
- self.assertEqual(d.button_new_keys.state(), ())
-
- def test_create_new_key_set_and_save_new_key_set(self):
- eq = self.assertEqual
- d = self.page
-
- # Use default as previously active keyset.
- d.keyset_source.set(True)
- d.builtin_name.set('IDLE Classic Windows')
- first_new = 'my new custom key set'
- second_new = 'my second custom keyset'
-
- # No changes, so keysets are an exact copy.
- self.assertNotIn(first_new, idleConf.userCfg)
- d.create_new_key_set(first_new)
- eq(idleConf.GetSectionList('user', 'keys'), [first_new])
- eq(idleConf.GetKeySet('IDLE Classic Windows'),
- idleConf.GetKeySet(first_new))
- eq(d.custom_name.get(), first_new)
- self.assertFalse(d.keyset_source.get()) # Use custom set.
- eq(d.set_keys_type.called, 1)
-
- # Test that changed keybindings are in new keyset.
- changes.add_option('keys', first_new, 'copy', '<Key-F11>')
- self.assertNotIn(second_new, idleConf.userCfg)
- d.create_new_key_set(second_new)
- eq(idleConf.GetSectionList('user', 'keys'), [first_new, second_new])
- self.assertNotEqual(idleConf.GetKeySet(first_new),
- idleConf.GetKeySet(second_new))
- # Check that difference in keysets was in option `copy` from `changes`.
- idleConf.SetOption('keys', first_new, 'copy', '<Key-F11>')
- eq(idleConf.GetKeySet(first_new), idleConf.GetKeySet(second_new))
-
- def test_load_keys_list(self):
- eq = self.assertEqual
- d = self.page
- gks = idleConf.GetKeySet = Func()
- del d.load_keys_list
- b = d.bindingslist
-
- b.delete(0, 'end')
- b.insert(0, '<<find>>')
- b.insert(1, '<<help>>')
- gks.result = {'<<copy>>': ['<Control-Key-c>', '<Control-Key-C>'],
- '<<force-open-completions>>': ['<Control-Key-space>'],
- '<<spam>>': ['<Key-F11>']}
- changes.add_option('keys', 'my keys', 'spam', '<Shift-Key-a>')
- expected = ('copy - <Control-Key-c> <Control-Key-C>',
- 'force-open-completions - <Control-Key-space>',
- 'spam - <Shift-Key-a>')
-
- # No current selection.
- d.load_keys_list('my keys')
- eq(b.get(0, 'end'), expected)
- eq(b.get('anchor'), '')
- eq(b.curselection(), ())
-
- # Check selection.
- b.selection_set(1)
- b.selection_anchor(1)
- d.load_keys_list('my keys')
- eq(b.get(0, 'end'), expected)
- eq(b.get('anchor'), 'force-open-completions - <Control-Key-space>')
- eq(b.curselection(), (1, ))
-
- # Change selection.
- b.selection_set(2)
- b.selection_anchor(2)
- d.load_keys_list('my keys')
- eq(b.get(0, 'end'), expected)
- eq(b.get('anchor'), 'spam - <Shift-Key-a>')
- eq(b.curselection(), (2, ))
- d.load_keys_list = Func()
-
- del idleConf.GetKeySet
-
- def test_delete_custom_keys(self):
- eq = self.assertEqual
- d = self.page
- d.button_delete_custom_keys.state(('!disabled',))
- yesno = d.askyesno = Func()
- dialog.deactivate_current_config = Func()
- dialog.activate_config_changes = Func()
-
- keyset_name = 'spam key set'
- idleConf.userCfg['keys'].SetOption(keyset_name, 'name', 'value')
- keyspage[keyset_name] = {'option': 'True'}
-
- # Force custom keyset.
- d.keyset_source.set(False)
- d.custom_name.set(keyset_name)
-
- # Cancel deletion.
- yesno.result = False
- d.button_delete_custom_keys.invoke()
- eq(yesno.called, 1)
- eq(keyspage[keyset_name], {'option': 'True'})
- eq(idleConf.GetSectionList('user', 'keys'), ['spam key set'])
- eq(dialog.deactivate_current_config.called, 0)
- eq(dialog.activate_config_changes.called, 0)
- eq(d.set_keys_type.called, 0)
-
- # Confirm deletion.
- yesno.result = True
- d.button_delete_custom_keys.invoke()
- eq(yesno.called, 2)
- self.assertNotIn(keyset_name, keyspage)
- eq(idleConf.GetSectionList('user', 'keys'), [])
- eq(d.custom_keyset_on.state(), ('disabled',))
- eq(d.custom_name.get(), '- no custom keys -')
- eq(dialog.deactivate_current_config.called, 1)
- eq(dialog.activate_config_changes.called, 1)
- eq(d.set_keys_type.called, 1)
-
- del dialog.activate_config_changes, dialog.deactivate_current_config
- del d.askyesno
-
-
-class GenPageTest(unittest.TestCase):
- """Test that general tab widgets enable users to make changes.
-
- Test that widget actions set vars, that var changes add
- options to changes and that helplist works correctly.
- """
- @classmethod
- def setUpClass(cls):
- page = cls.page = dialog.genpage
- dialog.note.select(page)
- page.set = page.set_add_delete_state = Func()
- page.upc = page.update_help_changes = Func()
- page.update()
-
- @classmethod
- def tearDownClass(cls):
- page = cls.page
- del page.set, page.set_add_delete_state
- del page.upc, page.update_help_changes
- page.helplist.delete(0, 'end')
- page.user_helplist.clear()
-
- def setUp(self):
- changes.clear()
-
- def test_load_general_cfg(self):
- # Set to wrong values, load, check right values.
- eq = self.assertEqual
- d = self.page
- d.startup_edit.set(1)
- d.autosave.set(1)
- d.win_width.set(1)
- d.win_height.set(1)
- d.helplist.insert('end', 'bad')
- d.user_helplist = ['bad', 'worse']
- idleConf.SetOption('main', 'HelpFiles', '1', 'name;file')
- d.load_general_cfg()
- eq(d.startup_edit.get(), 0)
- eq(d.autosave.get(), 0)
- eq(d.win_width.get(), '80')
- eq(d.win_height.get(), '40')
- eq(d.helplist.get(0, 'end'), ('name',))
- eq(d.user_helplist, [('name', 'file', '1')])
-
- def test_startup(self):
- d = self.page
- d.startup_editor_on.invoke()
- self.assertEqual(mainpage,
- {'General': {'editor-on-startup': '1'}})
- changes.clear()
- d.startup_shell_on.invoke()
- self.assertEqual(mainpage,
- {'General': {'editor-on-startup': '0'}})
-
- def test_editor_size(self):
- d = self.page
- d.win_height_int.delete(0, 'end')
- d.win_height_int.insert(0, '11')
- self.assertEqual(mainpage, {'EditorWindow': {'height': '11'}})
- changes.clear()
- d.win_width_int.delete(0, 'end')
- d.win_width_int.insert(0, '11')
- self.assertEqual(mainpage, {'EditorWindow': {'width': '11'}})
-
- def test_cursor_blink(self):
- self.page.cursor_blink_bool.invoke()
- self.assertEqual(mainpage, {'EditorWindow': {'cursor-blink': 'False'}})
-
- def test_autocomplete_wait(self):
- self.page.auto_wait_int.delete(0, 'end')
- self.page.auto_wait_int.insert(0, '11')
- self.assertEqual(extpage, {'AutoComplete': {'popupwait': '11'}})
-
- def test_parenmatch(self):
- d = self.page
- eq = self.assertEqual
- d.paren_style_type['menu'].invoke(0)
- eq(extpage, {'ParenMatch': {'style': 'opener'}})
- changes.clear()
- d.paren_flash_time.delete(0, 'end')
- d.paren_flash_time.insert(0, '11')
- eq(extpage, {'ParenMatch': {'flash-delay': '11'}})
- changes.clear()
- d.bell_on.invoke()
- eq(extpage, {'ParenMatch': {'bell': 'False'}})
-
- def test_autosave(self):
- d = self.page
- d.save_auto_on.invoke()
- self.assertEqual(mainpage, {'General': {'autosave': '1'}})
- d.save_ask_on.invoke()
- self.assertEqual(mainpage, {'General': {'autosave': '0'}})
-
- def test_paragraph(self):
- self.page.format_width_int.delete(0, 'end')
- self.page.format_width_int.insert(0, '11')
- self.assertEqual(extpage, {'FormatParagraph': {'max-width': '11'}})
-
- def test_context(self):
- self.page.context_int.delete(0, 'end')
- self.page.context_int.insert(0, '1')
- self.assertEqual(extpage, {'CodeContext': {'maxlines': '1'}})
-
- def test_source_selected(self):
- d = self.page
- d.set = d.set_add_delete_state
- d.upc = d.update_help_changes
- helplist = d.helplist
- dex = 'end'
- helplist.insert(dex, 'source')
- helplist.activate(dex)
-
- helplist.focus_force()
- helplist.see(dex)
- helplist.update()
- x, y, dx, dy = helplist.bbox(dex)
- x += dx // 2
- y += dy // 2
- d.set.called = d.upc.called = 0
- helplist.event_generate('<Enter>', x=0, y=0)
- helplist.event_generate('<Motion>', x=x, y=y)
- helplist.event_generate('<Button-1>', x=x, y=y)
- helplist.event_generate('<ButtonRelease-1>', x=x, y=y)
- self.assertEqual(helplist.get('anchor'), 'source')
- self.assertTrue(d.set.called)
- self.assertFalse(d.upc.called)
-
- def test_set_add_delete_state(self):
- # Call with 0 items, 1 unselected item, 1 selected item.
- eq = self.assertEqual
- d = self.page
- del d.set_add_delete_state # Unmask method.
- sad = d.set_add_delete_state
- h = d.helplist
-
- h.delete(0, 'end')
- sad()
- eq(d.button_helplist_edit.state(), ('disabled',))
- eq(d.button_helplist_remove.state(), ('disabled',))
-
- h.insert(0, 'source')
- sad()
- eq(d.button_helplist_edit.state(), ('disabled',))
- eq(d.button_helplist_remove.state(), ('disabled',))
-
- h.selection_set(0)
- sad()
- eq(d.button_helplist_edit.state(), ())
- eq(d.button_helplist_remove.state(), ())
- d.set_add_delete_state = Func() # Mask method.
-
- def test_helplist_item_add(self):
- # Call without and twice with HelpSource result.
- # Double call enables check on order.
- eq = self.assertEqual
- orig_helpsource = configdialog.HelpSource
- hs = configdialog.HelpSource = Func(return_self=True)
- d = self.page
- d.helplist.delete(0, 'end')
- d.user_helplist.clear()
- d.set.called = d.upc.called = 0
-
- hs.result = ''
- d.helplist_item_add()
- self.assertTrue(list(d.helplist.get(0, 'end')) ==
- d.user_helplist == [])
- self.assertFalse(d.upc.called)
-
- hs.result = ('name1', 'file1')
- d.helplist_item_add()
- hs.result = ('name2', 'file2')
- d.helplist_item_add()
- eq(d.helplist.get(0, 'end'), ('name1', 'name2'))
- eq(d.user_helplist, [('name1', 'file1'), ('name2', 'file2')])
- eq(d.upc.called, 2)
- self.assertFalse(d.set.called)
-
- configdialog.HelpSource = orig_helpsource
-
- def test_helplist_item_edit(self):
- # Call without and with HelpSource change.
- eq = self.assertEqual
- orig_helpsource = configdialog.HelpSource
- hs = configdialog.HelpSource = Func(return_self=True)
- d = self.page
- d.helplist.delete(0, 'end')
- d.helplist.insert(0, 'name1')
- d.helplist.selection_set(0)
- d.helplist.selection_anchor(0)
- d.user_helplist.clear()
- d.user_helplist.append(('name1', 'file1'))
- d.set.called = d.upc.called = 0
-
- hs.result = ''
- d.helplist_item_edit()
- hs.result = ('name1', 'file1')
- d.helplist_item_edit()
- eq(d.helplist.get(0, 'end'), ('name1',))
- eq(d.user_helplist, [('name1', 'file1')])
- self.assertFalse(d.upc.called)
-
- hs.result = ('name2', 'file2')
- d.helplist_item_edit()
- eq(d.helplist.get(0, 'end'), ('name2',))
- eq(d.user_helplist, [('name2', 'file2')])
- self.assertTrue(d.upc.called == d.set.called == 1)
-
- configdialog.HelpSource = orig_helpsource
-
- def test_helplist_item_remove(self):
- eq = self.assertEqual
- d = self.page
- d.helplist.delete(0, 'end')
- d.helplist.insert(0, 'name1')
- d.helplist.selection_set(0)
- d.helplist.selection_anchor(0)
- d.user_helplist.clear()
- d.user_helplist.append(('name1', 'file1'))
- d.set.called = d.upc.called = 0
-
- d.helplist_item_remove()
- eq(d.helplist.get(0, 'end'), ())
- eq(d.user_helplist, [])
- self.assertTrue(d.upc.called == d.set.called == 1)
-
- def test_update_help_changes(self):
- d = self.page
- del d.update_help_changes
- d.user_helplist.clear()
- d.user_helplist.append(('name1', 'file1'))
- d.user_helplist.append(('name2', 'file2'))
-
- d.update_help_changes()
- self.assertEqual(mainpage['HelpFiles'],
- {'1': 'name1;file1', '2': 'name2;file2'})
- d.update_help_changes = Func()
+'''
+import unittest
+from test.test_support import requires
+from Tkinter import Tk
+from idlelib.configDialog import ConfigDialog
+from idlelib.macosxSupport import _initializeTkVariantTests
-class VarTraceTest(unittest.TestCase):
+class ConfigDialogTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
- cls.tracers = configdialog.VarTrace()
- cls.iv = IntVar(root)
- cls.bv = BooleanVar(root)
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
+ _initializeTkVariantTests(cls.root)
@classmethod
def tearDownClass(cls):
- del cls.tracers, cls.iv, cls.bv
-
- def setUp(self):
- self.tracers.clear()
- self.called = 0
-
- def var_changed_increment(self, *params):
- self.called += 13
-
- def var_changed_boolean(self, *params):
- pass
-
- def test_init(self):
- tr = self.tracers
- tr.__init__()
- self.assertEqual(tr.untraced, [])
- self.assertEqual(tr.traced, [])
-
- def test_clear(self):
- tr = self.tracers
- tr.untraced.append(0)
- tr.traced.append(1)
- tr.clear()
- self.assertEqual(tr.untraced, [])
- self.assertEqual(tr.traced, [])
-
- def test_add(self):
- tr = self.tracers
- func = Func()
- cb = tr.make_callback = mock.Mock(return_value=func)
-
- iv = tr.add(self.iv, self.var_changed_increment)
- self.assertIs(iv, self.iv)
- bv = tr.add(self.bv, self.var_changed_boolean)
- self.assertIs(bv, self.bv)
-
- sv = StringVar(root)
- sv2 = tr.add(sv, ('main', 'section', 'option'))
- self.assertIs(sv2, sv)
- cb.assert_called_once()
- cb.assert_called_with(sv, ('main', 'section', 'option'))
-
- expected = [(iv, self.var_changed_increment),
- (bv, self.var_changed_boolean),
- (sv, func)]
- self.assertEqual(tr.traced, [])
- self.assertEqual(tr.untraced, expected)
-
- del tr.make_callback
-
- def test_make_callback(self):
- cb = self.tracers.make_callback(self.iv, ('main', 'section', 'option'))
- self.assertTrue(callable(cb))
- self.iv.set(42)
- # Not attached, so set didn't invoke the callback.
- self.assertNotIn('section', changes['main'])
- # Invoke callback manually.
- cb()
- self.assertIn('section', changes['main'])
- self.assertEqual(changes['main']['section']['option'], '42')
- changes.clear()
-
- def test_attach_detach(self):
- tr = self.tracers
- iv = tr.add(self.iv, self.var_changed_increment)
- bv = tr.add(self.bv, self.var_changed_boolean)
- expected = [(iv, self.var_changed_increment),
- (bv, self.var_changed_boolean)]
-
- # Attach callbacks and test call increment.
- tr.attach()
- self.assertEqual(tr.untraced, [])
- self.assertCountEqual(tr.traced, expected)
- iv.set(1)
- self.assertEqual(iv.get(), 1)
- self.assertEqual(self.called, 13)
-
- # Check that only one callback is attached to a variable.
- # If more than one callback were attached, then var_changed_increment
- # would be called twice and the counter would be 2.
- self.called = 0
- tr.attach()
- iv.set(1)
- self.assertEqual(self.called, 13)
+ cls.root.destroy()
+ del cls.root
- # Detach callbacks.
- self.called = 0
- tr.detach()
- self.assertEqual(tr.traced, [])
- self.assertCountEqual(tr.untraced, expected)
- iv.set(1)
- self.assertEqual(self.called, 0)
+ def test_dialog(self):
+ d = ConfigDialog(self.root, 'Test', _utest=True)
+ d.remove_var_callbacks()
if __name__ == '__main__':
diff --git a/Lib/idlelib/idle_test/test_debugger.py b/Lib/idlelib/idle_test/test_debugger.py
deleted file mode 100644
index 35efb34..0000000
--- a/Lib/idlelib/idle_test/test_debugger.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"Test debugger, coverage 19%"
-
-from idlelib import debugger
-import unittest
-from test.support import requires
-requires('gui')
-from tkinter import Tk
-
-
-class NameSpaceTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- debugger.NamespaceViewer(self.root, 'Test')
-
-
-# Other classes are Idb, Debugger, and StackViewer.
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_debugger_r.py b/Lib/idlelib/idle_test/test_debugger_r.py
deleted file mode 100644
index 199f634..0000000
--- a/Lib/idlelib/idle_test/test_debugger_r.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"Test debugger_r, coverage 30%."
-
-from idlelib import debugger_r
-import unittest
-from test.support import requires
-from tkinter import Tk
-
-
-class Test(unittest.TestCase):
-
-## @classmethod
-## def setUpClass(cls):
-## requires('gui')
-## cls.root = Tk()
-##
-## @classmethod
-## def tearDownClass(cls):
-## cls.root.destroy()
-## del cls.root
-
- def test_init(self):
- self.assertTrue(True) # Get coverage of import
-
-
-# Classes GUIProxy, IdbAdapter, FrameProxy, CodeProxy, DictProxy,
-# GUIAdapter, IdbProxy plus 7 module functions.
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_debugobj.py b/Lib/idlelib/idle_test/test_debugobj.py
deleted file mode 100644
index 131ce22..0000000
--- a/Lib/idlelib/idle_test/test_debugobj.py
+++ /dev/null
@@ -1,57 +0,0 @@
-"Test debugobj, coverage 40%."
-
-from idlelib import debugobj
-import unittest
-
-
-class ObjectTreeItemTest(unittest.TestCase):
-
- def test_init(self):
- ti = debugobj.ObjectTreeItem('label', 22)
- self.assertEqual(ti.labeltext, 'label')
- self.assertEqual(ti.object, 22)
- self.assertEqual(ti.setfunction, None)
-
-
-class ClassTreeItemTest(unittest.TestCase):
-
- def test_isexpandable(self):
- ti = debugobj.ClassTreeItem('label', 0)
- self.assertTrue(ti.IsExpandable())
-
-
-class AtomicObjectTreeItemTest(unittest.TestCase):
-
- def test_isexpandable(self):
- ti = debugobj.AtomicObjectTreeItem('label', 0)
- self.assertFalse(ti.IsExpandable())
-
-
-class SequenceTreeItemTest(unittest.TestCase):
-
- def test_isexpandable(self):
- ti = debugobj.SequenceTreeItem('label', ())
- self.assertFalse(ti.IsExpandable())
- ti = debugobj.SequenceTreeItem('label', (1,))
- self.assertTrue(ti.IsExpandable())
-
- def test_keys(self):
- ti = debugobj.SequenceTreeItem('label', 'abc')
- self.assertEqual(list(ti.keys()), [0, 1, 2])
-
-
-class DictTreeItemTest(unittest.TestCase):
-
- def test_isexpandable(self):
- ti = debugobj.DictTreeItem('label', {})
- self.assertFalse(ti.IsExpandable())
- ti = debugobj.DictTreeItem('label', {1:1})
- self.assertTrue(ti.IsExpandable())
-
- def test_keys(self):
- ti = debugobj.DictTreeItem('label', {1:1, 0:0, 2:2})
- self.assertEqual(ti.keys(), [0, 1, 2])
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_debugobj_r.py b/Lib/idlelib/idle_test/test_debugobj_r.py
deleted file mode 100644
index 86e51b6..0000000
--- a/Lib/idlelib/idle_test/test_debugobj_r.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"Test debugobj_r, coverage 56%."
-
-from idlelib import debugobj_r
-import unittest
-
-
-class WrappedObjectTreeItemTest(unittest.TestCase):
-
- def test_getattr(self):
- ti = debugobj_r.WrappedObjectTreeItem(list)
- self.assertEqual(ti.append, list.append)
-
-class StubObjectTreeItemTest(unittest.TestCase):
-
- def test_init(self):
- ti = debugobj_r.StubObjectTreeItem('socket', 1111)
- self.assertEqual(ti.sockio, 'socket')
- self.assertEqual(ti.oid, 1111)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_delegator.py b/Lib/idlelib/idle_test/test_delegator.py
index 9224162..b8ae5ee 100644
--- a/Lib/idlelib/idle_test/test_delegator.py
+++ b/Lib/idlelib/idle_test/test_delegator.py
@@ -1,44 +1,37 @@
-"Test delegator, coverage 100%."
-
-from idlelib.delegator import Delegator
import unittest
-
+from idlelib.Delegator import Delegator
class DelegatorTest(unittest.TestCase):
def test_mydel(self):
- # Test a simple use scenario.
+ # test a simple use scenario
- # Initialize an int delegator.
+ # initialize
mydel = Delegator(int)
self.assertIs(mydel.delegate, int)
self.assertEqual(mydel._Delegator__cache, set())
- # Trying to access a non-attribute of int fails.
- self.assertRaises(AttributeError, mydel.__getattr__, 'xyz')
- # Add real int attribute 'bit_length' by accessing it.
+ # add an attribute:
+ self.assertRaises(AttributeError, mydel.__getattr__, 'xyz')
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 attribute 'numerator'.
+ # add a second attribute
mydel.numerator
self.assertEqual(mydel._Delegator__cache, {'bit_length', 'numerator'})
- # Delete 'numerator'.
+ # delete the second (which, however, leaves it in the name cache)
del mydel.numerator
self.assertNotIn('numerator', mydel.__dict__)
- # 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
+ self.assertIn('numerator', mydel._Delegator__cache)
- # Change delegate to float, first resetting the attributes.
- mydel.setdelegate(float) # calls resetcache
+ # reset by calling .setdelegate, which calls .resetcache
+ mydel.setdelegate(float)
+ self.assertIs(mydel.delegate, float)
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
index 1747847..51d5c16 100644
--- a/Lib/idlelib/idle_test/test_editmenu.py
+++ b/Lib/idlelib/idle_test/test_editmenu.py
@@ -1,73 +1,100 @@
'''Test (selected) IDLE Edit menu items.
-Edit modules have their own test files
+Edit modules have their own test files files
'''
-from test.support import requires
-requires('gui')
-import tkinter as tk
-from tkinter import ttk
+from test.test_support import requires
+import Tkinter as tk
import unittest
-from idlelib import pyshell
+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):
+ requires('gui')
cls.root = root = tk.Tk()
- cls.root.withdraw()
- pyshell.fix_x11_paste(root)
+ root.withdraw()
+ PyShell.fix_x11_paste(root)
cls.text = tk.Text(root)
cls.entry = tk.Entry(root)
- cls.tentry = ttk.Entry(root)
cls.spin = tk.Spinbox(root)
root.clipboard_clear()
root.clipboard_append('two')
@classmethod
def tearDownClass(cls):
- del cls.text, cls.entry, cls.tentry
+ del cls.text, cls.entry, cls.spin
cls.root.clipboard_clear()
cls.root.update_idletasks()
+ cls.root.update()
cls.root.destroy()
del cls.root
- def test_paste_text(self):
- "Test pasting into text with and without a selection."
+ def test_paste_text_no_selection(self):
+ "Test pasting into text without a selection."
+ text = self.text
+ tag, ans = '', 'onetwo\n'
+ 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_text_selection(self):
+ "Test pasting into text with 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)
+ tag, ans = 'sel', 'two\n'
+ 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."
- # Generated <<Paste>> fails for tk entry without empty select
- # range for 'no selection'. Live widget works fine.
- for entry in self.entry, self.tentry:
- 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)
- entry.event_generate('<<Paste>>')
- self.assertEqual(entry.get(), ans)
+ def test_paste_entry_no_selection(self):
+ "Test pasting into an entry without a selection."
+ # On 3.6, generated <<Paste>> fails without empty select range
+ # for 'no selection'. Live widget works fine.
+ entry = self.entry
+ end, ans = 0, 'onetwo'
+ 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."
+ def test_paste_entry_selection(self):
+ "Test pasting into an entry with a selection."
+ entry = self.entry
+ end, ans = 'end', 'two'
+ entry.delete(0, 'end')
+ entry.insert(0, 'one')
+ entry.select_range(0, end)
+ entry.event_generate('<<Paste>>')
+ self.assertEqual(entry.get(), ans)
+
+ def test_paste_spin_no_selection(self):
+ "Test pasting into a spinbox 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)
+ end, ans = 0, 'onetwo'
+ spin.delete(0, 'end')
+ spin.insert(0, 'one')
+ spin.selection('range', 0, end) # see note
+ spin.event_generate('<<Paste>>')
+ self.assertEqual(spin.get(), ans)
+
+ def test_paste_spin_selection(self):
+ "Test pasting into a spinbox with a selection."
+ spin = self.spin
+ end, ans = 'end', 'two'
+ spin.delete(0, 'end')
+ spin.insert(0, 'one')
+ spin.selection('range', 0, end)
+ spin.event_generate('<<Paste>>')
+ self.assertEqual(spin.get(), ans)
if __name__ == '__main__':
diff --git a/Lib/idlelib/idle_test/test_editor.py b/Lib/idlelib/idle_test/test_editor.py
deleted file mode 100644
index 240db71..0000000
--- a/Lib/idlelib/idle_test/test_editor.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"Test editor, coverage 35%."
-
-from idlelib import editor
-import unittest
-from test.support import requires
-from tkinter import Tk
-
-Editor = editor.EditorWindow
-
-
-class EditorWindowTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.update_idletasks()
- for id in cls.root.tk.call('after', 'info'):
- cls.root.after_cancel(id)
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- e = Editor(root=self.root)
- self.assertEqual(e.root, self.root)
- e._close()
-
-
-class TestGetLineIndent(unittest.TestCase):
- def test_empty_lines(self):
- for tabwidth in [1, 2, 4, 6, 8]:
- for line in ['', '\n']:
- with self.subTest(line=line, tabwidth=tabwidth):
- self.assertEqual(
- editor.get_line_indent(line, tabwidth=tabwidth),
- (0, 0),
- )
-
- def test_tabwidth_4(self):
- # (line, (raw, effective))
- tests = (('no spaces', (0, 0)),
- # Internal space isn't counted.
- (' space test', (4, 4)),
- ('\ttab test', (1, 4)),
- ('\t\tdouble tabs test', (2, 8)),
- # Different results when mixing tabs and spaces.
- (' \tmixed test', (5, 8)),
- (' \t mixed test', (5, 6)),
- ('\t mixed test', (5, 8)),
- # Spaces not divisible by tabwidth.
- (' \tmixed test', (3, 4)),
- (' \t mixed test', (3, 5)),
- ('\t mixed test', (3, 6)),
- # Only checks spaces and tabs.
- ('\nnewline test', (0, 0)))
-
- for line, expected in tests:
- with self.subTest(line=line):
- self.assertEqual(
- editor.get_line_indent(line, tabwidth=4),
- expected,
- )
-
- def test_tabwidth_8(self):
- # (line, (raw, effective))
- tests = (('no spaces', (0, 0)),
- # Internal space isn't counted.
- (' space test', (8, 8)),
- ('\ttab test', (1, 8)),
- ('\t\tdouble tabs test', (2, 16)),
- # Different results when mixing tabs and spaces.
- (' \tmixed test', (9, 16)),
- (' \t mixed test', (9, 10)),
- ('\t mixed test', (9, 16)),
- # Spaces not divisible by tabwidth.
- (' \tmixed test', (3, 8)),
- (' \t mixed test', (3, 9)),
- ('\t mixed test', (3, 10)),
- # Only checks spaces and tabs.
- ('\nnewline test', (0, 0)))
-
- for line, expected in tests:
- with self.subTest(line=line):
- self.assertEqual(
- editor.get_line_indent(line, tabwidth=8),
- expected,
- )
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_filelist.py b/Lib/idlelib/idle_test/test_filelist.py
deleted file mode 100644
index 731f197..0000000
--- a/Lib/idlelib/idle_test/test_filelist.py
+++ /dev/null
@@ -1,33 +0,0 @@
-"Test filelist, coverage 19%."
-
-from idlelib import filelist
-import unittest
-from test.support import requires
-from tkinter import Tk
-
-class FileListTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.update_idletasks()
- for id in cls.root.tk.call('after', 'info'):
- cls.root.after_cancel(id)
- cls.root.destroy()
- del cls.root
-
- def test_new_empty(self):
- flist = filelist.FileList(self.root)
- self.assertEqual(flist.root, self.root)
- e = flist.new()
- self.assertEqual(type(e), flist.EditorWindow)
- e._close()
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_format.py b/Lib/idlelib/idle_test/test_formatparagraph.py
index a79bb51..068ae38 100644
--- a/Lib/idlelib/idle_test/test_format.py
+++ b/Lib/idlelib/idle_test/test_formatparagraph.py
@@ -1,12 +1,9 @@
-"Test format, coverage 99%."
-
-from idlelib import format as ft
+# Test the functions and main class method of FormatParagraph.py
import unittest
-from unittest import mock
-from test.support import requires
-from tkinter import Tk, Text
-from idlelib.editor import EditorWindow
-from idlelib.idle_test.mock_idle import Editor as MockEditor
+from idlelib import FormatParagraph as fp
+from idlelib.EditorWindow import EditorWindow
+from Tkinter import Tk, Text
+from test.test_support import requires
class Is_Get_Test(unittest.TestCase):
@@ -18,30 +15,30 @@ class Is_Get_Test(unittest.TestCase):
leadingws_nocomment = ' This is not a comment'
def test_is_all_white(self):
- self.assertTrue(ft.is_all_white(''))
- self.assertTrue(ft.is_all_white('\t\n\r\f\v'))
- self.assertFalse(ft.is_all_white(self.test_comment))
+ self.assertTrue(fp.is_all_white(''))
+ self.assertTrue(fp.is_all_white('\t\n\r\f\v'))
+ self.assertFalse(fp.is_all_white(self.test_comment))
def test_get_indent(self):
Equal = self.assertEqual
- Equal(ft.get_indent(self.test_comment), '')
- Equal(ft.get_indent(self.trailingws_comment), '')
- Equal(ft.get_indent(self.leadingws_comment), ' ')
- Equal(ft.get_indent(self.leadingws_nocomment), ' ')
+ Equal(fp.get_indent(self.test_comment), '')
+ Equal(fp.get_indent(self.trailingws_comment), '')
+ Equal(fp.get_indent(self.leadingws_comment), ' ')
+ Equal(fp.get_indent(self.leadingws_nocomment), ' ')
def test_get_comment_header(self):
Equal = self.assertEqual
# Test comment strings
- Equal(ft.get_comment_header(self.test_comment), '#')
- Equal(ft.get_comment_header(self.trailingws_comment), '#')
- Equal(ft.get_comment_header(self.leadingws_comment), ' #')
+ Equal(fp.get_comment_header(self.test_comment), '#')
+ Equal(fp.get_comment_header(self.trailingws_comment), '#')
+ Equal(fp.get_comment_header(self.leadingws_comment), ' #')
# Test non-comment strings
- Equal(ft.get_comment_header(self.leadingws_nocomment), ' ')
- Equal(ft.get_comment_header(self.test_nocomment), '')
+ Equal(fp.get_comment_header(self.leadingws_nocomment), ' ')
+ Equal(fp.get_comment_header(self.test_nocomment), '')
class FindTest(unittest.TestCase):
- """Test the find_paragraph function in paragraph module.
+ """Test the find_paragraph function in FormatParagraph.
Using the runcase() function, find_paragraph() is called with 'mark' set at
multiple indexes before and inside the test paragraph.
@@ -65,7 +62,7 @@ class FindTest(unittest.TestCase):
linelength = int(text.index("%d.end" % line).split('.')[1])
for col in (0, linelength//2, linelength):
tempindex = "%d.%d" % (line, col)
- self.assertEqual(ft.find_paragraph(text, tempindex), expected)
+ self.assertEqual(fp.find_paragraph(text, tempindex), expected)
text.delete('1.0', 'end')
def test_find_comment(self):
@@ -164,7 +161,7 @@ class ReformatFunctionTest(unittest.TestCase):
def test_reformat_paragraph(self):
Equal = self.assertEqual
- reform = ft.reformat_paragraph
+ reform = fp.reformat_paragraph
hw = "O hello world"
Equal(reform(' ', 1), ' ')
Equal(reform("Hello world", 20), "Hello world")
@@ -195,7 +192,7 @@ class ReformatCommentTest(unittest.TestCase):
test_string = (
" \"\"\"this is a test of a reformat for a triple quoted string"
" will it reformat to less than 70 characters for me?\"\"\"")
- result = ft.reformat_comment(test_string, 70, " ")
+ result = fp.reformat_comment(test_string, 70, " ")
expected = (
" \"\"\"this is a test of a reformat for a triple quoted string will it\n"
" reformat to less than 70 characters for me?\"\"\"")
@@ -204,7 +201,7 @@ class ReformatCommentTest(unittest.TestCase):
test_comment = (
"# this is a test of a reformat for a triple quoted string will "
"it reformat to less than 70 characters for me?")
- result = ft.reformat_comment(test_comment, 70, "#")
+ result = fp.reformat_comment(test_comment, 70, "#")
expected = (
"# this is a test of a reformat for a triple quoted string will it\n"
"# reformat to less than 70 characters for me?")
@@ -213,7 +210,7 @@ class ReformatCommentTest(unittest.TestCase):
class FormatClassTest(unittest.TestCase):
def test_init_close(self):
- instance = ft.FormatParagraph('editor')
+ instance = fp.FormatParagraph('editor')
self.assertEqual(instance.editwin, 'editor')
instance.close()
self.assertEqual(instance.editwin, None)
@@ -241,7 +238,7 @@ class TextWrapper:
class Editor:
def __init__(self, root):
self.text = TextWrapper(root)
- get_selection_indices = EditorWindow. get_selection_indices
+ get_selection_indices = EditorWindow. get_selection_indices.im_func
class FormatEventTest(unittest.TestCase):
"""Test the formatting of text inside a Text widget.
@@ -272,16 +269,14 @@ class FormatEventTest(unittest.TestCase):
def setUpClass(cls):
requires('gui')
cls.root = Tk()
- cls.root.withdraw()
editor = Editor(root=cls.root)
cls.text = editor.text.text # Test code does not need the wrapper.
- cls.formatter = ft.FormatParagraph(editor).format_paragraph_event
+ cls.formatter = fp.FormatParagraph(editor).format_paragraph_event
# Sets the insert mark just after the re-wrapped and inserted text.
@classmethod
def tearDownClass(cls):
del cls.text, cls.formatter
- cls.root.update_idletasks()
cls.root.destroy()
del cls.root
@@ -377,292 +372,5 @@ class FormatEventTest(unittest.TestCase):
## text.delete('1.0', 'end')
-class DummyEditwin:
- def __init__(self, root, text):
- self.root = root
- self.text = text
- self.indentwidth = 4
- self.tabwidth = 4
- self.usetabs = False
- self.context_use_ps1 = True
-
- _make_blanks = EditorWindow._make_blanks
- get_selection_indices = EditorWindow.get_selection_indices
-
-
-class FormatRegionTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.text = Text(cls.root)
- cls.text.undo_block_start = mock.Mock()
- cls.text.undo_block_stop = mock.Mock()
- cls.editor = DummyEditwin(cls.root, cls.text)
- cls.formatter = ft.FormatRegion(cls.editor)
-
- @classmethod
- def tearDownClass(cls):
- del cls.text, cls.formatter, cls.editor
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def setUp(self):
- self.text.insert('1.0', self.code_sample)
-
- def tearDown(self):
- self.text.delete('1.0', 'end')
-
- code_sample = """\
-# WS line needed for test.
-class C1():
- # Class comment.
- def __init__(self, a, b):
- self.a = a
- self.b = b
-
- def compare(self):
- if a > b:
- return a
- elif a < b:
- return b
- else:
- return None
-"""
-
- def test_get_region(self):
- get = self.formatter.get_region
- text = self.text
- eq = self.assertEqual
-
- # Add selection.
- text.tag_add('sel', '7.0', '10.0')
- expected_lines = ['',
- ' def compare(self):',
- ' if a > b:',
- '']
- eq(get(), ('7.0', '10.0', '\n'.join(expected_lines), expected_lines))
-
- # Remove selection.
- text.tag_remove('sel', '1.0', 'end')
- eq(get(), ('15.0', '16.0', '\n', ['', '']))
-
- def test_set_region(self):
- set_ = self.formatter.set_region
- text = self.text
- eq = self.assertEqual
-
- save_bell = text.bell
- text.bell = mock.Mock()
- line6 = self.code_sample.splitlines()[5]
- line10 = self.code_sample.splitlines()[9]
-
- text.tag_add('sel', '6.0', '11.0')
- head, tail, chars, lines = self.formatter.get_region()
-
- # No changes.
- set_(head, tail, chars, lines)
- text.bell.assert_called_once()
- eq(text.get('6.0', '11.0'), chars)
- eq(text.get('sel.first', 'sel.last'), chars)
- text.tag_remove('sel', '1.0', 'end')
-
- # Alter selected lines by changing lines and adding a newline.
- newstring = 'added line 1\n\n\n\n'
- newlines = newstring.split('\n')
- set_('7.0', '10.0', chars, newlines)
- # Selection changed.
- eq(text.get('sel.first', 'sel.last'), newstring)
- # Additional line added, so last index is changed.
- eq(text.get('7.0', '11.0'), newstring)
- # Before and after lines unchanged.
- eq(text.get('6.0', '7.0-1c'), line6)
- eq(text.get('11.0', '12.0-1c'), line10)
- text.tag_remove('sel', '1.0', 'end')
-
- text.bell = save_bell
-
- def test_indent_region_event(self):
- indent = self.formatter.indent_region_event
- text = self.text
- eq = self.assertEqual
-
- text.tag_add('sel', '7.0', '10.0')
- indent()
- # Blank lines aren't affected by indent.
- eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n'))
-
- def test_dedent_region_event(self):
- dedent = self.formatter.dedent_region_event
- text = self.text
- eq = self.assertEqual
-
- text.tag_add('sel', '7.0', '10.0')
- dedent()
- # Blank lines aren't affected by dedent.
- eq(text.get('7.0', '10.0'), ('\ndef compare(self):\n if a > b:\n'))
-
- def test_comment_region_event(self):
- comment = self.formatter.comment_region_event
- text = self.text
- eq = self.assertEqual
-
- text.tag_add('sel', '7.0', '10.0')
- comment()
- eq(text.get('7.0', '10.0'), ('##\n## def compare(self):\n## if a > b:\n'))
-
- def test_uncomment_region_event(self):
- comment = self.formatter.comment_region_event
- uncomment = self.formatter.uncomment_region_event
- text = self.text
- eq = self.assertEqual
-
- text.tag_add('sel', '7.0', '10.0')
- comment()
- uncomment()
- eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n'))
-
- # Only remove comments at the beginning of a line.
- text.tag_remove('sel', '1.0', 'end')
- text.tag_add('sel', '3.0', '4.0')
- uncomment()
- eq(text.get('3.0', '3.end'), (' # Class comment.'))
-
- self.formatter.set_region('3.0', '4.0', '', ['# Class comment.', ''])
- uncomment()
- eq(text.get('3.0', '3.end'), (' Class comment.'))
-
- @mock.patch.object(ft.FormatRegion, "_asktabwidth")
- def test_tabify_region_event(self, _asktabwidth):
- tabify = self.formatter.tabify_region_event
- text = self.text
- eq = self.assertEqual
-
- text.tag_add('sel', '7.0', '10.0')
- # No tabwidth selected.
- _asktabwidth.return_value = None
- self.assertIsNone(tabify())
-
- _asktabwidth.return_value = 3
- self.assertIsNotNone(tabify())
- eq(text.get('7.0', '10.0'), ('\n\t def compare(self):\n\t\t if a > b:\n'))
-
- @mock.patch.object(ft.FormatRegion, "_asktabwidth")
- def test_untabify_region_event(self, _asktabwidth):
- untabify = self.formatter.untabify_region_event
- text = self.text
- eq = self.assertEqual
-
- text.tag_add('sel', '7.0', '10.0')
- # No tabwidth selected.
- _asktabwidth.return_value = None
- self.assertIsNone(untabify())
-
- _asktabwidth.return_value = 2
- self.formatter.tabify_region_event()
- _asktabwidth.return_value = 3
- self.assertIsNotNone(untabify())
- eq(text.get('7.0', '10.0'), ('\n def compare(self):\n if a > b:\n'))
-
- @mock.patch.object(ft, "askinteger")
- def test_ask_tabwidth(self, askinteger):
- ask = self.formatter._asktabwidth
- askinteger.return_value = 10
- self.assertEqual(ask(), 10)
-
-
-class IndentsTest(unittest.TestCase):
-
- @mock.patch.object(ft, "askyesno")
- def test_toggle_tabs(self, askyesno):
- editor = DummyEditwin(None, None) # usetabs == False.
- indents = ft.Indents(editor)
- askyesno.return_value = True
-
- indents.toggle_tabs_event(None)
- self.assertEqual(editor.usetabs, True)
- self.assertEqual(editor.indentwidth, 8)
-
- indents.toggle_tabs_event(None)
- self.assertEqual(editor.usetabs, False)
- self.assertEqual(editor.indentwidth, 8)
-
- @mock.patch.object(ft, "askinteger")
- def test_change_indentwidth(self, askinteger):
- editor = DummyEditwin(None, None) # indentwidth == 4.
- indents = ft.Indents(editor)
-
- askinteger.return_value = None
- indents.change_indentwidth_event(None)
- self.assertEqual(editor.indentwidth, 4)
-
- askinteger.return_value = 3
- indents.change_indentwidth_event(None)
- self.assertEqual(editor.indentwidth, 3)
-
- askinteger.return_value = 5
- editor.usetabs = True
- indents.change_indentwidth_event(None)
- self.assertEqual(editor.indentwidth, 3)
-
-
-class RstripTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.text = Text(cls.root)
- cls.editor = MockEditor(text=cls.text)
- cls.do_rstrip = ft.Rstrip(cls.editor).do_rstrip
-
- @classmethod
- def tearDownClass(cls):
- del cls.text, cls.do_rstrip, cls.editor
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def tearDown(self):
- self.text.delete('1.0', 'end-1c')
-
- def test_rstrip_lines(self):
- original = (
- "Line with an ending tab \n"
- "Line ending in 5 spaces \n"
- "Linewithnospaces\n"
- " indented line\n"
- " indented line with trailing space \n"
- " \n")
- stripped = (
- "Line with an ending tab\n"
- "Line ending in 5 spaces\n"
- "Linewithnospaces\n"
- " indented line\n"
- " indented line with trailing space\n")
-
- self.text.insert('1.0', original)
- self.do_rstrip()
- self.assertEqual(self.text.get('1.0', 'insert'), stripped)
-
- def test_rstrip_end(self):
- text = self.text
- for code in ('', '\n', '\n\n\n'):
- with self.subTest(code=code):
- text.insert('1.0', code)
- self.do_rstrip()
- self.assertEqual(text.get('1.0','end-1c'), '')
- for code in ('a\n', 'a\n\n', 'a\n\n\n'):
- with self.subTest(code=code):
- text.delete('1.0', 'end-1c')
- text.insert('1.0', code)
- self.do_rstrip()
- self.assertEqual(text.get('1.0','end-1c'), 'a\n')
-
-
if __name__ == '__main__':
unittest.main(verbosity=2, exit=2)
diff --git a/Lib/idlelib/idle_test/test_grep.py b/Lib/idlelib/idle_test/test_grep.py
index a0b5b69..e9f4f22 100644
--- a/Lib/idlelib/idle_test/test_grep.py
+++ b/Lib/idlelib/idle_test/test_grep.py
@@ -1,17 +1,17 @@
""" !Changing this line will break Test_findfile.test_found!
-Non-gui unit tests for grep.GrepDialog methods.
+Non-gui unit tests for idlelib.GrepDialog methods.
dummy_command calls grep_it calls findfiles.
An exception raised in one method will fail callers.
Otherwise, tests are mostly independent.
-Currently only test grep_it, coverage 51%.
+*** Currently only test grep_it.
"""
-from idlelib import grep
import unittest
-from test.support import captured_stdout
+from test.test_support import captured_stdout, findfile
from idlelib.idle_test.mock_tk import Var
-import os
+from idlelib.GrepDialog import GrepDialog
import re
+__file__ = findfile('idlelib/idle_test') + '/test_grep.py'
class Dummy_searchengine:
'''GrepDialog.__init__ calls parent SearchDiabolBase which attaches the
@@ -23,97 +23,25 @@ class Dummy_searchengine:
searchengine = Dummy_searchengine()
-
class Dummy_grep:
# Methods tested
#default_command = GrepDialog.default_command
- grep_it = grep.GrepDialog.grep_it
+ grep_it = GrepDialog.grep_it.im_func
+ findfiles = GrepDialog.findfiles.im_func
# Other stuff needed
recvar = Var(False)
engine = searchengine
def close(self): # gui method
pass
-_grep = Dummy_grep()
-
+grep = Dummy_grep()
class FindfilesTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.realpath = os.path.realpath(__file__)
- cls.path = os.path.dirname(cls.realpath)
-
- @classmethod
- def tearDownClass(cls):
- del cls.realpath, cls.path
-
- def test_invaliddir(self):
- with captured_stdout() as s:
- filelist = list(grep.findfiles('invaliddir', '*.*', False))
- self.assertEqual(filelist, [])
- self.assertIn('invalid', s.getvalue())
-
- def test_curdir(self):
- # Test os.curdir.
- ff = grep.findfiles
- save_cwd = os.getcwd()
- os.chdir(self.path)
- filename = 'test_grep.py'
- filelist = list(ff(os.curdir, filename, False))
- self.assertIn(os.path.join(os.curdir, filename), filelist)
- os.chdir(save_cwd)
-
- def test_base(self):
- ff = grep.findfiles
- readme = os.path.join(self.path, 'README.txt')
-
- # Check for Python files in path where this file lives.
- filelist = list(ff(self.path, '*.py', False))
- # This directory has many Python files.
- self.assertGreater(len(filelist), 10)
- self.assertIn(self.realpath, filelist)
- self.assertNotIn(readme, filelist)
-
- # Look for .txt files in path where this file lives.
- filelist = list(ff(self.path, '*.txt', False))
- self.assertNotEqual(len(filelist), 0)
- self.assertNotIn(self.realpath, filelist)
- self.assertIn(readme, filelist)
-
- # Look for non-matching pattern.
- filelist = list(ff(self.path, 'grep.*', False))
- self.assertEqual(len(filelist), 0)
- self.assertNotIn(self.realpath, filelist)
-
- def test_recurse(self):
- ff = grep.findfiles
- parent = os.path.dirname(self.path)
- grepfile = os.path.join(parent, 'grep.py')
- pat = '*.py'
-
- # Get Python files only in parent directory.
- filelist = list(ff(parent, pat, False))
- parent_size = len(filelist)
- # Lots of Python files in idlelib.
- self.assertGreater(parent_size, 20)
- self.assertIn(grepfile, filelist)
- # Without subdirectories, this file isn't returned.
- self.assertNotIn(self.realpath, filelist)
-
- # Include subdirectories.
- filelist = list(ff(parent, pat, True))
- # More files found now.
- self.assertGreater(len(filelist), parent_size)
- self.assertIn(grepfile, filelist)
- # This file exists in list now.
- self.assertIn(self.realpath, filelist)
-
- # Check another level up the tree.
- parent = os.path.dirname(parent)
- filelist = list(ff(parent, '*.py', True))
- self.assertIn(self.realpath, filelist)
-
+ # findfiles is really a function, not a method, could be iterator
+ # test that filename return filename
+ # test that idlelib has many .py files
+ # test that recursive flag adds idle_test .py files
+ pass
class Grep_itTest(unittest.TestCase):
# Test captured reports with 0 and some hits.
@@ -121,9 +49,9 @@ class Grep_itTest(unittest.TestCase):
# from incomplete replacement, so 'later'.
def report(self, pat):
- _grep.engine._pat = pat
+ grep.engine._pat = pat
with captured_stdout() as s:
- _grep.grep_it(re.compile(pat), __file__)
+ grep.grep_it(re.compile(pat), __file__)
lines = s.getvalue().split('\n')
lines.pop() # remove bogus '' after last \n
return lines
@@ -145,12 +73,10 @@ class Grep_itTest(unittest.TestCase):
self.assertIn('2', lines[3]) # hits found 2
self.assertTrue(lines[4].startswith('(Hint:'))
-
class Default_commandTest(unittest.TestCase):
- # To write this, move outwin import to top of GrepDialog
+ # To write this, mode OutputWindow import to top of GrepDialog
# so it can be replaced by captured_stdout in class setup/teardown.
pass
-
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ unittest.main(verbosity=2, exit=False)
diff --git a/Lib/idlelib/idle_test/test_help.py b/Lib/idlelib/idle_test/test_help.py
deleted file mode 100644
index b542659..0000000
--- a/Lib/idlelib/idle_test/test_help.py
+++ /dev/null
@@ -1,34 +0,0 @@
-"Test help, coverage 87%."
-
-from idlelib import help
-import unittest
-from test.support import requires
-requires('gui')
-from os.path import abspath, dirname, join
-from tkinter import Tk
-
-
-class HelpFrameTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- "By itself, this tests that file parsed without exception."
- cls.root = root = Tk()
- root.withdraw()
- helpfile = join(dirname(dirname(abspath(__file__))), 'help.html')
- cls.frame = help.HelpFrame(root, helpfile)
-
- @classmethod
- def tearDownClass(cls):
- del cls.frame
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def test_line1(self):
- text = self.frame.text
- self.assertEqual(text.get('1.0', '1.end'), ' IDLE ')
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_help_about.py b/Lib/idlelib/idle_test/test_help_about.py
deleted file mode 100644
index 7c148d2..0000000
--- a/Lib/idlelib/idle_test/test_help_about.py
+++ /dev/null
@@ -1,182 +0,0 @@
-"""Test help_about, coverage 100%.
-help_about.build_bits branches on sys.platform='darwin'.
-'100% combines coverage on Mac and others.
-"""
-
-from idlelib import help_about
-import unittest
-from test.support import requires, findfile
-from tkinter import Tk, TclError
-from idlelib.idle_test.mock_idle import Func
-from idlelib.idle_test.mock_tk import Mbox_func
-from idlelib import textview
-import os.path
-from platform import python_version
-
-About = help_about.AboutDialog
-
-
-class LiveDialogTest(unittest.TestCase):
- """Simulate user clicking buttons other than [Close].
-
- Test that invoked textview has text from source.
- """
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.dialog = About(cls.root, 'About IDLE', _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- del cls.dialog
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def test_build_bits(self):
- self.assertIn(help_about.build_bits(), ('32', '64'))
-
- def test_dialog_title(self):
- """Test about dialog title"""
- self.assertEqual(self.dialog.title(), 'About IDLE')
-
- def test_dialog_logo(self):
- """Test about dialog logo."""
- path, file = os.path.split(self.dialog.icon_image['file'])
- fn, ext = os.path.splitext(file)
- self.assertEqual(fn, 'idle_48')
-
- def test_printer_buttons(self):
- """Test buttons whose commands use printer function."""
- dialog = self.dialog
- button_sources = [(dialog.py_license, license, 'license'),
- (dialog.py_copyright, copyright, 'copyright'),
- (dialog.py_credits, credits, 'credits')]
-
- for button, printer, name in button_sources:
- with self.subTest(name=name):
- printer._Printer__setup()
- button.invoke()
- get = dialog._current_textview.viewframe.textframe.text.get
- lines = printer._Printer__lines
- if len(lines) < 2:
- self.fail(name + ' full text was not found')
- self.assertEqual(lines[0], get('1.0', '1.end'))
- self.assertEqual(lines[1], get('2.0', '2.end'))
- dialog._current_textview.destroy()
-
- def test_file_buttons(self):
- """Test buttons that display files."""
- dialog = self.dialog
- button_sources = [(self.dialog.readme, 'README.txt', 'readme'),
- (self.dialog.idle_news, 'NEWS.txt', 'news'),
- (self.dialog.idle_credits, 'CREDITS.txt', 'credits')]
-
- for button, filename, name in button_sources:
- with self.subTest(name=name):
- button.invoke()
- fn = findfile(filename, subdir='idlelib')
- get = dialog._current_textview.viewframe.textframe.text.get
- with open(fn, encoding='utf-8') as f:
- self.assertEqual(f.readline().strip(), get('1.0', '1.end'))
- f.readline()
- self.assertEqual(f.readline().strip(), get('3.0', '3.end'))
- dialog._current_textview.destroy()
-
-
-class DefaultTitleTest(unittest.TestCase):
- "Test default title."
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.dialog = About(cls.root, _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- del cls.dialog
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def test_dialog_title(self):
- """Test about dialog title"""
- self.assertEqual(self.dialog.title(),
- f'About IDLE {python_version()}'
- f' ({help_about.build_bits()} bit)')
-
-
-class CloseTest(unittest.TestCase):
- """Simulate user clicking [Close] button"""
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.dialog = About(cls.root, 'About IDLE', _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- del cls.dialog
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def test_close(self):
- self.assertEqual(self.dialog.winfo_class(), 'Toplevel')
- self.dialog.button_ok.invoke()
- with self.assertRaises(TclError):
- self.dialog.winfo_class()
-
-
-class Dummy_about_dialog():
- # Dummy class for testing file display functions.
- idle_credits = About.show_idle_credits
- idle_readme = About.show_readme
- idle_news = About.show_idle_news
- # Called by the above
- display_file_text = About.display_file_text
- _utest = True
-
-
-class DisplayFileTest(unittest.TestCase):
- """Test functions that display files.
-
- While somewhat redundant with gui-based test_file_dialog,
- these unit tests run on all buildbots, not just a few.
- """
- dialog = Dummy_about_dialog()
-
- @classmethod
- def setUpClass(cls):
- cls.orig_error = textview.showerror
- cls.orig_view = textview.view_text
- cls.error = Mbox_func()
- cls.view = Func()
- textview.showerror = cls.error
- textview.view_text = cls.view
-
- @classmethod
- def tearDownClass(cls):
- textview.showerror = cls.orig_error
- textview.view_text = cls.orig_view
-
- def test_file_display(self):
- for handler in (self.dialog.idle_credits,
- self.dialog.idle_readme,
- self.dialog.idle_news):
- self.error.message = ''
- self.view.called = False
- with self.subTest(handler=handler):
- handler()
- self.assertEqual(self.error.message, '')
- self.assertEqual(self.view.called, True)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_helpabout.py b/Lib/idlelib/idle_test/test_helpabout.py
new file mode 100644
index 0000000..0046f87
--- /dev/null
+++ b/Lib/idlelib/idle_test/test_helpabout.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.im_func
+ idle_readme = About.ShowIDLEAbout.im_func
+ idle_news = About.ShowIDLENEWS.im_func
+ # Called by the above
+ display_file_text = About.display_file_text.im_func
+
+
+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.im_func
+
+ 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 343843c..0a1809d 100644
--- a/Lib/idlelib/idle_test/test_hyperparser.py
+++ b/Lib/idlelib/idle_test/test_hyperparser.py
@@ -1,21 +1,20 @@
-"Test hyperparser, coverage 98%."
-
-from idlelib.hyperparser import HyperParser
+"""Unittest for idlelib.HyperParser"""
import unittest
-from test.support import requires
-from tkinter import Tk, Text
-from idlelib.editor import EditorWindow
+from test.test_support import requires
+from Tkinter import Tk, Text
+from idlelib.EditorWindow import EditorWindow
+from idlelib.HyperParser import HyperParser
class DummyEditwin:
def __init__(self, text):
self.text = text
self.indentwidth = 8
self.tabwidth = 8
- self.prompt_last_line = '>>>'
+ self.context_use_ps1 = True
self.num_context_lines = 50, 500, 1000
- _build_char_in_string_func = EditorWindow._build_char_in_string_func
- is_char_in_string = EditorWindow.is_char_in_string
+ _build_char_in_string_func = EditorWindow._build_char_in_string_func.im_func
+ is_char_in_string = EditorWindow.is_char_in_string.im_func
class HyperParserTest(unittest.TestCase):
@@ -31,7 +30,6 @@ class HyperParserTest(unittest.TestCase):
"z = ((r'asdf')+('a')))\n"
'[x for x in\n'
'for = False\n'
- 'cliché = "this is a string with unicode, what a cliché"'
)
@classmethod
@@ -53,7 +51,7 @@ class HyperParserTest(unittest.TestCase):
def tearDown(self):
self.text.delete('1.0', 'end')
- self.editwin.prompt_last_line = '>>>'
+ self.editwin.context_use_ps1 = True
def get_parser(self, index):
"""
@@ -71,7 +69,7 @@ class HyperParserTest(unittest.TestCase):
self.assertIn('precedes', str(ve.exception))
# test without ps1
- self.editwin.prompt_last_line = ''
+ self.editwin.context_use_ps1 = False
# number of lines lesser than 50
p = self.get_parser('end')
@@ -96,8 +94,6 @@ class HyperParserTest(unittest.TestCase):
self.assertTrue(p.is_in_string())
p = get('4.6')
self.assertTrue(p.is_in_string())
- p = get('12.54')
- self.assertTrue(p.is_in_string())
def test_is_in_code(self):
get = self.get_parser
@@ -185,92 +181,12 @@ class HyperParserTest(unittest.TestCase):
p = get('10.0')
self.assertEqual(p.get_expression(), '')
- p = get('10.6')
- self.assertEqual(p.get_expression(), '')
-
- p = get('10.11')
- self.assertEqual(p.get_expression(), '')
-
p = get('11.3')
self.assertEqual(p.get_expression(), '')
p = get('11.11')
self.assertEqual(p.get_expression(), 'False')
- p = get('12.6')
- self.assertEqual(p.get_expression(), 'cliché')
-
- def test_eat_identifier(self):
- def is_valid_id(candidate):
- result = HyperParser._eat_identifier(candidate, 0, len(candidate))
- if result == len(candidate):
- return True
- elif result == 0:
- return False
- else:
- err_msg = "Unexpected result: {} (expected 0 or {}".format(
- result, len(candidate)
- )
- raise Exception(err_msg)
-
- # invalid first character which is valid elsewhere in an identifier
- self.assertFalse(is_valid_id('2notid'))
-
- # ASCII-only valid identifiers
- self.assertTrue(is_valid_id('valid_id'))
- self.assertTrue(is_valid_id('_valid_id'))
- self.assertTrue(is_valid_id('valid_id_'))
- self.assertTrue(is_valid_id('_2valid_id'))
-
- # keywords which should be "eaten"
- self.assertTrue(is_valid_id('True'))
- self.assertTrue(is_valid_id('False'))
- self.assertTrue(is_valid_id('None'))
-
- # keywords which should not be "eaten"
- self.assertFalse(is_valid_id('for'))
- self.assertFalse(is_valid_id('import'))
- self.assertFalse(is_valid_id('return'))
-
- # valid unicode identifiers
- self.assertTrue(is_valid_id('cliche'))
- self.assertTrue(is_valid_id('cliché'))
- self.assertTrue(is_valid_id('aÙ¢'))
-
- # invalid unicode identifiers
- self.assertFalse(is_valid_id('2a'))
- self.assertFalse(is_valid_id('Ù¢a'))
- self.assertFalse(is_valid_id('a²'))
-
- # valid identifier after "punctuation"
- self.assertEqual(HyperParser._eat_identifier('+ var', 0, 5), len('var'))
- self.assertEqual(HyperParser._eat_identifier('+var', 0, 4), len('var'))
- self.assertEqual(HyperParser._eat_identifier('.var', 0, 4), len('var'))
-
- # invalid identifiers
- self.assertFalse(is_valid_id('+'))
- self.assertFalse(is_valid_id(' '))
- self.assertFalse(is_valid_id(':'))
- self.assertFalse(is_valid_id('?'))
- self.assertFalse(is_valid_id('^'))
- self.assertFalse(is_valid_id('\\'))
- self.assertFalse(is_valid_id('"'))
- self.assertFalse(is_valid_id('"a string"'))
-
- def test_eat_identifier_various_lengths(self):
- eat_id = HyperParser._eat_identifier
-
- for length in range(1, 21):
- self.assertEqual(eat_id('a' * length, 0, length), length)
- self.assertEqual(eat_id('é' * length, 0, length), length)
- self.assertEqual(eat_id('a' + '2' * (length - 1), 0, length), length)
- self.assertEqual(eat_id('é' + '2' * (length - 1), 0, length), length)
- self.assertEqual(eat_id('é' + 'a' * (length - 1), 0, length), length)
- self.assertEqual(eat_id('é' * (length - 1) + 'a', 0, length), length)
- self.assertEqual(eat_id('+' * length, 0, length), 0)
- self.assertEqual(eat_id('2' + 'a' * (length - 1), 0, length), 0)
- self.assertEqual(eat_id('2' + 'é' * (length - 1), 0, length), 0)
-
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_history.py b/Lib/idlelib/idle_test/test_idlehistory.py
index 6753965..b076757 100644
--- a/Lib/idlelib/idle_test/test_history.py
+++ b/Lib/idlelib/idle_test/test_idlehistory.py
@@ -1,18 +1,15 @@
-" Test history, coverage 100%."
-
-from idlelib.history import History
import unittest
-from test.support import requires
+from test.test_support import requires
-import tkinter as tk
-from tkinter import Text as tkText
+import Tkinter as tk
+from Tkinter import Text as tkText
from idlelib.idle_test.mock_tk import Text as mkText
-from idlelib.config import idleConf
+from idlelib.IdleHistory import History
+from idlelib.configHandler import idleConf
line1 = 'a = 7'
line2 = 'b = a'
-
class StoreTest(unittest.TestCase):
'''Tests History.__init__ and History.store with mock Text'''
@@ -64,7 +61,6 @@ class TextWrapper:
def bell(self):
self._bell = True
-
class FetchTest(unittest.TestCase):
'''Test History.fetch with wrapped tk.Text.
'''
@@ -87,7 +83,7 @@ class FetchTest(unittest.TestCase):
cls.root.destroy()
del cls.root
- def fetch_test(self, reverse, line, prefix, index, *, bell=False):
+ def fetch_test(self, reverse, line, prefix, index, bell=False):
# Perform one fetch as invoked by Alt-N or Alt-P
# Test the result. The line test is the most important.
# The last two are diagnostic of fetch internals.
diff --git a/Lib/idlelib/idle_test/test_run.py b/Lib/idlelib/idle_test/test_io.py
index 9995dbe..ee017bb 100644
--- a/Lib/idlelib/idle_test/test_run.py
+++ b/Lib/idlelib/idle_test/test_io.py
@@ -1,44 +1,10 @@
-"Test run, coverage 42%."
-
-from idlelib import run
import unittest
-from unittest import mock
-from test.support import captured_stderr
-
import io
-import sys
-
-
-class RunTest(unittest.TestCase):
-
- def test_print_exception_unhashable(self):
- class UnhashableException(Exception):
- def __eq__(self, other):
- return True
-
- ex1 = UnhashableException('ex1')
- ex2 = UnhashableException('ex2')
- try:
- raise ex2 from ex1
- except UnhashableException:
- try:
- raise ex1
- except UnhashableException:
- with captured_stderr() as output:
- with mock.patch.object(run,
- 'cleanup_traceback') as ct:
- ct.side_effect = lambda t, e: t
- run.print_exception()
+from idlelib.PyShell import PseudoInputFile, PseudoOutputFile
+from test import test_support as support
- tb = output.getvalue().strip().splitlines()
- self.assertEqual(11, len(tb))
- self.assertIn('UnhashableException: ex2', tb[3])
- self.assertIn('UnhashableException: ex1', tb[10])
-
-# StdioFile tests.
-
-class S(str):
+class Base(object):
def __str__(self):
return '%s:str' % type(self).__name__
def __unicode__(self):
@@ -52,30 +18,153 @@ class S(str):
def __getslice__(self, *args):
return '%s:slice' % type(self).__name__
+class S(Base, str):
+ pass
+
+class U(Base, unicode):
+ pass
+
+class BA(Base, bytearray):
+ pass
class MockShell:
def __init__(self):
self.reset()
+
def write(self, *args):
self.written.append(args)
+
def readline(self):
return self.lines.pop()
+
def close(self):
pass
+
def reset(self):
self.written = []
+
def push(self, lines):
self.lines = list(lines)[::-1]
-class StdInputFilesTest(unittest.TestCase):
+class PseudeOutputFilesTest(unittest.TestCase):
+ def test_misc(self):
+ shell = MockShell()
+ f = PseudoOutputFile(shell, 'stdout', 'utf-8')
+ self.assertIsInstance(f, io.TextIOBase)
+ self.assertEqual(f.encoding, 'utf-8')
+ self.assertIsNone(f.errors)
+ self.assertIsNone(f.newlines)
+ self.assertEqual(f.name, '<stdout>')
+ self.assertFalse(f.closed)
+ self.assertTrue(f.isatty())
+ self.assertFalse(f.readable())
+ self.assertTrue(f.writable())
+ self.assertFalse(f.seekable())
+
+ def test_unsupported(self):
+ shell = MockShell()
+ f = PseudoOutputFile(shell, 'stdout', 'utf-8')
+ self.assertRaises(IOError, f.fileno)
+ self.assertRaises(IOError, f.tell)
+ self.assertRaises(IOError, f.seek, 0)
+ self.assertRaises(IOError, f.read, 0)
+ self.assertRaises(IOError, f.readline, 0)
+
+ def test_write(self):
+ shell = MockShell()
+ f = PseudoOutputFile(shell, 'stdout', 'utf-8')
+ f.write('test')
+ self.assertEqual(shell.written, [('test', 'stdout')])
+ shell.reset()
+ f.write('t\xe8st')
+ self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
+ shell.reset()
+ f.write(u't\xe8st')
+ self.assertEqual(shell.written, [(u't\xe8st', 'stdout')])
+ shell.reset()
+
+ f.write(S('t\xe8st'))
+ self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
+ self.assertEqual(type(shell.written[0][0]), str)
+ shell.reset()
+ f.write(BA('t\xe8st'))
+ self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
+ self.assertEqual(type(shell.written[0][0]), str)
+ shell.reset()
+ f.write(U(u't\xe8st'))
+ self.assertEqual(shell.written, [(u't\xe8st', 'stdout')])
+ self.assertEqual(type(shell.written[0][0]), unicode)
+ shell.reset()
+
+ self.assertRaises(TypeError, f.write)
+ self.assertEqual(shell.written, [])
+ self.assertRaises(TypeError, f.write, 123)
+ self.assertEqual(shell.written, [])
+ self.assertRaises(TypeError, f.write, 'test', 'spam')
+ self.assertEqual(shell.written, [])
+
+ def test_writelines(self):
+ shell = MockShell()
+ f = PseudoOutputFile(shell, 'stdout', 'utf-8')
+ f.writelines([])
+ self.assertEqual(shell.written, [])
+ shell.reset()
+ f.writelines(['one\n', 'two'])
+ self.assertEqual(shell.written,
+ [('one\n', 'stdout'), ('two', 'stdout')])
+ shell.reset()
+ f.writelines(['on\xe8\n', 'tw\xf2'])
+ self.assertEqual(shell.written,
+ [('on\xe8\n', 'stdout'), ('tw\xf2', 'stdout')])
+ shell.reset()
+ f.writelines([u'on\xe8\n', u'tw\xf2'])
+ self.assertEqual(shell.written,
+ [(u'on\xe8\n', 'stdout'), (u'tw\xf2', 'stdout')])
+ shell.reset()
+
+ f.writelines([S('t\xe8st')])
+ self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
+ self.assertEqual(type(shell.written[0][0]), str)
+ shell.reset()
+ f.writelines([BA('t\xe8st')])
+ self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
+ self.assertEqual(type(shell.written[0][0]), str)
+ shell.reset()
+ f.writelines([U(u't\xe8st')])
+ self.assertEqual(shell.written, [(u't\xe8st', 'stdout')])
+ self.assertEqual(type(shell.written[0][0]), unicode)
+ shell.reset()
+
+ self.assertRaises(TypeError, f.writelines)
+ self.assertEqual(shell.written, [])
+ self.assertRaises(TypeError, f.writelines, 123)
+ self.assertEqual(shell.written, [])
+ self.assertRaises(TypeError, f.writelines, [123])
+ self.assertEqual(shell.written, [])
+ self.assertRaises(TypeError, f.writelines, [], [])
+ self.assertEqual(shell.written, [])
+
+ def test_close(self):
+ shell = MockShell()
+ f = PseudoOutputFile(shell, 'stdout', 'utf-8')
+ self.assertFalse(f.closed)
+ f.write('test')
+ f.close()
+ self.assertTrue(f.closed)
+ self.assertRaises(ValueError, f.write, 'x')
+ self.assertEqual(shell.written, [('test', 'stdout')])
+ f.close()
+ self.assertRaises(TypeError, f.close, 1)
+
+class PseudeInputFilesTest(unittest.TestCase):
def test_misc(self):
shell = MockShell()
- f = run.StdInputFile(shell, 'stdin')
+ f = PseudoInputFile(shell, 'stdin', 'utf-8')
self.assertIsInstance(f, io.TextIOBase)
self.assertEqual(f.encoding, 'utf-8')
- self.assertEqual(f.errors, 'strict')
+ self.assertIsNone(f.errors)
self.assertIsNone(f.newlines)
self.assertEqual(f.name, '<stdin>')
self.assertFalse(f.closed)
@@ -86,16 +175,16 @@ class StdInputFilesTest(unittest.TestCase):
def test_unsupported(self):
shell = MockShell()
- f = run.StdInputFile(shell, 'stdin')
- self.assertRaises(OSError, f.fileno)
- self.assertRaises(OSError, f.tell)
- self.assertRaises(OSError, f.seek, 0)
- self.assertRaises(OSError, f.write, 'x')
- self.assertRaises(OSError, f.writelines, ['x'])
+ f = PseudoInputFile(shell, 'stdin', 'utf-8')
+ self.assertRaises(IOError, f.fileno)
+ self.assertRaises(IOError, f.tell)
+ self.assertRaises(IOError, f.seek, 0)
+ self.assertRaises(IOError, f.write, 'x')
+ self.assertRaises(IOError, f.writelines, ['x'])
def test_read(self):
shell = MockShell()
- f = run.StdInputFile(shell, 'stdin')
+ f = PseudoInputFile(shell, 'stdin', 'utf-8')
shell.push(['one\n', 'two\n', ''])
self.assertEqual(f.read(), 'one\ntwo\n')
shell.push(['one\n', 'two\n', ''])
@@ -115,7 +204,7 @@ class StdInputFilesTest(unittest.TestCase):
def test_readline(self):
shell = MockShell()
- f = run.StdInputFile(shell, 'stdin')
+ f = PseudoInputFile(shell, 'stdin', 'utf-8')
shell.push(['one\n', 'two\n', 'three\n', 'four\n'])
self.assertEqual(f.readline(), 'one\n')
self.assertEqual(f.readline(-1), 'two\n')
@@ -140,7 +229,7 @@ class StdInputFilesTest(unittest.TestCase):
def test_readlines(self):
shell = MockShell()
- f = run.StdInputFile(shell, 'stdin')
+ f = PseudoInputFile(shell, 'stdin', 'utf-8')
shell.push(['one\n', 'two\n', ''])
self.assertEqual(f.readlines(), ['one\n', 'two\n'])
shell.push(['one\n', 'two\n', ''])
@@ -161,7 +250,7 @@ class StdInputFilesTest(unittest.TestCase):
def test_close(self):
shell = MockShell()
- f = run.StdInputFile(shell, 'stdin')
+ f = PseudoInputFile(shell, 'stdin', 'utf-8')
shell.push(['one\n', 'two\n', ''])
self.assertFalse(f.closed)
self.assertEqual(f.readline(), 'one\n')
@@ -171,155 +260,8 @@ class StdInputFilesTest(unittest.TestCase):
self.assertRaises(TypeError, f.close, 1)
-class StdOutputFilesTest(unittest.TestCase):
-
- def test_misc(self):
- shell = MockShell()
- f = run.StdOutputFile(shell, 'stdout')
- self.assertIsInstance(f, io.TextIOBase)
- self.assertEqual(f.encoding, 'utf-8')
- self.assertEqual(f.errors, 'strict')
- self.assertIsNone(f.newlines)
- self.assertEqual(f.name, '<stdout>')
- self.assertFalse(f.closed)
- self.assertTrue(f.isatty())
- self.assertFalse(f.readable())
- self.assertTrue(f.writable())
- self.assertFalse(f.seekable())
-
- def test_unsupported(self):
- shell = MockShell()
- f = run.StdOutputFile(shell, 'stdout')
- self.assertRaises(OSError, f.fileno)
- self.assertRaises(OSError, f.tell)
- self.assertRaises(OSError, f.seek, 0)
- self.assertRaises(OSError, f.read, 0)
- self.assertRaises(OSError, f.readline, 0)
-
- def test_write(self):
- shell = MockShell()
- f = run.StdOutputFile(shell, 'stdout')
- f.write('test')
- self.assertEqual(shell.written, [('test', 'stdout')])
- shell.reset()
- f.write('t\xe8\u015b\U0001d599')
- self.assertEqual(shell.written, [('t\xe8\u015b\U0001d599', 'stdout')])
- shell.reset()
-
- f.write(S('t\xe8\u015b\U0001d599'))
- self.assertEqual(shell.written, [('t\xe8\u015b\U0001d599', 'stdout')])
- self.assertEqual(type(shell.written[0][0]), str)
- shell.reset()
-
- self.assertRaises(TypeError, f.write)
- self.assertEqual(shell.written, [])
- self.assertRaises(TypeError, f.write, b'test')
- self.assertRaises(TypeError, f.write, 123)
- self.assertEqual(shell.written, [])
- self.assertRaises(TypeError, f.write, 'test', 'spam')
- self.assertEqual(shell.written, [])
-
- def test_write_stderr_nonencodable(self):
- shell = MockShell()
- f = run.StdOutputFile(shell, 'stderr', 'iso-8859-15', 'backslashreplace')
- f.write('t\xe8\u015b\U0001d599\xa4')
- self.assertEqual(shell.written, [('t\xe8\\u015b\\U0001d599\\xa4', 'stderr')])
- shell.reset()
-
- f.write(S('t\xe8\u015b\U0001d599\xa4'))
- self.assertEqual(shell.written, [('t\xe8\\u015b\\U0001d599\\xa4', 'stderr')])
- self.assertEqual(type(shell.written[0][0]), str)
- shell.reset()
-
- self.assertRaises(TypeError, f.write)
- self.assertEqual(shell.written, [])
- self.assertRaises(TypeError, f.write, b'test')
- self.assertRaises(TypeError, f.write, 123)
- self.assertEqual(shell.written, [])
- self.assertRaises(TypeError, f.write, 'test', 'spam')
- self.assertEqual(shell.written, [])
-
- def test_writelines(self):
- shell = MockShell()
- f = run.StdOutputFile(shell, 'stdout')
- f.writelines([])
- self.assertEqual(shell.written, [])
- shell.reset()
- f.writelines(['one\n', 'two'])
- self.assertEqual(shell.written,
- [('one\n', 'stdout'), ('two', 'stdout')])
- shell.reset()
- f.writelines(['on\xe8\n', 'tw\xf2'])
- self.assertEqual(shell.written,
- [('on\xe8\n', 'stdout'), ('tw\xf2', 'stdout')])
- shell.reset()
-
- f.writelines([S('t\xe8st')])
- self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
- self.assertEqual(type(shell.written[0][0]), str)
- shell.reset()
-
- self.assertRaises(TypeError, f.writelines)
- self.assertEqual(shell.written, [])
- self.assertRaises(TypeError, f.writelines, 123)
- self.assertEqual(shell.written, [])
- self.assertRaises(TypeError, f.writelines, [b'test'])
- self.assertRaises(TypeError, f.writelines, [123])
- self.assertEqual(shell.written, [])
- self.assertRaises(TypeError, f.writelines, [], [])
- self.assertEqual(shell.written, [])
-
- def test_close(self):
- shell = MockShell()
- f = run.StdOutputFile(shell, 'stdout')
- self.assertFalse(f.closed)
- f.write('test')
- f.close()
- self.assertTrue(f.closed)
- self.assertRaises(ValueError, f.write, 'x')
- self.assertEqual(shell.written, [('test', 'stdout')])
- f.close()
- self.assertRaises(TypeError, f.close, 1)
-
-
-class TestSysRecursionLimitWrappers(unittest.TestCase):
-
- def test_bad_setrecursionlimit_calls(self):
- run.install_recursionlimit_wrappers()
- self.addCleanup(run.uninstall_recursionlimit_wrappers)
- f = sys.setrecursionlimit
- self.assertRaises(TypeError, f, limit=100)
- self.assertRaises(TypeError, f, 100, 1000)
- self.assertRaises(ValueError, f, 0)
-
- def test_roundtrip(self):
- run.install_recursionlimit_wrappers()
- self.addCleanup(run.uninstall_recursionlimit_wrappers)
-
- # check that setting the recursion limit works
- orig_reclimit = sys.getrecursionlimit()
- self.addCleanup(sys.setrecursionlimit, orig_reclimit)
- sys.setrecursionlimit(orig_reclimit + 3)
-
- # check that the new limit is returned by sys.getrecursionlimit()
- new_reclimit = sys.getrecursionlimit()
- self.assertEqual(new_reclimit, orig_reclimit + 3)
-
- def test_default_recursion_limit_preserved(self):
- orig_reclimit = sys.getrecursionlimit()
- run.install_recursionlimit_wrappers()
- self.addCleanup(run.uninstall_recursionlimit_wrappers)
- new_reclimit = sys.getrecursionlimit()
- self.assertEqual(new_reclimit, orig_reclimit)
-
- def test_fixdoc(self):
- def func(): "docstring"
- run.fixdoc(func, "more")
- self.assertEqual(func.__doc__, "docstring\n\nmore")
- func.__doc__ = None
- run.fixdoc(func, "more")
- self.assertEqual(func.__doc__, "more")
-
+def test_main():
+ support.run_unittest(PseudeOutputFilesTest, PseudeInputFilesTest)
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ test_main()
diff --git a/Lib/idlelib/idle_test/test_iomenu.py b/Lib/idlelib/idle_test/test_iomenu.py
deleted file mode 100644
index 99f4048..0000000
--- a/Lib/idlelib/idle_test/test_iomenu.py
+++ /dev/null
@@ -1,49 +0,0 @@
-"Test , coverage 17%."
-
-from idlelib import iomenu
-import unittest
-from test.support import requires
-from tkinter import Tk
-from idlelib.editor import EditorWindow
-
-
-class IOBindingTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.editwin = EditorWindow(root=cls.root)
- cls.io = iomenu.IOBinding(cls.editwin)
-
- @classmethod
- def tearDownClass(cls):
- cls.io.close()
- cls.editwin._close()
- del cls.editwin
- cls.root.update_idletasks()
- for id in cls.root.tk.call('after', 'info'):
- cls.root.after_cancel(id) # Need for EditorWindow.
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- self.assertIs(self.io.editwin, self.editwin)
-
- def test_fixnewlines_end(self):
- eq = self.assertEqual
- io = self.io
- fix = io.fixnewlines
- text = io.editwin.text
- self.editwin.interp = None
- eq(fix(), '')
- del self.editwin.interp
- text.insert(1.0, 'a')
- eq(fix(), 'a'+io.eol_convention)
- eq(text.get('1.0', 'end-1c'), 'a\n')
- eq(fix(), 'a'+io.eol_convention)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_macosx.py b/Lib/idlelib/idle_test/test_macosx.py
deleted file mode 100644
index b6bd922..0000000
--- a/Lib/idlelib/idle_test/test_macosx.py
+++ /dev/null
@@ -1,104 +0,0 @@
-"Test macosx, coverage 45% on Windows."
-
-from idlelib import macosx
-import unittest
-from test.support import requires
-import tkinter as tk
-import unittest.mock as mock
-from idlelib.filelist import FileList
-
-mactypes = {'carbon', 'cocoa', 'xquartz'}
-nontypes = {'other'}
-alltypes = mactypes | nontypes
-
-
-class InitTktypeTest(unittest.TestCase):
- "Test _init_tk_type."
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = tk.Tk()
- cls.root.withdraw()
- cls.orig_platform = macosx.platform
-
- @classmethod
- def tearDownClass(cls):
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
- macosx.platform = cls.orig_platform
-
- def test_init_sets_tktype(self):
- "Test that _init_tk_type sets _tk_type according to platform."
- for platform, types in ('darwin', alltypes), ('other', nontypes):
- with self.subTest(platform=platform):
- macosx.platform = platform
- macosx._tk_type == None
- macosx._init_tk_type()
- self.assertIn(macosx._tk_type, types)
-
-
-class IsTypeTkTest(unittest.TestCase):
- "Test each of the four isTypeTk predecates."
- isfuncs = ((macosx.isAquaTk, ('carbon', 'cocoa')),
- (macosx.isCarbonTk, ('carbon')),
- (macosx.isCocoaTk, ('cocoa')),
- (macosx.isXQuartz, ('xquartz')),
- )
-
- @mock.patch('idlelib.macosx._init_tk_type')
- def test_is_calls_init(self, mockinit):
- "Test that each isTypeTk calls _init_tk_type when _tk_type is None."
- macosx._tk_type = None
- for func, whentrue in self.isfuncs:
- with self.subTest(func=func):
- func()
- self.assertTrue(mockinit.called)
- mockinit.reset_mock()
-
- def test_isfuncs(self):
- "Test that each isTypeTk return correct bool."
- for func, whentrue in self.isfuncs:
- for tktype in alltypes:
- with self.subTest(func=func, whentrue=whentrue, tktype=tktype):
- macosx._tk_type = tktype
- (self.assertTrue if tktype in whentrue else self.assertFalse)\
- (func())
-
-
-class SetupTest(unittest.TestCase):
- "Test setupApp."
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = tk.Tk()
- cls.root.withdraw()
- def cmd(tkpath, func):
- assert isinstance(tkpath, str)
- assert isinstance(func, type(cmd))
- cls.root.createcommand = cmd
-
- @classmethod
- def tearDownClass(cls):
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- @mock.patch('idlelib.macosx.overrideRootMenu') #27312
- def test_setupapp(self, overrideRootMenu):
- "Call setupApp with each possible graphics type."
- root = self.root
- flist = FileList(root)
- for tktype in alltypes:
- with self.subTest(tktype=tktype):
- macosx._tk_type = tktype
- macosx.setupApp(root, flist)
- if tktype in ('carbon', 'cocoa'):
- self.assertTrue(overrideRootMenu.called)
- overrideRootMenu.reset_mock()
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_mainmenu.py b/Lib/idlelib/idle_test/test_mainmenu.py
deleted file mode 100644
index 7ec0368..0000000
--- a/Lib/idlelib/idle_test/test_mainmenu.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"Test mainmenu, coverage 100%."
-# Reported as 88%; mocking turtledemo absence would have no point.
-
-from idlelib import mainmenu
-import unittest
-
-
-class MainMenuTest(unittest.TestCase):
-
- def test_menudefs(self):
- actual = [item[0] for item in mainmenu.menudefs]
- expect = ['file', 'edit', 'format', 'run', 'shell',
- 'debug', 'options', 'window', 'help']
- self.assertEqual(actual, expect)
-
- def test_default_keydefs(self):
- self.assertGreaterEqual(len(mainmenu.default_keydefs), 50)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_multicall.py b/Lib/idlelib/idle_test/test_multicall.py
deleted file mode 100644
index ba582bb..0000000
--- a/Lib/idlelib/idle_test/test_multicall.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"Test multicall, coverage 33%."
-
-from idlelib import multicall
-import unittest
-from test.support import requires
-from tkinter import Tk, Text
-
-
-class MultiCallTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.mc = multicall.MultiCallCreator(Text)
-
- @classmethod
- def tearDownClass(cls):
- del cls.mc
- cls.root.update_idletasks()
-## for id in cls.root.tk.call('after', 'info'):
-## cls.root.after_cancel(id) # Need for EditorWindow.
- cls.root.destroy()
- del cls.root
-
- def test_creator(self):
- mc = self.mc
- self.assertIs(multicall._multicall_dict[Text], mc)
- self.assertTrue(issubclass(mc, Text))
- mc2 = multicall.MultiCallCreator(Text)
- self.assertIs(mc, mc2)
-
- def test_init(self):
- mctext = self.mc(self.root)
- self.assertIsInstance(mctext._MultiCall__binders, list)
-
- def test_yview(self):
- # Added for tree.wheel_event
- # (it depends on yview to not be overriden)
- mc = self.mc
- self.assertIs(mc.yview, Text.yview)
- mctext = self.mc(self.root)
- self.assertIs(mctext.yview.__func__, Text.yview)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_outwin.py b/Lib/idlelib/idle_test/test_outwin.py
deleted file mode 100644
index cd099ec..0000000
--- a/Lib/idlelib/idle_test/test_outwin.py
+++ /dev/null
@@ -1,171 +0,0 @@
-"Test outwin, coverage 76%."
-
-from idlelib import outwin
-import unittest
-from test.support import requires
-from tkinter import Tk, Text
-from idlelib.idle_test.mock_tk import Mbox_func
-from idlelib.idle_test.mock_idle import Func
-from unittest import mock
-
-
-class OutputWindowTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- root = cls.root = Tk()
- root.withdraw()
- w = cls.window = outwin.OutputWindow(None, None, None, root)
- cls.text = w.text = Text(root)
-
- @classmethod
- def tearDownClass(cls):
- cls.window.close()
- del cls.text, cls.window
- cls.root.destroy()
- del cls.root
-
- def setUp(self):
- self.text.delete('1.0', 'end')
-
- def test_ispythonsource(self):
- # OutputWindow overrides ispythonsource to always return False.
- w = self.window
- self.assertFalse(w.ispythonsource('test.txt'))
- self.assertFalse(w.ispythonsource(__file__))
-
- def test_window_title(self):
- self.assertEqual(self.window.top.title(), 'Output')
-
- def test_maybesave(self):
- w = self.window
- eq = self.assertEqual
- w.get_saved = Func()
-
- w.get_saved.result = False
- eq(w.maybesave(), 'no')
- eq(w.get_saved.called, 1)
-
- w.get_saved.result = True
- eq(w.maybesave(), 'yes')
- eq(w.get_saved.called, 2)
- del w.get_saved
-
- def test_write(self):
- eq = self.assertEqual
- delete = self.text.delete
- get = self.text.get
- write = self.window.write
-
- # Test bytes.
- b = b'Test bytes.'
- eq(write(b), len(b))
- eq(get('1.0', '1.end'), b.decode())
-
- # No new line - insert stays on same line.
- delete('1.0', 'end')
- test_text = 'test text'
- eq(write(test_text), len(test_text))
- eq(get('1.0', '1.end'), 'test text')
- eq(get('insert linestart', 'insert lineend'), 'test text')
-
- # New line - insert moves to next line.
- delete('1.0', 'end')
- test_text = 'test text\n'
- eq(write(test_text), len(test_text))
- eq(get('1.0', '1.end'), 'test text')
- eq(get('insert linestart', 'insert lineend'), '')
-
- # Text after new line is tagged for second line of Text widget.
- delete('1.0', 'end')
- test_text = 'test text\nLine 2'
- eq(write(test_text), len(test_text))
- eq(get('1.0', '1.end'), 'test text')
- eq(get('2.0', '2.end'), 'Line 2')
- eq(get('insert linestart', 'insert lineend'), 'Line 2')
-
- # Test tags.
- delete('1.0', 'end')
- test_text = 'test text\n'
- test_text2 = 'Line 2\n'
- eq(write(test_text, tags='mytag'), len(test_text))
- eq(write(test_text2, tags='secondtag'), len(test_text2))
- eq(get('mytag.first', 'mytag.last'), test_text)
- eq(get('secondtag.first', 'secondtag.last'), test_text2)
- eq(get('1.0', '1.end'), test_text.rstrip('\n'))
- eq(get('2.0', '2.end'), test_text2.rstrip('\n'))
-
- def test_writelines(self):
- eq = self.assertEqual
- get = self.text.get
- writelines = self.window.writelines
-
- writelines(('Line 1\n', 'Line 2\n', 'Line 3\n'))
- eq(get('1.0', '1.end'), 'Line 1')
- eq(get('2.0', '2.end'), 'Line 2')
- eq(get('3.0', '3.end'), 'Line 3')
- eq(get('insert linestart', 'insert lineend'), '')
-
- def test_goto_file_line(self):
- eq = self.assertEqual
- w = self.window
- text = self.text
-
- w.flist = mock.Mock()
- gfl = w.flist.gotofileline = Func()
- showerror = w.showerror = Mbox_func()
-
- # No file/line number.
- w.write('Not a file line')
- self.assertIsNone(w.goto_file_line())
- eq(gfl.called, 0)
- eq(showerror.title, 'No special line')
-
- # Current file/line number.
- w.write(f'{str(__file__)}: 42: spam\n')
- w.write(f'{str(__file__)}: 21: spam')
- self.assertIsNone(w.goto_file_line())
- eq(gfl.args, (str(__file__), 21))
-
- # Previous line has file/line number.
- text.delete('1.0', 'end')
- w.write(f'{str(__file__)}: 42: spam\n')
- w.write('Not a file line')
- self.assertIsNone(w.goto_file_line())
- eq(gfl.args, (str(__file__), 42))
-
- del w.flist.gotofileline, w.showerror
-
-
-class ModuleFunctionTest(unittest.TestCase):
-
- @classmethod
- def setUp(cls):
- outwin.file_line_progs = None
-
- def test_compile_progs(self):
- outwin.compile_progs()
- for pat, regex in zip(outwin.file_line_pats, outwin.file_line_progs):
- self.assertEqual(regex.pattern, pat)
-
- @mock.patch('builtins.open')
- def test_file_line_helper(self, mock_open):
- flh = outwin.file_line_helper
- test_lines = (
- (r'foo file "testfile1", line 42, bar', ('testfile1', 42)),
- (r'foo testfile2(21) bar', ('testfile2', 21)),
- (r' testfile3 : 42: foo bar\n', (' testfile3 ', 42)),
- (r'foo testfile4.py :1: ', ('foo testfile4.py ', 1)),
- ('testfile5: \u19D4\u19D2: ', ('testfile5', 42)),
- (r'testfile6: 42', None), # only one `:`
- (r'testfile7 42 text', None) # no separators
- )
- for line, expected_output in test_lines:
- self.assertEqual(flh(line), expected_output)
- if expected_output:
- mock_open.assert_called_with(expected_output[0], 'r')
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_parenmatch.py b/Lib/idlelib/idle_test/test_parenmatch.py
index 4a41d84..1621981 100644
--- a/Lib/idlelib/idle_test/test_parenmatch.py
+++ b/Lib/idlelib/idle_test/test_parenmatch.py
@@ -1,31 +1,39 @@
-"""Test parenmatch, coverage 91%.
-
-This must currently be a gui test because ParenMatch methods use
-several text methods not defined on idlelib.idle_test.mock_tk.Text.
-"""
-from idlelib.parenmatch import ParenMatch
-from test.support import requires
-requires('gui')
+"""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.
import unittest
-from unittest.mock import Mock
-from tkinter import Tk, Text
+from test.test_support import requires
+from Tkinter import Tk, Text
+from idlelib.ParenMatch import ParenMatch
+
+class Mock: # 2.7 does not have unittest.mock
+ def __init__(self, *args, **kwargs):
+ self.called = False
+
+ def __call__(self, *args, **kwargs):
+ self.called = True
+ def reset_mock(self, *args, **kwargs):
+ self.called = False
+
+ def after(self, *args, **kwargs):
+ pass
class DummyEditwin:
def __init__(self, text):
self.text = text
self.indentwidth = 8
self.tabwidth = 8
- self.prompt_last_line = '>>>' # Currently not used by parenmatch.
+ self.context_use_ps1 = True
class ParenMatchTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
+ requires('gui')
cls.root = Tk()
- cls.root.withdraw()
cls.text = Text(cls.root)
cls.editwin = DummyEditwin(cls.text)
cls.editwin.text_frame = Mock()
@@ -33,51 +41,52 @@ class ParenMatchTest(unittest.TestCase):
@classmethod
def tearDownClass(cls):
del cls.text, cls.editwin
- cls.root.update_idletasks()
cls.root.destroy()
del cls.root
def tearDown(self):
self.text.delete('1.0', 'end')
- def get_parenmatch(self):
+ def test_paren_expression(self):
+ """
+ Test ParenMatch with 'expression' style.
+ """
+ text = self.text
pm = ParenMatch(self.editwin)
- pm.bell = lambda: None
- return pm
+ pm.set_style('expression')
+
+ text.insert('insert', 'def foobar(a, b')
+ pm.flash_paren_event('event')
+ self.assertIn('<<parenmatch-check-restore>>', text.event_info())
+ self.assertTupleEqual(text.tag_prevrange('paren', 'end'),
+ ('1.10', '1.15'))
+ text.insert('insert', ')')
+ pm.restore_event()
+ self.assertNotIn('<<parenmatch-check-restore>>', text.event_info())
+ self.assertEqual(text.tag_prevrange('paren', 'end'), ())
+
+ # paren_closed_event can only be tested as below
+ pm.paren_closed_event('event')
+ self.assertTupleEqual(text.tag_prevrange('paren', 'end'),
+ ('1.10', '1.16'))
- def test_paren_styles(self):
+ def test_paren_default(self):
"""
- Test ParenMatch with each style.
+ Test ParenMatch with 'default' style.
"""
text = self.text
- pm = self.get_parenmatch()
- for style, range1, range2 in (
- ('opener', ('1.10', '1.11'), ('1.10', '1.11')),
- ('default',('1.10', '1.11'),('1.10', '1.11')),
- ('parens', ('1.14', '1.15'), ('1.15', '1.16')),
- ('expression', ('1.10', '1.15'), ('1.10', '1.16'))):
- with self.subTest(style=style):
- text.delete('1.0', 'end')
- pm.STYLE = style
- text.insert('insert', 'def foobar(a, b')
-
- pm.flash_paren_event('event')
- self.assertIn('<<parenmatch-check-restore>>', text.event_info())
- if style == 'parens':
- self.assertTupleEqual(text.tag_nextrange('paren', '1.0'),
- ('1.10', '1.11'))
- self.assertTupleEqual(
- text.tag_prevrange('paren', 'end'), range1)
-
- text.insert('insert', ')')
- pm.restore_event()
- self.assertNotIn('<<parenmatch-check-restore>>',
- text.event_info())
- self.assertEqual(text.tag_prevrange('paren', 'end'), ())
-
- pm.paren_closed_event('event')
- self.assertTupleEqual(
- text.tag_prevrange('paren', 'end'), range2)
+ pm = ParenMatch(self.editwin)
+ pm.set_style('default')
+
+ text.insert('insert', 'def foobar(a, b')
+ pm.flash_paren_event('event')
+ self.assertIn('<<parenmatch-check-restore>>', text.event_info())
+ self.assertTupleEqual(text.tag_prevrange('paren', 'end'),
+ ('1.10', '1.11'))
+ text.insert('insert', ')')
+ pm.restore_event()
+ self.assertNotIn('<<parenmatch-check-restore>>', text.event_info())
+ self.assertEqual(text.tag_prevrange('paren', 'end'), ())
def test_paren_corner(self):
"""
@@ -86,20 +95,20 @@ class ParenMatchTest(unittest.TestCase):
These cases force conditional expression and alternate paths.
"""
text = self.text
- pm = self.get_parenmatch()
+ pm = ParenMatch(self.editwin)
text.insert('insert', '# this is a commen)')
- pm.paren_closed_event('event')
+ self.assertIsNone(pm.paren_closed_event('event'))
text.insert('insert', '\ndef')
- pm.flash_paren_event('event')
- pm.paren_closed_event('event')
+ self.assertIsNone(pm.flash_paren_event('event'))
+ self.assertIsNone(pm.paren_closed_event('event'))
text.insert('insert', ' a, *arg)')
- pm.paren_closed_event('event')
+ self.assertIsNone(pm.paren_closed_event('event'))
def test_handle_restore_timer(self):
- pm = self.get_parenmatch()
+ pm = ParenMatch(self.editwin)
pm.restore_event = Mock()
pm.handle_restore_timer(0)
self.assertTrue(pm.restore_event.called)
diff --git a/Lib/idlelib/idle_test/test_pathbrowser.py b/Lib/idlelib/idle_test/test_pathbrowser.py
index 13d8b9e..f028414 100644
--- a/Lib/idlelib/idle_test/test_pathbrowser.py
+++ b/Lib/idlelib/idle_test/test_pathbrowser.py
@@ -1,69 +1,14 @@
-"Test pathbrowser, coverage 95%."
-
-from idlelib import pathbrowser
import unittest
-from test.support import requires
-from tkinter import Tk
-
-import os.path
-import pyclbr # for _modules
-import sys # for sys.path
-
-from idlelib.idle_test.mock_idle import Func
-import idlelib # for __file__
-from idlelib import browser
-from idlelib.tree import TreeNode
-
+import os
+import sys
+import idlelib
+from idlelib import PathBrowser
class PathBrowserTest(unittest.TestCase):
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.pb = pathbrowser.PathBrowser(cls.root, _utest=True)
-
- @classmethod
- def tearDownClass(cls):
- cls.pb.close()
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root, cls.pb
-
- def test_init(self):
- pb = self.pb
- eq = self.assertEqual
- eq(pb.master, self.root)
- eq(pyclbr._modules, {})
- self.assertIsInstance(pb.node, TreeNode)
- self.assertIsNotNone(browser.file_open)
-
- def test_settitle(self):
- pb = self.pb
- self.assertEqual(pb.top.title(), 'Path Browser')
- self.assertEqual(pb.top.iconname(), 'Path Browser')
-
- def test_rootnode(self):
- pb = self.pb
- rn = pb.rootnode()
- self.assertIsInstance(rn, pathbrowser.PathBrowserTreeItem)
-
- def test_close(self):
- pb = self.pb
- pb.top.destroy = Func()
- pb.node.destroy = Func()
- pb.close()
- self.assertTrue(pb.top.destroy.called)
- self.assertTrue(pb.node.destroy.called)
- del pb.top.destroy, pb.node.destroy
-
-
-class DirBrowserTreeItemTest(unittest.TestCase):
-
def test_DirBrowserTreeItem(self):
# Issue16226 - make sure that getting a sublist works
- d = pathbrowser.DirBrowserTreeItem('')
+ d = PathBrowser.DirBrowserTreeItem('')
d.GetSubList()
self.assertEqual('', d.GetText())
@@ -71,16 +16,13 @@ class DirBrowserTreeItemTest(unittest.TestCase):
self.assertEqual(d.ispackagedir(dir), True)
self.assertEqual(d.ispackagedir(dir + '/Icons'), False)
-
-class PathBrowserTreeItemTest(unittest.TestCase):
-
def test_PathBrowserTreeItem(self):
- p = pathbrowser.PathBrowserTreeItem()
+ p = PathBrowser.PathBrowserTreeItem()
self.assertEqual(p.GetText(), 'sys.path')
sub = p.GetSubList()
self.assertEqual(len(sub), len(sys.path))
- self.assertEqual(type(sub[0]), pathbrowser.DirBrowserTreeItem)
-
+ # Following fails in 2.7 because old-style class
+ #self.assertEqual(type(sub[0]), PathBrowser.DirBrowserTreeItem)
if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
diff --git a/Lib/idlelib/idle_test/test_percolator.py b/Lib/idlelib/idle_test/test_percolator.py
deleted file mode 100644
index 17668cc..0000000
--- a/Lib/idlelib/idle_test/test_percolator.py
+++ /dev/null
@@ -1,118 +0,0 @@
-"Test percolator, coverage 100%."
-
-from idlelib.percolator import Percolator, Delegator
-import unittest
-from test.support import requires
-requires('gui')
-from tkinter import Text, Tk, END
-
-
-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_pyparse.py b/Lib/idlelib/idle_test/test_pyparse.py
deleted file mode 100644
index f7154e6..0000000
--- a/Lib/idlelib/idle_test/test_pyparse.py
+++ /dev/null
@@ -1,466 +0,0 @@
-"Test pyparse, coverage 96%."
-
-from idlelib import pyparse
-import unittest
-from collections import namedtuple
-
-
-class ParseMapTest(unittest.TestCase):
-
- def test_parsemap(self):
- keepwhite = {ord(c): ord(c) for c in ' \t\n\r'}
- mapping = pyparse.ParseMap(keepwhite)
- self.assertEqual(mapping[ord('\t')], ord('\t'))
- self.assertEqual(mapping[ord('a')], ord('x'))
- self.assertEqual(mapping[1000], ord('x'))
-
- def test_trans(self):
- # trans is the production instance of ParseMap, used in _study1
- parser = pyparse.Parser(4, 4)
- self.assertEqual('\t a([{b}])b"c\'d\n'.translate(pyparse.trans),
- 'xxx(((x)))x"x\'x\n')
-
-
-class PyParseTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.parser = pyparse.Parser(indentwidth=4, tabwidth=4)
-
- @classmethod
- def tearDownClass(cls):
- del cls.parser
-
- def test_init(self):
- self.assertEqual(self.parser.indentwidth, 4)
- self.assertEqual(self.parser.tabwidth, 4)
-
- def test_set_code(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
-
- # Not empty and doesn't end with newline.
- with self.assertRaises(AssertionError):
- setcode('a')
-
- tests = ('',
- 'a\n')
-
- for string in tests:
- with self.subTest(string=string):
- setcode(string)
- eq(p.code, string)
- eq(p.study_level, 0)
-
- def test_find_good_parse_start(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- start = p.find_good_parse_start
-
- # Split def across lines.
- setcode('"""This is a module docstring"""\n'
- 'class C():\n'
- ' def __init__(self, a,\n'
- ' b=True):\n'
- ' pass\n'
- )
-
- # No value sent for is_char_in_string().
- self.assertIsNone(start())
-
- # Make text look like a string. This returns pos as the start
- # position, but it's set to None.
- self.assertIsNone(start(is_char_in_string=lambda index: True))
-
- # Make all text look like it's not in a string. This means that it
- # found a good start position.
- eq(start(is_char_in_string=lambda index: False), 44)
-
- # If the beginning of the def line is not in a string, then it
- # returns that as the index.
- eq(start(is_char_in_string=lambda index: index > 44), 44)
- # If the beginning of the def line is in a string, then it
- # looks for a previous index.
- eq(start(is_char_in_string=lambda index: index >= 44), 33)
- # If everything before the 'def' is in a string, then returns None.
- # The non-continuation def line returns 44 (see below).
- eq(start(is_char_in_string=lambda index: index < 44), None)
-
- # Code without extra line break in def line - mostly returns the same
- # values.
- setcode('"""This is a module docstring"""\n'
- 'class C():\n'
- ' def __init__(self, a, b=True):\n'
- ' pass\n'
- )
- eq(start(is_char_in_string=lambda index: False), 44)
- eq(start(is_char_in_string=lambda index: index > 44), 44)
- eq(start(is_char_in_string=lambda index: index >= 44), 33)
- # When the def line isn't split, this returns which doesn't match the
- # split line test.
- eq(start(is_char_in_string=lambda index: index < 44), 44)
-
- def test_set_lo(self):
- code = (
- '"""This is a module docstring"""\n'
- 'class C():\n'
- ' def __init__(self, a,\n'
- ' b=True):\n'
- ' pass\n'
- )
- p = self.parser
- p.set_code(code)
-
- # Previous character is not a newline.
- with self.assertRaises(AssertionError):
- p.set_lo(5)
-
- # A value of 0 doesn't change self.code.
- p.set_lo(0)
- self.assertEqual(p.code, code)
-
- # An index that is preceded by a newline.
- p.set_lo(44)
- self.assertEqual(p.code, code[44:])
-
- def test_study1(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- study = p._study1
-
- (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5)
- TestInfo = namedtuple('TestInfo', ['string', 'goodlines',
- 'continuation'])
- tests = (
- TestInfo('', [0], NONE),
- # Docstrings.
- TestInfo('"""This is a complete docstring."""\n', [0, 1], NONE),
- TestInfo("'''This is a complete docstring.'''\n", [0, 1], NONE),
- TestInfo('"""This is a continued docstring.\n', [0, 1], FIRST),
- TestInfo("'''This is a continued docstring.\n", [0, 1], FIRST),
- TestInfo('"""Closing quote does not match."\n', [0, 1], FIRST),
- TestInfo('"""Bracket in docstring [\n', [0, 1], FIRST),
- TestInfo("'''Incomplete two line docstring.\n\n", [0, 2], NEXT),
- # Single-quoted strings.
- TestInfo('"This is a complete string."\n', [0, 1], NONE),
- TestInfo('"This is an incomplete string.\n', [0, 1], NONE),
- TestInfo("'This is more incomplete.\n\n", [0, 1, 2], NONE),
- # Comment (backslash does not continue comments).
- TestInfo('# Comment\\\n', [0, 1], NONE),
- # Brackets.
- TestInfo('("""Complete string in bracket"""\n', [0, 1], BRACKET),
- TestInfo('("""Open string in bracket\n', [0, 1], FIRST),
- TestInfo('a = (1 + 2) - 5 *\\\n', [0, 1], BACKSLASH), # No bracket.
- TestInfo('\n def function1(self, a,\n b):\n',
- [0, 1, 3], NONE),
- TestInfo('\n def function1(self, a,\\\n', [0, 1, 2], BRACKET),
- TestInfo('\n def function1(self, a,\n', [0, 1, 2], BRACKET),
- TestInfo('())\n', [0, 1], NONE), # Extra closer.
- TestInfo(')(\n', [0, 1], BRACKET), # Extra closer.
- # For the mismatched example, it doesn't look like continuation.
- TestInfo('{)(]\n', [0, 1], NONE), # Mismatched.
- )
-
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string) # resets study_level
- study()
- eq(p.study_level, 1)
- eq(p.goodlines, test.goodlines)
- eq(p.continuation, test.continuation)
-
- # Called again, just returns without reprocessing.
- self.assertIsNone(study())
-
- def test_get_continuation_type(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- gettype = p.get_continuation_type
-
- (NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5)
- TestInfo = namedtuple('TestInfo', ['string', 'continuation'])
- tests = (
- TestInfo('', NONE),
- TestInfo('"""This is a continuation docstring.\n', FIRST),
- TestInfo("'''This is a multiline-continued docstring.\n\n", NEXT),
- TestInfo('a = (1 + 2) - 5 *\\\n', BACKSLASH),
- TestInfo('\n def function1(self, a,\\\n', BRACKET)
- )
-
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string)
- eq(gettype(), test.continuation)
-
- def test_study2(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- study = p._study2
-
- TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch',
- 'openbracket', 'bracketing'])
- tests = (
- TestInfo('', 0, 0, '', None, ((0, 0),)),
- TestInfo("'''This is a multiline continuation docstring.\n\n",
- 0, 48, "'", None, ((0, 0), (0, 1), (48, 0))),
- TestInfo(' # Comment\\\n',
- 0, 12, '', None, ((0, 0), (1, 1), (12, 0))),
- # A comment without a space is a special case
- TestInfo(' #Comment\\\n',
- 0, 0, '', None, ((0, 0),)),
- # Backslash continuation.
- TestInfo('a = (1 + 2) - 5 *\\\n',
- 0, 19, '*', None, ((0, 0), (4, 1), (11, 0))),
- # Bracket continuation with close.
- TestInfo('\n def function1(self, a,\n b):\n',
- 1, 48, ':', None, ((1, 0), (17, 1), (46, 0))),
- # Bracket continuation with unneeded backslash.
- TestInfo('\n def function1(self, a,\\\n',
- 1, 28, ',', 17, ((1, 0), (17, 1))),
- # Bracket continuation.
- TestInfo('\n def function1(self, a,\n',
- 1, 27, ',', 17, ((1, 0), (17, 1))),
- # Bracket continuation with comment at end of line with text.
- TestInfo('\n def function1(self, a, # End of line comment.\n',
- 1, 51, ',', 17, ((1, 0), (17, 1), (28, 2), (51, 1))),
- # Multi-line statement with comment line in between code lines.
- TestInfo(' a = ["first item",\n # Comment line\n "next item",\n',
- 0, 55, ',', 6, ((0, 0), (6, 1), (7, 2), (19, 1),
- (23, 2), (38, 1), (42, 2), (53, 1))),
- TestInfo('())\n',
- 0, 4, ')', None, ((0, 0), (0, 1), (2, 0), (3, 0))),
- TestInfo(')(\n', 0, 3, '(', 1, ((0, 0), (1, 0), (1, 1))),
- # Wrong closers still decrement stack level.
- TestInfo('{)(]\n',
- 0, 5, ']', None, ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))),
- # Character after backslash.
- TestInfo(':\\a\n', 0, 4, '\\a', None, ((0, 0),)),
- TestInfo('\n', 0, 0, '', None, ((0, 0),)),
- )
-
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string)
- study()
- eq(p.study_level, 2)
- eq(p.stmt_start, test.start)
- eq(p.stmt_end, test.end)
- eq(p.lastch, test.lastch)
- eq(p.lastopenbracketpos, test.openbracket)
- eq(p.stmt_bracketing, test.bracketing)
-
- # Called again, just returns without reprocessing.
- self.assertIsNone(study())
-
- def test_get_num_lines_in_stmt(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- getlines = p.get_num_lines_in_stmt
-
- TestInfo = namedtuple('TestInfo', ['string', 'lines'])
- tests = (
- TestInfo('[x for x in a]\n', 1), # Closed on one line.
- TestInfo('[x\nfor x in a\n', 2), # Not closed.
- TestInfo('[x\\\nfor x in a\\\n', 2), # "", uneeded backslashes.
- TestInfo('[x\nfor x in a\n]\n', 3), # Closed on multi-line.
- TestInfo('\n"""Docstring comment L1"""\nL2\nL3\nL4\n', 1),
- TestInfo('\n"""Docstring comment L1\nL2"""\nL3\nL4\n', 1),
- TestInfo('\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n', 4),
- TestInfo('\n\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n"""\n', 5)
- )
-
- # Blank string doesn't have enough elements in goodlines.
- setcode('')
- with self.assertRaises(IndexError):
- getlines()
-
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string)
- eq(getlines(), test.lines)
-
- def test_compute_bracket_indent(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- indent = p.compute_bracket_indent
-
- TestInfo = namedtuple('TestInfo', ['string', 'spaces'])
- tests = (
- TestInfo('def function1(self, a,\n', 14),
- # Characters after bracket.
- TestInfo('\n def function1(self, a,\n', 18),
- TestInfo('\n\tdef function1(self, a,\n', 18),
- # No characters after bracket.
- TestInfo('\n def function1(\n', 8),
- TestInfo('\n\tdef function1(\n', 8),
- TestInfo('\n def function1( \n', 8), # Ignore extra spaces.
- TestInfo('[\n"first item",\n # Comment line\n "next item",\n', 0),
- TestInfo('[\n "first item",\n # Comment line\n "next item",\n', 2),
- TestInfo('["first item",\n # Comment line\n "next item",\n', 1),
- TestInfo('(\n', 4),
- TestInfo('(a\n', 1),
- )
-
- # Must be C_BRACKET continuation type.
- setcode('def function1(self, a, b):\n')
- with self.assertRaises(AssertionError):
- indent()
-
- for test in tests:
- setcode(test.string)
- eq(indent(), test.spaces)
-
- def test_compute_backslash_indent(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- indent = p.compute_backslash_indent
-
- # Must be C_BACKSLASH continuation type.
- errors = (('def function1(self, a, b\\\n'), # Bracket.
- (' """ (\\\n'), # Docstring.
- ('a = #\\\n'), # Inline comment.
- )
- for string in errors:
- with self.subTest(string=string):
- setcode(string)
- with self.assertRaises(AssertionError):
- indent()
-
- TestInfo = namedtuple('TestInfo', ('string', 'spaces'))
- tests = (TestInfo('a = (1 + 2) - 5 *\\\n', 4),
- TestInfo('a = 1 + 2 - 5 *\\\n', 4),
- TestInfo(' a = 1 + 2 - 5 *\\\n', 8),
- TestInfo(' a = "spam"\\\n', 6),
- TestInfo(' a = \\\n"a"\\\n', 4),
- TestInfo(' a = #\\\n"a"\\\n', 5),
- TestInfo('a == \\\n', 2),
- TestInfo('a != \\\n', 2),
- # Difference between containing = and those not.
- TestInfo('\\\n', 2),
- TestInfo(' \\\n', 6),
- TestInfo('\t\\\n', 6),
- TestInfo('a\\\n', 3),
- TestInfo('{}\\\n', 4),
- TestInfo('(1 + 2) - 5 *\\\n', 3),
- )
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string)
- eq(indent(), test.spaces)
-
- def test_get_base_indent_string(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- baseindent = p.get_base_indent_string
-
- TestInfo = namedtuple('TestInfo', ['string', 'indent'])
- tests = (TestInfo('', ''),
- TestInfo('def a():\n', ''),
- TestInfo('\tdef a():\n', '\t'),
- TestInfo(' def a():\n', ' '),
- TestInfo(' def a(\n', ' '),
- TestInfo('\t\n def a(\n', ' '),
- TestInfo('\t\n # Comment.\n', ' '),
- )
-
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string)
- eq(baseindent(), test.indent)
-
- def test_is_block_opener(self):
- yes = self.assertTrue
- no = self.assertFalse
- p = self.parser
- setcode = p.set_code
- opener = p.is_block_opener
-
- TestInfo = namedtuple('TestInfo', ['string', 'assert_'])
- tests = (
- TestInfo('def a():\n', yes),
- TestInfo('\n def function1(self, a,\n b):\n', yes),
- TestInfo(':\n', yes),
- TestInfo('a:\n', yes),
- TestInfo('):\n', yes),
- TestInfo('(:\n', yes),
- TestInfo('":\n', no),
- TestInfo('\n def function1(self, a,\n', no),
- TestInfo('def function1(self, a):\n pass\n', no),
- TestInfo('# A comment:\n', no),
- TestInfo('"""A docstring:\n', no),
- TestInfo('"""A docstring:\n', no),
- )
-
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string)
- test.assert_(opener())
-
- def test_is_block_closer(self):
- yes = self.assertTrue
- no = self.assertFalse
- p = self.parser
- setcode = p.set_code
- closer = p.is_block_closer
-
- TestInfo = namedtuple('TestInfo', ['string', 'assert_'])
- tests = (
- TestInfo('return\n', yes),
- TestInfo('\tbreak\n', yes),
- TestInfo(' continue\n', yes),
- TestInfo(' raise\n', yes),
- TestInfo('pass \n', yes),
- TestInfo('pass\t\n', yes),
- TestInfo('return #\n', yes),
- TestInfo('raised\n', no),
- TestInfo('returning\n', no),
- TestInfo('# return\n', no),
- TestInfo('"""break\n', no),
- TestInfo('"continue\n', no),
- TestInfo('def function1(self, a):\n pass\n', yes),
- )
-
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string)
- test.assert_(closer())
-
- def test_get_last_stmt_bracketing(self):
- eq = self.assertEqual
- p = self.parser
- setcode = p.set_code
- bracketing = p.get_last_stmt_bracketing
-
- TestInfo = namedtuple('TestInfo', ['string', 'bracket'])
- tests = (
- TestInfo('', ((0, 0),)),
- TestInfo('a\n', ((0, 0),)),
- TestInfo('()()\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))),
- TestInfo('(\n)()\n', ((0, 0), (0, 1), (3, 0), (3, 1), (5, 0))),
- TestInfo('()\n()\n', ((3, 0), (3, 1), (5, 0))),
- TestInfo('()(\n)\n', ((0, 0), (0, 1), (2, 0), (2, 1), (5, 0))),
- TestInfo('(())\n', ((0, 0), (0, 1), (1, 2), (3, 1), (4, 0))),
- TestInfo('(\n())\n', ((0, 0), (0, 1), (2, 2), (4, 1), (5, 0))),
- # Same as matched test.
- TestInfo('{)(]\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))),
- TestInfo('(((())\n',
- ((0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (5, 3), (6, 2))),
- )
-
- for test in tests:
- with self.subTest(string=test.string):
- setcode(test.string)
- eq(bracketing(), test.bracket)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_pyshell.py b/Lib/idlelib/idle_test/test_pyshell.py
deleted file mode 100644
index 4a09667..0000000
--- a/Lib/idlelib/idle_test/test_pyshell.py
+++ /dev/null
@@ -1,64 +0,0 @@
-"Test pyshell, coverage 12%."
-# Plus coverage of test_warning. Was 20% with test_openshell.
-
-from idlelib import pyshell
-import unittest
-from test.support import requires
-from tkinter import Tk
-
-
-class FunctionTest(unittest.TestCase):
- # Test stand-alone module level non-gui functions.
-
- def test_restart_line_wide(self):
- eq = self.assertEqual
- for file, mul, extra in (('', 22, ''), ('finame', 21, '=')):
- width = 60
- bar = mul * '='
- with self.subTest(file=file, bar=bar):
- file = file or 'Shell'
- line = pyshell.restart_line(width, file)
- eq(len(line), width)
- eq(line, f"{bar+extra} RESTART: {file} {bar}")
-
- def test_restart_line_narrow(self):
- expect, taglen = "= RESTART: Shell", 16
- for width in (taglen-1, taglen, taglen+1):
- with self.subTest(width=width):
- self.assertEqual(pyshell.restart_line(width, ''), expect)
- self.assertEqual(pyshell.restart_line(taglen+2, ''), expect+' =')
-
-
-class PyShellFileListTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- #cls.root.update_idletasks()
-## for id in cls.root.tk.call('after', 'info'):
-## cls.root.after_cancel(id) # Need for EditorWindow.
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- psfl = pyshell.PyShellFileList(self.root)
- self.assertEqual(psfl.EditorWindow, pyshell.PyShellEditorWindow)
- self.assertIsNone(psfl.pyshell)
-
-# The following sometimes causes 'invalid command name "109734456recolorize"'.
-# Uncommenting after_cancel above prevents this, but results in
-# TclError: bad window path name ".!listedtoplevel.!frame.text"
-# which is normally prevented by after_cancel.
-## def test_openshell(self):
-## pyshell.use_subprocess = False
-## ps = pyshell.PyShellFileList(self.root).open_shell()
-## self.assertIsInstance(ps, pyshell.PyShell)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_query.py b/Lib/idlelib/idle_test/test_query.py
deleted file mode 100644
index f957585..0000000
--- a/Lib/idlelib/idle_test/test_query.py
+++ /dev/null
@@ -1,405 +0,0 @@
-"""Test query, coverage 93%).
-
-Non-gui tests for Query, SectionName, ModuleName, and HelpSource use
-dummy versions that extract the non-gui methods and add other needed
-attributes. GUI tests create an instance of each class and simulate
-entries and button clicks. Subclass tests only target the new code in
-the subclass definition.
-
-The appearance of the widgets is checked by the Query and
-HelpSource htests. These are run by running query.py.
-"""
-from idlelib import query
-import unittest
-from test.support import requires
-from tkinter import Tk, END
-
-import sys
-from unittest import mock
-from idlelib.idle_test.mock_tk import Var
-
-
-# NON-GUI TESTS
-
-class QueryTest(unittest.TestCase):
- "Test Query base class."
-
- class Dummy_Query:
- # Test the following Query methods.
- entry_ok = query.Query.entry_ok
- ok = query.Query.ok
- cancel = query.Query.cancel
- # Add attributes and initialization needed for tests.
- def __init__(self, dummy_entry):
- self.entry = Var(value=dummy_entry)
- self.entry_error = {'text': ''}
- self.result = None
- self.destroyed = False
- def showerror(self, message):
- self.entry_error['text'] = message
- def destroy(self):
- self.destroyed = True
-
- def test_entry_ok_blank(self):
- dialog = self.Dummy_Query(' ')
- self.assertEqual(dialog.entry_ok(), None)
- self.assertEqual((dialog.result, dialog.destroyed), (None, False))
- self.assertIn('blank line', dialog.entry_error['text'])
-
- def test_entry_ok_good(self):
- dialog = self.Dummy_Query(' good ')
- Equal = self.assertEqual
- Equal(dialog.entry_ok(), 'good')
- Equal((dialog.result, dialog.destroyed), (None, False))
- Equal(dialog.entry_error['text'], '')
-
- def test_ok_blank(self):
- dialog = self.Dummy_Query('')
- dialog.entry.focus_set = mock.Mock()
- self.assertEqual(dialog.ok(), None)
- self.assertTrue(dialog.entry.focus_set.called)
- del dialog.entry.focus_set
- self.assertEqual((dialog.result, dialog.destroyed), (None, False))
-
- def test_ok_good(self):
- dialog = self.Dummy_Query('good')
- self.assertEqual(dialog.ok(), None)
- self.assertEqual((dialog.result, dialog.destroyed), ('good', True))
-
- def test_cancel(self):
- dialog = self.Dummy_Query('does not matter')
- self.assertEqual(dialog.cancel(), None)
- self.assertEqual((dialog.result, dialog.destroyed), (None, True))
-
-
-class SectionNameTest(unittest.TestCase):
- "Test SectionName subclass of Query."
-
- class Dummy_SectionName:
- entry_ok = query.SectionName.entry_ok # Function being tested.
- used_names = ['used']
- def __init__(self, dummy_entry):
- self.entry = Var(value=dummy_entry)
- self.entry_error = {'text': ''}
- def showerror(self, message):
- self.entry_error['text'] = message
-
- def test_blank_section_name(self):
- dialog = self.Dummy_SectionName(' ')
- self.assertEqual(dialog.entry_ok(), None)
- self.assertIn('no name', dialog.entry_error['text'])
-
- def test_used_section_name(self):
- dialog = self.Dummy_SectionName('used')
- self.assertEqual(dialog.entry_ok(), None)
- self.assertIn('use', dialog.entry_error['text'])
-
- def test_long_section_name(self):
- dialog = self.Dummy_SectionName('good'*8)
- self.assertEqual(dialog.entry_ok(), None)
- self.assertIn('longer than 30', dialog.entry_error['text'])
-
- def test_good_section_name(self):
- dialog = self.Dummy_SectionName(' good ')
- self.assertEqual(dialog.entry_ok(), 'good')
- self.assertEqual(dialog.entry_error['text'], '')
-
-
-class ModuleNameTest(unittest.TestCase):
- "Test ModuleName subclass of Query."
-
- class Dummy_ModuleName:
- entry_ok = query.ModuleName.entry_ok # Function being tested.
- text0 = ''
- def __init__(self, dummy_entry):
- self.entry = Var(value=dummy_entry)
- self.entry_error = {'text': ''}
- def showerror(self, message):
- self.entry_error['text'] = message
-
- def test_blank_module_name(self):
- dialog = self.Dummy_ModuleName(' ')
- self.assertEqual(dialog.entry_ok(), None)
- self.assertIn('no name', dialog.entry_error['text'])
-
- def test_bogus_module_name(self):
- dialog = self.Dummy_ModuleName('__name_xyz123_should_not_exist__')
- self.assertEqual(dialog.entry_ok(), None)
- self.assertIn('not found', dialog.entry_error['text'])
-
- def test_c_source_name(self):
- dialog = self.Dummy_ModuleName('itertools')
- self.assertEqual(dialog.entry_ok(), None)
- self.assertIn('source-based', dialog.entry_error['text'])
-
- def test_good_module_name(self):
- dialog = self.Dummy_ModuleName('idlelib')
- self.assertTrue(dialog.entry_ok().endswith('__init__.py'))
- self.assertEqual(dialog.entry_error['text'], '')
-
-
-# 3 HelpSource test classes each test one method.
-
-class HelpsourceBrowsefileTest(unittest.TestCase):
- "Test browse_file method of ModuleName subclass of Query."
-
- class Dummy_HelpSource:
- browse_file = query.HelpSource.browse_file
- pathvar = Var()
-
- def test_file_replaces_path(self):
- dialog = self.Dummy_HelpSource()
- # Path is widget entry, either '' or something.
- # Func return is file dialog return, either '' or something.
- # Func return should override widget entry.
- # We need all 4 combinations to test all (most) code paths.
- for path, func, result in (
- ('', lambda a,b,c:'', ''),
- ('', lambda a,b,c: __file__, __file__),
- ('htest', lambda a,b,c:'', 'htest'),
- ('htest', lambda a,b,c: __file__, __file__)):
- with self.subTest():
- dialog.pathvar.set(path)
- dialog.askfilename = func
- dialog.browse_file()
- self.assertEqual(dialog.pathvar.get(), result)
-
-
-class HelpsourcePathokTest(unittest.TestCase):
- "Test path_ok method of HelpSource subclass of Query."
-
- class Dummy_HelpSource:
- path_ok = query.HelpSource.path_ok
- def __init__(self, dummy_path):
- self.path = Var(value=dummy_path)
- self.path_error = {'text': ''}
- def showerror(self, message, widget=None):
- self.path_error['text'] = message
-
- orig_platform = query.platform # Set in test_path_ok_file.
- @classmethod
- def tearDownClass(cls):
- query.platform = cls.orig_platform
-
- def test_path_ok_blank(self):
- dialog = self.Dummy_HelpSource(' ')
- self.assertEqual(dialog.path_ok(), None)
- self.assertIn('no help file', dialog.path_error['text'])
-
- def test_path_ok_bad(self):
- dialog = self.Dummy_HelpSource(__file__ + 'bad-bad-bad')
- self.assertEqual(dialog.path_ok(), None)
- self.assertIn('not exist', dialog.path_error['text'])
-
- def test_path_ok_web(self):
- dialog = self.Dummy_HelpSource('')
- Equal = self.assertEqual
- for url in 'www.py.org', 'http://py.org':
- with self.subTest():
- dialog.path.set(url)
- self.assertEqual(dialog.path_ok(), url)
- self.assertEqual(dialog.path_error['text'], '')
-
- def test_path_ok_file(self):
- dialog = self.Dummy_HelpSource('')
- for platform, prefix in ('darwin', 'file://'), ('other', ''):
- with self.subTest():
- query.platform = platform
- dialog.path.set(__file__)
- self.assertEqual(dialog.path_ok(), prefix + __file__)
- self.assertEqual(dialog.path_error['text'], '')
-
-
-class HelpsourceEntryokTest(unittest.TestCase):
- "Test entry_ok method of HelpSource subclass of Query."
-
- class Dummy_HelpSource:
- entry_ok = query.HelpSource.entry_ok
- entry_error = {}
- path_error = {}
- def item_ok(self):
- return self.name
- def path_ok(self):
- return self.path
-
- def test_entry_ok_helpsource(self):
- dialog = self.Dummy_HelpSource()
- for name, path, result in ((None, None, None),
- (None, 'doc.txt', None),
- ('doc', None, None),
- ('doc', 'doc.txt', ('doc', 'doc.txt'))):
- with self.subTest():
- dialog.name, dialog.path = name, path
- self.assertEqual(dialog.entry_ok(), result)
-
-
-# 2 CustomRun test classes each test one method.
-
-class CustomRunCLIargsokTest(unittest.TestCase):
- "Test cli_ok method of the CustomRun subclass of Query."
-
- class Dummy_CustomRun:
- cli_args_ok = query.CustomRun.cli_args_ok
- def __init__(self, dummy_entry):
- self.entry = Var(value=dummy_entry)
- self.entry_error = {'text': ''}
- def showerror(self, message):
- self.entry_error['text'] = message
-
- def test_blank_args(self):
- dialog = self.Dummy_CustomRun(' ')
- self.assertEqual(dialog.cli_args_ok(), [])
-
- def test_invalid_args(self):
- dialog = self.Dummy_CustomRun("'no-closing-quote")
- self.assertEqual(dialog.cli_args_ok(), None)
- self.assertIn('No closing', dialog.entry_error['text'])
-
- def test_good_args(self):
- args = ['-n', '10', '--verbose', '-p', '/path', '--name']
- dialog = self.Dummy_CustomRun(' '.join(args) + ' "my name"')
- self.assertEqual(dialog.cli_args_ok(), args + ["my name"])
- self.assertEqual(dialog.entry_error['text'], '')
-
-
-class CustomRunEntryokTest(unittest.TestCase):
- "Test entry_ok method of the CustomRun subclass of Query."
-
- class Dummy_CustomRun:
- entry_ok = query.CustomRun.entry_ok
- entry_error = {}
- restartvar = Var()
- def cli_args_ok(self):
- return self.cli_args
-
- def test_entry_ok_customrun(self):
- dialog = self.Dummy_CustomRun()
- for restart in {True, False}:
- dialog.restartvar.set(restart)
- for cli_args, result in ((None, None),
- (['my arg'], (['my arg'], restart))):
- with self.subTest(restart=restart, cli_args=cli_args):
- dialog.cli_args = cli_args
- self.assertEqual(dialog.entry_ok(), result)
-
-
-# GUI TESTS
-
-class QueryGuiTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = root = Tk()
- cls.root.withdraw()
- cls.dialog = query.Query(root, 'TEST', 'test', _utest=True)
- cls.dialog.destroy = mock.Mock()
-
- @classmethod
- def tearDownClass(cls):
- del cls.dialog.destroy
- del cls.dialog
- cls.root.destroy()
- del cls.root
-
- def setUp(self):
- self.dialog.entry.delete(0, 'end')
- self.dialog.result = None
- self.dialog.destroy.reset_mock()
-
- def test_click_ok(self):
- dialog = self.dialog
- dialog.entry.insert(0, 'abc')
- dialog.button_ok.invoke()
- self.assertEqual(dialog.result, 'abc')
- self.assertTrue(dialog.destroy.called)
-
- def test_click_blank(self):
- dialog = self.dialog
- dialog.button_ok.invoke()
- self.assertEqual(dialog.result, None)
- self.assertFalse(dialog.destroy.called)
-
- def test_click_cancel(self):
- dialog = self.dialog
- dialog.entry.insert(0, 'abc')
- dialog.button_cancel.invoke()
- self.assertEqual(dialog.result, None)
- self.assertTrue(dialog.destroy.called)
-
-
-class SectionnameGuiTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
-
- def test_click_section_name(self):
- root = Tk()
- root.withdraw()
- dialog = query.SectionName(root, 'T', 't', {'abc'}, _utest=True)
- Equal = self.assertEqual
- self.assertEqual(dialog.used_names, {'abc'})
- dialog.entry.insert(0, 'okay')
- dialog.button_ok.invoke()
- self.assertEqual(dialog.result, 'okay')
- root.destroy()
-
-
-class ModulenameGuiTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
-
- def test_click_module_name(self):
- root = Tk()
- root.withdraw()
- dialog = query.ModuleName(root, 'T', 't', 'idlelib', _utest=True)
- self.assertEqual(dialog.text0, 'idlelib')
- self.assertEqual(dialog.entry.get(), 'idlelib')
- dialog.button_ok.invoke()
- self.assertTrue(dialog.result.endswith('__init__.py'))
- root.destroy()
-
-
-class HelpsourceGuiTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
-
- def test_click_help_source(self):
- root = Tk()
- root.withdraw()
- dialog = query.HelpSource(root, 'T', menuitem='__test__',
- filepath=__file__, _utest=True)
- Equal = self.assertEqual
- Equal(dialog.entry.get(), '__test__')
- Equal(dialog.path.get(), __file__)
- dialog.button_ok.invoke()
- prefix = "file://" if sys.platform == 'darwin' else ''
- Equal(dialog.result, ('__test__', prefix + __file__))
- root.destroy()
-
-
-class CustomRunGuiTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
-
- def test_click_args(self):
- root = Tk()
- root.withdraw()
- dialog = query.CustomRun(root, 'Title',
- cli_args=['a', 'b=1'], _utest=True)
- self.assertEqual(dialog.entry.get(), 'a b=1')
- dialog.entry.insert(END, ' c')
- dialog.button_ok.invoke()
- self.assertEqual(dialog.result, (['a', 'b=1', 'c'], True))
- root.destroy()
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2, exit=False)
diff --git a/Lib/idlelib/idle_test/test_replace.py b/Lib/idlelib/idle_test/test_replace.py
deleted file mode 100644
index c3c5d2e..0000000
--- a/Lib/idlelib/idle_test/test_replace.py
+++ /dev/null
@@ -1,294 +0,0 @@
-"Test replace, coverage 78%."
-
-from idlelib.replace import ReplaceDialog
-import unittest
-from test.support import requires
-requires('gui')
-from tkinter import Tk, Text
-
-from unittest.mock import Mock
-from idlelib.idle_test.mock_tk import Mbox
-import idlelib.searchengine as se
-
-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 = ReplaceDialog(cls.root, cls.engine)
- cls.dialog.bell = lambda: None
- 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')
- replace()
- equal(text.get('1.8', '1.12'), 'asdf')
-
- # don't "match word" case
- text.mark_set('insert', '1.0')
- pv.set('is')
- rv.set('hello')
- replace()
- equal(text.get('1.2', '1.7'), 'hello')
-
- # don't "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(r'[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(r'[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(r'[\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_rpc.py b/Lib/idlelib/idle_test/test_rpc.py
deleted file mode 100644
index 81eff39..0000000
--- a/Lib/idlelib/idle_test/test_rpc.py
+++ /dev/null
@@ -1,29 +0,0 @@
-"Test rpc, coverage 20%."
-
-from idlelib import rpc
-import unittest
-
-
-
-class CodePicklerTest(unittest.TestCase):
-
- def test_pickle_unpickle(self):
- def f(): return a + b + c
- func, (cbytes,) = rpc.pickle_code(f.__code__)
- self.assertIs(func, rpc.unpickle_code)
- self.assertIn(b'test_rpc.py', cbytes)
- code = rpc.unpickle_code(cbytes)
- self.assertEqual(code.co_names, ('a', 'b', 'c'))
-
- def test_code_pickler(self):
- self.assertIn(type((lambda:None).__code__),
- rpc.CodePickler.dispatch_table)
-
- def test_dumps(self):
- def f(): pass
- # The main test here is that pickling code does not raise.
- self.assertIn(b'test_rpc.py', rpc.dumps(f.__code__))
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_rstrip.py b/Lib/idlelib/idle_test/test_rstrip.py
new file mode 100644
index 0000000..1c90b93
--- /dev/null
+++ b/Lib/idlelib/idle_test/test_rstrip.py
@@ -0,0 +1,49 @@
+import unittest
+import idlelib.RstripExtension as rs
+from idlelib.idle_test.mock_idle import Editor
+
+class rstripTest(unittest.TestCase):
+
+ def test_rstrip_line(self):
+ editor = Editor()
+ text = editor.text
+ do_rstrip = rs.RstripExtension(editor).do_rstrip
+
+ do_rstrip()
+ self.assertEqual(text.get('1.0', 'insert'), '')
+ text.insert('1.0', ' ')
+ do_rstrip()
+ self.assertEqual(text.get('1.0', 'insert'), '')
+ text.insert('1.0', ' \n')
+ do_rstrip()
+ self.assertEqual(text.get('1.0', 'insert'), '\n')
+
+ def test_rstrip_multiple(self):
+ editor = Editor()
+ # Uncomment following to verify that test passes with real widgets.
+## from idlelib.EditorWindow import EditorWindow as Editor
+## from tkinter import Tk
+## editor = Editor(root=Tk())
+ text = editor.text
+ do_rstrip = rs.RstripExtension(editor).do_rstrip
+
+ original = (
+ "Line with an ending tab \n"
+ "Line ending in 5 spaces \n"
+ "Linewithnospaces\n"
+ " indented line\n"
+ " indented line with trailing space \n"
+ " ")
+ stripped = (
+ "Line with an ending tab\n"
+ "Line ending in 5 spaces\n"
+ "Linewithnospaces\n"
+ " indented line\n"
+ " indented line with trailing space\n")
+
+ text.insert('1.0', original)
+ do_rstrip()
+ self.assertEqual(text.get('1.0', 'insert'), stripped)
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2, exit=False)
diff --git a/Lib/idlelib/idle_test/test_runscript.py b/Lib/idlelib/idle_test/test_runscript.py
deleted file mode 100644
index 5fc6018..0000000
--- a/Lib/idlelib/idle_test/test_runscript.py
+++ /dev/null
@@ -1,33 +0,0 @@
-"Test runscript, coverage 16%."
-
-from idlelib import runscript
-import unittest
-from test.support import requires
-from tkinter import Tk
-from idlelib.editor import EditorWindow
-
-
-class ScriptBindingTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.update_idletasks()
- for id in cls.root.tk.call('after', 'info'):
- cls.root.after_cancel(id) # Need for EditorWindow.
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- ew = EditorWindow(root=self.root)
- sb = runscript.ScriptBinding(ew)
- ew._close()
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_scrolledlist.py b/Lib/idlelib/idle_test/test_scrolledlist.py
deleted file mode 100644
index 2f819fd..0000000
--- a/Lib/idlelib/idle_test/test_scrolledlist.py
+++ /dev/null
@@ -1,27 +0,0 @@
-"Test scrolledlist, coverage 38%."
-
-from idlelib.scrolledlist import ScrolledList
-import unittest
-from test.support import requires
-requires('gui')
-from tkinter import Tk
-
-
-class ScrolledListTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.root = Tk()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.destroy()
- del cls.root
-
-
- def test_init(self):
- ScrolledList(self.root)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_search.py b/Lib/idlelib/idle_test/test_search.py
deleted file mode 100644
index de703c1..0000000
--- a/Lib/idlelib/idle_test/test_search.py
+++ /dev/null
@@ -1,80 +0,0 @@
-"Test search, coverage 69%."
-
-from idlelib import search
-import unittest
-from test.support import requires
-requires('gui')
-from tkinter import Tk, Text, BooleanVar
-from idlelib import searchengine
-
-# Does not currently test the event handler wrappers.
-# A usage test should simulate clicks and check highlighting.
-# Tests need to be coordinated with SearchDialogBase tests
-# to avoid duplication.
-
-
-class SearchDialogTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.root = Tk()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.destroy()
- del cls.root
-
- def setUp(self):
- self.engine = searchengine.SearchEngine(self.root)
- self.dialog = search.SearchDialog(self.root, self.engine)
- self.dialog.bell = lambda: None
- self.text = 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.dialog.bell = lambda: None
-
- 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_searchbase.py b/Lib/idlelib/idle_test/test_searchdialogbase.py
index aee0c4c..59b9bbf 100644
--- a/Lib/idlelib/idle_test/test_searchbase.py
+++ b/Lib/idlelib/idle_test/test_searchdialogbase.py
@@ -1,18 +1,18 @@
-"Test searchbase, coverage 98%."
-# The only thing not covered is inconsequential --
-# testing skipping of suite when self.needwrapbutton is false.
+'''Unittests for idlelib/SearchDialogBase.py
+Coverage: 99%. The only thing not covered is inconsequential --
+testing skipping of suite when self.needwrapbutton is false.
+
+'''
import unittest
-from test.support import requires
-from tkinter import Text, Tk, Toplevel
-from tkinter.ttk import Frame
-from idlelib import searchengine as se
-from idlelib import searchbase as sdb
+from test.test_support import requires
+from Tkinter import Text, Tk, Toplevel, Frame ## BooleanVar, StringVar
+from idlelib import SearchEngine as se
+from idlelib import SearchDialogBase as sdb
from idlelib.idle_test.mock_idle import Func
-## from idlelib.idle_test.mock_tk import Var
+##from idlelib.idle_test.mock_tk import Var
-# The ## imports above & following could help make some tests gui-free.
-# However, they currently make radiobutton tests fail.
+# The ## imports above & following could help make some tests gui-free.# However, they currently make radiobutton tests fail.
##def setUpModule():
## # Replace tk objects used to initialize se.SearchEngine.
## se.BooleanVar = Var
@@ -22,7 +22,6 @@ from idlelib.idle_test.mock_idle import Func
## se.BooleanVar = BooleanVar
## se.StringVar = StringVar
-
class SearchDialogBaseTest(unittest.TestCase):
@classmethod
@@ -32,7 +31,6 @@ class SearchDialogBaseTest(unittest.TestCase):
@classmethod
def tearDownClass(cls):
- cls.root.update_idletasks()
cls.root.destroy()
del cls.root
@@ -76,7 +74,7 @@ class SearchDialogBaseTest(unittest.TestCase):
def test_make_entry(self):
equal = self.assertEqual
self.dialog.row = 0
- self.dialog.top = self.root
+ self.dialog.top = Toplevel(self.root)
entry, label = self.dialog.make_entry("Test:", 'hello')
equal(label['text'], 'Test:')
@@ -89,7 +87,6 @@ class SearchDialogBaseTest(unittest.TestCase):
equal(self.dialog.row, 1)
def test_create_entries(self):
- self.dialog.top = self.root
self.dialog.row = 0
self.engine.setpat('hello')
self.dialog.create_entries()
@@ -97,18 +94,17 @@ class SearchDialogBaseTest(unittest.TestCase):
def test_make_frame(self):
self.dialog.row = 0
- self.dialog.top = self.root
+ self.dialog.top = Toplevel(self.root)
frame, label = self.dialog.make_frame()
self.assertEqual(label, '')
- self.assertEqual(str(type(frame)), "<class 'tkinter.ttk.Frame'>")
- # self.assertIsInstance(frame, Frame) fails when test is run by
- # test_idle not run from IDLE editor. See issue 33987 PR.
+ self.assertIsInstance(frame, Frame)
frame, label = self.dialog.make_frame('testlabel')
self.assertEqual(label['text'], 'testlabel')
+ self.assertIsInstance(frame, Frame)
def btn_test_setup(self, meth):
- self.dialog.top = self.root
+ self.dialog.top = Toplevel(self.root)
self.dialog.row = 0
return meth()
@@ -123,6 +119,11 @@ class SearchDialogBaseTest(unittest.TestCase):
var, label = spec
self.assertEqual(button['text'], label)
self.assertEqual(var.get(), state)
+ if state == 1:
+ button.deselect()
+ else:
+ button.select()
+ self.assertEqual(var.get(), 1 - state)
def test_create_other_buttons(self):
for state in (False, True):
@@ -138,23 +139,27 @@ class SearchDialogBaseTest(unittest.TestCase):
# hit other button, then this one
# indexes depend on button order
self.assertEqual(var.get(), state)
+ buttons[val].select()
+ self.assertEqual(var.get(), 1 - state)
+ buttons[1-val].select()
+ self.assertEqual(var.get(), state)
def test_make_button(self):
- self.dialog.top = self.root
+ self.dialog.top = Toplevel(self.root)
self.dialog.buttonframe = Frame(self.dialog.top)
btn = self.dialog.make_button('Test', self.dialog.close)
self.assertEqual(btn['text'], 'Test')
def test_create_command_buttons(self):
- self.dialog.top = self.root
self.dialog.create_command_buttons()
# Look for close button command in buttonframe
closebuttoncommand = ''
for child in self.dialog.buttonframe.winfo_children():
- if child['text'] == 'Close':
+ if child['text'] == 'close':
closebuttoncommand = child['command']
self.assertIn('close', closebuttoncommand)
+
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 3d26d62..8bf9d47 100644
--- a/Lib/idlelib/idle_test/test_searchengine.py
+++ b/Lib/idlelib/idle_test/test_searchengine.py
@@ -1,19 +1,18 @@
-"Test searchengine, coverage 99%."
-
-from idlelib import searchengine as se
-import unittest
-# from test.support import requires
-from tkinter import BooleanVar, StringVar, TclError # ,Tk, Text
-import tkinter.messagebox as tkMessageBox
-from idlelib.idle_test.mock_tk import Var, Mbox
-from idlelib.idle_test.mock_tk import Text as mockText
-import re
+'''Test functions and SearchEngine class in SearchEngine.py.'''
# With mock replacements, the module does not use any gui widgets.
# The use of tk.Text is avoided (for now, until mock Text is improved)
# by patching instances with an index function returning what is needed.
# This works because mock Text.get does not use .index.
-# The tkinter imports are used to restore searchengine.
+
+import re
+import unittest
+#from test.test_support import requires
+from Tkinter import BooleanVar, StringVar, TclError # ,Tk, Text
+import tkMessageBox
+from idlelib import SearchEngine as se
+from idlelib.idle_test.mock_tk import Var, Mbox
+from idlelib.idle_test.mock_tk import Text as mockText
def setUpModule():
# Replace s-e module tkinter imports other than non-gui TclError.
@@ -140,10 +139,10 @@ class SearchEngineTest(unittest.TestCase):
def test_setcookedpat(self):
engine = self.engine
- engine.setcookedpat(r'\s')
- self.assertEqual(engine.getpat(), r'\s')
+ engine.setcookedpat('\s')
+ self.assertEqual(engine.getpat(), '\s')
engine.revar.set(1)
- engine.setcookedpat(r'\s')
+ engine.setcookedpat('\s')
self.assertEqual(engine.getpat(), r'\\s')
def test_getcookedpat(self):
@@ -157,10 +156,10 @@ class SearchEngineTest(unittest.TestCase):
Equal(engine.getcookedpat(), r'\bhello\b')
engine.wordvar.set(False)
- engine.setpat(r'\s')
+ engine.setpat('\s')
Equal(engine.getcookedpat(), r'\\s')
engine.revar.set(True)
- Equal(engine.getcookedpat(), r'\s')
+ Equal(engine.getcookedpat(), '\s')
def test_getprog(self):
engine = self.engine
@@ -179,7 +178,7 @@ class SearchEngineTest(unittest.TestCase):
engine.revar.set(1)
Equal(engine.getprog(), None)
self.assertEqual(Mbox.showerror.message,
- 'Error: nothing to repeat at position 0\nPattern: +')
+ 'Error: nothing to repeat\nPattern: +')
def test_report_error(self):
showerror = Mbox.showerror
@@ -283,7 +282,7 @@ class ForwardBackwardTest(unittest.TestCase):
cls.pat = re.compile('target')
cls.res = (2, (10, 16)) # line, slice indexes of 'target'
cls.failpat = re.compile('xyz') # not in text
- cls.emptypat = re.compile(r'\w*') # empty match possible
+ cls.emptypat = re.compile('\w*') # empty match possible
def make_search(self, func):
def search(pat, line, col, wrap, ok=0):
@@ -327,4 +326,4 @@ class ForwardBackwardTest(unittest.TestCase):
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ unittest.main(verbosity=2, exit=2)
diff --git a/Lib/idlelib/idle_test/test_sidebar.py b/Lib/idlelib/idle_test/test_sidebar.py
deleted file mode 100644
index 0f5b4c7..0000000
--- a/Lib/idlelib/idle_test/test_sidebar.py
+++ /dev/null
@@ -1,375 +0,0 @@
-"""Test sidebar, coverage 93%"""
-import idlelib.sidebar
-from sys import platform
-from itertools import chain
-import unittest
-import unittest.mock
-from test.support import requires
-import tkinter as tk
-
-from idlelib.delegator import Delegator
-from idlelib.percolator import Percolator
-
-
-class Dummy_editwin:
- def __init__(self, text):
- self.text = text
- self.text_frame = self.text.master
- self.per = Percolator(text)
- self.undo = Delegator()
- self.per.insertfilter(self.undo)
-
- def setvar(self, name, value):
- pass
-
- def getlineno(self, index):
- return int(float(self.text.index(index)))
-
-
-class LineNumbersTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = tk.Tk()
-
- cls.text_frame = tk.Frame(cls.root)
- cls.text_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
- cls.text_frame.rowconfigure(1, weight=1)
- cls.text_frame.columnconfigure(1, weight=1)
-
- cls.text = tk.Text(cls.text_frame, width=80, height=24, wrap=tk.NONE)
- cls.text.grid(row=1, column=1, sticky=tk.NSEW)
-
- cls.editwin = Dummy_editwin(cls.text)
- cls.editwin.vbar = tk.Scrollbar(cls.text_frame)
-
- @classmethod
- def tearDownClass(cls):
- cls.editwin.per.close()
- cls.root.update()
- cls.root.destroy()
- del cls.text, cls.text_frame, cls.editwin, cls.root
-
- def setUp(self):
- self.linenumber = idlelib.sidebar.LineNumbers(self.editwin)
-
- self.highlight_cfg = {"background": '#abcdef',
- "foreground": '#123456'}
- orig_idleConf_GetHighlight = idlelib.sidebar.idleConf.GetHighlight
- def mock_idleconf_GetHighlight(theme, element):
- if element == 'linenumber':
- return self.highlight_cfg
- return orig_idleConf_GetHighlight(theme, element)
- GetHighlight_patcher = unittest.mock.patch.object(
- idlelib.sidebar.idleConf, 'GetHighlight', mock_idleconf_GetHighlight)
- GetHighlight_patcher.start()
- self.addCleanup(GetHighlight_patcher.stop)
-
- self.font_override = 'TkFixedFont'
- def mock_idleconf_GetFont(root, configType, section):
- return self.font_override
- GetFont_patcher = unittest.mock.patch.object(
- idlelib.sidebar.idleConf, 'GetFont', mock_idleconf_GetFont)
- GetFont_patcher.start()
- self.addCleanup(GetFont_patcher.stop)
-
- def tearDown(self):
- self.text.delete('1.0', 'end')
-
- def get_selection(self):
- return tuple(map(str, self.text.tag_ranges('sel')))
-
- def get_line_screen_position(self, line):
- bbox = self.linenumber.sidebar_text.bbox(f'{line}.end -1c')
- x = bbox[0] + 2
- y = bbox[1] + 2
- return x, y
-
- def assert_state_disabled(self):
- state = self.linenumber.sidebar_text.config()['state']
- self.assertEqual(state[-1], tk.DISABLED)
-
- def get_sidebar_text_contents(self):
- return self.linenumber.sidebar_text.get('1.0', tk.END)
-
- def assert_sidebar_n_lines(self, n_lines):
- expected = '\n'.join(chain(map(str, range(1, n_lines + 1)), ['']))
- self.assertEqual(self.get_sidebar_text_contents(), expected)
-
- def assert_text_equals(self, expected):
- return self.assertEqual(self.text.get('1.0', 'end'), expected)
-
- def test_init_empty(self):
- self.assert_sidebar_n_lines(1)
-
- def test_init_not_empty(self):
- self.text.insert('insert', 'foo bar\n'*3)
- self.assert_text_equals('foo bar\n'*3 + '\n')
- self.assert_sidebar_n_lines(4)
-
- def test_toggle_linenumbering(self):
- self.assertEqual(self.linenumber.is_shown, False)
- self.linenumber.show_sidebar()
- self.assertEqual(self.linenumber.is_shown, True)
- self.linenumber.hide_sidebar()
- self.assertEqual(self.linenumber.is_shown, False)
- self.linenumber.hide_sidebar()
- self.assertEqual(self.linenumber.is_shown, False)
- self.linenumber.show_sidebar()
- self.assertEqual(self.linenumber.is_shown, True)
- self.linenumber.show_sidebar()
- self.assertEqual(self.linenumber.is_shown, True)
-
- def test_insert(self):
- self.text.insert('insert', 'foobar')
- self.assert_text_equals('foobar\n')
- self.assert_sidebar_n_lines(1)
- self.assert_state_disabled()
-
- self.text.insert('insert', '\nfoo')
- self.assert_text_equals('foobar\nfoo\n')
- self.assert_sidebar_n_lines(2)
- self.assert_state_disabled()
-
- self.text.insert('insert', 'hello\n'*2)
- self.assert_text_equals('foobar\nfoohello\nhello\n\n')
- self.assert_sidebar_n_lines(4)
- self.assert_state_disabled()
-
- self.text.insert('insert', '\nworld')
- self.assert_text_equals('foobar\nfoohello\nhello\n\nworld\n')
- self.assert_sidebar_n_lines(5)
- self.assert_state_disabled()
-
- def test_delete(self):
- self.text.insert('insert', 'foobar')
- self.assert_text_equals('foobar\n')
- self.text.delete('1.1', '1.3')
- self.assert_text_equals('fbar\n')
- self.assert_sidebar_n_lines(1)
- self.assert_state_disabled()
-
- self.text.insert('insert', 'foo\n'*2)
- self.assert_text_equals('fbarfoo\nfoo\n\n')
- self.assert_sidebar_n_lines(3)
- self.assert_state_disabled()
-
- # Note: deleting up to "2.end" doesn't delete the final newline.
- self.text.delete('2.0', '2.end')
- self.assert_text_equals('fbarfoo\n\n\n')
- self.assert_sidebar_n_lines(3)
- self.assert_state_disabled()
-
- self.text.delete('1.3', 'end')
- self.assert_text_equals('fba\n')
- self.assert_sidebar_n_lines(1)
- self.assert_state_disabled()
-
- # Note: Text widgets always keep a single '\n' character at the end.
- self.text.delete('1.0', 'end')
- self.assert_text_equals('\n')
- self.assert_sidebar_n_lines(1)
- self.assert_state_disabled()
-
- def test_sidebar_text_width(self):
- """
- Test that linenumber text widget is always at the minimum
- width
- """
- def get_width():
- return self.linenumber.sidebar_text.config()['width'][-1]
-
- self.assert_sidebar_n_lines(1)
- self.assertEqual(get_width(), 1)
-
- self.text.insert('insert', 'foo')
- self.assert_sidebar_n_lines(1)
- self.assertEqual(get_width(), 1)
-
- self.text.insert('insert', 'foo\n'*8)
- self.assert_sidebar_n_lines(9)
- self.assertEqual(get_width(), 1)
-
- self.text.insert('insert', 'foo\n')
- self.assert_sidebar_n_lines(10)
- self.assertEqual(get_width(), 2)
-
- self.text.insert('insert', 'foo\n')
- self.assert_sidebar_n_lines(11)
- self.assertEqual(get_width(), 2)
-
- self.text.delete('insert -1l linestart', 'insert linestart')
- self.assert_sidebar_n_lines(10)
- self.assertEqual(get_width(), 2)
-
- self.text.delete('insert -1l linestart', 'insert linestart')
- self.assert_sidebar_n_lines(9)
- self.assertEqual(get_width(), 1)
-
- self.text.insert('insert', 'foo\n'*90)
- self.assert_sidebar_n_lines(99)
- self.assertEqual(get_width(), 2)
-
- self.text.insert('insert', 'foo\n')
- self.assert_sidebar_n_lines(100)
- self.assertEqual(get_width(), 3)
-
- self.text.insert('insert', 'foo\n')
- self.assert_sidebar_n_lines(101)
- self.assertEqual(get_width(), 3)
-
- self.text.delete('insert -1l linestart', 'insert linestart')
- self.assert_sidebar_n_lines(100)
- self.assertEqual(get_width(), 3)
-
- self.text.delete('insert -1l linestart', 'insert linestart')
- self.assert_sidebar_n_lines(99)
- self.assertEqual(get_width(), 2)
-
- self.text.delete('50.0 -1c', 'end -1c')
- self.assert_sidebar_n_lines(49)
- self.assertEqual(get_width(), 2)
-
- self.text.delete('5.0 -1c', 'end -1c')
- self.assert_sidebar_n_lines(4)
- self.assertEqual(get_width(), 1)
-
- # Note: Text widgets always keep a single '\n' character at the end.
- self.text.delete('1.0', 'end -1c')
- self.assert_sidebar_n_lines(1)
- self.assertEqual(get_width(), 1)
-
- def test_click_selection(self):
- self.linenumber.show_sidebar()
- self.text.insert('1.0', 'one\ntwo\nthree\nfour\n')
- self.root.update()
-
- # Click on the second line.
- x, y = self.get_line_screen_position(2)
- self.linenumber.sidebar_text.event_generate('<Button-1>', x=x, y=y)
- self.linenumber.sidebar_text.update()
- self.root.update()
-
- self.assertEqual(self.get_selection(), ('2.0', '3.0'))
-
- def simulate_drag(self, start_line, end_line):
- start_x, start_y = self.get_line_screen_position(start_line)
- end_x, end_y = self.get_line_screen_position(end_line)
-
- self.linenumber.sidebar_text.event_generate('<Button-1>',
- x=start_x, y=start_y)
- self.root.update()
-
- def lerp(a, b, steps):
- """linearly interpolate from a to b (inclusive) in equal steps"""
- last_step = steps - 1
- for i in range(steps):
- yield ((last_step - i) / last_step) * a + (i / last_step) * b
-
- for x, y in zip(
- map(int, lerp(start_x, end_x, steps=11)),
- map(int, lerp(start_y, end_y, steps=11)),
- ):
- self.linenumber.sidebar_text.event_generate('<B1-Motion>', x=x, y=y)
- self.root.update()
-
- self.linenumber.sidebar_text.event_generate('<ButtonRelease-1>',
- x=end_x, y=end_y)
- self.root.update()
-
- def test_drag_selection_down(self):
- self.linenumber.show_sidebar()
- self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n')
- self.root.update()
-
- # Drag from the second line to the fourth line.
- self.simulate_drag(2, 4)
- self.assertEqual(self.get_selection(), ('2.0', '5.0'))
-
- def test_drag_selection_up(self):
- self.linenumber.show_sidebar()
- self.text.insert('1.0', 'one\ntwo\nthree\nfour\nfive\n')
- self.root.update()
-
- # Drag from the fourth line to the second line.
- self.simulate_drag(4, 2)
- self.assertEqual(self.get_selection(), ('2.0', '5.0'))
-
- def test_scroll(self):
- self.linenumber.show_sidebar()
- self.text.insert('1.0', 'line\n' * 100)
- self.root.update()
-
- # Scroll down 10 lines.
- self.text.yview_scroll(10, 'unit')
- self.root.update()
- self.assertEqual(self.text.index('@0,0'), '11.0')
- self.assertEqual(self.linenumber.sidebar_text.index('@0,0'), '11.0')
-
- # Generate a mouse-wheel event and make sure it scrolled up or down.
- # The meaning of the "delta" is OS-dependant, so this just checks for
- # any change.
- self.linenumber.sidebar_text.event_generate('<MouseWheel>',
- x=0, y=0,
- delta=10)
- self.root.update()
- self.assertNotEqual(self.text.index('@0,0'), '11.0')
- self.assertNotEqual(self.linenumber.sidebar_text.index('@0,0'), '11.0')
-
- def test_font(self):
- ln = self.linenumber
-
- orig_font = ln.sidebar_text['font']
- test_font = 'TkTextFont'
- self.assertNotEqual(orig_font, test_font)
-
- # Ensure line numbers aren't shown.
- ln.hide_sidebar()
-
- self.font_override = test_font
- # Nothing breaks when line numbers aren't shown.
- ln.update_font()
-
- # Activate line numbers, previous font change is immediately effective.
- ln.show_sidebar()
- self.assertEqual(ln.sidebar_text['font'], test_font)
-
- # Call the font update with line numbers shown, change is picked up.
- self.font_override = orig_font
- ln.update_font()
- self.assertEqual(ln.sidebar_text['font'], orig_font)
-
- def test_highlight_colors(self):
- ln = self.linenumber
-
- orig_colors = dict(self.highlight_cfg)
- test_colors = {'background': '#222222', 'foreground': '#ffff00'}
-
- def assert_colors_are_equal(colors):
- self.assertEqual(ln.sidebar_text['background'], colors['background'])
- self.assertEqual(ln.sidebar_text['foreground'], colors['foreground'])
-
- # Ensure line numbers aren't shown.
- ln.hide_sidebar()
-
- self.highlight_cfg = test_colors
- # Nothing breaks with inactive code context.
- ln.update_colors()
-
- # Show line numbers, previous colors change is immediately effective.
- ln.show_sidebar()
- assert_colors_are_equal(test_colors)
-
- # Call colors update with no change to the configured colors.
- ln.update_colors()
- assert_colors_are_equal(test_colors)
-
- # Call the colors update with line numbers shown, change is picked up.
- self.highlight_cfg = orig_colors
- ln.update_colors()
- assert_colors_are_equal(orig_colors)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_squeezer.py b/Lib/idlelib/idle_test/test_squeezer.py
deleted file mode 100644
index 1af2ce8..0000000
--- a/Lib/idlelib/idle_test/test_squeezer.py
+++ /dev/null
@@ -1,476 +0,0 @@
-"Test squeezer, coverage 95%"
-
-from collections import namedtuple
-from textwrap import dedent
-from tkinter import Text, Tk
-import unittest
-from unittest.mock import Mock, NonCallableMagicMock, patch, sentinel, ANY
-from test.support import requires
-
-from idlelib.config import idleConf
-from idlelib.squeezer import count_lines_with_wrapping, ExpandingButton, \
- Squeezer
-from idlelib import macosx
-from idlelib.textview import view_text
-from idlelib.tooltip import Hovertip
-from idlelib.pyshell import PyShell
-
-
-SENTINEL_VALUE = sentinel.SENTINEL_VALUE
-
-
-def get_test_tk_root(test_instance):
- """Helper for tests: Create a root Tk object."""
- requires('gui')
- root = Tk()
- root.withdraw()
-
- def cleanup_root():
- root.update_idletasks()
- root.destroy()
- test_instance.addCleanup(cleanup_root)
-
- return root
-
-
-class CountLinesTest(unittest.TestCase):
- """Tests for the count_lines_with_wrapping function."""
- def check(self, expected, text, linewidth):
- return self.assertEqual(
- expected,
- count_lines_with_wrapping(text, linewidth),
- )
-
- def test_count_empty(self):
- """Test with an empty string."""
- self.assertEqual(count_lines_with_wrapping(""), 0)
-
- def test_count_begins_with_empty_line(self):
- """Test with a string which begins with a newline."""
- self.assertEqual(count_lines_with_wrapping("\ntext"), 2)
-
- def test_count_ends_with_empty_line(self):
- """Test with a string which ends with a newline."""
- self.assertEqual(count_lines_with_wrapping("text\n"), 1)
-
- def test_count_several_lines(self):
- """Test with several lines of text."""
- self.assertEqual(count_lines_with_wrapping("1\n2\n3\n"), 3)
-
- def test_empty_lines(self):
- self.check(expected=1, text='\n', linewidth=80)
- self.check(expected=2, text='\n\n', linewidth=80)
- self.check(expected=10, text='\n' * 10, linewidth=80)
-
- def test_long_line(self):
- self.check(expected=3, text='a' * 200, linewidth=80)
- self.check(expected=3, text='a' * 200 + '\n', linewidth=80)
-
- def test_several_lines_different_lengths(self):
- text = dedent("""\
- 13 characters
- 43 is the number of characters on this line
-
- 7 chars
- 13 characters""")
- self.check(expected=5, text=text, linewidth=80)
- self.check(expected=5, text=text + '\n', linewidth=80)
- self.check(expected=6, text=text, linewidth=40)
- self.check(expected=7, text=text, linewidth=20)
- self.check(expected=11, text=text, linewidth=10)
-
-
-class SqueezerTest(unittest.TestCase):
- """Tests for the Squeezer class."""
- def make_mock_editor_window(self, with_text_widget=False):
- """Create a mock EditorWindow instance."""
- editwin = NonCallableMagicMock()
- editwin.width = 80
-
- if with_text_widget:
- editwin.root = get_test_tk_root(self)
- text_widget = self.make_text_widget(root=editwin.root)
- editwin.text = editwin.per.bottom = text_widget
-
- return editwin
-
- def make_squeezer_instance(self, editor_window=None):
- """Create an actual Squeezer instance with a mock EditorWindow."""
- if editor_window is None:
- editor_window = self.make_mock_editor_window()
- squeezer = Squeezer(editor_window)
- return squeezer
-
- def make_text_widget(self, root=None):
- if root is None:
- root = get_test_tk_root(self)
- text_widget = Text(root)
- text_widget["font"] = ('Courier', 10)
- text_widget.mark_set("iomark", "1.0")
- return text_widget
-
- def set_idleconf_option_with_cleanup(self, configType, section, option, value):
- prev_val = idleConf.GetOption(configType, section, option)
- idleConf.SetOption(configType, section, option, value)
- self.addCleanup(idleConf.SetOption,
- configType, section, option, prev_val)
-
- def test_count_lines(self):
- """Test Squeezer.count_lines() with various inputs."""
- editwin = self.make_mock_editor_window()
- squeezer = self.make_squeezer_instance(editwin)
-
- for text_code, line_width, expected in [
- (r"'\n'", 80, 1),
- (r"'\n' * 3", 80, 3),
- (r"'a' * 40 + '\n'", 80, 1),
- (r"'a' * 80 + '\n'", 80, 1),
- (r"'a' * 200 + '\n'", 80, 3),
- (r"'aa\t' * 20", 80, 2),
- (r"'aa\t' * 21", 80, 3),
- (r"'aa\t' * 20", 40, 4),
- ]:
- with self.subTest(text_code=text_code,
- line_width=line_width,
- expected=expected):
- text = eval(text_code)
- with patch.object(editwin, 'width', line_width):
- self.assertEqual(squeezer.count_lines(text), expected)
-
- def test_init(self):
- """Test the creation of Squeezer instances."""
- editwin = self.make_mock_editor_window()
- squeezer = self.make_squeezer_instance(editwin)
- self.assertIs(squeezer.editwin, editwin)
- self.assertEqual(squeezer.expandingbuttons, [])
-
- def test_write_no_tags(self):
- """Test Squeezer's overriding of the EditorWindow's write() method."""
- editwin = self.make_mock_editor_window()
- for text in ['', 'TEXT', 'LONG TEXT' * 1000, 'MANY_LINES\n' * 100]:
- editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE)
- squeezer = self.make_squeezer_instance(editwin)
-
- self.assertEqual(squeezer.editwin.write(text, ()), SENTINEL_VALUE)
- self.assertEqual(orig_write.call_count, 1)
- orig_write.assert_called_with(text, ())
- self.assertEqual(len(squeezer.expandingbuttons), 0)
-
- def test_write_not_stdout(self):
- """Test Squeezer's overriding of the EditorWindow's write() method."""
- for text in ['', 'TEXT', 'LONG TEXT' * 1000, 'MANY_LINES\n' * 100]:
- editwin = self.make_mock_editor_window()
- editwin.write.return_value = SENTINEL_VALUE
- orig_write = editwin.write
- squeezer = self.make_squeezer_instance(editwin)
-
- self.assertEqual(squeezer.editwin.write(text, "stderr"),
- SENTINEL_VALUE)
- self.assertEqual(orig_write.call_count, 1)
- orig_write.assert_called_with(text, "stderr")
- self.assertEqual(len(squeezer.expandingbuttons), 0)
-
- def test_write_stdout(self):
- """Test Squeezer's overriding of the EditorWindow's write() method."""
- editwin = self.make_mock_editor_window()
-
- for text in ['', 'TEXT']:
- editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE)
- squeezer = self.make_squeezer_instance(editwin)
- squeezer.auto_squeeze_min_lines = 50
-
- self.assertEqual(squeezer.editwin.write(text, "stdout"),
- SENTINEL_VALUE)
- self.assertEqual(orig_write.call_count, 1)
- orig_write.assert_called_with(text, "stdout")
- self.assertEqual(len(squeezer.expandingbuttons), 0)
-
- for text in ['LONG TEXT' * 1000, 'MANY_LINES\n' * 100]:
- editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE)
- squeezer = self.make_squeezer_instance(editwin)
- squeezer.auto_squeeze_min_lines = 50
-
- self.assertEqual(squeezer.editwin.write(text, "stdout"), None)
- self.assertEqual(orig_write.call_count, 0)
- self.assertEqual(len(squeezer.expandingbuttons), 1)
-
- def test_auto_squeeze(self):
- """Test that the auto-squeezing creates an ExpandingButton properly."""
- editwin = self.make_mock_editor_window(with_text_widget=True)
- text_widget = editwin.text
- squeezer = self.make_squeezer_instance(editwin)
- squeezer.auto_squeeze_min_lines = 5
- squeezer.count_lines = Mock(return_value=6)
-
- editwin.write('TEXT\n'*6, "stdout")
- self.assertEqual(text_widget.get('1.0', 'end'), '\n')
- self.assertEqual(len(squeezer.expandingbuttons), 1)
-
- def test_squeeze_current_text_event(self):
- """Test the squeeze_current_text event."""
- # Squeezing text should work for both stdout and stderr.
- for tag_name in ["stdout", "stderr"]:
- editwin = self.make_mock_editor_window(with_text_widget=True)
- text_widget = editwin.text
- squeezer = self.make_squeezer_instance(editwin)
- squeezer.count_lines = Mock(return_value=6)
-
- # Prepare some text in the Text widget.
- text_widget.insert("1.0", "SOME\nTEXT\n", tag_name)
- text_widget.mark_set("insert", "1.0")
- self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
-
- self.assertEqual(len(squeezer.expandingbuttons), 0)
-
- # Test squeezing the current text.
- retval = squeezer.squeeze_current_text_event(event=Mock())
- self.assertEqual(retval, "break")
- self.assertEqual(text_widget.get('1.0', 'end'), '\n\n')
- self.assertEqual(len(squeezer.expandingbuttons), 1)
- self.assertEqual(squeezer.expandingbuttons[0].s, 'SOME\nTEXT')
-
- # Test that expanding the squeezed text works and afterwards
- # the Text widget contains the original text.
- squeezer.expandingbuttons[0].expand(event=Mock())
- self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
- self.assertEqual(len(squeezer.expandingbuttons), 0)
-
- def test_squeeze_current_text_event_no_allowed_tags(self):
- """Test that the event doesn't squeeze text without a relevant tag."""
- editwin = self.make_mock_editor_window(with_text_widget=True)
- text_widget = editwin.text
- squeezer = self.make_squeezer_instance(editwin)
- squeezer.count_lines = Mock(return_value=6)
-
- # Prepare some text in the Text widget.
- text_widget.insert("1.0", "SOME\nTEXT\n", "TAG")
- text_widget.mark_set("insert", "1.0")
- self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
-
- self.assertEqual(len(squeezer.expandingbuttons), 0)
-
- # Test squeezing the current text.
- retval = squeezer.squeeze_current_text_event(event=Mock())
- self.assertEqual(retval, "break")
- self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
- self.assertEqual(len(squeezer.expandingbuttons), 0)
-
- def test_squeeze_text_before_existing_squeezed_text(self):
- """Test squeezing text before existing squeezed text."""
- editwin = self.make_mock_editor_window(with_text_widget=True)
- text_widget = editwin.text
- squeezer = self.make_squeezer_instance(editwin)
- squeezer.count_lines = Mock(return_value=6)
-
- # Prepare some text in the Text widget and squeeze it.
- text_widget.insert("1.0", "SOME\nTEXT\n", "stdout")
- text_widget.mark_set("insert", "1.0")
- squeezer.squeeze_current_text_event(event=Mock())
- self.assertEqual(len(squeezer.expandingbuttons), 1)
-
- # Test squeezing the current text.
- text_widget.insert("1.0", "MORE\nSTUFF\n", "stdout")
- text_widget.mark_set("insert", "1.0")
- retval = squeezer.squeeze_current_text_event(event=Mock())
- self.assertEqual(retval, "break")
- self.assertEqual(text_widget.get('1.0', 'end'), '\n\n\n')
- self.assertEqual(len(squeezer.expandingbuttons), 2)
- self.assertTrue(text_widget.compare(
- squeezer.expandingbuttons[0],
- '<',
- squeezer.expandingbuttons[1],
- ))
-
- def test_reload(self):
- """Test the reload() class-method."""
- editwin = self.make_mock_editor_window(with_text_widget=True)
- squeezer = self.make_squeezer_instance(editwin)
-
- orig_auto_squeeze_min_lines = squeezer.auto_squeeze_min_lines
-
- # Increase auto-squeeze-min-lines.
- new_auto_squeeze_min_lines = orig_auto_squeeze_min_lines + 10
- self.set_idleconf_option_with_cleanup(
- 'main', 'PyShell', 'auto-squeeze-min-lines',
- str(new_auto_squeeze_min_lines))
-
- Squeezer.reload()
- self.assertEqual(squeezer.auto_squeeze_min_lines,
- new_auto_squeeze_min_lines)
-
- def test_reload_no_squeezer_instances(self):
- """Test that Squeezer.reload() runs without any instances existing."""
- Squeezer.reload()
-
-
-class ExpandingButtonTest(unittest.TestCase):
- """Tests for the ExpandingButton class."""
- # In these tests the squeezer instance is a mock, but actual tkinter
- # Text and Button instances are created.
- def make_mock_squeezer(self):
- """Helper for tests: Create a mock Squeezer object."""
- root = get_test_tk_root(self)
- squeezer = Mock()
- squeezer.editwin.text = Text(root)
-
- # Set default values for the configuration settings.
- squeezer.auto_squeeze_min_lines = 50
- return squeezer
-
- @patch('idlelib.squeezer.Hovertip', autospec=Hovertip)
- def test_init(self, MockHovertip):
- """Test the simplest creation of an ExpandingButton."""
- squeezer = self.make_mock_squeezer()
- text_widget = squeezer.editwin.text
-
- expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
- self.assertEqual(expandingbutton.s, 'TEXT')
-
- # Check that the underlying tkinter.Button is properly configured.
- self.assertEqual(expandingbutton.master, text_widget)
- self.assertTrue('50 lines' in expandingbutton.cget('text'))
-
- # Check that the text widget still contains no text.
- self.assertEqual(text_widget.get('1.0', 'end'), '\n')
-
- # Check that the mouse events are bound.
- self.assertIn('<Double-Button-1>', expandingbutton.bind())
- right_button_code = '<Button-%s>' % ('2' if macosx.isAquaTk() else '3')
- self.assertIn(right_button_code, expandingbutton.bind())
-
- # Check that ToolTip was called once, with appropriate values.
- self.assertEqual(MockHovertip.call_count, 1)
- MockHovertip.assert_called_with(expandingbutton, ANY, hover_delay=ANY)
-
- # Check that 'right-click' appears in the tooltip text.
- tooltip_text = MockHovertip.call_args[0][1]
- self.assertIn('right-click', tooltip_text.lower())
-
- def test_expand(self):
- """Test the expand event."""
- squeezer = self.make_mock_squeezer()
- expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
-
- # Insert the button into the text widget
- # (this is normally done by the Squeezer class).
- text_widget = expandingbutton.text
- text_widget.window_create("1.0", window=expandingbutton)
-
- # Set base_text to the text widget, so that changes are actually
- # made to it (by ExpandingButton) and we can inspect these
- # changes afterwards.
- expandingbutton.base_text = expandingbutton.text
-
- # trigger the expand event
- retval = expandingbutton.expand(event=Mock())
- self.assertEqual(retval, None)
-
- # Check that the text was inserted into the text widget.
- self.assertEqual(text_widget.get('1.0', 'end'), 'TEXT\n')
-
- # Check that the 'TAGS' tag was set on the inserted text.
- text_end_index = text_widget.index('end-1c')
- self.assertEqual(text_widget.get('1.0', text_end_index), 'TEXT')
- self.assertEqual(text_widget.tag_nextrange('TAGS', '1.0'),
- ('1.0', text_end_index))
-
- # Check that the button removed itself from squeezer.expandingbuttons.
- self.assertEqual(squeezer.expandingbuttons.remove.call_count, 1)
- squeezer.expandingbuttons.remove.assert_called_with(expandingbutton)
-
- def test_expand_dangerous_oupput(self):
- """Test that expanding very long output asks user for confirmation."""
- squeezer = self.make_mock_squeezer()
- text = 'a' * 10**5
- expandingbutton = ExpandingButton(text, 'TAGS', 50, squeezer)
- expandingbutton.set_is_dangerous()
- self.assertTrue(expandingbutton.is_dangerous)
-
- # Insert the button into the text widget
- # (this is normally done by the Squeezer class).
- text_widget = expandingbutton.text
- text_widget.window_create("1.0", window=expandingbutton)
-
- # Set base_text to the text widget, so that changes are actually
- # made to it (by ExpandingButton) and we can inspect these
- # changes afterwards.
- expandingbutton.base_text = expandingbutton.text
-
- # Patch the message box module to always return False.
- with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox:
- mock_msgbox.askokcancel.return_value = False
- mock_msgbox.askyesno.return_value = False
- # Trigger the expand event.
- retval = expandingbutton.expand(event=Mock())
-
- # Check that the event chain was broken and no text was inserted.
- self.assertEqual(retval, 'break')
- self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), '')
-
- # Patch the message box module to always return True.
- with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox:
- mock_msgbox.askokcancel.return_value = True
- mock_msgbox.askyesno.return_value = True
- # Trigger the expand event.
- retval = expandingbutton.expand(event=Mock())
-
- # Check that the event chain wasn't broken and the text was inserted.
- self.assertEqual(retval, None)
- self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), text)
-
- def test_copy(self):
- """Test the copy event."""
- # Testing with the actual clipboard proved problematic, so this
- # test replaces the clipboard manipulation functions with mocks
- # and checks that they are called appropriately.
- squeezer = self.make_mock_squeezer()
- expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
- expandingbutton.clipboard_clear = Mock()
- expandingbutton.clipboard_append = Mock()
-
- # Trigger the copy event.
- retval = expandingbutton.copy(event=Mock())
- self.assertEqual(retval, None)
-
- # Vheck that the expanding button called clipboard_clear() and
- # clipboard_append('TEXT') once each.
- self.assertEqual(expandingbutton.clipboard_clear.call_count, 1)
- self.assertEqual(expandingbutton.clipboard_append.call_count, 1)
- expandingbutton.clipboard_append.assert_called_with('TEXT')
-
- def test_view(self):
- """Test the view event."""
- squeezer = self.make_mock_squeezer()
- expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
- expandingbutton.selection_own = Mock()
-
- with patch('idlelib.squeezer.view_text', autospec=view_text)\
- as mock_view_text:
- # Trigger the view event.
- expandingbutton.view(event=Mock())
-
- # Check that the expanding button called view_text.
- self.assertEqual(mock_view_text.call_count, 1)
-
- # Check that the proper text was passed.
- self.assertEqual(mock_view_text.call_args[0][2], 'TEXT')
-
- def test_rmenu(self):
- """Test the context menu."""
- squeezer = self.make_mock_squeezer()
- expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
- with patch('tkinter.Menu') as mock_Menu:
- mock_menu = Mock()
- mock_Menu.return_value = mock_menu
- mock_event = Mock()
- mock_event.x = 10
- mock_event.y = 10
- expandingbutton.context_menu_event(event=mock_event)
- self.assertEqual(mock_menu.add_command.call_count,
- len(expandingbutton.rmenu_specs))
- for label, *data in expandingbutton.rmenu_specs:
- mock_menu.add_command.assert_any_call(label=label, command=ANY)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_stackviewer.py b/Lib/idlelib/idle_test/test_stackviewer.py
deleted file mode 100644
index 98f53f9..0000000
--- a/Lib/idlelib/idle_test/test_stackviewer.py
+++ /dev/null
@@ -1,47 +0,0 @@
-"Test stackviewer, coverage 63%."
-
-from idlelib import stackviewer
-import unittest
-from test.support import requires
-from tkinter import Tk
-
-from idlelib.tree import TreeNode, ScrolledCanvas
-import sys
-
-
-class StackBrowserTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- svs = stackviewer.sys
- try:
- abc
- except NameError:
- svs.last_type, svs.last_value, svs.last_traceback = (
- sys.exc_info())
-
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- svs = stackviewer.sys
- del svs.last_traceback, svs.last_type, svs.last_value
-
- cls.root.update_idletasks()
-## for id in cls.root.tk.call('after', 'info'):
-## cls.root.after_cancel(id) # Need for EditorWindow.
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- sb = stackviewer.StackBrowser(self.root)
- isi = self.assertIsInstance
- isi(stackviewer.sc, ScrolledCanvas)
- isi(stackviewer.item, stackviewer.StackTreeItem)
- isi(stackviewer.node, TreeNode)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_statusbar.py b/Lib/idlelib/idle_test/test_statusbar.py
deleted file mode 100644
index 203a57d..0000000
--- a/Lib/idlelib/idle_test/test_statusbar.py
+++ /dev/null
@@ -1,41 +0,0 @@
-"Test statusbar, coverage 100%."
-
-from idlelib import statusbar
-import unittest
-from test.support import requires
-from tkinter import Tk
-
-
-class Test(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.update_idletasks()
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- bar = statusbar.MultiStatusBar(self.root)
- self.assertEqual(bar.labels, {})
-
- def test_set_label(self):
- bar = statusbar.MultiStatusBar(self.root)
- bar.set_label('left', text='sometext', width=10)
- self.assertIn('left', bar.labels)
- left = bar.labels['left']
- self.assertEqual(left['text'], 'sometext')
- self.assertEqual(left['width'], 10)
- bar.set_label('left', text='revised text')
- self.assertEqual(left['text'], 'revised text')
- bar.set_label('right', text='correct text')
- self.assertEqual(bar.labels['right']['text'], 'correct text')
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_text.py b/Lib/idlelib/idle_test/test_text.py
index 0f31179..50d3fac 100644
--- a/Lib/idlelib/idle_test/test_text.py
+++ b/Lib/idlelib/idle_test/test_text.py
@@ -1,19 +1,17 @@
-''' Test mock_tk.Text class against tkinter.Text class
-
-Run same tests with both by creating a mixin class.
-'''
+# Test mock_tk.Text class against tkinter.Text class by running same tests with both.
import unittest
-from test.support import requires
+from test.test_support import requires
+
from _tkinter import TclError
class TextTest(object):
- "Define items common to both sets of tests."
- hw = 'hello\nworld' # Several tests insert this after initialization.
+ hw = 'hello\nworld' # usual initial insert after initialization
hwn = hw+'\n' # \n present at initialization, before insert
- # setUpClass defines cls.Text and maybe cls.root.
- # setUp defines self.text from Text and maybe root.
+ Text = None
+ def setUp(self):
+ self.text = self.Text()
def test_init(self):
self.assertEqual(self.text.get('1.0'), '\n')
@@ -198,10 +196,6 @@ class MockTextTest(TextTest, unittest.TestCase):
from idlelib.idle_test.mock_tk import Text
cls.Text = Text
- def setUp(self):
- self.text = self.Text()
-
-
def test_decode(self):
# test endflags (-1, 0) not tested by test_index (which uses +1)
decode = self.text._decode
@@ -219,7 +213,7 @@ class TkTextTest(TextTest, unittest.TestCase):
@classmethod
def setUpClass(cls):
requires('gui')
- from tkinter import Tk, Text
+ from Tkinter import Tk, Text
cls.Text = Text
cls.root = Tk()
@@ -228,9 +222,6 @@ class TkTextTest(TextTest, unittest.TestCase):
cls.root.destroy()
del cls.root
- def setUp(self):
- self.text = self.Text(self.root)
-
if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
diff --git a/Lib/idlelib/idle_test/test_textview.py b/Lib/idlelib/idle_test/test_textview.py
index 7189378..fa437fc 100644
--- a/Lib/idlelib/idle_test/test_textview.py
+++ b/Lib/idlelib/idle_test/test_textview.py
@@ -1,232 +1,95 @@
-"""Test textview, coverage 100%.
+'''Test the functions and main class method of textView.py.'''
-Since all methods and functions create (or destroy) a ViewWindow, which
-is a widget containing a widget, etcetera, all tests must be gui tests.
-Using mock Text would not change this. Other mocks are used to retrieve
-information about calls.
-"""
-from idlelib import textview as tv
-from test.support import requires
-requires('gui')
-
-import os
import unittest
-from tkinter import Tk, TclError, CHAR, NONE, WORD
-from tkinter.ttk import Button
+import os
+from test.test_support import requires
+from Tkinter import Tk
+from idlelib import textView as tv
from idlelib.idle_test.mock_idle import Func
-from idlelib.idle_test.mock_tk import Mbox_func
-
-def setUpModule():
- global root
- root = Tk()
- root.withdraw()
-
-def tearDownModule():
- global root
- root.update_idletasks()
- root.destroy()
- del root
-
-# If we call ViewWindow or wrapper functions with defaults
-# modal=True, _utest=False, test hangs on call to wait_window.
-# Have also gotten tk error 'can't invoke "event" command'.
+from idlelib.idle_test.mock_tk import Mbox
-class VW(tv.ViewWindow): # Used in ViewWindowTest.
+class TV(tv.TextViewer): # Use in TextViewTest
transient = Func()
grab_set = Func()
wait_window = Func()
-
-# Call wrapper class VW with mock wait_window.
-class ViewWindowTest(unittest.TestCase):
-
- def setUp(self):
- VW.transient.__init__()
- VW.grab_set.__init__()
- VW.wait_window.__init__()
-
- def test_init_modal(self):
- view = VW(root, 'Title', 'test text')
- self.assertTrue(VW.transient.called)
- self.assertTrue(VW.grab_set.called)
- self.assertTrue(VW.wait_window.called)
- view.ok()
-
- def test_init_nonmodal(self):
- view = VW(root, 'Title', 'test text', modal=False)
- self.assertFalse(VW.transient.called)
- self.assertFalse(VW.grab_set.called)
- self.assertFalse(VW.wait_window.called)
- view.ok()
-
- def test_ok(self):
- view = VW(root, 'Title', 'test text', modal=False)
- view.destroy = Func()
- view.ok()
- self.assertTrue(view.destroy.called)
- del view.destroy # Unmask real function.
- view.destroy()
-
-
-class AutoHideScrollbarTest(unittest.TestCase):
- # Method set is tested in ScrollableTextFrameTest
- def test_forbidden_geometry(self):
- scroll = tv.AutoHideScrollbar(root)
- self.assertRaises(TclError, scroll.pack)
- self.assertRaises(TclError, scroll.place)
-
-
-class ScrollableTextFrameTest(unittest.TestCase):
+class textviewClassTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
- cls.root = root = Tk()
- root.withdraw()
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
@classmethod
def tearDownClass(cls):
- cls.root.update_idletasks()
cls.root.destroy()
del cls.root
- def make_frame(self, wrap=NONE, **kwargs):
- frame = tv.ScrollableTextFrame(self.root, wrap=wrap, **kwargs)
- def cleanup_frame():
- frame.update_idletasks()
- frame.destroy()
- self.addCleanup(cleanup_frame)
- return frame
-
- def test_line1(self):
- frame = self.make_frame()
- frame.text.insert('1.0', 'test text')
- self.assertEqual(frame.text.get('1.0', '1.end'), 'test text')
+ def setUp(self):
+ TV.transient.__init__()
+ TV.grab_set.__init__()
+ TV.wait_window.__init__()
- def test_horiz_scrollbar(self):
- # The horizontal scrollbar should be shown/hidden according to
- # the 'wrap' setting: It should only be shown when 'wrap' is
- # set to NONE.
+ def test_init_modal(self):
+ view = TV(self.root, 'Title', 'test text')
+ self.assertTrue(TV.transient.called)
+ self.assertTrue(TV.grab_set.called)
+ self.assertTrue(TV.wait_window.called)
+ view.Ok()
- # wrap = NONE -> with horizontal scrolling
- frame = self.make_frame(wrap=NONE)
- self.assertEqual(frame.text.cget('wrap'), NONE)
- self.assertIsNotNone(frame.xscroll)
+ def test_init_nonmodal(self):
+ view = TV(self.root, 'Title', 'test text', modal=False)
+ self.assertFalse(TV.transient.called)
+ self.assertFalse(TV.grab_set.called)
+ self.assertFalse(TV.wait_window.called)
+ view.Ok()
- # wrap != NONE -> no horizontal scrolling
- for wrap in [CHAR, WORD]:
- with self.subTest(wrap=wrap):
- frame = self.make_frame(wrap=wrap)
- self.assertEqual(frame.text.cget('wrap'), wrap)
- self.assertIsNone(frame.xscroll)
+ def test_ok(self):
+ view = TV(self.root, 'Title', 'test text', modal=False)
+ view.destroy = Func()
+ view.Ok()
+ self.assertTrue(view.destroy.called)
+ del view.destroy # Unmask the real function.
+ view.destroy()
-class ViewFrameTest(unittest.TestCase):
+class ViewFunctionTest(unittest.TestCase):
@classmethod
def setUpClass(cls):
- cls.root = root = Tk()
- root.withdraw()
- cls.frame = tv.ViewFrame(root, 'test text')
+ requires('gui')
+ cls.root = Tk()
+ cls.root.withdraw()
+ cls.orig_mbox = tv.tkMessageBox
+ tv.tkMessageBox = Mbox
@classmethod
def tearDownClass(cls):
- del cls.frame
- cls.root.update_idletasks()
cls.root.destroy()
del cls.root
-
- def test_line1(self):
- get = self.frame.text.get
- self.assertEqual(get('1.0', '1.end'), 'test text')
-
-
-# Call ViewWindow with modal=False.
-class ViewFunctionTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.orig_error = tv.showerror
- tv.showerror = Mbox_func()
-
- @classmethod
- def tearDownClass(cls):
- tv.showerror = cls.orig_error
- del cls.orig_error
+ tv.tkMessageBox = cls.orig_mbox
+ del cls.orig_mbox
def test_view_text(self):
- view = tv.view_text(root, 'Title', 'test text', modal=False)
- self.assertIsInstance(view, tv.ViewWindow)
- self.assertIsInstance(view.viewframe, tv.ViewFrame)
- view.viewframe.ok()
+ # If modal True, get tkinter error 'can't invoke "event" command'.
+ view = tv.view_text(self.root, 'Title', 'test text', modal=False)
+ self.assertIsInstance(view, tv.TextViewer)
+ view.Ok()
def test_view_file(self):
- view = tv.view_file(root, 'Title', __file__, 'ascii', modal=False)
- self.assertIsInstance(view, tv.ViewWindow)
- self.assertIsInstance(view.viewframe, tv.ViewFrame)
- get = view.viewframe.textframe.text.get
- self.assertIn('Test', get('1.0', '1.end'))
- view.ok()
-
- def test_bad_file(self):
- # Mock showerror will be used; view_file will return None.
- view = tv.view_file(root, 'Title', 'abc.xyz', 'ascii', modal=False)
- self.assertIsNone(view)
- self.assertEqual(tv.showerror.title, 'File Load Error')
-
- def test_bad_encoding(self):
- p = os.path
- fn = p.abspath(p.join(p.dirname(__file__), '..', 'CREDITS.txt'))
- view = tv.view_file(root, 'Title', fn, 'ascii', modal=False)
+ test_dir = os.path.dirname(__file__)
+ testfile = os.path.join(test_dir, 'test_textview.py')
+ view = tv.view_file(self.root, 'Title', testfile, modal=False)
+ self.assertIsInstance(view, tv.TextViewer)
+ self.assertIn('Test', view.textView.get('1.0', '1.end'))
+ view.Ok()
+
+ # Mock messagebox will be used; view_file will return None.
+ testfile = os.path.join(test_dir, '../notthere.py')
+ view = tv.view_file(self.root, 'Title', testfile, modal=False)
self.assertIsNone(view)
- self.assertEqual(tv.showerror.title, 'Unicode Decode Error')
-
- def test_nowrap(self):
- view = tv.view_text(root, 'Title', 'test', modal=False, wrap='none')
- text_widget = view.viewframe.textframe.text
- self.assertEqual(text_widget.cget('wrap'), 'none')
-
-
-# Call ViewWindow with _utest=True.
-class ButtonClickTest(unittest.TestCase):
-
- def setUp(self):
- self.view = None
- self.called = False
-
- def tearDown(self):
- if self.view:
- self.view.destroy()
-
- def test_view_text_bind_with_button(self):
- def _command():
- self.called = True
- self.view = tv.view_text(root, 'TITLE_TEXT', 'COMMAND', _utest=True)
- button = Button(root, text='BUTTON', command=_command)
- button.invoke()
- self.addCleanup(button.destroy)
-
- self.assertEqual(self.called, True)
- self.assertEqual(self.view.title(), 'TITLE_TEXT')
- self.assertEqual(self.view.viewframe.textframe.text.get('1.0', '1.end'),
- 'COMMAND')
-
- def test_view_file_bind_with_button(self):
- def _command():
- self.called = True
- self.view = tv.view_file(root, 'TITLE_FILE', __file__,
- encoding='ascii', _utest=True)
- button = Button(root, text='BUTTON', command=_command)
- button.invoke()
- self.addCleanup(button.destroy)
-
- self.assertEqual(self.called, True)
- self.assertEqual(self.view.title(), 'TITLE_FILE')
- get = self.view.viewframe.textframe.text.get
- with open(__file__) as f:
- self.assertEqual(get('1.0', '1.end'), f.readline().strip())
- f.readline()
- self.assertEqual(get('3.0', '3.end'), f.readline().strip())
if __name__ == '__main__':
diff --git a/Lib/idlelib/idle_test/test_tooltip.py b/Lib/idlelib/idle_test/test_tooltip.py
deleted file mode 100644
index c616d4f..0000000
--- a/Lib/idlelib/idle_test/test_tooltip.py
+++ /dev/null
@@ -1,161 +0,0 @@
-"""Test tooltip, coverage 100%.
-
-Coverage is 100% after excluding 6 lines with "# pragma: no cover".
-They involve TclErrors that either should or should not happen in a
-particular situation, and which are 'pass'ed if they do.
-"""
-
-from idlelib.tooltip import TooltipBase, Hovertip
-from test.support import requires
-requires('gui')
-
-from functools import wraps
-import time
-from tkinter import Button, Tk, Toplevel
-import unittest
-
-
-def setUpModule():
- global root
- root = Tk()
-
-def tearDownModule():
- global root
- root.update_idletasks()
- root.destroy()
- del root
-
-
-def add_call_counting(func):
- @wraps(func)
- def wrapped_func(*args, **kwargs):
- wrapped_func.call_args_list.append((args, kwargs))
- return func(*args, **kwargs)
- wrapped_func.call_args_list = []
- return wrapped_func
-
-
-def _make_top_and_button(testobj):
- global root
- top = Toplevel(root)
- testobj.addCleanup(top.destroy)
- top.title("Test tooltip")
- button = Button(top, text='ToolTip test button')
- button.pack()
- testobj.addCleanup(button.destroy)
- top.lift()
- return top, button
-
-
-class ToolTipBaseTest(unittest.TestCase):
- def setUp(self):
- self.top, self.button = _make_top_and_button(self)
-
- def test_base_class_is_unusable(self):
- global root
- top = Toplevel(root)
- self.addCleanup(top.destroy)
-
- button = Button(top, text='ToolTip test button')
- button.pack()
- self.addCleanup(button.destroy)
-
- with self.assertRaises(NotImplementedError):
- tooltip = TooltipBase(button)
- tooltip.showtip()
-
-
-class HovertipTest(unittest.TestCase):
- def setUp(self):
- self.top, self.button = _make_top_and_button(self)
-
- def is_tipwindow_shown(self, tooltip):
- return tooltip.tipwindow and tooltip.tipwindow.winfo_viewable()
-
- def test_showtip(self):
- tooltip = Hovertip(self.button, 'ToolTip text')
- self.addCleanup(tooltip.hidetip)
- self.assertFalse(self.is_tipwindow_shown(tooltip))
- tooltip.showtip()
- self.assertTrue(self.is_tipwindow_shown(tooltip))
-
- def test_showtip_twice(self):
- tooltip = Hovertip(self.button, 'ToolTip text')
- self.addCleanup(tooltip.hidetip)
- self.assertFalse(self.is_tipwindow_shown(tooltip))
- tooltip.showtip()
- self.assertTrue(self.is_tipwindow_shown(tooltip))
- orig_tipwindow = tooltip.tipwindow
- tooltip.showtip()
- self.assertTrue(self.is_tipwindow_shown(tooltip))
- self.assertIs(tooltip.tipwindow, orig_tipwindow)
-
- def test_hidetip(self):
- tooltip = Hovertip(self.button, 'ToolTip text')
- self.addCleanup(tooltip.hidetip)
- tooltip.showtip()
- tooltip.hidetip()
- self.assertFalse(self.is_tipwindow_shown(tooltip))
-
- def test_showtip_on_mouse_enter_no_delay(self):
- tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None)
- self.addCleanup(tooltip.hidetip)
- tooltip.showtip = add_call_counting(tooltip.showtip)
- root.update()
- self.assertFalse(self.is_tipwindow_shown(tooltip))
- self.button.event_generate('<Enter>', x=0, y=0)
- root.update()
- self.assertTrue(self.is_tipwindow_shown(tooltip))
- self.assertGreater(len(tooltip.showtip.call_args_list), 0)
-
- def test_hover_with_delay(self):
- # Run multiple tests requiring an actual delay simultaneously.
-
- # Test #1: A hover tip with a non-zero delay appears after the delay.
- tooltip1 = Hovertip(self.button, 'ToolTip text', hover_delay=100)
- self.addCleanup(tooltip1.hidetip)
- tooltip1.showtip = add_call_counting(tooltip1.showtip)
- root.update()
- self.assertFalse(self.is_tipwindow_shown(tooltip1))
- self.button.event_generate('<Enter>', x=0, y=0)
- root.update()
- self.assertFalse(self.is_tipwindow_shown(tooltip1))
-
- # Test #2: A hover tip with a non-zero delay doesn't appear when
- # the mouse stops hovering over the base widget before the delay
- # expires.
- tooltip2 = Hovertip(self.button, 'ToolTip text', hover_delay=100)
- self.addCleanup(tooltip2.hidetip)
- tooltip2.showtip = add_call_counting(tooltip2.showtip)
- root.update()
- self.button.event_generate('<Enter>', x=0, y=0)
- root.update()
- self.button.event_generate('<Leave>', x=0, y=0)
- root.update()
-
- time.sleep(0.15)
- root.update()
-
- # Test #1 assertions.
- self.assertTrue(self.is_tipwindow_shown(tooltip1))
- self.assertGreater(len(tooltip1.showtip.call_args_list), 0)
-
- # Test #2 assertions.
- self.assertFalse(self.is_tipwindow_shown(tooltip2))
- self.assertEqual(tooltip2.showtip.call_args_list, [])
-
- def test_hidetip_on_mouse_leave(self):
- tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None)
- self.addCleanup(tooltip.hidetip)
- tooltip.showtip = add_call_counting(tooltip.showtip)
- root.update()
- self.button.event_generate('<Enter>', x=0, y=0)
- root.update()
- self.button.event_generate('<Leave>', x=0, y=0)
- root.update()
- self.assertFalse(self.is_tipwindow_shown(tooltip))
- self.assertGreater(len(tooltip.showtip.call_args_list), 0)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_tree.py b/Lib/idlelib/idle_test/test_tree.py
deleted file mode 100644
index b3e4c10..0000000
--- a/Lib/idlelib/idle_test/test_tree.py
+++ /dev/null
@@ -1,60 +0,0 @@
-"Test tree. coverage 56%."
-
-from idlelib import tree
-import unittest
-from test.support import requires
-requires('gui')
-from tkinter import Tk, EventType, SCROLL
-
-
-class TreeTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- # Start with code slightly adapted from htest.
- sc = tree.ScrolledCanvas(
- self.root, bg="white", highlightthickness=0, takefocus=1)
- sc.frame.pack(expand=1, fill="both", side='left')
- item = tree.FileTreeItem(tree.ICONDIR)
- node = tree.TreeNode(sc.canvas, None, item)
- node.expand()
-
-
-class TestScrollEvent(unittest.TestCase):
-
- def test_wheel_event(self):
- # Fake widget class containing `yview` only.
- class _Widget:
- def __init__(widget, *expected):
- widget.expected = expected
- def yview(widget, *args):
- self.assertTupleEqual(widget.expected, args)
- # Fake event class
- class _Event:
- pass
- # (type, delta, num, amount)
- tests = ((EventType.MouseWheel, 120, -1, -5),
- (EventType.MouseWheel, -120, -1, 5),
- (EventType.ButtonPress, -1, 4, -5),
- (EventType.ButtonPress, -1, 5, 5))
-
- event = _Event()
- for ty, delta, num, amount in tests:
- event.type = ty
- event.delta = delta
- event.num = num
- res = tree.wheel_event(event, _Widget(SCROLL, amount, "units"))
- self.assertEqual(res, "break")
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_undo.py b/Lib/idlelib/idle_test/test_undo.py
deleted file mode 100644
index beb5b58..0000000
--- a/Lib/idlelib/idle_test/test_undo.py
+++ /dev/null
@@ -1,135 +0,0 @@
-"Test undo, coverage 77%."
-# Only test UndoDelegator so far.
-
-from idlelib.undo import UndoDelegator
-import unittest
-from test.support import requires
-requires('gui')
-
-from unittest.mock import Mock
-from tkinter import Text, Tk
-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.delegator.bell = Mock()
- self.percolator.insertfilter(self.delegator)
-
- 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 221068c..da1d8a1 100644
--- a/Lib/idlelib/idle_test/test_warning.py
+++ b/Lib/idlelib/idle_test/test_warning.py
@@ -1,23 +1,25 @@
-'''Test warnings replacement in pyshell.py and run.py.
+'''Test warnings replacement in PyShell.py and run.py.
This file could be expanded to include traceback overrides
(in same two modules). If so, change name.
Revise if output destination changes (http://bugs.python.org/issue18318).
Make sure warnings module is left unaltered (http://bugs.python.org/issue18081).
'''
-from idlelib import run
-from idlelib import pyshell as shell
+
import unittest
-from test.support import captured_stderr
-import warnings
+from test.test_support import captured_stderr
+import warnings
# Try to capture default showwarning before Idle modules are imported.
showwarning = warnings.showwarning
# But if we run this file within idle, we are in the middle of the run.main loop
# and default showwarnings has already been replaced.
running_in_idle = 'idle' in showwarning.__name__
-# The following was generated from pyshell.idle_formatwarning
+from idlelib import run
+from idlelib import PyShell as shell
+
+# The following was generated from PyShell.idle_formatwarning
# and checked as matching expectation.
idlemsg = '''
Warning (from warnings module):
@@ -27,7 +29,6 @@ UserWarning: Test
'''
shellmsg = idlemsg + ">>> "
-
class RunWarnTest(unittest.TestCase):
@unittest.skipIf(running_in_idle, "Does not work when run within Idle.")
@@ -45,7 +46,6 @@ class RunWarnTest(unittest.TestCase):
# The following uses .splitlines to erase line-ending differences
self.assertEqual(idlemsg.splitlines(), f.getvalue().splitlines())
-
class ShellWarnTest(unittest.TestCase):
@unittest.skipIf(running_in_idle, "Does not work when run within Idle.")
@@ -70,4 +70,4 @@ class ShellWarnTest(unittest.TestCase):
if __name__ == '__main__':
- unittest.main(verbosity=2)
+ unittest.main(verbosity=2, exit=False)
diff --git a/Lib/idlelib/idle_test/test_redirector.py b/Lib/idlelib/idle_test/test_widgetredir.py
index a97b300..e35ea41 100644
--- a/Lib/idlelib/idle_test/test_redirector.py
+++ b/Lib/idlelib/idle_test/test_widgetredir.py
@@ -1,10 +1,12 @@
-"Test redirector, coverage 100%."
+"""Unittest for idlelib.WidgetRedirector
-from idlelib.redirector import WidgetRedirector
+100% coverage
+"""
+from test.test_support import requires
import unittest
-from test.support import requires
-from tkinter import Tk, Text, TclError
from idlelib.idle_test.mock_idle import Func
+from Tkinter import Tk, Text, TclError
+from idlelib.WidgetRedirector import WidgetRedirector
class InitCloseTest(unittest.TestCase):
@@ -49,7 +51,6 @@ class WidgetRedirectorTest(unittest.TestCase):
@classmethod
def tearDownClass(cls):
del cls.text
- cls.root.update_idletasks()
cls.root.destroy()
del cls.root
@@ -118,5 +119,6 @@ class WidgetRedirectorTest(unittest.TestCase):
self.assertEqual(self.root.call(self.text._w, 'insert', 'boo'), '')
+
if __name__ == '__main__':
unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_window.py b/Lib/idlelib/idle_test/test_window.py
deleted file mode 100644
index 5a2645b..0000000
--- a/Lib/idlelib/idle_test/test_window.py
+++ /dev/null
@@ -1,45 +0,0 @@
-"Test window, coverage 47%."
-
-from idlelib import window
-import unittest
-from test.support import requires
-from tkinter import Tk
-
-
-class WindowListTest(unittest.TestCase):
-
- def test_init(self):
- wl = window.WindowList()
- self.assertEqual(wl.dict, {})
- self.assertEqual(wl.callbacks, [])
-
- # Further tests need mock Window.
-
-
-class ListedToplevelTest(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- window.registry = set()
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
-
- @classmethod
- def tearDownClass(cls):
- window.registry = window.WindowList()
- cls.root.update_idletasks()
-## for id in cls.root.tk.call('after', 'info'):
-## cls.root.after_cancel(id) # Need for EditorWindow.
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
-
- win = window.ListedToplevel(self.root)
- self.assertIn(win, window.registry)
- self.assertEqual(win.focused_widget, win)
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)
diff --git a/Lib/idlelib/idle_test/test_zoomheight.py b/Lib/idlelib/idle_test/test_zoomheight.py
deleted file mode 100644
index aa5bdfb..0000000
--- a/Lib/idlelib/idle_test/test_zoomheight.py
+++ /dev/null
@@ -1,39 +0,0 @@
-"Test zoomheight, coverage 66%."
-# Some code is system dependent.
-
-from idlelib import zoomheight
-import unittest
-from test.support import requires
-from tkinter import Tk
-from idlelib.editor import EditorWindow
-
-
-class Test(unittest.TestCase):
-
- @classmethod
- def setUpClass(cls):
- requires('gui')
- cls.root = Tk()
- cls.root.withdraw()
- cls.editwin = EditorWindow(root=cls.root)
-
- @classmethod
- def tearDownClass(cls):
- cls.editwin._close()
- cls.root.update_idletasks()
- for id in cls.root.tk.call('after', 'info'):
- cls.root.after_cancel(id) # Need for EditorWindow.
- cls.root.destroy()
- del cls.root
-
- def test_init(self):
- zoom = zoomheight.ZoomHeight(self.editwin)
- self.assertIs(zoom.editwin, self.editwin)
-
- def test_zoom_height_event(self):
- zoom = zoomheight.ZoomHeight(self.editwin)
- zoom.zoom_height_event()
-
-
-if __name__ == '__main__':
- unittest.main(verbosity=2)