using for loop to install conda package
This commit is contained in:
238
.CondaPkg/env/Lib/idlelib/idle_test/README.txt
vendored
Normal file
238
.CondaPkg/env/Lib/idlelib/idle_test/README.txt
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
README FOR IDLE TESTS IN IDLELIB.IDLE_TEST
|
||||
|
||||
0. Quick Start
|
||||
|
||||
Automated unit tests were added in 3.3 for Python 3.x.
|
||||
To run the tests from a command line:
|
||||
|
||||
python -m test.test_idle
|
||||
|
||||
Human-mediated tests were added later in 3.4.
|
||||
|
||||
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.
|
||||
|
||||
Remove the imports of requires and tkinter if not needed. Otherwise,
|
||||
add to the tkinter imports as needed.
|
||||
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
if __name__ == "__main__":
|
||||
from unittest import main
|
||||
main('idlelib.idle_test.test_abc', verbosity=2, exit=False)
|
||||
|
||||
The ', exit=False' is only needed if an htest follows.
|
||||
|
||||
|
||||
|
||||
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.
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = tk.Tk()
|
||||
cls.text = tk.Text(root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.text
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
The update_idletasks call is sometimes needed to prevent the following
|
||||
warning either when running a test alone or as part of the test suite
|
||||
(#27196). 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
|
||||
|
||||
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 on Windows by a service that is not allowed
|
||||
to interact with the graphical environment.
|
||||
|
||||
- The tests are being run on Linux and X Windows is not available.
|
||||
|
||||
- The tests are being run on Mac OSX in a process that cannot make a
|
||||
window manager connection.
|
||||
|
||||
- tkinter.Tk cannot be successfully instantiated for some reason.
|
||||
|
||||
- test.support.use_resources has been set by something other than
|
||||
regrtest.py and does not contain "gui".
|
||||
|
||||
Tests of non-GUI operations should avoid creating tk widgets. Incidental
|
||||
uses of tk variables and messageboxes can be replaced by the mock
|
||||
classes in idle_test/mock_tk.py. The mock text handles some uses of the
|
||||
tk Text widget.
|
||||
|
||||
|
||||
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.
|
||||
|
||||
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.)
|
||||
|
||||
python -m idlelib.xyz
|
||||
python -m idlelib.idle_test.test_xyz
|
||||
|
||||
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'.
|
||||
|
||||
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 '*'.
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
|
||||
|
||||
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:
|
||||
|
||||
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.)
|
||||
17
.CondaPkg/env/Lib/idlelib/idle_test/__init__.py
vendored
Normal file
17
.CondaPkg/env/Lib/idlelib/idle_test/__init__.py
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'''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.
|
||||
'''
|
||||
from os.path import dirname
|
||||
|
||||
def load_tests(loader, standard_tests, pattern):
|
||||
this_dir = dirname(__file__)
|
||||
top_dir = dirname(dirname(this_dir))
|
||||
package_tests = loader.discover(start_dir=this_dir, pattern='test*.py',
|
||||
top_level_dir=top_dir)
|
||||
standard_tests.addTests(package_tests)
|
||||
return standard_tests
|
||||
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/__init__.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/htest.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/htest.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/mock_idle.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/mock_idle.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/mock_tk.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/mock_tk.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/template.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/template.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_autocomplete.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_autocomplete.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_autocomplete_w.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_autocomplete_w.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_autoexpand.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_autoexpand.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_browser.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_browser.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_calltip.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_calltip.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_calltip_w.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_calltip_w.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_codecontext.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_codecontext.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_colorizer.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_colorizer.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_config.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_config.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_config_key.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_config_key.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_configdialog.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_configdialog.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_debugger.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_debugger.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_debugger_r.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_debugger_r.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_debugobj.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_debugobj.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_debugobj_r.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_debugobj_r.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_delegator.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_delegator.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_editmenu.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_editmenu.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_editor.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_editor.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_filelist.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_filelist.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_format.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_format.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_grep.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_grep.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_help.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_help.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_help_about.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_help_about.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_history.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_history.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_hyperparser.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_hyperparser.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_iomenu.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_iomenu.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_macosx.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_macosx.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_mainmenu.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_mainmenu.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_multicall.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_multicall.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_outwin.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_outwin.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_parenmatch.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_parenmatch.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_pathbrowser.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_pathbrowser.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_percolator.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_percolator.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_pyparse.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_pyparse.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_pyshell.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_pyshell.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_query.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_query.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_redirector.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_redirector.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_replace.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_replace.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_rpc.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_rpc.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_run.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_run.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_runscript.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_runscript.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_scrolledlist.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_scrolledlist.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_search.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_search.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_searchbase.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_searchbase.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_searchengine.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_searchengine.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_sidebar.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_sidebar.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_squeezer.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_squeezer.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_stackviewer.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_stackviewer.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_statusbar.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_statusbar.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_text.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_text.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_textview.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_textview.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_tooltip.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_tooltip.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_tree.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_tree.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_undo.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_undo.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_util.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_util.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_warning.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_warning.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_window.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_window.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_zoomheight.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_zoomheight.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_zzdummy.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/test_zzdummy.cpython-311.pyc
vendored
Normal file
Binary file not shown.
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/tkinter_testing_utils.cpython-311.pyc
vendored
Normal file
BIN
.CondaPkg/env/Lib/idlelib/idle_test/__pycache__/tkinter_testing_utils.cpython-311.pyc
vendored
Normal file
Binary file not shown.
4
.CondaPkg/env/Lib/idlelib/idle_test/example_noext
vendored
Normal file
4
.CondaPkg/env/Lib/idlelib/idle_test/example_noext
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
#!usr/bin/env python
|
||||
|
||||
def example_function(some_argument):
|
||||
pass
|
||||
2
.CondaPkg/env/Lib/idlelib/idle_test/example_stub.pyi
vendored
Normal file
2
.CondaPkg/env/Lib/idlelib/idle_test/example_stub.pyi
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
class Example:
|
||||
def method(self, argument1: str, argument2: list[int]) -> None: ...
|
||||
445
.CondaPkg/env/Lib/idlelib/idle_test/htest.py
vendored
Normal file
445
.CondaPkg/env/Lib/idlelib/idle_test/htest.py
vendored
Normal file
@@ -0,0 +1,445 @@
|
||||
'''Run human tests of Idle's window, dialog, and popup widgets.
|
||||
|
||||
run(*tests)
|
||||
Create a master Tk window. Within that, run each callable in tests
|
||||
after finding the matching test spec in this file. If tests is empty,
|
||||
run an htest for each spec dict in this file after finding the matching
|
||||
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).
|
||||
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
|
||||
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
|
||||
function names, such as _editor_window', should start with '_'.
|
||||
|
||||
|
||||
End the module with
|
||||
|
||||
if __name__ == '__main__':
|
||||
<unittest, if there is one>
|
||||
from idlelib.idle_test.htest import run
|
||||
run(X)
|
||||
|
||||
To have wrapper functions and test invocation code ignored by coveragepy
|
||||
reports, put '# htest #' on the def statement header line.
|
||||
|
||||
def _wrapper(parent): # htest #
|
||||
|
||||
Also make sure that the 'if __name__' line matches the above. Then have
|
||||
make sure that .coveragerc includes the following.
|
||||
|
||||
[report]
|
||||
exclude_lines =
|
||||
.*# htest #
|
||||
if __name__ == .__main__.:
|
||||
|
||||
(The "." instead of "'" is intentional and necessary.)
|
||||
|
||||
|
||||
To run any X, this file must contain a matching instance of the
|
||||
following template, with X.__name__ prepended to '_spec'.
|
||||
When all tests are run, the prefix is use to get X.
|
||||
|
||||
_spec = {
|
||||
'file': '',
|
||||
'kwds': {'title': ''},
|
||||
'msg': ""
|
||||
}
|
||||
|
||||
file (no .py): run() imports file.py.
|
||||
kwds: augmented with {'parent':root} and passed to X as **kwds.
|
||||
title: an example kwd; some widgets need this, delete if not.
|
||||
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)
|
||||
'''
|
||||
|
||||
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()
|
||||
|
||||
AboutDialog_spec = {
|
||||
'file': 'help_about',
|
||||
'kwds': {'title': 'help_about test',
|
||||
'_htest': True,
|
||||
},
|
||||
'msg': "Click on URL to open in default browser.\n"
|
||||
"Verify x.y.z versions and test each button, including Close.\n "
|
||||
}
|
||||
|
||||
# TODO implement ^\; adding '<Control-Key-\\>' to function does not work.
|
||||
_calltip_window_spec = {
|
||||
'file': 'calltip_w',
|
||||
'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',
|
||||
'kwds': {},
|
||||
'msg': "Inspect names of module, class(with superclass if "
|
||||
"applicable), methods and functions.\nToggle nested items.\n"
|
||||
"Double clicking on items prints a traceback for an exception "
|
||||
"that is ignored."
|
||||
}
|
||||
|
||||
_color_delegator_spec = {
|
||||
'file': 'colorizer',
|
||||
'kwds': {},
|
||||
'msg': "The text is sample Python code.\n"
|
||||
"Ensure components like comments, keywords, builtins,\n"
|
||||
"string, definitions, and break are correctly colored.\n"
|
||||
"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',
|
||||
'kwds': {'title': 'ConfigDialogTest',
|
||||
'_htest': True,},
|
||||
'msg': "IDLE preferences dialog.\n"
|
||||
"In the 'Fonts/Tabs' tab, changing font face, should update the "
|
||||
"font face of the text in the area below it.\nIn the "
|
||||
"'Highlighting' tab, try different color schemes. Clicking "
|
||||
"items in the sample program should update the choices above it."
|
||||
"\nIn the 'Keys', 'General' and 'Extensions' tabs, test settings "
|
||||
"of interest."
|
||||
"\n[Ok] to close the dialog.[Apply] to apply the settings and "
|
||||
"and [Cancel] to revert all changes.\nRe-run the test to ensure "
|
||||
"changes made have persisted."
|
||||
}
|
||||
|
||||
# TODO Improve message
|
||||
_dyn_option_menu_spec = {
|
||||
'file': 'dynoption',
|
||||
'kwds': {},
|
||||
'msg': "Select one of the many options in the 'old option set'.\n"
|
||||
"Click the button to change the option set.\n"
|
||||
"Select one of the many options in the 'new option set'."
|
||||
}
|
||||
|
||||
# TODO edit wrapper
|
||||
_editor_window_spec = {
|
||||
'file': 'editor',
|
||||
'kwds': {},
|
||||
'msg': "Test editor functions of interest.\n"
|
||||
"Best to close editor first."
|
||||
}
|
||||
|
||||
GetKeysDialog_spec = {
|
||||
'file': 'config_key',
|
||||
'kwds': {'title': 'Test keybindings',
|
||||
'action': 'find-again',
|
||||
'current_key_sequences': [['<Control-Key-g>', '<Key-F3>', '<Control-Key-G>']],
|
||||
'_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 "
|
||||
"entry is used."
|
||||
}
|
||||
|
||||
_grep_dialog_spec = {
|
||||
'file': 'grep',
|
||||
'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 "
|
||||
"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',
|
||||
'kwds': {},
|
||||
'msg': "Test the following bindings.\n"
|
||||
"<Control-o> to open file from dialog.\n"
|
||||
"Edit the file.\n"
|
||||
"<Control-p> to print the file.\n"
|
||||
"<Control-s> to save the file.\n"
|
||||
"<Alt-s> to save-as another file.\n"
|
||||
"<Control-c> to save-copy-as another file.\n"
|
||||
"Check that changes were saved by opening the file elsewhere."
|
||||
}
|
||||
|
||||
_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',
|
||||
'kwds': {},
|
||||
'msg': "The following actions should trigger a print to console or IDLE"
|
||||
" Shell.\nEntering and leaving the text area, key entry, "
|
||||
"<Control-Key>,\n<Alt-Key-a>, <Control-Key-a>, "
|
||||
"<Alt-Control-Key-a>, \n<Control-Button-1>, <Alt-Button-1> and "
|
||||
"focusing out of the window\nare sequences to be tested."
|
||||
}
|
||||
|
||||
_multistatus_bar_spec = {
|
||||
'file': 'statusbar',
|
||||
'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',
|
||||
'kwds': {},
|
||||
'msg': "Double click on items up to the lowest level.\n"
|
||||
"Attributes of the objects and related information "
|
||||
"will be displayed side-by-side at each level."
|
||||
}
|
||||
|
||||
_path_browser_spec = {
|
||||
'file': 'pathbrowser',
|
||||
'kwds': {},
|
||||
'msg': "Test for correct display of all paths in sys.path.\n"
|
||||
"Toggle nested items up to the lowest level.\n"
|
||||
"Double clicking on an item prints a traceback\n"
|
||||
"for an exception that is ignored."
|
||||
}
|
||||
|
||||
_percolator_spec = {
|
||||
'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 "
|
||||
"output to the console or to the IDLE shell.\n"
|
||||
"If both the tracers are 'on', the output from the tracer which "
|
||||
"was switched 'on' later, should be printed first\n"
|
||||
"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',
|
||||
'kwds': {},
|
||||
'msg': "Click the 'Replace' button.\n"
|
||||
"Test various replace options in the 'Replace dialog'.\n"
|
||||
"Click [Close] or [X] to close the 'Replace Dialog'."
|
||||
}
|
||||
|
||||
_search_dialog_spec = {
|
||||
'file': 'search',
|
||||
'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',
|
||||
'kwds': {},
|
||||
'msg': "You should see a scrollable list of items\n"
|
||||
"Selecting (clicking) or double clicking an item "
|
||||
"prints the name to the console or Idle shell.\n"
|
||||
"Right clicking an item will display a popup."
|
||||
}
|
||||
|
||||
show_idlehelp_spec = {
|
||||
'file': 'help',
|
||||
'kwds': {},
|
||||
'msg': "If the help text displays, this works.\n"
|
||||
"Text is selectable. Window is scrollable."
|
||||
}
|
||||
|
||||
_stack_viewer_spec = {
|
||||
'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"
|
||||
}
|
||||
|
||||
_tooltip_spec = {
|
||||
'file': 'tooltip',
|
||||
'kwds': {},
|
||||
'msg': "Place mouse cursor over both the buttons\n"
|
||||
"A tooltip should appear with some text."
|
||||
}
|
||||
|
||||
_tree_widget_spec = {
|
||||
'file': 'tree',
|
||||
'kwds': {},
|
||||
'msg': "The canvas is scrollable.\n"
|
||||
"Click on folders up to to the lowest level."
|
||||
}
|
||||
|
||||
_undo_delegator_spec = {
|
||||
'file': 'undo',
|
||||
'kwds': {},
|
||||
'msg': "Click [Undo] to undo any action.\n"
|
||||
"Click [Redo] to redo any action.\n"
|
||||
"Click [Dump] to dump the current state "
|
||||
"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',
|
||||
'kwds': {},
|
||||
'msg': "Every text insert should be printed to the console "
|
||||
"or the IDLE shell."
|
||||
}
|
||||
|
||||
def run(*tests):
|
||||
root = tk.Tk()
|
||||
root.title('IDLE htest')
|
||||
root.resizable(0, 0)
|
||||
|
||||
# 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)
|
||||
text.config(yscrollcommand=scrollbar.set)
|
||||
scrollbar.pack(side='right', fill='y', expand=False)
|
||||
text.pack(side='left', fill='both', expand=True)
|
||||
|
||||
test_list = [] # List of tuples of the form (spec, callable widget)
|
||||
if tests:
|
||||
for test in tests:
|
||||
test_spec = globals()[test.__name__ + '_spec']
|
||||
test_spec['name'] = test.__name__
|
||||
test_list.append((test_spec, test))
|
||||
else:
|
||||
for k, d in globals().items():
|
||||
if k.endswith('_spec'):
|
||||
test_name = k[:-5]
|
||||
test_spec = d
|
||||
test_spec['name'] = test_name
|
||||
mod = import_module('idlelib.' + test_spec['file'])
|
||||
test = getattr(mod, test_name)
|
||||
test_list.append((test_spec, test))
|
||||
|
||||
test_name = tk.StringVar(root)
|
||||
callable_object = None
|
||||
test_kwds = None
|
||||
|
||||
def next_test():
|
||||
|
||||
nonlocal test_name, callable_object, test_kwds
|
||||
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'])
|
||||
|
||||
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)
|
||||
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.pack()
|
||||
next_button.pack()
|
||||
next_button.focus_set()
|
||||
root.bind('<Key-Return>', run_test)
|
||||
root.bind('<Key-Escape>', close)
|
||||
|
||||
next_test()
|
||||
root.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
run()
|
||||
61
.CondaPkg/env/Lib/idlelib/idle_test/mock_idle.py
vendored
Normal file
61
.CondaPkg/env/Lib/idlelib/idle_test/mock_idle.py
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
'''Mock classes that imitate idlelib modules or classes.
|
||||
|
||||
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.
|
||||
Mock_tk.Var and Mbox_func are special variants of this.
|
||||
'''
|
||||
def __init__(self, result=None, return_self=False):
|
||||
self.called = 0
|
||||
self.result = result
|
||||
self.return_self = return_self
|
||||
self.args = None
|
||||
self.kwds = None
|
||||
def __call__(self, *args, **kwds):
|
||||
self.called += 1
|
||||
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.
|
||||
'''
|
||||
def __init__(self, flist=None, filename=None, key=None, root=None,
|
||||
text=None): # Allow real Text with mock Editor.
|
||||
self.text = text or Text()
|
||||
self.undo = UndoDelegator()
|
||||
|
||||
def get_selection_indices(self):
|
||||
first = self.text.index('1.0')
|
||||
last = self.text.index('end')
|
||||
return first, last
|
||||
|
||||
|
||||
class UndoDelegator:
|
||||
'''Minimally imitate undo.UndoDelegator class.
|
||||
'''
|
||||
# A real undo block is only needed for user interaction.
|
||||
def undo_block_start(*args):
|
||||
pass
|
||||
def undo_block_stop(*args):
|
||||
pass
|
||||
307
.CondaPkg/env/Lib/idlelib/idle_test/mock_tk.py
vendored
Normal file
307
.CondaPkg/env/Lib/idlelib/idle_test/mock_tk.py
vendored
Normal file
@@ -0,0 +1,307 @@
|
||||
"""Classes that replace tkinter gui objects used by an object being tested.
|
||||
|
||||
A gui object is anything with a master or parent parameter, which is
|
||||
typically required in spite of what the doc strings say.
|
||||
"""
|
||||
import re
|
||||
from _tkinter import TclError
|
||||
|
||||
|
||||
class Event:
|
||||
'''Minimal mock with attributes for testing event handlers.
|
||||
|
||||
This is not a gui object, but is used as an argument for callbacks
|
||||
that access attributes of the event passed. If a callback ignores
|
||||
the event, other than the fact that is happened, pass 'event'.
|
||||
|
||||
Keyboard, mouse, window, and other sources generate Event instances.
|
||||
Event instances have the following attributes: serial (number of
|
||||
event), time (of event), type (of event as number), widget (in which
|
||||
event occurred), and x,y (position of mouse). There are other
|
||||
attributes for specific events, such as keycode for key events.
|
||||
tkinter.Event.__doc__ has more but is still not complete.
|
||||
'''
|
||||
def __init__(self, **kwds):
|
||||
"Create event with attributes needed for test"
|
||||
self.__dict__.update(kwds)
|
||||
|
||||
|
||||
class Var:
|
||||
"Use for String/Int/BooleanVar: incomplete"
|
||||
def __init__(self, master=None, value=None, name=None):
|
||||
self.master = master
|
||||
self.value = value
|
||||
self.name = name
|
||||
def set(self, value):
|
||||
self.value = value
|
||||
def get(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class Mbox_func:
|
||||
"""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.
|
||||
The test can set the result returned to ask function
|
||||
"""
|
||||
def __init__(self, result=None):
|
||||
self.result = result # Return None for all show funcs
|
||||
def __call__(self, title, message, *args, **kwds):
|
||||
# Save all args for possible examination by tester
|
||||
self.title = title
|
||||
self.message = message
|
||||
self.args = args
|
||||
self.kwds = kwds
|
||||
return self.result # Set by tester for ask functions
|
||||
|
||||
|
||||
class Mbox:
|
||||
"""Mock for tkinter.messagebox with an Mbox_func for each function.
|
||||
|
||||
Example usage in test_module.py for testing functions in module.py:
|
||||
---
|
||||
from idlelib.idle_test.mock_tk import Mbox
|
||||
import module
|
||||
|
||||
orig_mbox = module.messagebox
|
||||
showerror = Mbox.showerror # example, for attribute access in test methods
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
module.messagebox = Mbox
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
module.messagebox = orig_mbox
|
||||
---
|
||||
For 'ask' functions, set func.result return value before calling the method
|
||||
that uses the message function. When messagebox functions are the
|
||||
only GUI calls in a method, this replacement makes the method GUI-free,
|
||||
"""
|
||||
askokcancel = Mbox_func() # True or False
|
||||
askquestion = Mbox_func() # 'yes' or 'no'
|
||||
askretrycancel = Mbox_func() # True or False
|
||||
askyesno = Mbox_func() # True or False
|
||||
askyesnocancel = Mbox_func() # True, False, or None
|
||||
showerror = Mbox_func() # None
|
||||
showinfo = Mbox_func() # None
|
||||
showwarning = Mbox_func() # None
|
||||
|
||||
|
||||
class Text:
|
||||
"""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.
|
||||
The mock adds an empty string at the beginning of the list so that the
|
||||
index of actual lines start at 1, as with Tk. The methods never see this.
|
||||
Tk initializes files with a terminal \n that cannot be deleted. It is
|
||||
invisible in the sense that one cannot move the cursor beyond it.
|
||||
|
||||
This class is only tested (and valid) with strings of ascii chars.
|
||||
For testing, we are not concerned with Tk Text's treatment of,
|
||||
for instance, 0-width characters or character + accent.
|
||||
"""
|
||||
def __init__(self, master=None, cnf={}, **kw):
|
||||
'''Initialize mock, non-gui, text-only Text widget.
|
||||
|
||||
At present, all args are ignored. Almost all affect visual behavior.
|
||||
There are just a few Text-only options that affect text behavior.
|
||||
'''
|
||||
self.data = ['', '\n']
|
||||
|
||||
def index(self, index):
|
||||
"Return string version of index decoded according to current text."
|
||||
return "%s.%s" % self._decode(index, endflag=1)
|
||||
|
||||
def _decode(self, index, endflag=0):
|
||||
"""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
|
||||
self.data. For many indexes, the result is initially (1, 0).
|
||||
|
||||
The input index may have any of several possible forms:
|
||||
* line.char float: converted to 'line.char' string;
|
||||
* 'line.char' string, where line and char are decimal integers;
|
||||
* 'line.char lineend', where lineend='lineend' (and char is ignored);
|
||||
* 'line.end', where end='end' (same as above);
|
||||
* 'insert', the positions before terminal \n;
|
||||
* 'end', whose meaning depends on the endflag passed to ._endex.
|
||||
* 'sel.first' or 'sel.last', where sel is a tag -- not implemented.
|
||||
"""
|
||||
if isinstance(index, (float, bytes)):
|
||||
index = str(index)
|
||||
try:
|
||||
index=index.lower()
|
||||
except AttributeError:
|
||||
raise TclError('bad text index "%s"' % index) from None
|
||||
|
||||
lastline = len(self.data) - 1 # same as number of text lines
|
||||
if index == 'insert':
|
||||
return lastline, len(self.data[lastline]) - 1
|
||||
elif index == 'end':
|
||||
return self._endex(endflag)
|
||||
|
||||
line, char = index.split('.')
|
||||
line = int(line)
|
||||
|
||||
# Out of bounds line becomes first or last ('end') index
|
||||
if line < 1:
|
||||
return 1, 0
|
||||
elif line > lastline:
|
||||
return self._endex(endflag)
|
||||
|
||||
linelength = len(self.data[line]) -1 # position before/at \n
|
||||
if char.endswith(' lineend') or char == 'end':
|
||||
return line, linelength
|
||||
# Tk requires that ignored chars before ' lineend' be valid int
|
||||
if m := re.fullmatch(r'end-(\d*)c', char, re.A): # Used by hyperparser.
|
||||
return line, linelength - int(m.group(1))
|
||||
|
||||
# Out of bounds char becomes first or last index of line
|
||||
char = int(char)
|
||||
if char < 0:
|
||||
char = 0
|
||||
elif char > linelength:
|
||||
char = linelength
|
||||
return line, char
|
||||
|
||||
def _endex(self, endflag):
|
||||
'''Return position for 'end' or line overflow corresponding to endflag.
|
||||
|
||||
-1: position before terminal \n; for .insert(), .delete
|
||||
0: position after terminal \n; for .get, .delete index 1
|
||||
1: same viewed as beginning of non-existent next line (for .index)
|
||||
'''
|
||||
n = len(self.data)
|
||||
if endflag == 1:
|
||||
return n, 0
|
||||
else:
|
||||
n -= 1
|
||||
return n, len(self.data[n]) + endflag
|
||||
|
||||
def insert(self, index, chars):
|
||||
"Insert chars before the character at index."
|
||||
|
||||
if not chars: # ''.splitlines() is [], not ['']
|
||||
return
|
||||
chars = chars.splitlines(True)
|
||||
if chars[-1][-1] == '\n':
|
||||
chars.append('')
|
||||
line, char = self._decode(index, -1)
|
||||
before = self.data[line][:char]
|
||||
after = self.data[line][char:]
|
||||
self.data[line] = before + chars[0]
|
||||
self.data[line+1:line+1] = chars[1:]
|
||||
self.data[line+len(chars)-1] += after
|
||||
|
||||
def get(self, index1, index2=None):
|
||||
"Return slice from index1 to index2 (default is 'index1+1')."
|
||||
|
||||
startline, startchar = self._decode(index1)
|
||||
if index2 is None:
|
||||
endline, endchar = startline, startchar+1
|
||||
else:
|
||||
endline, endchar = self._decode(index2)
|
||||
|
||||
if startline == endline:
|
||||
return self.data[startline][startchar:endchar]
|
||||
else:
|
||||
lines = [self.data[startline][startchar:]]
|
||||
for i in range(startline+1, endline):
|
||||
lines.append(self.data[i])
|
||||
lines.append(self.data[endline][:endchar])
|
||||
return ''.join(lines)
|
||||
|
||||
def delete(self, index1, index2=None):
|
||||
'''Delete slice from index1 to index2 (default is 'index1+1').
|
||||
|
||||
Adjust default index2 ('index+1) for line ends.
|
||||
Do not delete the terminal \n at the very end of self.data ([-1][-1]).
|
||||
'''
|
||||
startline, startchar = self._decode(index1, -1)
|
||||
if index2 is None:
|
||||
if startchar < len(self.data[startline])-1:
|
||||
# not deleting \n
|
||||
endline, endchar = startline, startchar+1
|
||||
elif startline < len(self.data) - 1:
|
||||
# deleting non-terminal \n, convert 'index1+1 to start of next line
|
||||
endline, endchar = startline+1, 0
|
||||
else:
|
||||
# do not delete terminal \n if index1 == 'insert'
|
||||
return
|
||||
else:
|
||||
endline, endchar = self._decode(index2, -1)
|
||||
# restricting end position to insert position excludes terminal \n
|
||||
|
||||
if startline == endline and startchar < endchar:
|
||||
self.data[startline] = self.data[startline][:startchar] + \
|
||||
self.data[startline][endchar:]
|
||||
elif startline < endline:
|
||||
self.data[startline] = self.data[startline][:startchar] + \
|
||||
self.data[endline][endchar:]
|
||||
startline += 1
|
||||
for i in range(startline, endline+1):
|
||||
del self.data[startline]
|
||||
|
||||
def compare(self, index1, op, index2):
|
||||
line1, char1 = self._decode(index1)
|
||||
line2, char2 = self._decode(index2)
|
||||
if op == '<':
|
||||
return line1 < line2 or line1 == line2 and char1 < char2
|
||||
elif op == '<=':
|
||||
return line1 < line2 or line1 == line2 and char1 <= char2
|
||||
elif op == '>':
|
||||
return line1 > line2 or line1 == line2 and char1 > char2
|
||||
elif op == '>=':
|
||||
return line1 > line2 or line1 == line2 and char1 >= char2
|
||||
elif op == '==':
|
||||
return line1 == line2 and char1 == char2
|
||||
elif op == '!=':
|
||||
return line1 != line2 or char1 != char2
|
||||
else:
|
||||
raise TclError('''bad comparison operator "%s": '''
|
||||
'''must be <, <=, ==, >=, >, or !=''' % op)
|
||||
|
||||
# The following Text methods normally do something and return None.
|
||||
# Whether doing nothing is sufficient for a test will depend on the test.
|
||||
|
||||
def mark_set(self, name, index):
|
||||
"Set mark *name* before the character at index."
|
||||
pass
|
||||
|
||||
def mark_unset(self, *markNames):
|
||||
"Delete all marks in markNames."
|
||||
|
||||
def tag_remove(self, tagName, index1, index2=None):
|
||||
"Remove tag tagName from all characters between index1 and index2."
|
||||
pass
|
||||
|
||||
# The following Text methods affect the graphics screen and return None.
|
||||
# Doing nothing should always be sufficient for tests.
|
||||
|
||||
def scan_dragto(self, x, y):
|
||||
"Adjust the view of the text according to scan_mark"
|
||||
|
||||
def scan_mark(self, x, y):
|
||||
"Remember the current X, Y coordinates."
|
||||
|
||||
def see(self, index):
|
||||
"Scroll screen to make the character at INDEX is visible."
|
||||
pass
|
||||
|
||||
# The following is a Misc method inherited by Text.
|
||||
# It should properly go in a Misc mock, but is included here for now.
|
||||
|
||||
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
|
||||
30
.CondaPkg/env/Lib/idlelib/idle_test/template.py
vendored
Normal file
30
.CondaPkg/env/Lib/idlelib/idle_test/template.py
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
"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)
|
||||
305
.CondaPkg/env/Lib/idlelib/idle_test/test_autocomplete.py
vendored
Normal file
305
.CondaPkg/env/Lib/idlelib/idle_test/test_autocomplete.py
vendored
Normal file
@@ -0,0 +1,305 @@
|
||||
"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__
|
||||
|
||||
import idlelib.autocomplete as ac
|
||||
import idlelib.autocomplete_w as acw
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
from idlelib.idle_test.mock_tk import Event
|
||||
|
||||
|
||||
class DummyEditwin:
|
||||
def __init__(self, root, text):
|
||||
self.root = root
|
||||
self.text = text
|
||||
self.indentwidth = 8
|
||||
self.tabwidth = 8
|
||||
self.prompt_last_line = '>>>' # Currently not used by autocomplete.
|
||||
|
||||
|
||||
class AutoCompleteTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
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.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)
|
||||
|
||||
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)
|
||||
|
||||
def test_autocomplete_event(self):
|
||||
Equal = self.assertEqual
|
||||
acp = self.autocomplete
|
||||
|
||||
# Result of autocomplete event: If modified tab, None.
|
||||
ev = Event(mc_state=True)
|
||||
self.assertIsNone(acp.autocomplete_event(ev))
|
||||
del ev.mc_state
|
||||
|
||||
# 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'.
|
||||
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
|
||||
|
||||
# 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)
|
||||
|
||||
def test_try_open_completions_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
|
||||
|
||||
# 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')
|
||||
|
||||
# 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')
|
||||
|
||||
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()
|
||||
|
||||
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')
|
||||
|
||||
def test_completion_kwds(self):
|
||||
self.assertIn('and', ac.completion_kwds)
|
||||
self.assertIn('case', ac.completion_kwds)
|
||||
self.assertNotIn('None', ac.completion_kwds)
|
||||
|
||||
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 hasattr(__main__, '__file__') and __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__.
|
||||
self.assertIn('nonlocal', b) # From keyword.kwlist.
|
||||
pos = b.index('False') # Test False not included twice.
|
||||
self.assertNotEqual(b[pos+1], 'False')
|
||||
|
||||
# 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'])
|
||||
|
||||
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')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
32
.CondaPkg/env/Lib/idlelib/idle_test/test_autocomplete_w.py
vendored
Normal file
32
.CondaPkg/env/Lib/idlelib/idle_test/test_autocomplete_w.py
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
"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, tags=None)
|
||||
|
||||
@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)
|
||||
155
.CondaPkg/env/Lib/idlelib/idle_test/test_autoexpand.py
vendored
Normal file
155
.CondaPkg/env/Lib/idlelib/idle_test/test_autoexpand.py
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
"Test autoexpand, coverage 100%."
|
||||
|
||||
from idlelib.autoexpand import AutoExpand
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Text, Tk
|
||||
|
||||
|
||||
class DummyEditwin:
|
||||
# AutoExpand.__init__ only needs .text
|
||||
def __init__(self, text):
|
||||
self.text = text
|
||||
|
||||
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)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.text, cls.auto_expand
|
||||
if hasattr(cls, 'tk'):
|
||||
cls.tk.destroy()
|
||||
del cls.tk
|
||||
|
||||
def tearDown(self):
|
||||
self.text.delete('1.0', 'end')
|
||||
|
||||
def test_get_prevword(self):
|
||||
text = self.text
|
||||
previous = self.auto_expand.getprevword
|
||||
equal = self.assertEqual
|
||||
|
||||
equal(previous(), '')
|
||||
|
||||
text.insert('insert', 't')
|
||||
equal(previous(), 't')
|
||||
|
||||
text.insert('insert', 'his')
|
||||
equal(previous(), 'this')
|
||||
|
||||
text.insert('insert', ' ')
|
||||
equal(previous(), '')
|
||||
|
||||
text.insert('insert', 'is')
|
||||
equal(previous(), 'is')
|
||||
|
||||
text.insert('insert', '\nsample\nstring')
|
||||
equal(previous(), 'string')
|
||||
|
||||
text.delete('3.0', 'insert')
|
||||
equal(previous(), '')
|
||||
|
||||
text.delete('1.0', 'end')
|
||||
equal(previous(), '')
|
||||
|
||||
def test_before_only(self):
|
||||
previous = self.auto_expand.getprevword
|
||||
expand = self.auto_expand.expand_word_event
|
||||
equal = self.assertEqual
|
||||
|
||||
self.text.insert('insert', 'ab ac bx ad ab a')
|
||||
equal(self.auto_expand.getwords(), ['ab', 'ad', 'ac', 'a'])
|
||||
expand('event')
|
||||
equal(previous(), 'ab')
|
||||
expand('event')
|
||||
equal(previous(), 'ad')
|
||||
expand('event')
|
||||
equal(previous(), 'ac')
|
||||
expand('event')
|
||||
equal(previous(), 'a')
|
||||
|
||||
def test_after_only(self):
|
||||
# Also add punctuation 'noise' that should be ignored.
|
||||
text = self.text
|
||||
previous = self.auto_expand.getprevword
|
||||
expand = self.auto_expand.expand_word_event
|
||||
equal = self.assertEqual
|
||||
|
||||
text.insert('insert', 'a, [ab] ac: () bx"" cd ac= ad ya')
|
||||
text.mark_set('insert', '1.1')
|
||||
equal(self.auto_expand.getwords(), ['ab', 'ac', 'ad', 'a'])
|
||||
expand('event')
|
||||
equal(previous(), 'ab')
|
||||
expand('event')
|
||||
equal(previous(), 'ac')
|
||||
expand('event')
|
||||
equal(previous(), 'ad')
|
||||
expand('event')
|
||||
equal(previous(), 'a')
|
||||
|
||||
def test_both_before_after(self):
|
||||
text = self.text
|
||||
previous = self.auto_expand.getprevword
|
||||
expand = self.auto_expand.expand_word_event
|
||||
equal = self.assertEqual
|
||||
|
||||
text.insert('insert', 'ab xy yz\n')
|
||||
text.insert('insert', 'a ac by ac')
|
||||
|
||||
text.mark_set('insert', '2.1')
|
||||
equal(self.auto_expand.getwords(), ['ab', 'ac', 'a'])
|
||||
expand('event')
|
||||
equal(previous(), 'ab')
|
||||
expand('event')
|
||||
equal(previous(), 'ac')
|
||||
expand('event')
|
||||
equal(previous(), 'a')
|
||||
|
||||
def test_other_expand_cases(self):
|
||||
text = self.text
|
||||
expand = self.auto_expand.expand_word_event
|
||||
equal = self.assertEqual
|
||||
|
||||
# no expansion candidate found
|
||||
equal(self.auto_expand.getwords(), [])
|
||||
equal(expand('event'), 'break')
|
||||
|
||||
text.insert('insert', 'bx cy dz a')
|
||||
equal(self.auto_expand.getwords(), [])
|
||||
|
||||
# reset state by successfully expanding once
|
||||
# move cursor to another position and expand again
|
||||
text.insert('insert', 'ac xy a ac ad a')
|
||||
text.mark_set('insert', '1.7')
|
||||
expand('event')
|
||||
initial_state = self.auto_expand.state
|
||||
text.mark_set('insert', '1.end')
|
||||
expand('event')
|
||||
new_state = self.auto_expand.state
|
||||
self.assertNotEqual(initial_state, new_state)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
257
.CondaPkg/env/Lib/idlelib/idle_test/test_browser.py
vendored
Normal file
257
.CondaPkg/env/Lib/idlelib/idle_test/test_browser.py
vendored
Normal file
@@ -0,0 +1,257 @@
|
||||
"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 idlelib.util import py_extensions
|
||||
|
||||
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
|
||||
|
||||
def test_is_browseable_extension(self):
|
||||
path = "/path/to/file"
|
||||
for ext in py_extensions:
|
||||
with self.subTest(ext=ext):
|
||||
filename = f'{path}{ext}'
|
||||
actual = browser.is_browseable_extension(filename)
|
||||
expected = ext not in browser.browseable_extension_blocklist
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
||||
# 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, end_lineno=9)
|
||||
F1 = mb._nest_function(C0, 'F1', 3, 5)
|
||||
C1 = mb._nest_class(C0, 'C1', 6, 9, [''])
|
||||
C2 = mb._nest_class(C1, 'C2', 7, 9)
|
||||
F3 = mb._nest_function(C2, 'F3', 9, 9)
|
||||
f0 = mb.Function(module, 'f0', fname, 11, end_lineno=15)
|
||||
f1 = mb._nest_function(f0, 'f1', 12, 14)
|
||||
f2 = mb._nest_function(f1, 'f2', 13, 13)
|
||||
c1 = mb._nest_class(f0, 'c1', 15, 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_once_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)
|
||||
365
.CondaPkg/env/Lib/idlelib/idle_test/test_calltip.py
vendored
Normal file
365
.CondaPkg/env/Lib/idlelib/idle_test/test_calltip.py
vendored
Normal file
@@ -0,0 +1,365 @@
|
||||
"Test calltip, coverage 76%"
|
||||
|
||||
from idlelib import calltip
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
import textwrap
|
||||
import types
|
||||
import re
|
||||
from idlelib.idle_test.mock_tk import Text
|
||||
|
||||
|
||||
# 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=(), /)'
|
||||
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)\n'
|
||||
'Initialize self. See help(type(self)) for accurate signature.')
|
||||
append_doc = "\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,
|
||||
'(function, instance, /)\n'
|
||||
'Create a bound instance method object.')
|
||||
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=' [...]')
|
||||
Object for wrapping/filling text. The public interface consists of
|
||||
the wrap() and fill() methods; the other methods are just there for
|
||||
subclasses to override in order to tweak the default behaviour.
|
||||
If you want to completely replace the main wrapping algorithm,
|
||||
you\'ll probably have to override _wrap_chunks().''')
|
||||
|
||||
def test_properly_formatted(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_buggy_getattr_class(self):
|
||||
class NoCall:
|
||||
def __getattr__(self, name): # Not invoked for class attribute.
|
||||
raise IndexError # Bug.
|
||||
class CallA(NoCall):
|
||||
def __call__(self, ci): # Bug does not matter.
|
||||
pass
|
||||
class CallB(NoCall):
|
||||
def __call__(oui, a, b, c): # Non-standard 'self'.
|
||||
pass
|
||||
|
||||
for meth, mtip in ((NoCall, default_tip), (CallA, default_tip),
|
||||
(NoCall(), ''), (CallA(), '(ci)'),
|
||||
(CallB(), '(a, b, c)')):
|
||||
with self.subTest(meth=meth, mtip=mtip):
|
||||
self.assertEqual(get_spec(meth), mtip)
|
||||
|
||||
def test_metaclass_class(self): # Failure case for issue 38689.
|
||||
class Type(type): # Type() requires 3 type args, returns class.
|
||||
__class__ = property({}.__getitem__, {}.__setitem__)
|
||||
class Object(metaclass=Type):
|
||||
__slots__ = '__class__'
|
||||
for meth, mtip in ((Type, get_spec(type)), (Object, default_tip),
|
||||
(Object(), '')):
|
||||
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)
|
||||
|
||||
|
||||
# Test the 9 Calltip methods.
|
||||
# open_calltip is about half the code; the others are fairly trivial.
|
||||
# The default mocks are what are needed for open_calltip.
|
||||
|
||||
class mock_Shell:
|
||||
"Return mock sufficient to pass to hyperparser."
|
||||
def __init__(self, text):
|
||||
text.tag_prevrange = Mock(return_value=None)
|
||||
self.text = text
|
||||
self.prompt_last_line = ">>> "
|
||||
self.indentwidth = 4
|
||||
self.tabwidth = 8
|
||||
|
||||
|
||||
class mock_TipWindow:
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def showtip(self, text, parenleft, parenright):
|
||||
self.args = parenleft, parenright
|
||||
self.parenline, self.parencol = map(int, parenleft.split('.'))
|
||||
|
||||
|
||||
class WrappedCalltip(calltip.Calltip):
|
||||
def _make_tk_calltip_window(self):
|
||||
return mock_TipWindow()
|
||||
|
||||
def remove_calltip_window(self, event=None):
|
||||
if self.active_calltip: # Setup to None.
|
||||
self.active_calltip = None
|
||||
self.tips_removed += 1 # Setup to 0.
|
||||
|
||||
def fetch_tip(self, expression):
|
||||
return 'tip'
|
||||
|
||||
|
||||
class CalltipTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.text = Text()
|
||||
cls.ct = WrappedCalltip(mock_Shell(cls.text))
|
||||
|
||||
def setUp(self):
|
||||
self.text.delete('1.0', 'end') # Insert and call
|
||||
self.ct.active_calltip = None
|
||||
# Test .active_calltip, +args
|
||||
self.ct.tips_removed = 0
|
||||
|
||||
def open_close(self, testfunc):
|
||||
# Open-close template with testfunc called in between.
|
||||
opentip = self.ct.open_calltip
|
||||
self.text.insert(1.0, 'f(')
|
||||
opentip(False)
|
||||
self.tip = self.ct.active_calltip
|
||||
testfunc(self) ###
|
||||
self.text.insert('insert', ')')
|
||||
opentip(False)
|
||||
self.assertIsNone(self.ct.active_calltip, None)
|
||||
|
||||
def test_open_close(self):
|
||||
def args(self):
|
||||
self.assertEqual(self.tip.args, ('1.1', '1.end'))
|
||||
self.open_close(args)
|
||||
|
||||
def test_repeated_force(self):
|
||||
def force(self):
|
||||
for char in 'abc':
|
||||
self.text.insert('insert', 'a')
|
||||
self.ct.open_calltip(True)
|
||||
self.ct.open_calltip(True)
|
||||
self.assertIs(self.ct.active_calltip, self.tip)
|
||||
self.open_close(force)
|
||||
|
||||
def test_repeated_parens(self):
|
||||
def parens(self):
|
||||
for context in "a", "'":
|
||||
with self.subTest(context=context):
|
||||
self.text.insert('insert', context)
|
||||
for char in '(()())':
|
||||
self.text.insert('insert', char)
|
||||
self.assertIs(self.ct.active_calltip, self.tip)
|
||||
self.text.insert('insert', "'")
|
||||
self.open_close(parens)
|
||||
|
||||
def test_comment_parens(self):
|
||||
def comment(self):
|
||||
self.text.insert('insert', "# ")
|
||||
for char in '(()())':
|
||||
self.text.insert('insert', char)
|
||||
self.assertIs(self.ct.active_calltip, self.tip)
|
||||
self.text.insert('insert', "\n")
|
||||
self.open_close(comment)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
29
.CondaPkg/env/Lib/idlelib/idle_test/test_calltip_w.py
vendored
Normal file
29
.CondaPkg/env/Lib/idlelib/idle_test/test_calltip_w.py
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
"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)
|
||||
455
.CondaPkg/env/Lib/idlelib/idle_test/test_codecontext.py
vendored
Normal file
455
.CondaPkg/env/Lib/idlelib/idle_test/test_codecontext.py
vendored
Normal file
@@ -0,0 +1,455 @@
|
||||
"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)
|
||||
|
||||
# Context selection stops jump.
|
||||
cc.text.yview('5.0')
|
||||
cc.update_code_context()
|
||||
cc.context.tag_add('sel', '1.0', '2.0')
|
||||
cc.context.mark_set('insert', '1.0')
|
||||
jump() # Without selection, to line 2.
|
||||
eq(cc.topvisible, 5)
|
||||
|
||||
@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)
|
||||
622
.CondaPkg/env/Lib/idlelib/idle_test/test_colorizer.py
vendored
Normal file
622
.CondaPkg/env/Lib/idlelib/idle_test/test_colorizer.py
vendored
Normal file
@@ -0,0 +1,622 @@
|
||||
"Test colorizer, coverage 99%."
|
||||
from idlelib import colorizer
|
||||
from test.support import requires
|
||||
import unittest
|
||||
from unittest import mock
|
||||
from idlelib.idle_test.tkinter_testing_utils import run_in_tk_mainloop
|
||||
|
||||
from functools import partial
|
||||
import textwrap
|
||||
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 = textwrap.dedent("""\
|
||||
if True: int ('1') # keyword, builtin, string, comment
|
||||
elif False: print(0) # 'string' in comment
|
||||
else: float(None) # if in comment
|
||||
if iF + If + IF: 'keyword matching must respect case'
|
||||
if'': x or'' # valid keyword-string no-space combinations
|
||||
async def f(): await g()
|
||||
# Strings should be entirely colored, including quotes.
|
||||
'x', '''x''', "x", \"""x\"""
|
||||
'abc\\
|
||||
def'
|
||||
'''abc\\
|
||||
def'''
|
||||
# All valid prefixes for unicode and byte strings should be colored.
|
||||
r'x', u'x', R'x', U'x', f'x', F'x'
|
||||
fr'x', Fr'x', fR'x', FR'x', rf'x', rF'x', Rf'x', RF'x'
|
||||
b'x',B'x', br'x',Br'x',bR'x',BR'x', rb'x', rB'x',Rb'x',RB'x'
|
||||
# Invalid combinations of legal characters should be half colored.
|
||||
ur'x', ru'x', uf'x', fu'x', UR'x', ufr'x', rfu'x', xf'x', fx'x'
|
||||
match point:
|
||||
case (x, 0) as _:
|
||||
print(f"X={x}")
|
||||
case [_, [_], "_",
|
||||
_]:
|
||||
pass
|
||||
case _ if ("a" if _ else set()): pass
|
||||
case _:
|
||||
raise ValueError("Not a point _")
|
||||
'''
|
||||
case _:'''
|
||||
"match x:"
|
||||
""")
|
||||
|
||||
|
||||
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()
|
||||
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.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', ()),
|
||||
('8.0', ('STRING',)), ('8.4', ()), ('8.5', ('STRING',)),
|
||||
('8.12', ()), ('8.14', ('STRING',)),
|
||||
('19.0', ('KEYWORD',)),
|
||||
('20.4', ('KEYWORD',)), ('20.16', ('KEYWORD',)),# ('20.19', ('KEYWORD',)),
|
||||
#('22.4', ('KEYWORD',)), ('22.10', ('KEYWORD',)), ('22.14', ('KEYWORD',)), ('22.19', ('STRING',)),
|
||||
#('23.12', ('KEYWORD',)),
|
||||
('24.8', ('KEYWORD',)),
|
||||
('25.4', ('KEYWORD',)), ('25.9', ('KEYWORD',)),
|
||||
('25.11', ('KEYWORD',)), ('25.15', ('STRING',)),
|
||||
('25.19', ('KEYWORD',)), ('25.22', ()),
|
||||
('25.24', ('KEYWORD',)), ('25.29', ('BUILTIN',)), ('25.37', ('KEYWORD',)),
|
||||
('26.4', ('KEYWORD',)), ('26.9', ('KEYWORD',)),# ('26.11', ('KEYWORD',)), ('26.14', (),),
|
||||
('27.25', ('STRING',)), ('27.38', ('STRING',)),
|
||||
('29.0', ('STRING',)),
|
||||
('30.1', ('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', '8.0'), ('8.0', '8.3'))
|
||||
eq(text.tag_nextrange('STRING', '8.3'), ('8.5', '8.12'))
|
||||
eq(text.tag_nextrange('STRING', '8.12'), ('8.14', '8.17'))
|
||||
eq(text.tag_nextrange('STRING', '8.17'), ('8.19', '8.26'))
|
||||
eq(text.tag_nextrange('SYNC', '8.0'), ('8.26', '9.0'))
|
||||
eq(text.tag_nextrange('SYNC', '30.0'), ('30.10', '32.0'))
|
||||
|
||||
def _assert_highlighting(self, source, tag_ranges):
|
||||
"""Check highlighting of a given piece of code.
|
||||
|
||||
This inserts just this code into the Text widget. It will then
|
||||
check that the resulting highlighting tag ranges exactly match
|
||||
those described in the given `tag_ranges` dict.
|
||||
|
||||
Note that the irrelevant tags 'sel', 'TODO' and 'SYNC' are
|
||||
ignored.
|
||||
"""
|
||||
text = self.text
|
||||
|
||||
with mock.patch.object(colorizer.ColorDelegator, 'notify_range'):
|
||||
text.delete('1.0', 'end-1c')
|
||||
text.insert('insert', source)
|
||||
text.tag_add('TODO', '1.0', 'end-1c')
|
||||
self.color.recolorize_main()
|
||||
|
||||
# Make a dict with highlighting tag ranges in the Text widget.
|
||||
text_tag_ranges = {}
|
||||
for tag in set(text.tag_names()) - {'sel', 'TODO', 'SYNC'}:
|
||||
indexes = [rng.string for rng in text.tag_ranges(tag)]
|
||||
for index_pair in zip(indexes[::2], indexes[1::2]):
|
||||
text_tag_ranges.setdefault(tag, []).append(index_pair)
|
||||
|
||||
self.assertEqual(text_tag_ranges, tag_ranges)
|
||||
|
||||
with mock.patch.object(colorizer.ColorDelegator, 'notify_range'):
|
||||
text.delete('1.0', 'end-1c')
|
||||
|
||||
def test_def_statement(self):
|
||||
# empty def
|
||||
self._assert_highlighting('def', {'KEYWORD': [('1.0', '1.3')]})
|
||||
|
||||
# def followed by identifier
|
||||
self._assert_highlighting('def foo:', {'KEYWORD': [('1.0', '1.3')],
|
||||
'DEFINITION': [('1.4', '1.7')]})
|
||||
|
||||
# def followed by partial identifier
|
||||
self._assert_highlighting('def fo', {'KEYWORD': [('1.0', '1.3')],
|
||||
'DEFINITION': [('1.4', '1.6')]})
|
||||
|
||||
# def followed by non-keyword
|
||||
self._assert_highlighting('def ++', {'KEYWORD': [('1.0', '1.3')]})
|
||||
|
||||
def test_match_soft_keyword(self):
|
||||
# empty match
|
||||
self._assert_highlighting('match', {'KEYWORD': [('1.0', '1.5')]})
|
||||
|
||||
# match followed by partial identifier
|
||||
self._assert_highlighting('match fo', {'KEYWORD': [('1.0', '1.5')]})
|
||||
|
||||
# match followed by identifier and colon
|
||||
self._assert_highlighting('match foo:', {'KEYWORD': [('1.0', '1.5')]})
|
||||
|
||||
# match followed by keyword
|
||||
self._assert_highlighting('match and', {'KEYWORD': [('1.6', '1.9')]})
|
||||
|
||||
# match followed by builtin with keyword prefix
|
||||
self._assert_highlighting('match int:', {'KEYWORD': [('1.0', '1.5')],
|
||||
'BUILTIN': [('1.6', '1.9')]})
|
||||
|
||||
# match followed by non-text operator
|
||||
self._assert_highlighting('match^', {})
|
||||
self._assert_highlighting('match @', {})
|
||||
|
||||
# match followed by colon
|
||||
self._assert_highlighting('match :', {})
|
||||
|
||||
# match followed by comma
|
||||
self._assert_highlighting('match\t,', {})
|
||||
|
||||
# match followed by a lone underscore
|
||||
self._assert_highlighting('match _:', {'KEYWORD': [('1.0', '1.5')]})
|
||||
|
||||
def test_case_soft_keyword(self):
|
||||
# empty case
|
||||
self._assert_highlighting('case', {'KEYWORD': [('1.0', '1.4')]})
|
||||
|
||||
# case followed by partial identifier
|
||||
self._assert_highlighting('case fo', {'KEYWORD': [('1.0', '1.4')]})
|
||||
|
||||
# case followed by identifier and colon
|
||||
self._assert_highlighting('case foo:', {'KEYWORD': [('1.0', '1.4')]})
|
||||
|
||||
# case followed by keyword
|
||||
self._assert_highlighting('case and', {'KEYWORD': [('1.5', '1.8')]})
|
||||
|
||||
# case followed by builtin with keyword prefix
|
||||
self._assert_highlighting('case int:', {'KEYWORD': [('1.0', '1.4')],
|
||||
'BUILTIN': [('1.5', '1.8')]})
|
||||
|
||||
# case followed by non-text operator
|
||||
self._assert_highlighting('case^', {})
|
||||
self._assert_highlighting('case @', {})
|
||||
|
||||
# case followed by colon
|
||||
self._assert_highlighting('case :', {})
|
||||
|
||||
# case followed by comma
|
||||
self._assert_highlighting('case\t,', {})
|
||||
|
||||
# case followed by a lone underscore
|
||||
self._assert_highlighting('case _:', {'KEYWORD': [('1.0', '1.4'),
|
||||
('1.5', '1.6')]})
|
||||
|
||||
def test_long_multiline_string(self):
|
||||
source = textwrap.dedent('''\
|
||||
"""a
|
||||
b
|
||||
c
|
||||
d
|
||||
e"""
|
||||
''')
|
||||
self._assert_highlighting(source, {'STRING': [('1.0', '5.4')]})
|
||||
|
||||
@run_in_tk_mainloop(delay=50)
|
||||
def test_incremental_editing(self):
|
||||
text = self.text
|
||||
eq = self.assertEqual
|
||||
|
||||
# Simulate typing 'inte'. During this, the highlighting should
|
||||
# change from normal to keyword to builtin to normal.
|
||||
text.insert('insert', 'i')
|
||||
yield
|
||||
eq(text.tag_nextrange('BUILTIN', '1.0'), ())
|
||||
eq(text.tag_nextrange('KEYWORD', '1.0'), ())
|
||||
|
||||
text.insert('insert', 'n')
|
||||
yield
|
||||
eq(text.tag_nextrange('BUILTIN', '1.0'), ())
|
||||
eq(text.tag_nextrange('KEYWORD', '1.0'), ('1.0', '1.2'))
|
||||
|
||||
text.insert('insert', 't')
|
||||
yield
|
||||
eq(text.tag_nextrange('BUILTIN', '1.0'), ('1.0', '1.3'))
|
||||
eq(text.tag_nextrange('KEYWORD', '1.0'), ())
|
||||
|
||||
text.insert('insert', 'e')
|
||||
yield
|
||||
eq(text.tag_nextrange('BUILTIN', '1.0'), ())
|
||||
eq(text.tag_nextrange('KEYWORD', '1.0'), ())
|
||||
|
||||
# Simulate deleting three characters from the end of 'inte'.
|
||||
# During this, the highlighting should change from normal to
|
||||
# builtin to keyword to normal.
|
||||
text.delete('insert-1c', 'insert')
|
||||
yield
|
||||
eq(text.tag_nextrange('BUILTIN', '1.0'), ('1.0', '1.3'))
|
||||
eq(text.tag_nextrange('KEYWORD', '1.0'), ())
|
||||
|
||||
text.delete('insert-1c', 'insert')
|
||||
yield
|
||||
eq(text.tag_nextrange('BUILTIN', '1.0'), ())
|
||||
eq(text.tag_nextrange('KEYWORD', '1.0'), ('1.0', '1.2'))
|
||||
|
||||
text.delete('insert-1c', 'insert')
|
||||
yield
|
||||
eq(text.tag_nextrange('BUILTIN', '1.0'), ())
|
||||
eq(text.tag_nextrange('KEYWORD', '1.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)
|
||||
805
.CondaPkg/env/Lib/idlelib/idle_test/test_config.py
vendored
Normal file
805
.CondaPkg/env/Lib/idlelib/idle_test/test_config.py
vendored
Normal file
@@ -0,0 +1,805 @@
|
||||
"""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)
|
||||
356
.CondaPkg/env/Lib/idlelib/idle_test/test_config_key.py
vendored
Normal file
356
.CondaPkg/env/Lib/idlelib/idle_test/test_config_key.py
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
"""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
|
||||
|
||||
|
||||
class ValidationTest(unittest.TestCase):
|
||||
"Test validation methods: ok, keys_ok, bind_ok."
|
||||
|
||||
class Validator(config_key.GetKeysFrame):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*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, '<<Test>>', keylist)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.dialog
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del 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 = config_key.GetKeysFrame(cls.root, '<<Test>>', [])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.dialog
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del 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.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(config_key.GetKeysFrame):
|
||||
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, '<<Test>>', [])
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.dialog
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del 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(config_key.GetKeysFrame, '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(config_key.GetKeysFrame, '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 CancelWindowTest(unittest.TestCase):
|
||||
"Simulate user clicking [Cancel] button."
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.dialog = config_key.GetKeysWindow(
|
||||
cls.root, 'Title', '<<Test>>', [], _utest=True)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.dialog.cancel()
|
||||
del cls.dialog
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
@mock.patch.object(config_key.GetKeysFrame, 'ok')
|
||||
def test_cancel(self, mock_frame_ok):
|
||||
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, '')
|
||||
mock_frame_ok.assert_not_called()
|
||||
|
||||
|
||||
class OKWindowTest(unittest.TestCase):
|
||||
"Simulate user clicking [OK] button."
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.dialog = config_key.GetKeysWindow(
|
||||
cls.root, 'Title', '<<Test>>', [], _utest=True)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.dialog.cancel()
|
||||
del cls.dialog
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
@mock.patch.object(config_key.GetKeysFrame, 'ok')
|
||||
def test_ok(self, mock_frame_ok):
|
||||
self.assertEqual(self.dialog.winfo_class(), 'Toplevel')
|
||||
self.dialog.button_ok.invoke()
|
||||
with self.assertRaises(TclError):
|
||||
self.dialog.winfo_class()
|
||||
mock_frame_ok.assert_called()
|
||||
|
||||
|
||||
class WindowResultTest(unittest.TestCase):
|
||||
"Test window result get and set."
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.dialog = config_key.GetKeysWindow(
|
||||
cls.root, 'Title', '<<Test>>', [], _utest=True)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.dialog.cancel()
|
||||
del cls.dialog
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_result(self):
|
||||
dialog = self.dialog
|
||||
eq = self.assertEqual
|
||||
|
||||
dialog.result = ''
|
||||
eq(dialog.result, '')
|
||||
eq(dialog.frame.result,'')
|
||||
|
||||
dialog.result = 'bar'
|
||||
eq(dialog.result,'bar')
|
||||
eq(dialog.frame.result,'bar')
|
||||
|
||||
dialog.frame.result = 'foo'
|
||||
eq(dialog.result, 'foo')
|
||||
eq(dialog.frame.result,'foo')
|
||||
|
||||
|
||||
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)
|
||||
1583
.CondaPkg/env/Lib/idlelib/idle_test/test_configdialog.py
vendored
Normal file
1583
.CondaPkg/env/Lib/idlelib/idle_test/test_configdialog.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
29
.CondaPkg/env/Lib/idlelib/idle_test/test_debugger.py
vendored
Normal file
29
.CondaPkg/env/Lib/idlelib/idle_test/test_debugger.py
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
"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)
|
||||
36
.CondaPkg/env/Lib/idlelib/idle_test/test_debugger_r.py
vendored
Normal file
36
.CondaPkg/env/Lib/idlelib/idle_test/test_debugger_r.py
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
"Test debugger_r, coverage 30%."
|
||||
|
||||
from idlelib import debugger_r
|
||||
import unittest
|
||||
|
||||
# Boilerplate likely to be needed for future test classes.
|
||||
##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()
|
||||
|
||||
# GUIProxy, IdbAdapter, FrameProxy, CodeProxy, DictProxy,
|
||||
# GUIAdapter, IdbProxy, and 7 functions still need tests.
|
||||
|
||||
class IdbAdapterTest(unittest.TestCase):
|
||||
|
||||
def test_dict_item_noattr(self): # Issue 33065.
|
||||
|
||||
class BinData:
|
||||
def __repr__(self):
|
||||
return self.length
|
||||
|
||||
debugger_r.dicttable[0] = {'BinData': BinData()}
|
||||
idb = debugger_r.IdbAdapter(None)
|
||||
self.assertTrue(idb.dict_item(0, 'BinData'))
|
||||
debugger_r.dicttable.clear()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
57
.CondaPkg/env/Lib/idlelib/idle_test/test_debugobj.py
vendored
Normal file
57
.CondaPkg/env/Lib/idlelib/idle_test/test_debugobj.py
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
"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)
|
||||
22
.CondaPkg/env/Lib/idlelib/idle_test/test_debugobj_r.py
vendored
Normal file
22
.CondaPkg/env/Lib/idlelib/idle_test/test_debugobj_r.py
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
"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)
|
||||
44
.CondaPkg/env/Lib/idlelib/idle_test/test_delegator.py
vendored
Normal file
44
.CondaPkg/env/Lib/idlelib/idle_test/test_delegator.py
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
"Test delegator, coverage 100%."
|
||||
|
||||
from idlelib.delegator import Delegator
|
||||
import unittest
|
||||
|
||||
|
||||
class DelegatorTest(unittest.TestCase):
|
||||
|
||||
def test_mydel(self):
|
||||
# Test a simple use scenario.
|
||||
|
||||
# Initialize an int delegator.
|
||||
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.
|
||||
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'.
|
||||
mydel.numerator
|
||||
self.assertEqual(mydel._Delegator__cache, {'bit_length', 'numerator'})
|
||||
|
||||
# Delete 'numerator'.
|
||||
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
|
||||
|
||||
# Change delegate to float, first resetting the attributes.
|
||||
mydel.setdelegate(float) # calls resetcache
|
||||
self.assertNotIn('bit_length', mydel.__dict__)
|
||||
self.assertEqual(mydel._Delegator__cache, set())
|
||||
self.assertIs(mydel.delegate, float)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=2)
|
||||
74
.CondaPkg/env/Lib/idlelib/idle_test/test_editmenu.py
vendored
Normal file
74
.CondaPkg/env/Lib/idlelib/idle_test/test_editmenu.py
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
'''Test (selected) IDLE Edit menu items.
|
||||
|
||||
Edit modules have their own test files
|
||||
'''
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
import unittest
|
||||
from idlelib import pyshell
|
||||
|
||||
class PasteTest(unittest.TestCase):
|
||||
'''Test pasting into widgets that allow pasting.
|
||||
|
||||
On X11, replacing selections requires tk fix.
|
||||
'''
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = root = tk.Tk()
|
||||
cls.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
|
||||
cls.root.clipboard_clear()
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_paste_text(self):
|
||||
"Test pasting into text with and without a selection."
|
||||
text = self.text
|
||||
for tag, ans in ('', 'onetwo\n'), ('sel', 'two\n'):
|
||||
with self.subTest(tag=tag, ans=ans):
|
||||
text.delete('1.0', 'end')
|
||||
text.insert('1.0', 'one', tag)
|
||||
text.event_generate('<<Paste>>')
|
||||
self.assertEqual(text.get('1.0', 'end'), ans)
|
||||
|
||||
def test_paste_entry(self):
|
||||
"Test pasting into an entry with and without a selection."
|
||||
# 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_spin(self):
|
||||
"Test pasting into a spinbox with and without a selection."
|
||||
# See note above for entry.
|
||||
spin = self.spin
|
||||
for end, ans in (0, 'onetwo'), ('end', 'two'):
|
||||
with self.subTest(end=end, ans=ans):
|
||||
spin.delete(0, 'end')
|
||||
spin.insert(0, 'one')
|
||||
spin.selection('range', 0, end) # see note
|
||||
spin.event_generate('<<Paste>>')
|
||||
self.assertEqual(spin.get(), ans)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
211
.CondaPkg/env/Lib/idlelib/idle_test/test_editor.py
vendored
Normal file
211
.CondaPkg/env/Lib/idlelib/idle_test/test_editor.py
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
"Test editor, coverage 35%."
|
||||
|
||||
from idlelib import editor
|
||||
import unittest
|
||||
from collections import namedtuple
|
||||
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,
|
||||
)
|
||||
|
||||
|
||||
def insert(text, string):
|
||||
text.delete('1.0', 'end')
|
||||
text.insert('end', string)
|
||||
text.update() # Force update for colorizer to finish.
|
||||
|
||||
|
||||
class IndentAndNewlineTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.window = Editor(root=cls.root)
|
||||
cls.window.indentwidth = 2
|
||||
cls.window.tabwidth = 2
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.window._close()
|
||||
del cls.window
|
||||
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_indent_and_newline_event(self):
|
||||
eq = self.assertEqual
|
||||
w = self.window
|
||||
text = w.text
|
||||
get = text.get
|
||||
nl = w.newline_and_indent_event
|
||||
|
||||
TestInfo = namedtuple('Tests', ['label', 'text', 'expected', 'mark'])
|
||||
|
||||
tests = (TestInfo('Empty line inserts with no indent.',
|
||||
' \n def __init__(self):',
|
||||
'\n \n def __init__(self):\n',
|
||||
'1.end'),
|
||||
TestInfo('Inside bracket before space, deletes space.',
|
||||
' def f1(self, a, b):',
|
||||
' def f1(self,\n a, b):\n',
|
||||
'1.14'),
|
||||
TestInfo('Inside bracket after space, deletes space.',
|
||||
' def f1(self, a, b):',
|
||||
' def f1(self,\n a, b):\n',
|
||||
'1.15'),
|
||||
TestInfo('Inside string with one line - no indent.',
|
||||
' """Docstring."""',
|
||||
' """Docstring.\n"""\n',
|
||||
'1.15'),
|
||||
TestInfo('Inside string with more than one line.',
|
||||
' """Docstring.\n Docstring Line 2"""',
|
||||
' """Docstring.\n Docstring Line 2\n """\n',
|
||||
'2.18'),
|
||||
TestInfo('Backslash with one line.',
|
||||
'a =\\',
|
||||
'a =\\\n \n',
|
||||
'1.end'),
|
||||
TestInfo('Backslash with more than one line.',
|
||||
'a =\\\n multiline\\',
|
||||
'a =\\\n multiline\\\n \n',
|
||||
'2.end'),
|
||||
TestInfo('Block opener - indents +1 level.',
|
||||
' def f1(self):\n pass',
|
||||
' def f1(self):\n \n pass\n',
|
||||
'1.end'),
|
||||
TestInfo('Block closer - dedents -1 level.',
|
||||
' def f1(self):\n pass',
|
||||
' def f1(self):\n pass\n \n',
|
||||
'2.end'),
|
||||
)
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(label=test.label):
|
||||
insert(text, test.text)
|
||||
text.mark_set('insert', test.mark)
|
||||
nl(event=None)
|
||||
eq(get('1.0', 'end'), test.expected)
|
||||
|
||||
# Selected text.
|
||||
insert(text, ' def f1(self, a, b):\n return a + b')
|
||||
text.tag_add('sel', '1.17', '1.end')
|
||||
nl(None)
|
||||
# Deletes selected text before adding new line.
|
||||
eq(get('1.0', 'end'), ' def f1(self, a,\n \n return a + b\n')
|
||||
|
||||
|
||||
class RMenuTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.window = Editor(root=cls.root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.window._close()
|
||||
del cls.window
|
||||
cls.root.update_idletasks()
|
||||
for id in cls.root.tk.call('after', 'info'):
|
||||
cls.root.after_cancel(id)
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
class DummyRMenu:
|
||||
def tk_popup(x, y): pass
|
||||
|
||||
def test_rclick(self):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
33
.CondaPkg/env/Lib/idlelib/idle_test/test_filelist.py
vendored
Normal file
33
.CondaPkg/env/Lib/idlelib/idle_test/test_filelist.py
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
"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)
|
||||
668
.CondaPkg/env/Lib/idlelib/idle_test/test_format.py
vendored
Normal file
668
.CondaPkg/env/Lib/idlelib/idle_test/test_format.py
vendored
Normal file
@@ -0,0 +1,668 @@
|
||||
"Test format, coverage 99%."
|
||||
|
||||
from idlelib import format as ft
|
||||
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
|
||||
|
||||
|
||||
class Is_Get_Test(unittest.TestCase):
|
||||
"""Test the is_ and get_ functions"""
|
||||
test_comment = '# This is a comment'
|
||||
test_nocomment = 'This is not a comment'
|
||||
trailingws_comment = '# This is a comment '
|
||||
leadingws_comment = ' # This is a comment'
|
||||
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))
|
||||
|
||||
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), ' ')
|
||||
|
||||
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), ' #')
|
||||
# Test non-comment strings
|
||||
Equal(ft.get_comment_header(self.leadingws_nocomment), ' ')
|
||||
Equal(ft.get_comment_header(self.test_nocomment), '')
|
||||
|
||||
|
||||
class FindTest(unittest.TestCase):
|
||||
"""Test the find_paragraph function in paragraph module.
|
||||
|
||||
Using the runcase() function, find_paragraph() is called with 'mark' set at
|
||||
multiple indexes before and inside the test paragraph.
|
||||
|
||||
It appears that code with the same indentation as a quoted string is grouped
|
||||
as part of the same paragraph, which is probably incorrect behavior.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
from idlelib.idle_test.mock_tk import Text
|
||||
cls.text = Text()
|
||||
|
||||
def runcase(self, inserttext, stopline, expected):
|
||||
# Check that find_paragraph returns the expected paragraph when
|
||||
# the mark index is set to beginning, middle, end of each line
|
||||
# up to but not including the stop line
|
||||
text = self.text
|
||||
text.insert('1.0', inserttext)
|
||||
for line in range(1, stopline):
|
||||
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)
|
||||
text.delete('1.0', 'end')
|
||||
|
||||
def test_find_comment(self):
|
||||
comment = (
|
||||
"# Comment block with no blank lines before\n"
|
||||
"# Comment line\n"
|
||||
"\n")
|
||||
self.runcase(comment, 3, ('1.0', '3.0', '#', comment[0:58]))
|
||||
|
||||
comment = (
|
||||
"\n"
|
||||
"# Comment block with whitespace line before and after\n"
|
||||
"# Comment line\n"
|
||||
"\n")
|
||||
self.runcase(comment, 4, ('2.0', '4.0', '#', comment[1:70]))
|
||||
|
||||
comment = (
|
||||
"\n"
|
||||
" # Indented comment block with whitespace before and after\n"
|
||||
" # Comment line\n"
|
||||
"\n")
|
||||
self.runcase(comment, 4, ('2.0', '4.0', ' #', comment[1:82]))
|
||||
|
||||
comment = (
|
||||
"\n"
|
||||
"# Single line comment\n"
|
||||
"\n")
|
||||
self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:23]))
|
||||
|
||||
comment = (
|
||||
"\n"
|
||||
" # Single line comment with leading whitespace\n"
|
||||
"\n")
|
||||
self.runcase(comment, 3, ('2.0', '3.0', ' #', comment[1:51]))
|
||||
|
||||
comment = (
|
||||
"\n"
|
||||
"# Comment immediately followed by code\n"
|
||||
"x = 42\n"
|
||||
"\n")
|
||||
self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:40]))
|
||||
|
||||
comment = (
|
||||
"\n"
|
||||
" # Indented comment immediately followed by code\n"
|
||||
"x = 42\n"
|
||||
"\n")
|
||||
self.runcase(comment, 3, ('2.0', '3.0', ' #', comment[1:53]))
|
||||
|
||||
comment = (
|
||||
"\n"
|
||||
"# Comment immediately followed by indented code\n"
|
||||
" x = 42\n"
|
||||
"\n")
|
||||
self.runcase(comment, 3, ('2.0', '3.0', '#', comment[1:49]))
|
||||
|
||||
def test_find_paragraph(self):
|
||||
teststring = (
|
||||
'"""String with no blank lines before\n'
|
||||
'String line\n'
|
||||
'"""\n'
|
||||
'\n')
|
||||
self.runcase(teststring, 4, ('1.0', '4.0', '', teststring[0:53]))
|
||||
|
||||
teststring = (
|
||||
"\n"
|
||||
'"""String with whitespace line before and after\n'
|
||||
'String line.\n'
|
||||
'"""\n'
|
||||
'\n')
|
||||
self.runcase(teststring, 5, ('2.0', '5.0', '', teststring[1:66]))
|
||||
|
||||
teststring = (
|
||||
'\n'
|
||||
' """Indented string with whitespace before and after\n'
|
||||
' Comment string.\n'
|
||||
' """\n'
|
||||
'\n')
|
||||
self.runcase(teststring, 5, ('2.0', '5.0', ' ', teststring[1:85]))
|
||||
|
||||
teststring = (
|
||||
'\n'
|
||||
'"""Single line string."""\n'
|
||||
'\n')
|
||||
self.runcase(teststring, 3, ('2.0', '3.0', '', teststring[1:27]))
|
||||
|
||||
teststring = (
|
||||
'\n'
|
||||
' """Single line string with leading whitespace."""\n'
|
||||
'\n')
|
||||
self.runcase(teststring, 3, ('2.0', '3.0', ' ', teststring[1:55]))
|
||||
|
||||
|
||||
class ReformatFunctionTest(unittest.TestCase):
|
||||
"""Test the reformat_paragraph function without the editor window."""
|
||||
|
||||
def test_reformat_paragraph(self):
|
||||
Equal = self.assertEqual
|
||||
reform = ft.reformat_paragraph
|
||||
hw = "O hello world"
|
||||
Equal(reform(' ', 1), ' ')
|
||||
Equal(reform("Hello world", 20), "Hello world")
|
||||
|
||||
# Test without leading newline
|
||||
Equal(reform(hw, 1), "O\nhello\nworld")
|
||||
Equal(reform(hw, 6), "O\nhello\nworld")
|
||||
Equal(reform(hw, 7), "O hello\nworld")
|
||||
Equal(reform(hw, 12), "O hello\nworld")
|
||||
Equal(reform(hw, 13), "O hello world")
|
||||
|
||||
# Test with leading newline
|
||||
hw = "\nO hello world"
|
||||
Equal(reform(hw, 1), "\nO\nhello\nworld")
|
||||
Equal(reform(hw, 6), "\nO\nhello\nworld")
|
||||
Equal(reform(hw, 7), "\nO hello\nworld")
|
||||
Equal(reform(hw, 12), "\nO hello\nworld")
|
||||
Equal(reform(hw, 13), "\nO hello world")
|
||||
|
||||
|
||||
class ReformatCommentTest(unittest.TestCase):
|
||||
"""Test the reformat_comment function without the editor window."""
|
||||
|
||||
def test_reformat_comment(self):
|
||||
Equal = self.assertEqual
|
||||
|
||||
# reformat_comment formats to a minimum of 20 characters
|
||||
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, " ")
|
||||
expected = (
|
||||
" \"\"\"this is a test of a reformat for a triple quoted string will it\n"
|
||||
" reformat to less than 70 characters for me?\"\"\"")
|
||||
Equal(result, expected)
|
||||
|
||||
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, "#")
|
||||
expected = (
|
||||
"# this is a test of a reformat for a triple quoted string will it\n"
|
||||
"# reformat to less than 70 characters for me?")
|
||||
Equal(result, expected)
|
||||
|
||||
|
||||
class FormatClassTest(unittest.TestCase):
|
||||
def test_init_close(self):
|
||||
instance = ft.FormatParagraph('editor')
|
||||
self.assertEqual(instance.editwin, 'editor')
|
||||
instance.close()
|
||||
self.assertEqual(instance.editwin, None)
|
||||
|
||||
|
||||
# For testing format_paragraph_event, Initialize FormatParagraph with
|
||||
# a mock Editor with .text and .get_selection_indices. The text must
|
||||
# be a Text wrapper that adds two methods
|
||||
|
||||
# A real EditorWindow creates unneeded, time-consuming baggage and
|
||||
# sometimes emits shutdown warnings like this:
|
||||
# "warning: callback failed in WindowList <class '_tkinter.TclError'>
|
||||
# : invalid command name ".55131368.windows".
|
||||
# Calling EditorWindow._close in tearDownClass prevents this but causes
|
||||
# other problems (windows left open).
|
||||
|
||||
class TextWrapper:
|
||||
def __init__(self, master):
|
||||
self.text = Text(master=master)
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.text, name)
|
||||
def undo_block_start(self): pass
|
||||
def undo_block_stop(self): pass
|
||||
|
||||
class Editor:
|
||||
def __init__(self, root):
|
||||
self.text = TextWrapper(root)
|
||||
get_selection_indices = EditorWindow. get_selection_indices
|
||||
|
||||
class FormatEventTest(unittest.TestCase):
|
||||
"""Test the formatting of text inside a Text widget.
|
||||
|
||||
This is done with FormatParagraph.format.paragraph_event,
|
||||
which calls functions in the module as appropriate.
|
||||
"""
|
||||
test_string = (
|
||||
" '''this is a test of a reformat for a triple "
|
||||
"quoted string will it reformat to less than 70 "
|
||||
"characters for me?'''\n")
|
||||
multiline_test_string = (
|
||||
" '''The first line is under the max width.\n"
|
||||
" The second line's length is way over the max width. It goes "
|
||||
"on and on until it is over 100 characters long.\n"
|
||||
" Same thing with the third line. It is also way over the max "
|
||||
"width, but FormatParagraph will fix it.\n"
|
||||
" '''\n")
|
||||
multiline_test_comment = (
|
||||
"# The first line is under the max width.\n"
|
||||
"# The second line's length is way over the max width. It goes on "
|
||||
"and on until it is over 100 characters long.\n"
|
||||
"# Same thing with the third line. It is also way over the max "
|
||||
"width, but FormatParagraph will fix it.\n"
|
||||
"# The fourth line is short like the first line.")
|
||||
|
||||
@classmethod
|
||||
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
|
||||
# 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
|
||||
|
||||
def test_short_line(self):
|
||||
self.text.insert('1.0', "Short line\n")
|
||||
self.formatter("Dummy")
|
||||
self.assertEqual(self.text.get('1.0', 'insert'), "Short line\n" )
|
||||
self.text.delete('1.0', 'end')
|
||||
|
||||
def test_long_line(self):
|
||||
text = self.text
|
||||
|
||||
# Set cursor ('insert' mark) to '1.0', within text.
|
||||
text.insert('1.0', self.test_string)
|
||||
text.mark_set('insert', '1.0')
|
||||
self.formatter('ParameterDoesNothing', limit=70)
|
||||
result = text.get('1.0', 'insert')
|
||||
# find function includes \n
|
||||
expected = (
|
||||
" '''this is a test of a reformat for a triple quoted string will it\n"
|
||||
" reformat to less than 70 characters for me?'''\n") # yes
|
||||
self.assertEqual(result, expected)
|
||||
text.delete('1.0', 'end')
|
||||
|
||||
# Select from 1.11 to line end.
|
||||
text.insert('1.0', self.test_string)
|
||||
text.tag_add('sel', '1.11', '1.end')
|
||||
self.formatter('ParameterDoesNothing', limit=70)
|
||||
result = text.get('1.0', 'insert')
|
||||
# selection excludes \n
|
||||
expected = (
|
||||
" '''this is a test of a reformat for a triple quoted string will it reformat\n"
|
||||
" to less than 70 characters for me?'''") # no
|
||||
self.assertEqual(result, expected)
|
||||
text.delete('1.0', 'end')
|
||||
|
||||
def test_multiple_lines(self):
|
||||
text = self.text
|
||||
# Select 2 long lines.
|
||||
text.insert('1.0', self.multiline_test_string)
|
||||
text.tag_add('sel', '2.0', '4.0')
|
||||
self.formatter('ParameterDoesNothing', limit=70)
|
||||
result = text.get('2.0', 'insert')
|
||||
expected = (
|
||||
" The second line's length is way over the max width. It goes on and\n"
|
||||
" on until it is over 100 characters long. Same thing with the third\n"
|
||||
" line. It is also way over the max width, but FormatParagraph will\n"
|
||||
" fix it.\n")
|
||||
self.assertEqual(result, expected)
|
||||
text.delete('1.0', 'end')
|
||||
|
||||
def test_comment_block(self):
|
||||
text = self.text
|
||||
|
||||
# Set cursor ('insert') to '1.0', within block.
|
||||
text.insert('1.0', self.multiline_test_comment)
|
||||
self.formatter('ParameterDoesNothing', limit=70)
|
||||
result = text.get('1.0', 'insert')
|
||||
expected = (
|
||||
"# The first line is under the max width. The second line's length is\n"
|
||||
"# way over the max width. It goes on and on until it is over 100\n"
|
||||
"# characters long. Same thing with the third line. It is also way over\n"
|
||||
"# the max width, but FormatParagraph will fix it. The fourth line is\n"
|
||||
"# short like the first line.\n")
|
||||
self.assertEqual(result, expected)
|
||||
text.delete('1.0', 'end')
|
||||
|
||||
# Select line 2, verify line 1 unaffected.
|
||||
text.insert('1.0', self.multiline_test_comment)
|
||||
text.tag_add('sel', '2.0', '3.0')
|
||||
self.formatter('ParameterDoesNothing', limit=70)
|
||||
result = text.get('1.0', 'insert')
|
||||
expected = (
|
||||
"# The first line is under the max width.\n"
|
||||
"# The second line's length is way over the max width. It goes on and\n"
|
||||
"# on until it is over 100 characters long.\n")
|
||||
self.assertEqual(result, expected)
|
||||
text.delete('1.0', 'end')
|
||||
|
||||
# The following block worked with EditorWindow but fails with the mock.
|
||||
# Lines 2 and 3 get pasted together even though the previous block left
|
||||
# the previous line alone. More investigation is needed.
|
||||
## # Select lines 3 and 4
|
||||
## text.insert('1.0', self.multiline_test_comment)
|
||||
## text.tag_add('sel', '3.0', '5.0')
|
||||
## self.formatter('ParameterDoesNothing')
|
||||
## result = text.get('3.0', 'insert')
|
||||
## expected = (
|
||||
##"# Same thing with the third line. It is also way over the max width,\n"
|
||||
##"# but FormatParagraph will fix it. The fourth line is short like the\n"
|
||||
##"# first line.\n")
|
||||
## self.assertEqual(result, expected)
|
||||
## 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)
|
||||
156
.CondaPkg/env/Lib/idlelib/idle_test/test_grep.py
vendored
Normal file
156
.CondaPkg/env/Lib/idlelib/idle_test/test_grep.py
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
""" !Changing this line will break Test_findfile.test_found!
|
||||
Non-gui unit tests for grep.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%.
|
||||
"""
|
||||
from idlelib import grep
|
||||
import unittest
|
||||
from test.support import captured_stdout
|
||||
from idlelib.idle_test.mock_tk import Var
|
||||
import os
|
||||
import re
|
||||
|
||||
|
||||
class Dummy_searchengine:
|
||||
'''GrepDialog.__init__ calls parent SearchDiabolBase which attaches the
|
||||
passed in SearchEngine instance as attribute 'engine'. Only a few of the
|
||||
many possible self.engine.x attributes are needed here.
|
||||
'''
|
||||
def getpat(self):
|
||||
return self._pat
|
||||
|
||||
searchengine = Dummy_searchengine()
|
||||
|
||||
|
||||
class Dummy_grep:
|
||||
# Methods tested
|
||||
#default_command = GrepDialog.default_command
|
||||
grep_it = grep.GrepDialog.grep_it
|
||||
# Other stuff needed
|
||||
recvar = Var(False)
|
||||
engine = searchengine
|
||||
def close(self): # gui method
|
||||
pass
|
||||
|
||||
_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)
|
||||
|
||||
|
||||
class Grep_itTest(unittest.TestCase):
|
||||
# Test captured reports with 0 and some hits.
|
||||
# Should test file names, but Windows reports have mixed / and \ separators
|
||||
# from incomplete replacement, so 'later'.
|
||||
|
||||
def report(self, pat):
|
||||
_grep.engine._pat = pat
|
||||
with captured_stdout() as s:
|
||||
_grep.grep_it(re.compile(pat), __file__)
|
||||
lines = s.getvalue().split('\n')
|
||||
lines.pop() # remove bogus '' after last \n
|
||||
return lines
|
||||
|
||||
def test_unfound(self):
|
||||
pat = 'xyz*'*7
|
||||
lines = self.report(pat)
|
||||
self.assertEqual(len(lines), 2)
|
||||
self.assertIn(pat, lines[0])
|
||||
self.assertEqual(lines[1], 'No hits.')
|
||||
|
||||
def test_found(self):
|
||||
|
||||
pat = '""" !Changing this line will break Test_findfile.test_found!'
|
||||
lines = self.report(pat)
|
||||
self.assertEqual(len(lines), 5)
|
||||
self.assertIn(pat, lines[0])
|
||||
self.assertIn('py: 1:', lines[1]) # line number 1
|
||||
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
|
||||
# so it can be replaced by captured_stdout in class setup/teardown.
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
34
.CondaPkg/env/Lib/idlelib/idle_test/test_help.py
vendored
Normal file
34
.CondaPkg/env/Lib/idlelib/idle_test/test_help.py
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
"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)
|
||||
182
.CondaPkg/env/Lib/idlelib/idle_test/test_help_about.py
vendored
Normal file
182
.CondaPkg/env/Lib/idlelib/idle_test/test_help_about.py
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
"""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)
|
||||
172
.CondaPkg/env/Lib/idlelib/idle_test/test_history.py
vendored
Normal file
172
.CondaPkg/env/Lib/idlelib/idle_test/test_history.py
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
" Test history, coverage 100%."
|
||||
|
||||
from idlelib.history import History
|
||||
import unittest
|
||||
from test.support import requires
|
||||
|
||||
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
|
||||
|
||||
line1 = 'a = 7'
|
||||
line2 = 'b = a'
|
||||
|
||||
|
||||
class StoreTest(unittest.TestCase):
|
||||
'''Tests History.__init__ and History.store with mock Text'''
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.text = mkText()
|
||||
cls.history = History(cls.text)
|
||||
|
||||
def tearDown(self):
|
||||
self.text.delete('1.0', 'end')
|
||||
self.history.history = []
|
||||
|
||||
def test_init(self):
|
||||
self.assertIs(self.history.text, self.text)
|
||||
self.assertEqual(self.history.history, [])
|
||||
self.assertIsNone(self.history.prefix)
|
||||
self.assertIsNone(self.history.pointer)
|
||||
self.assertEqual(self.history.cyclic,
|
||||
idleConf.GetOption("main", "History", "cyclic", 1, "bool"))
|
||||
|
||||
def test_store_short(self):
|
||||
self.history.store('a')
|
||||
self.assertEqual(self.history.history, [])
|
||||
self.history.store(' a ')
|
||||
self.assertEqual(self.history.history, [])
|
||||
|
||||
def test_store_dup(self):
|
||||
self.history.store(line1)
|
||||
self.assertEqual(self.history.history, [line1])
|
||||
self.history.store(line2)
|
||||
self.assertEqual(self.history.history, [line1, line2])
|
||||
self.history.store(line1)
|
||||
self.assertEqual(self.history.history, [line2, line1])
|
||||
|
||||
def test_store_reset(self):
|
||||
self.history.prefix = line1
|
||||
self.history.pointer = 0
|
||||
self.history.store(line2)
|
||||
self.assertIsNone(self.history.prefix)
|
||||
self.assertIsNone(self.history.pointer)
|
||||
|
||||
|
||||
class TextWrapper:
|
||||
def __init__(self, master):
|
||||
self.text = tkText(master=master)
|
||||
self._bell = False
|
||||
def __getattr__(self, name):
|
||||
return getattr(self.text, name)
|
||||
def bell(self):
|
||||
self._bell = True
|
||||
|
||||
|
||||
class FetchTest(unittest.TestCase):
|
||||
'''Test History.fetch with wrapped tk.Text.
|
||||
'''
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = tk.Tk()
|
||||
cls.root.withdraw()
|
||||
|
||||
def setUp(self):
|
||||
self.text = text = TextWrapper(self.root)
|
||||
text.insert('1.0', ">>> ")
|
||||
text.mark_set('iomark', '1.4')
|
||||
text.mark_gravity('iomark', 'left')
|
||||
self.history = History(text)
|
||||
self.history.history = [line1, line2]
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
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.
|
||||
History = self.history
|
||||
History.fetch(reverse)
|
||||
|
||||
Equal = self.assertEqual
|
||||
Equal(self.text.get('iomark', 'end-1c'), line)
|
||||
Equal(self.text._bell, bell)
|
||||
if bell:
|
||||
self.text._bell = False
|
||||
Equal(History.prefix, prefix)
|
||||
Equal(History.pointer, index)
|
||||
Equal(self.text.compare("insert", '==', "end-1c"), 1)
|
||||
|
||||
def test_fetch_prev_cyclic(self):
|
||||
prefix = ''
|
||||
test = self.fetch_test
|
||||
test(True, line2, prefix, 1)
|
||||
test(True, line1, prefix, 0)
|
||||
test(True, prefix, None, None, bell=True)
|
||||
|
||||
def test_fetch_next_cyclic(self):
|
||||
prefix = ''
|
||||
test = self.fetch_test
|
||||
test(False, line1, prefix, 0)
|
||||
test(False, line2, prefix, 1)
|
||||
test(False, prefix, None, None, bell=True)
|
||||
|
||||
# Prefix 'a' tests skip line2, which starts with 'b'
|
||||
def test_fetch_prev_prefix(self):
|
||||
prefix = 'a'
|
||||
self.text.insert('iomark', prefix)
|
||||
self.fetch_test(True, line1, prefix, 0)
|
||||
self.fetch_test(True, prefix, None, None, bell=True)
|
||||
|
||||
def test_fetch_next_prefix(self):
|
||||
prefix = 'a'
|
||||
self.text.insert('iomark', prefix)
|
||||
self.fetch_test(False, line1, prefix, 0)
|
||||
self.fetch_test(False, prefix, None, None, bell=True)
|
||||
|
||||
def test_fetch_prev_noncyclic(self):
|
||||
prefix = ''
|
||||
self.history.cyclic = False
|
||||
test = self.fetch_test
|
||||
test(True, line2, prefix, 1)
|
||||
test(True, line1, prefix, 0)
|
||||
test(True, line1, prefix, 0, bell=True)
|
||||
|
||||
def test_fetch_next_noncyclic(self):
|
||||
prefix = ''
|
||||
self.history.cyclic = False
|
||||
test = self.fetch_test
|
||||
test(False, prefix, None, None, bell=True)
|
||||
test(True, line2, prefix, 1)
|
||||
test(False, prefix, None, None, bell=True)
|
||||
test(False, prefix, None, None, bell=True)
|
||||
|
||||
def test_fetch_cursor_move(self):
|
||||
# Move cursor after fetch
|
||||
self.history.fetch(reverse=True) # initialization
|
||||
self.text.mark_set('insert', 'iomark')
|
||||
self.fetch_test(True, line2, None, None, bell=True)
|
||||
|
||||
def test_fetch_edit(self):
|
||||
# Edit after fetch
|
||||
self.history.fetch(reverse=True) # initialization
|
||||
self.text.delete('iomark', 'insert', )
|
||||
self.text.insert('iomark', 'a =')
|
||||
self.fetch_test(True, line1, 'a =', 0) # prefix is reset
|
||||
|
||||
def test_history_prev_next(self):
|
||||
# Minimally test functions bound to events
|
||||
self.history.history_prev('dummy event')
|
||||
self.assertEqual(self.history.pointer, 1)
|
||||
self.history.history_next('dummy event')
|
||||
self.assertEqual(self.history.pointer, None)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=2)
|
||||
276
.CondaPkg/env/Lib/idlelib/idle_test/test_hyperparser.py
vendored
Normal file
276
.CondaPkg/env/Lib/idlelib/idle_test/test_hyperparser.py
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
"Test hyperparser, coverage 98%."
|
||||
|
||||
from idlelib.hyperparser import HyperParser
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk, Text
|
||||
from idlelib.editor import EditorWindow
|
||||
|
||||
class DummyEditwin:
|
||||
def __init__(self, text):
|
||||
self.text = text
|
||||
self.indentwidth = 8
|
||||
self.tabwidth = 8
|
||||
self.prompt_last_line = '>>>'
|
||||
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
|
||||
|
||||
|
||||
class HyperParserTest(unittest.TestCase):
|
||||
code = (
|
||||
'"""This is a module docstring"""\n'
|
||||
'# this line is a comment\n'
|
||||
'x = "this is a string"\n'
|
||||
"y = 'this is also a string'\n"
|
||||
'l = [i for i in range(10)]\n'
|
||||
'm = [py*py for # comment\n'
|
||||
' py in l]\n'
|
||||
'x.__len__\n'
|
||||
"z = ((r'asdf')+('a')))\n"
|
||||
'[x for x in\n'
|
||||
'for = False\n'
|
||||
'cliché = "this is a string with unicode, what a cliché"'
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.text = Text(cls.root)
|
||||
cls.editwin = DummyEditwin(cls.text)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.text, cls.editwin
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.text.insert('insert', self.code)
|
||||
|
||||
def tearDown(self):
|
||||
self.text.delete('1.0', 'end')
|
||||
self.editwin.prompt_last_line = '>>>'
|
||||
|
||||
def get_parser(self, index):
|
||||
"""
|
||||
Return a parser object with index at 'index'
|
||||
"""
|
||||
return HyperParser(self.editwin, index)
|
||||
|
||||
def test_init(self):
|
||||
"""
|
||||
test corner cases in the init method
|
||||
"""
|
||||
with self.assertRaises(ValueError) as ve:
|
||||
self.text.tag_add('console', '1.0', '1.end')
|
||||
p = self.get_parser('1.5')
|
||||
self.assertIn('precedes', str(ve.exception))
|
||||
|
||||
# test without ps1
|
||||
self.editwin.prompt_last_line = ''
|
||||
|
||||
# number of lines lesser than 50
|
||||
p = self.get_parser('end')
|
||||
self.assertEqual(p.rawtext, self.text.get('1.0', 'end'))
|
||||
|
||||
# number of lines greater than 50
|
||||
self.text.insert('end', self.text.get('1.0', 'end')*4)
|
||||
p = self.get_parser('54.5')
|
||||
|
||||
def test_is_in_string(self):
|
||||
get = self.get_parser
|
||||
|
||||
p = get('1.0')
|
||||
self.assertFalse(p.is_in_string())
|
||||
p = get('1.4')
|
||||
self.assertTrue(p.is_in_string())
|
||||
p = get('2.3')
|
||||
self.assertFalse(p.is_in_string())
|
||||
p = get('3.3')
|
||||
self.assertFalse(p.is_in_string())
|
||||
p = get('3.7')
|
||||
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
|
||||
|
||||
p = get('1.0')
|
||||
self.assertTrue(p.is_in_code())
|
||||
p = get('1.1')
|
||||
self.assertFalse(p.is_in_code())
|
||||
p = get('2.5')
|
||||
self.assertFalse(p.is_in_code())
|
||||
p = get('3.4')
|
||||
self.assertTrue(p.is_in_code())
|
||||
p = get('3.6')
|
||||
self.assertFalse(p.is_in_code())
|
||||
p = get('4.14')
|
||||
self.assertFalse(p.is_in_code())
|
||||
|
||||
def test_get_surrounding_bracket(self):
|
||||
get = self.get_parser
|
||||
|
||||
def without_mustclose(parser):
|
||||
# a utility function to get surrounding bracket
|
||||
# with mustclose=False
|
||||
return parser.get_surrounding_brackets(mustclose=False)
|
||||
|
||||
def with_mustclose(parser):
|
||||
# a utility function to get surrounding bracket
|
||||
# with mustclose=True
|
||||
return parser.get_surrounding_brackets(mustclose=True)
|
||||
|
||||
p = get('3.2')
|
||||
self.assertIsNone(with_mustclose(p))
|
||||
self.assertIsNone(without_mustclose(p))
|
||||
|
||||
p = get('5.6')
|
||||
self.assertTupleEqual(without_mustclose(p), ('5.4', '5.25'))
|
||||
self.assertTupleEqual(without_mustclose(p), with_mustclose(p))
|
||||
|
||||
p = get('5.23')
|
||||
self.assertTupleEqual(without_mustclose(p), ('5.21', '5.24'))
|
||||
self.assertTupleEqual(without_mustclose(p), with_mustclose(p))
|
||||
|
||||
p = get('6.15')
|
||||
self.assertTupleEqual(without_mustclose(p), ('6.4', '6.end'))
|
||||
self.assertIsNone(with_mustclose(p))
|
||||
|
||||
p = get('9.end')
|
||||
self.assertIsNone(with_mustclose(p))
|
||||
self.assertIsNone(without_mustclose(p))
|
||||
|
||||
def test_get_expression(self):
|
||||
get = self.get_parser
|
||||
|
||||
p = get('4.2')
|
||||
self.assertEqual(p.get_expression(), 'y ')
|
||||
|
||||
p = get('4.7')
|
||||
with self.assertRaises(ValueError) as ve:
|
||||
p.get_expression()
|
||||
self.assertIn('is inside a code', str(ve.exception))
|
||||
|
||||
p = get('5.25')
|
||||
self.assertEqual(p.get_expression(), 'range(10)')
|
||||
|
||||
p = get('6.7')
|
||||
self.assertEqual(p.get_expression(), 'py')
|
||||
|
||||
p = get('6.8')
|
||||
self.assertEqual(p.get_expression(), '')
|
||||
|
||||
p = get('7.9')
|
||||
self.assertEqual(p.get_expression(), 'py')
|
||||
|
||||
p = get('8.end')
|
||||
self.assertEqual(p.get_expression(), 'x.__len__')
|
||||
|
||||
p = get('9.13')
|
||||
self.assertEqual(p.get_expression(), "r'asdf'")
|
||||
|
||||
p = get('9.17')
|
||||
with self.assertRaises(ValueError) as ve:
|
||||
p.get_expression()
|
||||
self.assertIn('is inside a code', str(ve.exception))
|
||||
|
||||
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)
|
||||
78
.CondaPkg/env/Lib/idlelib/idle_test/test_iomenu.py
vendored
Normal file
78
.CondaPkg/env/Lib/idlelib/idle_test/test_iomenu.py
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
"Test , coverage 17%."
|
||||
|
||||
from idlelib import iomenu
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
from idlelib.editor import EditorWindow
|
||||
from idlelib import util
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
|
||||
|
||||
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
|
||||
|
||||
# Make the editor temporarily look like Shell.
|
||||
self.editwin.interp = None
|
||||
shelltext = '>>> if 1'
|
||||
self.editwin.get_prompt_text = Func(result=shelltext)
|
||||
eq(fix(), shelltext) # Get... call and '\n' not added.
|
||||
del self.editwin.interp, self.editwin.get_prompt_text
|
||||
|
||||
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)
|
||||
|
||||
|
||||
def _extension_in_filetypes(extension):
|
||||
return any(
|
||||
f'*{extension}' in filetype_tuple[1]
|
||||
for filetype_tuple in iomenu.IOBinding.filetypes
|
||||
)
|
||||
|
||||
|
||||
class FiletypesTest(unittest.TestCase):
|
||||
def test_python_source_files(self):
|
||||
for extension in util.py_extensions:
|
||||
with self.subTest(extension=extension):
|
||||
self.assertTrue(
|
||||
_extension_in_filetypes(extension)
|
||||
)
|
||||
|
||||
def test_text_files(self):
|
||||
self.assertTrue(_extension_in_filetypes('.txt'))
|
||||
|
||||
def test_all_files(self):
|
||||
self.assertTrue(_extension_in_filetypes(''))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
||||
113
.CondaPkg/env/Lib/idlelib/idle_test/test_macosx.py
vendored
Normal file
113
.CondaPkg/env/Lib/idlelib/idle_test/test_macosx.py
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
"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
|
||||
|
||||
|
||||
def setUpModule():
|
||||
global orig_tktype
|
||||
orig_tktype = macosx._tk_type
|
||||
|
||||
|
||||
def tearDownModule():
|
||||
macosx._tk_type = orig_tktype
|
||||
|
||||
|
||||
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)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user