mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +00:00
python-3.6.zip added from Github
README.cosmo contains the necessary links.
This commit is contained in:
parent
75fc601ff5
commit
0c4c56ff39
4219 changed files with 1968626 additions and 0 deletions
238
third_party/python/Lib/idlelib/idle_test/README.txt
vendored
Normal file
238
third_party/python/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
third_party/python/Lib/idlelib/idle_test/__init__.py
vendored
Normal file
17
third_party/python/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
|
415
third_party/python/Lib/idlelib/idle_test/htest.py
vendored
Normal file
415
third_party/python/Lib/idlelib/idle_test/htest.py
vendored
Normal file
|
@ -0,0 +1,415 @@
|
|||
'''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 corresonding class. Or the
|
||||
Toplevel may contain the widget to be tested or set up a context in
|
||||
which a test widget is invoked. In this latter case, the callable is a
|
||||
wrapper function that sets up the Toplevel and other objects. Wrapper
|
||||
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 tkinter as tk
|
||||
from tkinter.ttk import Scrollbar
|
||||
tk.NoDefaultRoot()
|
||||
|
||||
AboutDialog_spec = {
|
||||
'file': 'help_about',
|
||||
'kwds': {'title': 'help_about test',
|
||||
'_htest': True,
|
||||
},
|
||||
'msg': "Test every button. Ensure Python, TK and IDLE versions "
|
||||
"are correctly displayed.\n [Close] to exit.",
|
||||
}
|
||||
|
||||
# TODO implement ^\; adding '<Control-Key-\\>' to function does not work.
|
||||
_calltip_window_spec = {
|
||||
'file': 'calltip_w',
|
||||
'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"
|
||||
}
|
||||
|
||||
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."
|
||||
}
|
||||
|
||||
# Update once issue21519 is resolved.
|
||||
GetKeysDialog_spec = {
|
||||
'file': 'config_key',
|
||||
'kwds': {'title': 'Test keybindings',
|
||||
'action': 'find-again',
|
||||
'currentKeySequences': [''] ,
|
||||
'_htest': True,
|
||||
},
|
||||
'msg': "Test for different key modifier sequences.\n"
|
||||
"<nothing> is invalid.\n"
|
||||
"No modifier key is invalid.\n"
|
||||
"Shift key with [a-z],[0-9], function key, move key, tab, space "
|
||||
"is invalid.\nNo validity checking if advanced key binding "
|
||||
"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."
|
||||
}
|
||||
|
||||
_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 upto 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 upto 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 upto 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',
|
||||
'text': '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()
|
60
third_party/python/Lib/idlelib/idle_test/mock_idle.py
vendored
Normal file
60
third_party/python/Lib/idlelib/idle_test/mock_idle.py
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
'''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):
|
||||
self.text = 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
|
303
third_party/python/Lib/idlelib/idle_test/mock_tk.py
vendored
Normal file
303
third_party/python/Lib/idlelib/idle_test/mock_tk.py
vendored
Normal file
|
@ -0,0 +1,303 @@
|
|||
"""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.
|
||||
"""
|
||||
|
||||
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 examime.
|
||||
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.
|
||||
|
||||
This module was 'tkMessageBox' in 2.x; hence the 'import as' in 3.x.
|
||||
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.tkMessageBox
|
||||
showerror = Mbox.showerror # example, for attribute access in test methods
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
module.tkMessageBox = Mbox
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
module.tkMessageBox = orig_mbox
|
||||
---
|
||||
For 'ask' functions, set func.result return value before calling the method
|
||||
that uses the message function. When tkMessageBox functions are the
|
||||
only gui alls 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
|
||||
|
||||
from _tkinter import TclError
|
||||
|
||||
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
|
||||
|
||||
# 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
third_party/python/Lib/idlelib/idle_test/template.py
vendored
Normal file
30
third_party/python/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)
|
144
third_party/python/Lib/idlelib/idle_test/test_autocomplete.py
vendored
Normal file
144
third_party/python/Lib/idlelib/idle_test/test_autocomplete.py
vendored
Normal file
|
@ -0,0 +1,144 @@
|
|||
"Test autocomplete, coverage 57%."
|
||||
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk, Text
|
||||
|
||||
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.context_use_ps1 = True
|
||||
|
||||
|
||||
class AutoCompleteTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.text = Text(cls.root)
|
||||
cls.editor = DummyEditwin(cls.root, cls.text)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.editor, cls.text
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.editor.text.delete('1.0', 'end')
|
||||
self.autocomplete = ac.AutoComplete(self.editor)
|
||||
|
||||
def test_init(self):
|
||||
self.assertEqual(self.autocomplete.editwin, self.editor)
|
||||
|
||||
def test_make_autocomplete_window(self):
|
||||
testwin = self.autocomplete._make_autocomplete_window()
|
||||
self.assertIsInstance(testwin, acw.AutoCompleteWindow)
|
||||
|
||||
def test_remove_autocomplete_window(self):
|
||||
self.autocomplete.autocompletewindow = (
|
||||
self.autocomplete._make_autocomplete_window())
|
||||
self.autocomplete._remove_autocomplete_window()
|
||||
self.assertIsNone(self.autocomplete.autocompletewindow)
|
||||
|
||||
def test_force_open_completions_event(self):
|
||||
# Test that force_open_completions_event calls _open_completions
|
||||
o_cs = Func()
|
||||
self.autocomplete.open_completions = o_cs
|
||||
self.autocomplete.force_open_completions_event('event')
|
||||
self.assertEqual(o_cs.args, (True, False, True))
|
||||
|
||||
def test_try_open_completions_event(self):
|
||||
Equal = self.assertEqual
|
||||
autocomplete = self.autocomplete
|
||||
trycompletions = self.autocomplete.try_open_completions_event
|
||||
o_c_l = Func()
|
||||
autocomplete._open_completions_later = o_c_l
|
||||
|
||||
# _open_completions_later should not be called with no text in editor
|
||||
trycompletions('event')
|
||||
Equal(o_c_l.args, None)
|
||||
|
||||
# _open_completions_later should be called with COMPLETE_ATTRIBUTES (1)
|
||||
self.text.insert('1.0', 're.')
|
||||
trycompletions('event')
|
||||
Equal(o_c_l.args, (False, False, False, 1))
|
||||
|
||||
# _open_completions_later should be called with COMPLETE_FILES (2)
|
||||
self.text.delete('1.0', 'end')
|
||||
self.text.insert('1.0', '"./Lib/')
|
||||
trycompletions('event')
|
||||
Equal(o_c_l.args, (False, False, False, 2))
|
||||
|
||||
def test_autocomplete_event(self):
|
||||
Equal = self.assertEqual
|
||||
autocomplete = self.autocomplete
|
||||
|
||||
# Test that the autocomplete event is ignored if user is pressing a
|
||||
# modifier key in addition to the tab key
|
||||
ev = Event(mc_state=True)
|
||||
self.assertIsNone(autocomplete.autocomplete_event(ev))
|
||||
del ev.mc_state
|
||||
|
||||
# Test that tab after whitespace is ignored.
|
||||
self.text.insert('1.0', ' """Docstring.\n ')
|
||||
self.assertIsNone(autocomplete.autocomplete_event(ev))
|
||||
self.text.delete('1.0', 'end')
|
||||
|
||||
# If autocomplete window is open, complete() method is called
|
||||
self.text.insert('1.0', 're.')
|
||||
# This must call autocomplete._make_autocomplete_window()
|
||||
Equal(self.autocomplete.autocomplete_event(ev), 'break')
|
||||
|
||||
# If autocomplete window is not active or does not exist,
|
||||
# open_completions is called. Return depends on its return.
|
||||
autocomplete._remove_autocomplete_window()
|
||||
o_cs = Func() # .result = None
|
||||
autocomplete.open_completions = o_cs
|
||||
Equal(self.autocomplete.autocomplete_event(ev), None)
|
||||
Equal(o_cs.args, (False, True, True))
|
||||
o_cs.result = True
|
||||
Equal(self.autocomplete.autocomplete_event(ev), 'break')
|
||||
Equal(o_cs.args, (False, True, True))
|
||||
|
||||
def test_open_completions_later(self):
|
||||
# Test that autocomplete._delayed_completion_id is set
|
||||
pass
|
||||
|
||||
def test_delayed_open_completions(self):
|
||||
# Test that autocomplete._delayed_completion_id set to None and that
|
||||
# open_completions only called if insertion index is the same as
|
||||
# _delayed_completion_index
|
||||
pass
|
||||
|
||||
def test_open_completions(self):
|
||||
# Test completions of files and attributes as well as non-completion
|
||||
# of errors
|
||||
pass
|
||||
|
||||
def test_fetch_completions(self):
|
||||
# Test that fetch_completions returns 2 lists:
|
||||
# For attribute completion, a large list containing all variables, and
|
||||
# a small list containing non-private variables.
|
||||
# For file completion, a large list containing all files in the path,
|
||||
# and a small list containing files that do not start with '.'
|
||||
pass
|
||||
|
||||
def test_get_entity(self):
|
||||
# Test that a name is in the namespace of sys.modules and
|
||||
# __main__.__dict__
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
32
third_party/python/Lib/idlelib/idle_test/test_autocomplete_w.py
vendored
Normal file
32
third_party/python/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)
|
||||
|
||||
@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
third_party/python/Lib/idlelib/idle_test/test_autoexpand.py
vendored
Normal file
155
third_party/python/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 Dummy_Editwin:
|
||||
# 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(Dummy_Editwin(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)
|
248
third_party/python/Lib/idlelib/idle_test/test_browser.py
vendored
Normal file
248
third_party/python/Lib/idlelib/idle_test/test_browser.py
vendored
Normal file
|
@ -0,0 +1,248 @@
|
|||
"Test browser, coverage 90%."
|
||||
|
||||
from idlelib import browser
|
||||
from test.support import requires
|
||||
import unittest
|
||||
from unittest import mock
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
|
||||
from collections import deque
|
||||
import os.path
|
||||
from idlelib import _pyclbr as pyclbr
|
||||
from tkinter import Tk
|
||||
|
||||
from idlelib.tree import TreeNode
|
||||
|
||||
|
||||
class ModuleBrowserTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.mb = browser.ModuleBrowser(cls.root, __file__, _utest=True)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.mb.close()
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root, cls.mb
|
||||
|
||||
def test_init(self):
|
||||
mb = self.mb
|
||||
eq = self.assertEqual
|
||||
eq(mb.path, __file__)
|
||||
eq(pyclbr._modules, {})
|
||||
self.assertIsInstance(mb.node, TreeNode)
|
||||
self.assertIsNotNone(browser.file_open)
|
||||
|
||||
def test_settitle(self):
|
||||
mb = self.mb
|
||||
self.assertIn(os.path.basename(__file__), mb.top.title())
|
||||
self.assertEqual(mb.top.iconname(), 'Module Browser')
|
||||
|
||||
def test_rootnode(self):
|
||||
mb = self.mb
|
||||
rn = mb.rootnode()
|
||||
self.assertIsInstance(rn, browser.ModuleBrowserTreeItem)
|
||||
|
||||
def test_close(self):
|
||||
mb = self.mb
|
||||
mb.top.destroy = Func()
|
||||
mb.node.destroy = Func()
|
||||
mb.close()
|
||||
self.assertTrue(mb.top.destroy.called)
|
||||
self.assertTrue(mb.node.destroy.called)
|
||||
del mb.top.destroy, mb.node.destroy
|
||||
|
||||
|
||||
# Nested tree same as in test_pyclbr.py except for supers on C0. C1.
|
||||
mb = pyclbr
|
||||
module, fname = 'test', 'test.py'
|
||||
f0 = mb.Function(module, 'f0', fname, 1)
|
||||
f1 = mb._nest_function(f0, 'f1', 2)
|
||||
f2 = mb._nest_function(f1, 'f2', 3)
|
||||
c1 = mb._nest_class(f0, 'c1', 5)
|
||||
C0 = mb.Class(module, 'C0', ['base'], fname, 6)
|
||||
F1 = mb._nest_function(C0, 'F1', 8)
|
||||
C1 = mb._nest_class(C0, 'C1', 11, [''])
|
||||
C2 = mb._nest_class(C1, 'C2', 12)
|
||||
F3 = mb._nest_function(C2, 'F3', 14)
|
||||
mock_pyclbr_tree = {'f0': f0, 'C0': C0}
|
||||
|
||||
# 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, [f0, C0])
|
||||
eq(tcl[0].name, 'f0')
|
||||
eq(tcl[1].name, 'C0(base)')
|
||||
# Check that second call does not change suffix.
|
||||
tcl = list(transform(mock_pyclbr_tree, 'test'))
|
||||
eq(tcl[1].name, 'C0(base)')
|
||||
# Nothing to traverse if parameter name isn't same as tree module.
|
||||
tcl = list(transform(mock_pyclbr_tree, 'different name'))
|
||||
eq(tcl, [])
|
||||
|
||||
def test_transform_node_children(self):
|
||||
eq = self.assertEqual
|
||||
transform = browser.transform_children
|
||||
# Class with two children, one name altered.
|
||||
tcl = list(transform(C0.children))
|
||||
eq(tcl, [F1, C1])
|
||||
eq(tcl[0].name, 'F1')
|
||||
eq(tcl[1].name, 'C1()')
|
||||
tcl = list(transform(C0.children))
|
||||
eq(tcl[1].name, 'C1()')
|
||||
# Function with two children.
|
||||
eq(list(transform(f0.children)), [f1, c1])
|
||||
|
||||
|
||||
class ModuleBrowserTreeItemTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.mbt = browser.ModuleBrowserTreeItem(fname)
|
||||
|
||||
def test_init(self):
|
||||
self.assertEqual(self.mbt.file, fname)
|
||||
|
||||
def test_gettext(self):
|
||||
self.assertEqual(self.mbt.GetText(), fname)
|
||||
|
||||
def test_geticonname(self):
|
||||
self.assertEqual(self.mbt.GetIconName(), 'python')
|
||||
|
||||
def test_isexpandable(self):
|
||||
self.assertTrue(self.mbt.IsExpandable())
|
||||
|
||||
def test_listchildren(self):
|
||||
save_rex = browser.pyclbr.readmodule_ex
|
||||
save_tc = browser.transform_children
|
||||
browser.pyclbr.readmodule_ex = Func(result=mock_pyclbr_tree)
|
||||
browser.transform_children = Func(result=[f0, C0])
|
||||
try:
|
||||
self.assertEqual(self.mbt.listchildren(), [f0, C0])
|
||||
finally:
|
||||
browser.pyclbr.readmodule_ex = save_rex
|
||||
browser.transform_children = save_tc
|
||||
|
||||
def test_getsublist(self):
|
||||
mbt = self.mbt
|
||||
mbt.listchildren = Func(result=[f0, C0])
|
||||
sub0, sub1 = mbt.GetSubList()
|
||||
del mbt.listchildren
|
||||
self.assertIsInstance(sub0, browser.ChildBrowserTreeItem)
|
||||
self.assertIsInstance(sub1, browser.ChildBrowserTreeItem)
|
||||
self.assertEqual(sub0.name, 'f0')
|
||||
self.assertEqual(sub1.name, 'C0(base)')
|
||||
|
||||
@mock.patch('idlelib.browser.file_open')
|
||||
def test_ondoubleclick(self, fopen):
|
||||
mbt = self.mbt
|
||||
|
||||
with mock.patch('os.path.exists', return_value=False):
|
||||
mbt.OnDoubleClick()
|
||||
fopen.assert_not_called()
|
||||
|
||||
with mock.patch('os.path.exists', return_value=True):
|
||||
mbt.OnDoubleClick()
|
||||
fopen.assert_called()
|
||||
fopen.called_with(fname)
|
||||
|
||||
|
||||
class ChildBrowserTreeItemTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
CBT = browser.ChildBrowserTreeItem
|
||||
cls.cbt_f1 = CBT(f1)
|
||||
cls.cbt_C1 = CBT(C1)
|
||||
cls.cbt_F1 = CBT(F1)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.cbt_C1, cls.cbt_f1, cls.cbt_F1
|
||||
|
||||
def test_init(self):
|
||||
eq = self.assertEqual
|
||||
eq(self.cbt_C1.name, 'C1()')
|
||||
self.assertFalse(self.cbt_C1.isfunction)
|
||||
eq(self.cbt_f1.name, 'f1')
|
||||
self.assertTrue(self.cbt_f1.isfunction)
|
||||
|
||||
def test_gettext(self):
|
||||
self.assertEqual(self.cbt_C1.GetText(), 'class C1()')
|
||||
self.assertEqual(self.cbt_f1.GetText(), 'def f1(...)')
|
||||
|
||||
def test_geticonname(self):
|
||||
self.assertEqual(self.cbt_C1.GetIconName(), 'folder')
|
||||
self.assertEqual(self.cbt_f1.GetIconName(), 'python')
|
||||
|
||||
def test_isexpandable(self):
|
||||
self.assertTrue(self.cbt_C1.IsExpandable())
|
||||
self.assertTrue(self.cbt_f1.IsExpandable())
|
||||
self.assertFalse(self.cbt_F1.IsExpandable())
|
||||
|
||||
def test_getsublist(self):
|
||||
eq = self.assertEqual
|
||||
CBT = browser.ChildBrowserTreeItem
|
||||
|
||||
f1sublist = self.cbt_f1.GetSubList()
|
||||
self.assertIsInstance(f1sublist[0], CBT)
|
||||
eq(len(f1sublist), 1)
|
||||
eq(f1sublist[0].name, 'f2')
|
||||
|
||||
eq(self.cbt_F1.GetSubList(), [])
|
||||
|
||||
@mock.patch('idlelib.browser.file_open')
|
||||
def test_ondoubleclick(self, fopen):
|
||||
goto = fopen.return_value.gotoline = mock.Mock()
|
||||
self.cbt_F1.OnDoubleClick()
|
||||
fopen.assert_called()
|
||||
goto.assert_called()
|
||||
goto.assert_called_with(self.cbt_F1.obj.lineno)
|
||||
# Failure test would have to raise OSError or AttributeError.
|
||||
|
||||
|
||||
class NestedChildrenTest(unittest.TestCase):
|
||||
"Test that all the nodes in a nested tree are added to the BrowserTree."
|
||||
|
||||
def test_nested(self):
|
||||
queue = deque()
|
||||
actual_names = []
|
||||
# The tree items are processed in breadth first order.
|
||||
# Verify that processing each sublist hits every node and
|
||||
# in the right order.
|
||||
expected_names = ['f0', 'C0(base)',
|
||||
'f1', 'c1', 'F1', 'C1()',
|
||||
'f2', 'C2',
|
||||
'F3']
|
||||
CBT = browser.ChildBrowserTreeItem
|
||||
queue.extend((CBT(f0), CBT(C0)))
|
||||
while queue:
|
||||
cb = queue.popleft()
|
||||
sublist = cb.GetSubList()
|
||||
queue.extend(sublist)
|
||||
self.assertIn(cb.name, cb.GetText())
|
||||
self.assertIn(cb.GetIconName(), ('python', 'folder'))
|
||||
self.assertIs(cb.IsExpandable(), sublist != [])
|
||||
actual_names.append(cb.name)
|
||||
self.assertEqual(actual_names, expected_names)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
216
third_party/python/Lib/idlelib/idle_test/test_calltip.py
vendored
Normal file
216
third_party/python/Lib/idlelib/idle_test/test_calltip.py
vendored
Normal file
|
@ -0,0 +1,216 @@
|
|||
"Test calltip, coverage 60%"
|
||||
|
||||
from idlelib import calltip
|
||||
import unittest
|
||||
import textwrap
|
||||
import types
|
||||
|
||||
default_tip = calltip._default_callable_argspec
|
||||
|
||||
|
||||
# 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)"
|
||||
# attaching .tip to wrapped methods does not work
|
||||
@classmethod
|
||||
def cm(cls, a): 'doc'
|
||||
@staticmethod
|
||||
def sm(b): 'doc'
|
||||
|
||||
|
||||
tc = TC()
|
||||
signature = calltip.get_argspec # 2.7 and 3.x use different functions
|
||||
|
||||
|
||||
class Get_signatureTest(unittest.TestCase):
|
||||
# The signature function must return a string, even if blank.
|
||||
# Test a variety of objects to be sure that none cause it to raise
|
||||
# (quite aside from getting as correct an answer as possible).
|
||||
# The tests of builtins may break if 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):
|
||||
|
||||
# Python class that inherits builtin methods
|
||||
class List(list): "List() doc"
|
||||
|
||||
# Simulate builtin with no docstring for default tip test
|
||||
class SB: __call__ = None
|
||||
|
||||
def gtest(obj, out):
|
||||
self.assertEqual(signature(obj), out)
|
||||
|
||||
if List.__doc__ is not None:
|
||||
gtest(List, List.__doc__) # This and append_doc changed in 3.7.
|
||||
gtest(list.__new__,
|
||||
'(*args, **kwargs)\n'
|
||||
'Create and return a new object.'
|
||||
' See help(type) for accurate signature.')
|
||||
gtest(list.__init__,
|
||||
'(self, /, *args, **kwargs)'
|
||||
+ calltip._argument_positional + '\n' +
|
||||
'Initialize self. See help(type(self)) for accurate signature.')
|
||||
append_doc = "L.append(object) -> None -- append object to end"
|
||||
gtest(list.append, append_doc)
|
||||
gtest([].append, append_doc)
|
||||
gtest(List.append, append_doc)
|
||||
|
||||
gtest(types.MethodType, "method(function, instance)")
|
||||
gtest(SB(), default_tip)
|
||||
import re
|
||||
p = re.compile('')
|
||||
gtest(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''')
|
||||
gtest(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(signature(textwrap.TextWrapper), '''\
|
||||
(width=70, initial_indent='', subsequent_indent='', expand_tabs=True,
|
||||
replace_whitespace=True, fix_sentence_endings=False, break_long_words=True,
|
||||
drop_whitespace=True, break_on_hyphens=True, tabsize=8, *, max_lines=None,
|
||||
placeholder=' [...]')''')
|
||||
|
||||
def test_docline_truncation(self):
|
||||
def f(): pass
|
||||
f.__doc__ = 'a'*300
|
||||
self.assertEqual(signature(f), '()\n' + 'a' * (calltip._MAX_COLS-3) + '...')
|
||||
|
||||
def test_multiline_docstring(self):
|
||||
# Test fewer lines than max.
|
||||
self.assertEqual(signature(range),
|
||||
"range(stop) -> range object\n"
|
||||
"range(start, stop[, step]) -> range object")
|
||||
|
||||
# Test max lines
|
||||
self.assertEqual(signature(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(signature(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):
|
||||
self.assertEqual(signature(func), func.tip + doc)
|
||||
|
||||
def test_methods(self):
|
||||
doc = '\ndoc' if TC.__doc__ is not None else ''
|
||||
for meth in (TC.t1, TC.t2, TC.t3, TC.t4, TC.t5, TC.t6, TC.__call__):
|
||||
self.assertEqual(signature(meth), meth.tip + doc)
|
||||
self.assertEqual(signature(TC.cm), "(a)" + doc)
|
||||
self.assertEqual(signature(TC.sm), "(b)" + doc)
|
||||
|
||||
def test_bound_methods(self):
|
||||
# test that first parameter is correctly removed from argspec
|
||||
doc = '\ndoc' if TC.__doc__ is not None else ''
|
||||
for meth, mtip in ((tc.t1, "()"), (tc.t4, "(*args)"),
|
||||
(tc.t6, "(self)"), (tc.__call__, '(ci)'),
|
||||
(tc, '(ci)'), (TC.cm, "(a)"),):
|
||||
self.assertEqual(signature(meth), mtip + doc)
|
||||
|
||||
def test_starred_parameter(self):
|
||||
# test that starred first parameter is *not* removed from argspec
|
||||
class C:
|
||||
def m1(*args): pass
|
||||
c = C()
|
||||
for meth, mtip in ((C.m1, '(*args)'), (c.m1, "(*args)"),):
|
||||
self.assertEqual(signature(meth), mtip)
|
||||
|
||||
def test_invalid_method_signature(self):
|
||||
class C:
|
||||
def m2(**kwargs): pass
|
||||
class Test:
|
||||
def __call__(*, a): pass
|
||||
|
||||
mtip = calltip._invalid_method
|
||||
self.assertEqual(signature(C().m2), mtip)
|
||||
self.assertEqual(signature(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):
|
||||
def nd(s):
|
||||
pass
|
||||
TC.nd = nd
|
||||
self.assertEqual(signature(nd), "(s)")
|
||||
self.assertEqual(signature(TC.nd), "(s)")
|
||||
self.assertEqual(signature(tc.nd), "()")
|
||||
|
||||
def test_attribute_exception(self):
|
||||
class NoCall:
|
||||
def __getattr__(self, name):
|
||||
raise BaseException
|
||||
class CallA(NoCall):
|
||||
def __call__(oui, a, b, c):
|
||||
pass
|
||||
class CallB(NoCall):
|
||||
def __call__(self, ci):
|
||||
pass
|
||||
|
||||
for meth, mtip in ((NoCall, default_tip), (CallA, default_tip),
|
||||
(NoCall(), ''), (CallA(), '(a, b, c)'),
|
||||
(CallB(), '(ci)')):
|
||||
self.assertEqual(signature(meth), mtip)
|
||||
|
||||
def test_non_callables(self):
|
||||
for obj in (0, 0.0, '0', b'0', [], {}):
|
||||
self.assertEqual(signature(obj), '')
|
||||
|
||||
|
||||
class Get_entityTest(unittest.TestCase):
|
||||
def test_bad_entity(self):
|
||||
self.assertIsNone(calltip.get_entity('1/0'))
|
||||
def test_good_entity(self):
|
||||
self.assertIs(calltip.get_entity('int'), int)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
29
third_party/python/Lib/idlelib/idle_test/test_calltip_w.py
vendored
Normal file
29
third_party/python/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)
|
403
third_party/python/Lib/idlelib/idle_test/test_codecontext.py
vendored
Normal file
403
third_party/python/Lib/idlelib/idle_test/test_codecontext.py
vendored
Normal file
|
@ -0,0 +1,403 @@
|
|||
"Test codecontext, coverage 100%"
|
||||
|
||||
from idlelib import codecontext
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import 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
|
||||
|
||||
|
||||
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.pack(side='top', fill='both', expand=1)
|
||||
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.cc = codecontext.CodeContext(self.editor)
|
||||
|
||||
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.textfont, ed.text['font'])
|
||||
self.assertIsNone(cc.context)
|
||||
eq(cc.info, [(0, -1, '', False)])
|
||||
eq(cc.topvisible, 1)
|
||||
eq(self.root.tk.call('after', 'info', self.cc.t1)[1], 'timer')
|
||||
eq(self.root.tk.call('after', 'info', self.cc.t2)[1], 'timer')
|
||||
|
||||
def test_del(self):
|
||||
self.cc.__del__()
|
||||
with self.assertRaises(TclError) as msg:
|
||||
self.root.tk.call('after', 'info', self.cc.t1)
|
||||
self.assertIn("doesn't exist", msg)
|
||||
with self.assertRaises(TclError) as msg:
|
||||
self.root.tk.call('after', 'info', self.cc.t2)
|
||||
self.assertIn("doesn't exist", msg)
|
||||
# For coverage on the except. Have to delete because the
|
||||
# above Tcl error is caught by after_cancel.
|
||||
del self.cc.t1, self.cc.t2
|
||||
self.cc.__del__()
|
||||
|
||||
def test_reload(self):
|
||||
codecontext.CodeContext.reload()
|
||||
self.assertEqual(self.cc.colors, {'background': 'lightgray',
|
||||
'foreground': '#000000'})
|
||||
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.
|
||||
eq(toggle(), 'break')
|
||||
self.assertIsNotNone(cc.context)
|
||||
eq(cc.context['font'], cc.textfont)
|
||||
eq(cc.context['fg'], cc.colors['foreground'])
|
||||
eq(cc.context['bg'], cc.colors['background'])
|
||||
eq(cc.context.get('1.0', 'end-1c'), '')
|
||||
|
||||
# Toggle off.
|
||||
eq(toggle(), 'break')
|
||||
self.assertIsNone(cc.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(f'{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(f'{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(f'{12}.0')
|
||||
cc.update_code_context()
|
||||
eq(cc.topvisible, 12)
|
||||
cc.context.mark_set('insert', '1.0')
|
||||
jump()
|
||||
eq(cc.topvisible, 8)
|
||||
|
||||
@mock.patch.object(codecontext.CodeContext, 'update_code_context')
|
||||
def test_timer_event(self, mock_update):
|
||||
# Ensure code context is not active.
|
||||
if self.cc.context:
|
||||
self.cc.toggle_code_context_event()
|
||||
self.cc.timer_event()
|
||||
mock_update.assert_not_called()
|
||||
|
||||
# Activate code context.
|
||||
self.cc.toggle_code_context_event()
|
||||
self.cc.timer_event()
|
||||
mock_update.assert_called()
|
||||
|
||||
def test_config_timer_event(self):
|
||||
eq = self.assertEqual
|
||||
cc = self.cc
|
||||
save_font = cc.text['font']
|
||||
save_colors = codecontext.CodeContext.colors
|
||||
test_font = 'FakeFont'
|
||||
test_colors = {'background': '#222222', 'foreground': '#ffff00'}
|
||||
|
||||
# Ensure code context is not active.
|
||||
if cc.context:
|
||||
cc.toggle_code_context_event()
|
||||
|
||||
# Nothing updates on inactive code context.
|
||||
cc.text['font'] = test_font
|
||||
codecontext.CodeContext.colors = test_colors
|
||||
cc.config_timer_event()
|
||||
eq(cc.textfont, save_font)
|
||||
eq(cc.contextcolors, save_colors)
|
||||
|
||||
# Activate code context, but no change to font or color.
|
||||
cc.toggle_code_context_event()
|
||||
cc.text['font'] = save_font
|
||||
codecontext.CodeContext.colors = save_colors
|
||||
cc.config_timer_event()
|
||||
eq(cc.textfont, save_font)
|
||||
eq(cc.contextcolors, save_colors)
|
||||
eq(cc.context['font'], save_font)
|
||||
eq(cc.context['background'], save_colors['background'])
|
||||
eq(cc.context['foreground'], save_colors['foreground'])
|
||||
|
||||
# Active code context, change font.
|
||||
cc.text['font'] = test_font
|
||||
cc.config_timer_event()
|
||||
eq(cc.textfont, test_font)
|
||||
eq(cc.contextcolors, save_colors)
|
||||
eq(cc.context['font'], test_font)
|
||||
eq(cc.context['background'], save_colors['background'])
|
||||
eq(cc.context['foreground'], save_colors['foreground'])
|
||||
|
||||
# Active code context, change color.
|
||||
cc.text['font'] = save_font
|
||||
codecontext.CodeContext.colors = test_colors
|
||||
cc.config_timer_event()
|
||||
eq(cc.textfont, save_font)
|
||||
eq(cc.contextcolors, test_colors)
|
||||
eq(cc.context['font'], save_font)
|
||||
eq(cc.context['background'], test_colors['background'])
|
||||
eq(cc.context['foreground'], test_colors['foreground'])
|
||||
codecontext.CodeContext.colors = save_colors
|
||||
cc.config_timer_event()
|
||||
|
||||
|
||||
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)
|
53
third_party/python/Lib/idlelib/idle_test/test_colorizer.py
vendored
Normal file
53
third_party/python/Lib/idlelib/idle_test/test_colorizer.py
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
"Test colorizer, coverage 25%."
|
||||
|
||||
from idlelib import colorizer
|
||||
from test.support import requires
|
||||
from tkinter import Tk, Text
|
||||
import unittest
|
||||
|
||||
|
||||
class FunctionTest(unittest.TestCase):
|
||||
|
||||
def test_any(self):
|
||||
self.assertTrue(colorizer.any('test', ('a', 'b')))
|
||||
|
||||
def test_make_pat(self):
|
||||
self.assertTrue(colorizer.make_pat())
|
||||
|
||||
|
||||
class ColorConfigTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.text = Text(cls.root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.text
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_colorizer(self):
|
||||
colorizer.color_config(self.text)
|
||||
|
||||
|
||||
class ColorDelegatorTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_colorizer(self):
|
||||
colorizer.ColorDelegator()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
822
third_party/python/Lib/idlelib/idle_test/test_config.py
vendored
Normal file
822
third_party/python/Lib/idlelib/idle_test/test_config.py
vendored
Normal file
|
@ -0,0 +1,822 @@
|
|||
"""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_remove_file(self):
|
||||
with tempfile.TemporaryDirectory() as tdir:
|
||||
path = os.path.join(tdir, 'test.cfg')
|
||||
parser = self.new_parser(path)
|
||||
parser.RemoveFile() # Should not raise exception.
|
||||
|
||||
parser.AddSection('Foo')
|
||||
parser.SetOption('Foo', 'bar', 'true')
|
||||
parser.Save()
|
||||
self.assertTrue(os.path.exists(path))
|
||||
parser.RemoveFile()
|
||||
self.assertFalse(os.path.exists(path))
|
||||
|
||||
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 config_type, parser in conf.defaultCfg.items():
|
||||
self.assertEqual(parser.file,
|
||||
os.path.join(idle_dir, 'config-%s.def' % config_type))
|
||||
for config_type, parser in conf.userCfg.items():
|
||||
self.assertEqual(parser.file,
|
||||
os.path.join(conf.userdir, 'config-%s.cfg' % config_type))
|
||||
|
||||
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'})
|
||||
eq(conf.GetHighlight('IDLE Classic', 'normal', 'fg'), '#000000')
|
||||
eq(conf.GetHighlight('IDLE Classic', 'normal', 'bg'), '#ffffff')
|
||||
with self.assertRaises(config.InvalidFgBg):
|
||||
conf.GetHighlight('IDLE Classic', 'normal', 'fb')
|
||||
|
||||
# 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):
|
||||
"XXX: NOT YET DONE"
|
||||
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()
|
||||
|
||||
# Conflic 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)
|
99
third_party/python/Lib/idlelib/idle_test/test_config_key.py
vendored
Normal file
99
third_party/python/Lib/idlelib/idle_test/test_config_key.py
vendored
Normal file
|
@ -0,0 +1,99 @@
|
|||
"Test config_key, coverage 75%"
|
||||
|
||||
from idlelib import config_key
|
||||
from test.support import requires
|
||||
import unittest
|
||||
from tkinter import Tk
|
||||
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, KeysOK, bind_ok."
|
||||
|
||||
class Validator(config_key.GetKeysDialog):
|
||||
def __init__(self, *args, **kwargs):
|
||||
config_key.GetKeysDialog.__init__(self, *args, **kwargs)
|
||||
class listKeysFinal:
|
||||
get = Func()
|
||||
self.listKeysFinal = listKeysFinal
|
||||
GetModifiers = Func()
|
||||
showerror = Mbox_func()
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
keylist = [['<Key-F12>'], ['<Control-Key-x>', '<Control-Key-X>']]
|
||||
cls.dialog = cls.Validator(
|
||||
cls.root, 'Title', '<<Test>>', keylist, _utest=True)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.dialog.Cancel()
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.dialog, cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.dialog.showerror.message = ''
|
||||
# A test that needs a particular final key value should set it.
|
||||
# A test that sets a non-blank modifier list should reset it to [].
|
||||
|
||||
def test_ok_empty(self):
|
||||
self.dialog.keyString.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.keyString.set('<Key-F11>')
|
||||
self.dialog.listKeysFinal.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.KeysOK('<Control-Shift'))
|
||||
self.assertIn('Missing the final', self.dialog.showerror.message)
|
||||
|
||||
def test_keys_no_modifier_bad(self):
|
||||
self.dialog.listKeysFinal.get.result = 'A'
|
||||
self.assertFalse(self.dialog.KeysOK('<Key-A>'))
|
||||
self.assertIn('No modifier', self.dialog.showerror.message)
|
||||
|
||||
def test_keys_no_modifier_ok(self):
|
||||
self.dialog.listKeysFinal.get.result = 'F11'
|
||||
self.assertTrue(self.dialog.KeysOK('<Key-F11>'))
|
||||
self.assertEqual(self.dialog.showerror.message, '')
|
||||
|
||||
def test_keys_shift_bad(self):
|
||||
self.dialog.listKeysFinal.get.result = 'a'
|
||||
self.dialog.GetModifiers.result = ['Shift']
|
||||
self.assertFalse(self.dialog.KeysOK('<a>'))
|
||||
self.assertIn('shift modifier', self.dialog.showerror.message)
|
||||
self.dialog.GetModifiers.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.listKeysFinal.get.result = final
|
||||
self.dialog.GetModifiers.result = mods
|
||||
self.assertFalse(self.dialog.KeysOK(seq))
|
||||
self.assertIn('already in use', self.dialog.showerror.message)
|
||||
self.dialog.GetModifiers.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)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
1418
third_party/python/Lib/idlelib/idle_test/test_configdialog.py
vendored
Normal file
1418
third_party/python/Lib/idlelib/idle_test/test_configdialog.py
vendored
Normal file
File diff suppressed because it is too large
Load diff
29
third_party/python/Lib/idlelib/idle_test/test_debugger.py
vendored
Normal file
29
third_party/python/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)
|
29
third_party/python/Lib/idlelib/idle_test/test_debugger_r.py
vendored
Normal file
29
third_party/python/Lib/idlelib/idle_test/test_debugger_r.py
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
"Test debugger_r, coverage 30%."
|
||||
|
||||
from idlelib import debugger_r
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
## @classmethod
|
||||
## def setUpClass(cls):
|
||||
## requires('gui')
|
||||
## cls.root = Tk()
|
||||
##
|
||||
## @classmethod
|
||||
## def tearDownClass(cls):
|
||||
## cls.root.destroy()
|
||||
## del cls.root
|
||||
|
||||
def test_init(self):
|
||||
self.assertTrue(True) # Get coverage of import
|
||||
|
||||
|
||||
# Classes GUIProxy, IdbAdapter, FrameProxy, CodeProxy, DictProxy,
|
||||
# GUIAdapter, IdbProxy plus 7 module functions.
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
57
third_party/python/Lib/idlelib/idle_test/test_debugobj.py
vendored
Normal file
57
third_party/python/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
third_party/python/Lib/idlelib/idle_test/test_debugobj_r.py
vendored
Normal file
22
third_party/python/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
third_party/python/Lib/idlelib/idle_test/test_delegator.py
vendored
Normal file
44
third_party/python/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
third_party/python/Lib/idlelib/idle_test/test_editmenu.py
vendored
Normal file
74
third_party/python/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)
|
46
third_party/python/Lib/idlelib/idle_test/test_editor.py
vendored
Normal file
46
third_party/python/Lib/idlelib/idle_test/test_editor.py
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
"Test editor, coverage 35%."
|
||||
|
||||
from idlelib import editor
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
Editor = editor.EditorWindow
|
||||
|
||||
|
||||
class EditorWindowTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.update_idletasks()
|
||||
for id in cls.root.tk.call('after', 'info'):
|
||||
cls.root.after_cancel(id)
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
e = Editor(root=self.root)
|
||||
self.assertEqual(e.root, self.root)
|
||||
e._close()
|
||||
|
||||
|
||||
class EditorFunctionTest(unittest.TestCase):
|
||||
|
||||
def test_filename_to_unicode(self):
|
||||
func = Editor._filename_to_unicode
|
||||
class dummy():
|
||||
filesystemencoding = 'utf-8'
|
||||
pairs = (('abc', 'abc'), ('a\U00011111c', 'a\ufffdc'),
|
||||
(b'abc', 'abc'), (b'a\xf0\x91\x84\x91c', 'a\ufffdc'))
|
||||
for inp, out in pairs:
|
||||
self.assertEqual(func(dummy, inp), out)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
33
third_party/python/Lib/idlelib/idle_test/test_filelist.py
vendored
Normal file
33
third_party/python/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)
|
86
third_party/python/Lib/idlelib/idle_test/test_grep.py
vendored
Normal file
86
third_party/python/Lib/idlelib/idle_test/test_grep.py
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
""" !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.grep import GrepDialog
|
||||
import unittest
|
||||
from test.support import captured_stdout
|
||||
from idlelib.idle_test.mock_tk import Var
|
||||
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 = GrepDialog.grep_it
|
||||
findfiles = GrepDialog.findfiles
|
||||
# Other stuff needed
|
||||
recvar = Var(False)
|
||||
engine = searchengine
|
||||
def close(self): # gui method
|
||||
pass
|
||||
|
||||
grep = Dummy_grep()
|
||||
|
||||
|
||||
class FindfilesTest(unittest.TestCase):
|
||||
# findfiles is really a function, not a method, could be iterator
|
||||
# test that filename return filename
|
||||
# test that idlelib has many .py files
|
||||
# test that recursive flag adds idle_test .py files
|
||||
pass
|
||||
|
||||
|
||||
class Grep_itTest(unittest.TestCase):
|
||||
# Test captured reports with 0 and some hits.
|
||||
# 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
third_party/python/Lib/idlelib/idle_test/test_help.py
vendored
Normal file
34
third_party/python/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)
|
180
third_party/python/Lib/idlelib/idle_test/test_help_about.py
vendored
Normal file
180
third_party/python/Lib/idlelib/idle_test/test_help_about.py
vendored
Normal file
|
@ -0,0 +1,180 @@
|
|||
"""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
|
||||
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
third_party/python/Lib/idlelib/idle_test/test_history.py
vendored
Normal file
172
third_party/python/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
third_party/python/Lib/idlelib/idle_test/test_hyperparser.py
vendored
Normal file
276
third_party/python/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.context_use_ps1 = True
|
||||
self.num_context_lines = 50, 500, 1000
|
||||
|
||||
_build_char_in_string_func = EditorWindow._build_char_in_string_func
|
||||
is_char_in_string = EditorWindow.is_char_in_string
|
||||
|
||||
|
||||
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.context_use_ps1 = True
|
||||
|
||||
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.context_use_ps1 = False
|
||||
|
||||
# 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)
|
37
third_party/python/Lib/idlelib/idle_test/test_iomenu.py
vendored
Normal file
37
third_party/python/Lib/idlelib/idle_test/test_iomenu.py
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
"Test , coverage 16%."
|
||||
|
||||
from idlelib import iomenu
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
from idlelib.editor import EditorWindow
|
||||
|
||||
|
||||
class IOBindigTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.editwin = EditorWindow(root=cls.root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.editwin._close()
|
||||
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):
|
||||
io = iomenu.IOBinding(self.editwin)
|
||||
self.assertIs(io.editwin, self.editwin)
|
||||
io.close
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
104
third_party/python/Lib/idlelib/idle_test/test_macosx.py
vendored
Normal file
104
third_party/python/Lib/idlelib/idle_test/test_macosx.py
vendored
Normal file
|
@ -0,0 +1,104 @@
|
|||
"Test macosx, coverage 45% on Windows."
|
||||
|
||||
from idlelib import macosx
|
||||
import unittest
|
||||
from test.support import requires
|
||||
import tkinter as tk
|
||||
import unittest.mock as mock
|
||||
from idlelib.filelist import FileList
|
||||
|
||||
mactypes = {'carbon', 'cocoa', 'xquartz'}
|
||||
nontypes = {'other'}
|
||||
alltypes = mactypes | nontypes
|
||||
|
||||
|
||||
class InitTktypeTest(unittest.TestCase):
|
||||
"Test _init_tk_type."
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = tk.Tk()
|
||||
cls.root.withdraw()
|
||||
cls.orig_platform = macosx.platform
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
macosx.platform = cls.orig_platform
|
||||
|
||||
def test_init_sets_tktype(self):
|
||||
"Test that _init_tk_type sets _tk_type according to platform."
|
||||
for platform, types in ('darwin', alltypes), ('other', nontypes):
|
||||
with self.subTest(platform=platform):
|
||||
macosx.platform = platform
|
||||
macosx._tk_type == None
|
||||
macosx._init_tk_type()
|
||||
self.assertIn(macosx._tk_type, types)
|
||||
|
||||
|
||||
class IsTypeTkTest(unittest.TestCase):
|
||||
"Test each of the four isTypeTk predecates."
|
||||
isfuncs = ((macosx.isAquaTk, ('carbon', 'cocoa')),
|
||||
(macosx.isCarbonTk, ('carbon')),
|
||||
(macosx.isCocoaTk, ('cocoa')),
|
||||
(macosx.isXQuartz, ('xquartz')),
|
||||
)
|
||||
|
||||
@mock.patch('idlelib.macosx._init_tk_type')
|
||||
def test_is_calls_init(self, mockinit):
|
||||
"Test that each isTypeTk calls _init_tk_type when _tk_type is None."
|
||||
macosx._tk_type = None
|
||||
for func, whentrue in self.isfuncs:
|
||||
with self.subTest(func=func):
|
||||
func()
|
||||
self.assertTrue(mockinit.called)
|
||||
mockinit.reset_mock()
|
||||
|
||||
def test_isfuncs(self):
|
||||
"Test that each isTypeTk return correct bool."
|
||||
for func, whentrue in self.isfuncs:
|
||||
for tktype in alltypes:
|
||||
with self.subTest(func=func, whentrue=whentrue, tktype=tktype):
|
||||
macosx._tk_type = tktype
|
||||
(self.assertTrue if tktype in whentrue else self.assertFalse)\
|
||||
(func())
|
||||
|
||||
|
||||
class SetupTest(unittest.TestCase):
|
||||
"Test setupApp."
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = tk.Tk()
|
||||
cls.root.withdraw()
|
||||
def cmd(tkpath, func):
|
||||
assert isinstance(tkpath, str)
|
||||
assert isinstance(func, type(cmd))
|
||||
cls.root.createcommand = cmd
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
@mock.patch('idlelib.macosx.overrideRootMenu') #27312
|
||||
def test_setupapp(self, overrideRootMenu):
|
||||
"Call setupApp with each possible graphics type."
|
||||
root = self.root
|
||||
flist = FileList(root)
|
||||
for tktype in alltypes:
|
||||
with self.subTest(tktype=tktype):
|
||||
macosx._tk_type = tktype
|
||||
macosx.setupApp(root, flist)
|
||||
if tktype in ('carbon', 'cocoa'):
|
||||
self.assertTrue(overrideRootMenu.called)
|
||||
overrideRootMenu.reset_mock()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
21
third_party/python/Lib/idlelib/idle_test/test_mainmenu.py
vendored
Normal file
21
third_party/python/Lib/idlelib/idle_test/test_mainmenu.py
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
"Test mainmenu, coverage 100%."
|
||||
# Reported as 88%; mocking turtledemo absence would have no point.
|
||||
|
||||
from idlelib import mainmenu
|
||||
import unittest
|
||||
|
||||
|
||||
class MainMenuTest(unittest.TestCase):
|
||||
|
||||
def test_menudefs(self):
|
||||
actual = [item[0] for item in mainmenu.menudefs]
|
||||
expect = ['file', 'edit', 'format', 'run', 'shell',
|
||||
'debug', 'options', 'window', 'help']
|
||||
self.assertEqual(actual, expect)
|
||||
|
||||
def test_default_keydefs(self):
|
||||
self.assertGreaterEqual(len(mainmenu.default_keydefs), 50)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
40
third_party/python/Lib/idlelib/idle_test/test_multicall.py
vendored
Normal file
40
third_party/python/Lib/idlelib/idle_test/test_multicall.py
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
"Test multicall, coverage 33%."
|
||||
|
||||
from idlelib import multicall
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk, Text
|
||||
|
||||
|
||||
class MultiCallTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.mc = multicall.MultiCallCreator(Text)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.mc
|
||||
cls.root.update_idletasks()
|
||||
## for id in cls.root.tk.call('after', 'info'):
|
||||
## cls.root.after_cancel(id) # Need for EditorWindow.
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_creator(self):
|
||||
mc = self.mc
|
||||
self.assertIs(multicall._multicall_dict[Text], mc)
|
||||
self.assertTrue(issubclass(mc, Text))
|
||||
mc2 = multicall.MultiCallCreator(Text)
|
||||
self.assertIs(mc, mc2)
|
||||
|
||||
def test_init(self):
|
||||
mctext = self.mc(self.root)
|
||||
self.assertIsInstance(mctext._MultiCall__binders, list)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
171
third_party/python/Lib/idlelib/idle_test/test_outwin.py
vendored
Normal file
171
third_party/python/Lib/idlelib/idle_test/test_outwin.py
vendored
Normal file
|
@ -0,0 +1,171 @@
|
|||
"Test outwin, coverage 76%."
|
||||
|
||||
from idlelib import outwin
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk, Text
|
||||
from idlelib.idle_test.mock_tk import Mbox_func
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
from unittest import mock
|
||||
|
||||
|
||||
class OutputWindowTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
root = cls.root = Tk()
|
||||
root.withdraw()
|
||||
w = cls.window = outwin.OutputWindow(None, None, None, root)
|
||||
cls.text = w.text = Text(root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.window.close()
|
||||
del cls.text, cls.window
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.text.delete('1.0', 'end')
|
||||
|
||||
def test_ispythonsource(self):
|
||||
# OutputWindow overrides ispythonsource to always return False.
|
||||
w = self.window
|
||||
self.assertFalse(w.ispythonsource('test.txt'))
|
||||
self.assertFalse(w.ispythonsource(__file__))
|
||||
|
||||
def test_window_title(self):
|
||||
self.assertEqual(self.window.top.title(), 'Output')
|
||||
|
||||
def test_maybesave(self):
|
||||
w = self.window
|
||||
eq = self.assertEqual
|
||||
w.get_saved = Func()
|
||||
|
||||
w.get_saved.result = False
|
||||
eq(w.maybesave(), 'no')
|
||||
eq(w.get_saved.called, 1)
|
||||
|
||||
w.get_saved.result = True
|
||||
eq(w.maybesave(), 'yes')
|
||||
eq(w.get_saved.called, 2)
|
||||
del w.get_saved
|
||||
|
||||
def test_write(self):
|
||||
eq = self.assertEqual
|
||||
delete = self.text.delete
|
||||
get = self.text.get
|
||||
write = self.window.write
|
||||
|
||||
# Test bytes.
|
||||
b = b'Test bytes.'
|
||||
eq(write(b), len(b))
|
||||
eq(get('1.0', '1.end'), b.decode())
|
||||
|
||||
# No new line - insert stays on same line.
|
||||
delete('1.0', 'end')
|
||||
test_text = 'test text'
|
||||
eq(write(test_text), len(test_text))
|
||||
eq(get('1.0', '1.end'), 'test text')
|
||||
eq(get('insert linestart', 'insert lineend'), 'test text')
|
||||
|
||||
# New line - insert moves to next line.
|
||||
delete('1.0', 'end')
|
||||
test_text = 'test text\n'
|
||||
eq(write(test_text), len(test_text))
|
||||
eq(get('1.0', '1.end'), 'test text')
|
||||
eq(get('insert linestart', 'insert lineend'), '')
|
||||
|
||||
# Text after new line is tagged for second line of Text widget.
|
||||
delete('1.0', 'end')
|
||||
test_text = 'test text\nLine 2'
|
||||
eq(write(test_text), len(test_text))
|
||||
eq(get('1.0', '1.end'), 'test text')
|
||||
eq(get('2.0', '2.end'), 'Line 2')
|
||||
eq(get('insert linestart', 'insert lineend'), 'Line 2')
|
||||
|
||||
# Test tags.
|
||||
delete('1.0', 'end')
|
||||
test_text = 'test text\n'
|
||||
test_text2 = 'Line 2\n'
|
||||
eq(write(test_text, tags='mytag'), len(test_text))
|
||||
eq(write(test_text2, tags='secondtag'), len(test_text2))
|
||||
eq(get('mytag.first', 'mytag.last'), test_text)
|
||||
eq(get('secondtag.first', 'secondtag.last'), test_text2)
|
||||
eq(get('1.0', '1.end'), test_text.rstrip('\n'))
|
||||
eq(get('2.0', '2.end'), test_text2.rstrip('\n'))
|
||||
|
||||
def test_writelines(self):
|
||||
eq = self.assertEqual
|
||||
get = self.text.get
|
||||
writelines = self.window.writelines
|
||||
|
||||
writelines(('Line 1\n', 'Line 2\n', 'Line 3\n'))
|
||||
eq(get('1.0', '1.end'), 'Line 1')
|
||||
eq(get('2.0', '2.end'), 'Line 2')
|
||||
eq(get('3.0', '3.end'), 'Line 3')
|
||||
eq(get('insert linestart', 'insert lineend'), '')
|
||||
|
||||
def test_goto_file_line(self):
|
||||
eq = self.assertEqual
|
||||
w = self.window
|
||||
text = self.text
|
||||
|
||||
w.flist = mock.Mock()
|
||||
gfl = w.flist.gotofileline = Func()
|
||||
showerror = w.showerror = Mbox_func()
|
||||
|
||||
# No file/line number.
|
||||
w.write('Not a file line')
|
||||
self.assertIsNone(w.goto_file_line())
|
||||
eq(gfl.called, 0)
|
||||
eq(showerror.title, 'No special line')
|
||||
|
||||
# Current file/line number.
|
||||
w.write(f'{str(__file__)}: 42: spam\n')
|
||||
w.write(f'{str(__file__)}: 21: spam')
|
||||
self.assertIsNone(w.goto_file_line())
|
||||
eq(gfl.args, (str(__file__), 21))
|
||||
|
||||
# Previous line has file/line number.
|
||||
text.delete('1.0', 'end')
|
||||
w.write(f'{str(__file__)}: 42: spam\n')
|
||||
w.write('Not a file line')
|
||||
self.assertIsNone(w.goto_file_line())
|
||||
eq(gfl.args, (str(__file__), 42))
|
||||
|
||||
del w.flist.gotofileline, w.showerror
|
||||
|
||||
|
||||
class ModuleFunctionTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
outwin.file_line_progs = None
|
||||
|
||||
def test_compile_progs(self):
|
||||
outwin.compile_progs()
|
||||
for pat, regex in zip(outwin.file_line_pats, outwin.file_line_progs):
|
||||
self.assertEqual(regex.pattern, pat)
|
||||
|
||||
@mock.patch('builtins.open')
|
||||
def test_file_line_helper(self, mock_open):
|
||||
flh = outwin.file_line_helper
|
||||
test_lines = (
|
||||
(r'foo file "testfile1", line 42, bar', ('testfile1', 42)),
|
||||
(r'foo testfile2(21) bar', ('testfile2', 21)),
|
||||
(r' testfile3 : 42: foo bar\n', (' testfile3 ', 42)),
|
||||
(r'foo testfile4.py :1: ', ('foo testfile4.py ', 1)),
|
||||
('testfile5: \u19D4\u19D2: ', ('testfile5', 42)),
|
||||
(r'testfile6: 42', None), # only one `:`
|
||||
(r'testfile7 42 text', None) # no separators
|
||||
)
|
||||
for line, expected_output in test_lines:
|
||||
self.assertEqual(flh(line), expected_output)
|
||||
if expected_output:
|
||||
mock_open.assert_called_with(expected_output[0], 'r')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
379
third_party/python/Lib/idlelib/idle_test/test_paragraph.py
vendored
Normal file
379
third_party/python/Lib/idlelib/idle_test/test_paragraph.py
vendored
Normal file
|
@ -0,0 +1,379 @@
|
|||
"Test paragraph, coverage 76%."
|
||||
|
||||
from idlelib import paragraph as pg
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk, Text
|
||||
from idlelib.editor import EditorWindow
|
||||
|
||||
|
||||
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(pg.is_all_white(''))
|
||||
self.assertTrue(pg.is_all_white('\t\n\r\f\v'))
|
||||
self.assertFalse(pg.is_all_white(self.test_comment))
|
||||
|
||||
def test_get_indent(self):
|
||||
Equal = self.assertEqual
|
||||
Equal(pg.get_indent(self.test_comment), '')
|
||||
Equal(pg.get_indent(self.trailingws_comment), '')
|
||||
Equal(pg.get_indent(self.leadingws_comment), ' ')
|
||||
Equal(pg.get_indent(self.leadingws_nocomment), ' ')
|
||||
|
||||
def test_get_comment_header(self):
|
||||
Equal = self.assertEqual
|
||||
# Test comment strings
|
||||
Equal(pg.get_comment_header(self.test_comment), '#')
|
||||
Equal(pg.get_comment_header(self.trailingws_comment), '#')
|
||||
Equal(pg.get_comment_header(self.leadingws_comment), ' #')
|
||||
# Test non-comment strings
|
||||
Equal(pg.get_comment_header(self.leadingws_nocomment), ' ')
|
||||
Equal(pg.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(pg.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 = pg.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 = pg.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 = pg.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 = pg.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 = pg.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')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=2)
|
112
third_party/python/Lib/idlelib/idle_test/test_parenmatch.py
vendored
Normal file
112
third_party/python/Lib/idlelib/idle_test/test_parenmatch.py
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
"""Test parenmatch, coverage 91%.
|
||||
|
||||
This must currently be a gui test because ParenMatch methods use
|
||||
several text methods not defined on idlelib.idle_test.mock_tk.Text.
|
||||
"""
|
||||
from idlelib.parenmatch import ParenMatch
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
from tkinter import Tk, Text
|
||||
|
||||
|
||||
class DummyEditwin:
|
||||
def __init__(self, text):
|
||||
self.text = text
|
||||
self.indentwidth = 8
|
||||
self.tabwidth = 8
|
||||
self.context_use_ps1 = True
|
||||
|
||||
|
||||
class ParenMatchTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.text = Text(cls.root)
|
||||
cls.editwin = DummyEditwin(cls.text)
|
||||
cls.editwin.text_frame = Mock()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.text, cls.editwin
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def tearDown(self):
|
||||
self.text.delete('1.0', 'end')
|
||||
|
||||
def get_parenmatch(self):
|
||||
pm = ParenMatch(self.editwin)
|
||||
pm.bell = lambda: None
|
||||
return pm
|
||||
|
||||
def test_paren_styles(self):
|
||||
"""
|
||||
Test ParenMatch with each style.
|
||||
"""
|
||||
text = self.text
|
||||
pm = self.get_parenmatch()
|
||||
for style, range1, range2 in (
|
||||
('opener', ('1.10', '1.11'), ('1.10', '1.11')),
|
||||
('default',('1.10', '1.11'),('1.10', '1.11')),
|
||||
('parens', ('1.14', '1.15'), ('1.15', '1.16')),
|
||||
('expression', ('1.10', '1.15'), ('1.10', '1.16'))):
|
||||
with self.subTest(style=style):
|
||||
text.delete('1.0', 'end')
|
||||
pm.STYLE = style
|
||||
text.insert('insert', 'def foobar(a, b')
|
||||
|
||||
pm.flash_paren_event('event')
|
||||
self.assertIn('<<parenmatch-check-restore>>', text.event_info())
|
||||
if style == 'parens':
|
||||
self.assertTupleEqual(text.tag_nextrange('paren', '1.0'),
|
||||
('1.10', '1.11'))
|
||||
self.assertTupleEqual(
|
||||
text.tag_prevrange('paren', 'end'), range1)
|
||||
|
||||
text.insert('insert', ')')
|
||||
pm.restore_event()
|
||||
self.assertNotIn('<<parenmatch-check-restore>>',
|
||||
text.event_info())
|
||||
self.assertEqual(text.tag_prevrange('paren', 'end'), ())
|
||||
|
||||
pm.paren_closed_event('event')
|
||||
self.assertTupleEqual(
|
||||
text.tag_prevrange('paren', 'end'), range2)
|
||||
|
||||
def test_paren_corner(self):
|
||||
"""
|
||||
Test corner cases in flash_paren_event and paren_closed_event.
|
||||
|
||||
These cases force conditional expression and alternate paths.
|
||||
"""
|
||||
text = self.text
|
||||
pm = self.get_parenmatch()
|
||||
|
||||
text.insert('insert', '# this is a commen)')
|
||||
pm.paren_closed_event('event')
|
||||
|
||||
text.insert('insert', '\ndef')
|
||||
pm.flash_paren_event('event')
|
||||
pm.paren_closed_event('event')
|
||||
|
||||
text.insert('insert', ' a, *arg)')
|
||||
pm.paren_closed_event('event')
|
||||
|
||||
def test_handle_restore_timer(self):
|
||||
pm = self.get_parenmatch()
|
||||
pm.restore_event = Mock()
|
||||
pm.handle_restore_timer(0)
|
||||
self.assertTrue(pm.restore_event.called)
|
||||
pm.restore_event.reset_mock()
|
||||
pm.handle_restore_timer(1)
|
||||
self.assertFalse(pm.restore_event.called)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
86
third_party/python/Lib/idlelib/idle_test/test_pathbrowser.py
vendored
Normal file
86
third_party/python/Lib/idlelib/idle_test/test_pathbrowser.py
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
"Test pathbrowser, coverage 95%."
|
||||
|
||||
from idlelib import pathbrowser
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
import os.path
|
||||
import pyclbr # for _modules
|
||||
import sys # for sys.path
|
||||
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
import idlelib # for __file__
|
||||
from idlelib import browser
|
||||
from idlelib.tree import TreeNode
|
||||
|
||||
|
||||
class PathBrowserTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.pb = pathbrowser.PathBrowser(cls.root, _utest=True)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.pb.close()
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root, cls.pb
|
||||
|
||||
def test_init(self):
|
||||
pb = self.pb
|
||||
eq = self.assertEqual
|
||||
eq(pb.master, self.root)
|
||||
eq(pyclbr._modules, {})
|
||||
self.assertIsInstance(pb.node, TreeNode)
|
||||
self.assertIsNotNone(browser.file_open)
|
||||
|
||||
def test_settitle(self):
|
||||
pb = self.pb
|
||||
self.assertEqual(pb.top.title(), 'Path Browser')
|
||||
self.assertEqual(pb.top.iconname(), 'Path Browser')
|
||||
|
||||
def test_rootnode(self):
|
||||
pb = self.pb
|
||||
rn = pb.rootnode()
|
||||
self.assertIsInstance(rn, pathbrowser.PathBrowserTreeItem)
|
||||
|
||||
def test_close(self):
|
||||
pb = self.pb
|
||||
pb.top.destroy = Func()
|
||||
pb.node.destroy = Func()
|
||||
pb.close()
|
||||
self.assertTrue(pb.top.destroy.called)
|
||||
self.assertTrue(pb.node.destroy.called)
|
||||
del pb.top.destroy, pb.node.destroy
|
||||
|
||||
|
||||
class DirBrowserTreeItemTest(unittest.TestCase):
|
||||
|
||||
def test_DirBrowserTreeItem(self):
|
||||
# Issue16226 - make sure that getting a sublist works
|
||||
d = pathbrowser.DirBrowserTreeItem('')
|
||||
d.GetSubList()
|
||||
self.assertEqual('', d.GetText())
|
||||
|
||||
dir = os.path.split(os.path.abspath(idlelib.__file__))[0]
|
||||
self.assertEqual(d.ispackagedir(dir), True)
|
||||
self.assertEqual(d.ispackagedir(dir + '/Icons'), False)
|
||||
|
||||
|
||||
class PathBrowserTreeItemTest(unittest.TestCase):
|
||||
|
||||
def test_PathBrowserTreeItem(self):
|
||||
p = pathbrowser.PathBrowserTreeItem()
|
||||
self.assertEqual(p.GetText(), 'sys.path')
|
||||
sub = p.GetSubList()
|
||||
self.assertEqual(len(sub), len(sys.path))
|
||||
self.assertEqual(type(sub[0]), pathbrowser.DirBrowserTreeItem)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=False)
|
118
third_party/python/Lib/idlelib/idle_test/test_percolator.py
vendored
Normal file
118
third_party/python/Lib/idlelib/idle_test/test_percolator.py
vendored
Normal file
|
@ -0,0 +1,118 @@
|
|||
"Test percolator, coverage 100%."
|
||||
|
||||
from idlelib.percolator import Percolator, Delegator
|
||||
import unittest
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
from tkinter import Text, Tk, END
|
||||
|
||||
|
||||
class MyFilter(Delegator):
|
||||
def __init__(self):
|
||||
Delegator.__init__(self, None)
|
||||
|
||||
def insert(self, *args):
|
||||
self.insert_called_with = args
|
||||
self.delegate.insert(*args)
|
||||
|
||||
def delete(self, *args):
|
||||
self.delete_called_with = args
|
||||
self.delegate.delete(*args)
|
||||
|
||||
def uppercase_insert(self, index, chars, tags=None):
|
||||
chars = chars.upper()
|
||||
self.delegate.insert(index, chars)
|
||||
|
||||
def lowercase_insert(self, index, chars, tags=None):
|
||||
chars = chars.lower()
|
||||
self.delegate.insert(index, chars)
|
||||
|
||||
def dont_insert(self, index, chars, tags=None):
|
||||
pass
|
||||
|
||||
|
||||
class PercolatorTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = Tk()
|
||||
cls.text = Text(cls.root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.text
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.percolator = Percolator(self.text)
|
||||
self.filter_one = MyFilter()
|
||||
self.filter_two = MyFilter()
|
||||
self.percolator.insertfilter(self.filter_one)
|
||||
self.percolator.insertfilter(self.filter_two)
|
||||
|
||||
def tearDown(self):
|
||||
self.percolator.close()
|
||||
self.text.delete('1.0', END)
|
||||
|
||||
def test_insertfilter(self):
|
||||
self.assertIsNotNone(self.filter_one.delegate)
|
||||
self.assertEqual(self.percolator.top, self.filter_two)
|
||||
self.assertEqual(self.filter_two.delegate, self.filter_one)
|
||||
self.assertEqual(self.filter_one.delegate, self.percolator.bottom)
|
||||
|
||||
def test_removefilter(self):
|
||||
filter_three = MyFilter()
|
||||
self.percolator.removefilter(self.filter_two)
|
||||
self.assertEqual(self.percolator.top, self.filter_one)
|
||||
self.assertIsNone(self.filter_two.delegate)
|
||||
|
||||
filter_three = MyFilter()
|
||||
self.percolator.insertfilter(self.filter_two)
|
||||
self.percolator.insertfilter(filter_three)
|
||||
self.percolator.removefilter(self.filter_one)
|
||||
self.assertEqual(self.percolator.top, filter_three)
|
||||
self.assertEqual(filter_three.delegate, self.filter_two)
|
||||
self.assertEqual(self.filter_two.delegate, self.percolator.bottom)
|
||||
self.assertIsNone(self.filter_one.delegate)
|
||||
|
||||
def test_insert(self):
|
||||
self.text.insert('insert', 'foo')
|
||||
self.assertEqual(self.text.get('1.0', END), 'foo\n')
|
||||
self.assertTupleEqual(self.filter_one.insert_called_with,
|
||||
('insert', 'foo', None))
|
||||
|
||||
def test_modify_insert(self):
|
||||
self.filter_one.insert = self.filter_one.uppercase_insert
|
||||
self.text.insert('insert', 'bAr')
|
||||
self.assertEqual(self.text.get('1.0', END), 'BAR\n')
|
||||
|
||||
def test_modify_chain_insert(self):
|
||||
filter_three = MyFilter()
|
||||
self.percolator.insertfilter(filter_three)
|
||||
self.filter_two.insert = self.filter_two.uppercase_insert
|
||||
self.filter_one.insert = self.filter_one.lowercase_insert
|
||||
self.text.insert('insert', 'BaR')
|
||||
self.assertEqual(self.text.get('1.0', END), 'bar\n')
|
||||
|
||||
def test_dont_insert(self):
|
||||
self.filter_one.insert = self.filter_one.dont_insert
|
||||
self.text.insert('insert', 'foo bar')
|
||||
self.assertEqual(self.text.get('1.0', END), '\n')
|
||||
self.filter_one.insert = self.filter_one.dont_insert
|
||||
self.text.insert('insert', 'foo bar')
|
||||
self.assertEqual(self.text.get('1.0', END), '\n')
|
||||
|
||||
def test_without_filter(self):
|
||||
self.text.insert('insert', 'hello')
|
||||
self.assertEqual(self.text.get('1.0', 'end'), 'hello\n')
|
||||
|
||||
def test_delete(self):
|
||||
self.text.insert('insert', 'foo')
|
||||
self.text.delete('1.0', '1.2')
|
||||
self.assertEqual(self.text.get('1.0', END), 'o\n')
|
||||
self.assertTupleEqual(self.filter_one.delete_called_with,
|
||||
('1.0', '1.2'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
466
third_party/python/Lib/idlelib/idle_test/test_pyparse.py
vendored
Normal file
466
third_party/python/Lib/idlelib/idle_test/test_pyparse.py
vendored
Normal file
|
@ -0,0 +1,466 @@
|
|||
"Test pyparse, coverage 96%."
|
||||
|
||||
from idlelib import pyparse
|
||||
import unittest
|
||||
from collections import namedtuple
|
||||
|
||||
|
||||
class ParseMapTest(unittest.TestCase):
|
||||
|
||||
def test_parsemap(self):
|
||||
keepwhite = {ord(c): ord(c) for c in ' \t\n\r'}
|
||||
mapping = pyparse.ParseMap(keepwhite)
|
||||
self.assertEqual(mapping[ord('\t')], ord('\t'))
|
||||
self.assertEqual(mapping[ord('a')], ord('x'))
|
||||
self.assertEqual(mapping[1000], ord('x'))
|
||||
|
||||
def test_trans(self):
|
||||
# trans is the production instance of ParseMap, used in _study1
|
||||
parser = pyparse.Parser(4, 4)
|
||||
self.assertEqual('\t a([{b}])b"c\'d\n'.translate(pyparse.trans),
|
||||
'xxx(((x)))x"x\'x\n')
|
||||
|
||||
|
||||
class PyParseTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.parser = pyparse.Parser(indentwidth=4, tabwidth=4)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.parser
|
||||
|
||||
def test_init(self):
|
||||
self.assertEqual(self.parser.indentwidth, 4)
|
||||
self.assertEqual(self.parser.tabwidth, 4)
|
||||
|
||||
def test_set_code(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
|
||||
# Not empty and doesn't end with newline.
|
||||
with self.assertRaises(AssertionError):
|
||||
setcode('a')
|
||||
|
||||
tests = ('',
|
||||
'a\n')
|
||||
|
||||
for string in tests:
|
||||
with self.subTest(string=string):
|
||||
setcode(string)
|
||||
eq(p.code, string)
|
||||
eq(p.study_level, 0)
|
||||
|
||||
def test_find_good_parse_start(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
start = p.find_good_parse_start
|
||||
|
||||
# Split def across lines.
|
||||
setcode('"""This is a module docstring"""\n'
|
||||
'class C():\n'
|
||||
' def __init__(self, a,\n'
|
||||
' b=True):\n'
|
||||
' pass\n'
|
||||
)
|
||||
|
||||
# No value sent for is_char_in_string().
|
||||
self.assertIsNone(start())
|
||||
|
||||
# Make text look like a string. This returns pos as the start
|
||||
# position, but it's set to None.
|
||||
self.assertIsNone(start(is_char_in_string=lambda index: True))
|
||||
|
||||
# Make all text look like it's not in a string. This means that it
|
||||
# found a good start position.
|
||||
eq(start(is_char_in_string=lambda index: False), 44)
|
||||
|
||||
# If the beginning of the def line is not in a string, then it
|
||||
# returns that as the index.
|
||||
eq(start(is_char_in_string=lambda index: index > 44), 44)
|
||||
# If the beginning of the def line is in a string, then it
|
||||
# looks for a previous index.
|
||||
eq(start(is_char_in_string=lambda index: index >= 44), 33)
|
||||
# If everything before the 'def' is in a string, then returns None.
|
||||
# The non-continuation def line returns 44 (see below).
|
||||
eq(start(is_char_in_string=lambda index: index < 44), None)
|
||||
|
||||
# Code without extra line break in def line - mostly returns the same
|
||||
# values.
|
||||
setcode('"""This is a module docstring"""\n'
|
||||
'class C():\n'
|
||||
' def __init__(self, a, b=True):\n'
|
||||
' pass\n'
|
||||
)
|
||||
eq(start(is_char_in_string=lambda index: False), 44)
|
||||
eq(start(is_char_in_string=lambda index: index > 44), 44)
|
||||
eq(start(is_char_in_string=lambda index: index >= 44), 33)
|
||||
# When the def line isn't split, this returns which doesn't match the
|
||||
# split line test.
|
||||
eq(start(is_char_in_string=lambda index: index < 44), 44)
|
||||
|
||||
def test_set_lo(self):
|
||||
code = (
|
||||
'"""This is a module docstring"""\n'
|
||||
'class C():\n'
|
||||
' def __init__(self, a,\n'
|
||||
' b=True):\n'
|
||||
' pass\n'
|
||||
)
|
||||
p = self.parser
|
||||
p.set_code(code)
|
||||
|
||||
# Previous character is not a newline.
|
||||
with self.assertRaises(AssertionError):
|
||||
p.set_lo(5)
|
||||
|
||||
# A value of 0 doesn't change self.code.
|
||||
p.set_lo(0)
|
||||
self.assertEqual(p.code, code)
|
||||
|
||||
# An index that is preceded by a newline.
|
||||
p.set_lo(44)
|
||||
self.assertEqual(p.code, code[44:])
|
||||
|
||||
def test_study1(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
study = p._study1
|
||||
|
||||
(NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5)
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'goodlines',
|
||||
'continuation'])
|
||||
tests = (
|
||||
TestInfo('', [0], NONE),
|
||||
# Docstrings.
|
||||
TestInfo('"""This is a complete docstring."""\n', [0, 1], NONE),
|
||||
TestInfo("'''This is a complete docstring.'''\n", [0, 1], NONE),
|
||||
TestInfo('"""This is a continued docstring.\n', [0, 1], FIRST),
|
||||
TestInfo("'''This is a continued docstring.\n", [0, 1], FIRST),
|
||||
TestInfo('"""Closing quote does not match."\n', [0, 1], FIRST),
|
||||
TestInfo('"""Bracket in docstring [\n', [0, 1], FIRST),
|
||||
TestInfo("'''Incomplete two line docstring.\n\n", [0, 2], NEXT),
|
||||
# Single-quoted strings.
|
||||
TestInfo('"This is a complete string."\n', [0, 1], NONE),
|
||||
TestInfo('"This is an incomplete string.\n', [0, 1], NONE),
|
||||
TestInfo("'This is more incomplete.\n\n", [0, 1, 2], NONE),
|
||||
# Comment (backslash does not continue comments).
|
||||
TestInfo('# Comment\\\n', [0, 1], NONE),
|
||||
# Brackets.
|
||||
TestInfo('("""Complete string in bracket"""\n', [0, 1], BRACKET),
|
||||
TestInfo('("""Open string in bracket\n', [0, 1], FIRST),
|
||||
TestInfo('a = (1 + 2) - 5 *\\\n', [0, 1], BACKSLASH), # No bracket.
|
||||
TestInfo('\n def function1(self, a,\n b):\n',
|
||||
[0, 1, 3], NONE),
|
||||
TestInfo('\n def function1(self, a,\\\n', [0, 1, 2], BRACKET),
|
||||
TestInfo('\n def function1(self, a,\n', [0, 1, 2], BRACKET),
|
||||
TestInfo('())\n', [0, 1], NONE), # Extra closer.
|
||||
TestInfo(')(\n', [0, 1], BRACKET), # Extra closer.
|
||||
# For the mismatched example, it doesn't look like contination.
|
||||
TestInfo('{)(]\n', [0, 1], NONE), # Mismatched.
|
||||
)
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string) # resets study_level
|
||||
study()
|
||||
eq(p.study_level, 1)
|
||||
eq(p.goodlines, test.goodlines)
|
||||
eq(p.continuation, test.continuation)
|
||||
|
||||
# Called again, just returns without reprocessing.
|
||||
self.assertIsNone(study())
|
||||
|
||||
def test_get_continuation_type(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
gettype = p.get_continuation_type
|
||||
|
||||
(NONE, BACKSLASH, FIRST, NEXT, BRACKET) = range(5)
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'continuation'])
|
||||
tests = (
|
||||
TestInfo('', NONE),
|
||||
TestInfo('"""This is a continuation docstring.\n', FIRST),
|
||||
TestInfo("'''This is a multiline-continued docstring.\n\n", NEXT),
|
||||
TestInfo('a = (1 + 2) - 5 *\\\n', BACKSLASH),
|
||||
TestInfo('\n def function1(self, a,\\\n', BRACKET)
|
||||
)
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string)
|
||||
eq(gettype(), test.continuation)
|
||||
|
||||
def test_study2(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
study = p._study2
|
||||
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'start', 'end', 'lastch',
|
||||
'openbracket', 'bracketing'])
|
||||
tests = (
|
||||
TestInfo('', 0, 0, '', None, ((0, 0),)),
|
||||
TestInfo("'''This is a multiline continutation docstring.\n\n",
|
||||
0, 49, "'", None, ((0, 0), (0, 1), (49, 0))),
|
||||
TestInfo(' # Comment\\\n',
|
||||
0, 12, '', None, ((0, 0), (1, 1), (12, 0))),
|
||||
# A comment without a space is a special case
|
||||
TestInfo(' #Comment\\\n',
|
||||
0, 0, '', None, ((0, 0),)),
|
||||
# Backslash continuation.
|
||||
TestInfo('a = (1 + 2) - 5 *\\\n',
|
||||
0, 19, '*', None, ((0, 0), (4, 1), (11, 0))),
|
||||
# Bracket continuation with close.
|
||||
TestInfo('\n def function1(self, a,\n b):\n',
|
||||
1, 48, ':', None, ((1, 0), (17, 1), (46, 0))),
|
||||
# Bracket continuation with unneeded backslash.
|
||||
TestInfo('\n def function1(self, a,\\\n',
|
||||
1, 28, ',', 17, ((1, 0), (17, 1))),
|
||||
# Bracket continuation.
|
||||
TestInfo('\n def function1(self, a,\n',
|
||||
1, 27, ',', 17, ((1, 0), (17, 1))),
|
||||
# Bracket continuation with comment at end of line with text.
|
||||
TestInfo('\n def function1(self, a, # End of line comment.\n',
|
||||
1, 51, ',', 17, ((1, 0), (17, 1), (28, 2), (51, 1))),
|
||||
# Multi-line statement with comment line in between code lines.
|
||||
TestInfo(' a = ["first item",\n # Comment line\n "next item",\n',
|
||||
0, 55, ',', 6, ((0, 0), (6, 1), (7, 2), (19, 1),
|
||||
(23, 2), (38, 1), (42, 2), (53, 1))),
|
||||
TestInfo('())\n',
|
||||
0, 4, ')', None, ((0, 0), (0, 1), (2, 0), (3, 0))),
|
||||
TestInfo(')(\n', 0, 3, '(', 1, ((0, 0), (1, 0), (1, 1))),
|
||||
# Wrong closers still decrement stack level.
|
||||
TestInfo('{)(]\n',
|
||||
0, 5, ']', None, ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))),
|
||||
# Character after backslash.
|
||||
TestInfo(':\\a\n', 0, 4, '\\a', None, ((0, 0),)),
|
||||
TestInfo('\n', 0, 0, '', None, ((0, 0),)),
|
||||
)
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string)
|
||||
study()
|
||||
eq(p.study_level, 2)
|
||||
eq(p.stmt_start, test.start)
|
||||
eq(p.stmt_end, test.end)
|
||||
eq(p.lastch, test.lastch)
|
||||
eq(p.lastopenbracketpos, test.openbracket)
|
||||
eq(p.stmt_bracketing, test.bracketing)
|
||||
|
||||
# Called again, just returns without reprocessing.
|
||||
self.assertIsNone(study())
|
||||
|
||||
def test_get_num_lines_in_stmt(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
getlines = p.get_num_lines_in_stmt
|
||||
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'lines'])
|
||||
tests = (
|
||||
TestInfo('[x for x in a]\n', 1), # Closed on one line.
|
||||
TestInfo('[x\nfor x in a\n', 2), # Not closed.
|
||||
TestInfo('[x\\\nfor x in a\\\n', 2), # "", uneeded backslashes.
|
||||
TestInfo('[x\nfor x in a\n]\n', 3), # Closed on multi-line.
|
||||
TestInfo('\n"""Docstring comment L1"""\nL2\nL3\nL4\n', 1),
|
||||
TestInfo('\n"""Docstring comment L1\nL2"""\nL3\nL4\n', 1),
|
||||
TestInfo('\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n', 4),
|
||||
TestInfo('\n\n"""Docstring comment L1\\\nL2\\\nL3\\\nL4\\\n"""\n', 5)
|
||||
)
|
||||
|
||||
# Blank string doesn't have enough elements in goodlines.
|
||||
setcode('')
|
||||
with self.assertRaises(IndexError):
|
||||
getlines()
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string)
|
||||
eq(getlines(), test.lines)
|
||||
|
||||
def test_compute_bracket_indent(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
indent = p.compute_bracket_indent
|
||||
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'spaces'])
|
||||
tests = (
|
||||
TestInfo('def function1(self, a,\n', 14),
|
||||
# Characters after bracket.
|
||||
TestInfo('\n def function1(self, a,\n', 18),
|
||||
TestInfo('\n\tdef function1(self, a,\n', 18),
|
||||
# No characters after bracket.
|
||||
TestInfo('\n def function1(\n', 8),
|
||||
TestInfo('\n\tdef function1(\n', 8),
|
||||
TestInfo('\n def function1( \n', 8), # Ignore extra spaces.
|
||||
TestInfo('[\n"first item",\n # Comment line\n "next item",\n', 0),
|
||||
TestInfo('[\n "first item",\n # Comment line\n "next item",\n', 2),
|
||||
TestInfo('["first item",\n # Comment line\n "next item",\n', 1),
|
||||
TestInfo('(\n', 4),
|
||||
TestInfo('(a\n', 1),
|
||||
)
|
||||
|
||||
# Must be C_BRACKET continuation type.
|
||||
setcode('def function1(self, a, b):\n')
|
||||
with self.assertRaises(AssertionError):
|
||||
indent()
|
||||
|
||||
for test in tests:
|
||||
setcode(test.string)
|
||||
eq(indent(), test.spaces)
|
||||
|
||||
def test_compute_backslash_indent(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
indent = p.compute_backslash_indent
|
||||
|
||||
# Must be C_BACKSLASH continuation type.
|
||||
errors = (('def function1(self, a, b\\\n'), # Bracket.
|
||||
(' """ (\\\n'), # Docstring.
|
||||
('a = #\\\n'), # Inline comment.
|
||||
)
|
||||
for string in errors:
|
||||
with self.subTest(string=string):
|
||||
setcode(string)
|
||||
with self.assertRaises(AssertionError):
|
||||
indent()
|
||||
|
||||
TestInfo = namedtuple('TestInfo', ('string', 'spaces'))
|
||||
tests = (TestInfo('a = (1 + 2) - 5 *\\\n', 4),
|
||||
TestInfo('a = 1 + 2 - 5 *\\\n', 4),
|
||||
TestInfo(' a = 1 + 2 - 5 *\\\n', 8),
|
||||
TestInfo(' a = "spam"\\\n', 6),
|
||||
TestInfo(' a = \\\n"a"\\\n', 4),
|
||||
TestInfo(' a = #\\\n"a"\\\n', 5),
|
||||
TestInfo('a == \\\n', 2),
|
||||
TestInfo('a != \\\n', 2),
|
||||
# Difference between containing = and those not.
|
||||
TestInfo('\\\n', 2),
|
||||
TestInfo(' \\\n', 6),
|
||||
TestInfo('\t\\\n', 6),
|
||||
TestInfo('a\\\n', 3),
|
||||
TestInfo('{}\\\n', 4),
|
||||
TestInfo('(1 + 2) - 5 *\\\n', 3),
|
||||
)
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string)
|
||||
eq(indent(), test.spaces)
|
||||
|
||||
def test_get_base_indent_string(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
baseindent = p.get_base_indent_string
|
||||
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'indent'])
|
||||
tests = (TestInfo('', ''),
|
||||
TestInfo('def a():\n', ''),
|
||||
TestInfo('\tdef a():\n', '\t'),
|
||||
TestInfo(' def a():\n', ' '),
|
||||
TestInfo(' def a(\n', ' '),
|
||||
TestInfo('\t\n def a(\n', ' '),
|
||||
TestInfo('\t\n # Comment.\n', ' '),
|
||||
)
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string)
|
||||
eq(baseindent(), test.indent)
|
||||
|
||||
def test_is_block_opener(self):
|
||||
yes = self.assertTrue
|
||||
no = self.assertFalse
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
opener = p.is_block_opener
|
||||
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'assert_'])
|
||||
tests = (
|
||||
TestInfo('def a():\n', yes),
|
||||
TestInfo('\n def function1(self, a,\n b):\n', yes),
|
||||
TestInfo(':\n', yes),
|
||||
TestInfo('a:\n', yes),
|
||||
TestInfo('):\n', yes),
|
||||
TestInfo('(:\n', yes),
|
||||
TestInfo('":\n', no),
|
||||
TestInfo('\n def function1(self, a,\n', no),
|
||||
TestInfo('def function1(self, a):\n pass\n', no),
|
||||
TestInfo('# A comment:\n', no),
|
||||
TestInfo('"""A docstring:\n', no),
|
||||
TestInfo('"""A docstring:\n', no),
|
||||
)
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string)
|
||||
test.assert_(opener())
|
||||
|
||||
def test_is_block_closer(self):
|
||||
yes = self.assertTrue
|
||||
no = self.assertFalse
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
closer = p.is_block_closer
|
||||
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'assert_'])
|
||||
tests = (
|
||||
TestInfo('return\n', yes),
|
||||
TestInfo('\tbreak\n', yes),
|
||||
TestInfo(' continue\n', yes),
|
||||
TestInfo(' raise\n', yes),
|
||||
TestInfo('pass \n', yes),
|
||||
TestInfo('pass\t\n', yes),
|
||||
TestInfo('return #\n', yes),
|
||||
TestInfo('raised\n', no),
|
||||
TestInfo('returning\n', no),
|
||||
TestInfo('# return\n', no),
|
||||
TestInfo('"""break\n', no),
|
||||
TestInfo('"continue\n', no),
|
||||
TestInfo('def function1(self, a):\n pass\n', yes),
|
||||
)
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string)
|
||||
test.assert_(closer())
|
||||
|
||||
def test_get_last_stmt_bracketing(self):
|
||||
eq = self.assertEqual
|
||||
p = self.parser
|
||||
setcode = p.set_code
|
||||
bracketing = p.get_last_stmt_bracketing
|
||||
|
||||
TestInfo = namedtuple('TestInfo', ['string', 'bracket'])
|
||||
tests = (
|
||||
TestInfo('', ((0, 0),)),
|
||||
TestInfo('a\n', ((0, 0),)),
|
||||
TestInfo('()()\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))),
|
||||
TestInfo('(\n)()\n', ((0, 0), (0, 1), (3, 0), (3, 1), (5, 0))),
|
||||
TestInfo('()\n()\n', ((3, 0), (3, 1), (5, 0))),
|
||||
TestInfo('()(\n)\n', ((0, 0), (0, 1), (2, 0), (2, 1), (5, 0))),
|
||||
TestInfo('(())\n', ((0, 0), (0, 1), (1, 2), (3, 1), (4, 0))),
|
||||
TestInfo('(\n())\n', ((0, 0), (0, 1), (2, 2), (4, 1), (5, 0))),
|
||||
# Same as matched test.
|
||||
TestInfo('{)(]\n', ((0, 0), (0, 1), (2, 0), (2, 1), (4, 0))),
|
||||
TestInfo('(((())\n',
|
||||
((0, 0), (0, 1), (1, 2), (2, 3), (3, 4), (5, 3), (6, 2))),
|
||||
)
|
||||
|
||||
for test in tests:
|
||||
with self.subTest(string=test.string):
|
||||
setcode(test.string)
|
||||
eq(bracketing(), test.bracket)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
42
third_party/python/Lib/idlelib/idle_test/test_pyshell.py
vendored
Normal file
42
third_party/python/Lib/idlelib/idle_test/test_pyshell.py
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
"Test pyshell, coverage 12%."
|
||||
# Plus coverage of test_warning. Was 20% with test_openshell.
|
||||
|
||||
from idlelib import pyshell
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
|
||||
class PyShellFileListTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
#cls.root.update_idletasks()
|
||||
## for id in cls.root.tk.call('after', 'info'):
|
||||
## cls.root.after_cancel(id) # Need for EditorWindow.
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
psfl = pyshell.PyShellFileList(self.root)
|
||||
self.assertEqual(psfl.EditorWindow, pyshell.PyShellEditorWindow)
|
||||
self.assertIsNone(psfl.pyshell)
|
||||
|
||||
# The following sometimes causes 'invalid command name "109734456recolorize"'.
|
||||
# Uncommenting after_cancel above prevents this, but results in
|
||||
# TclError: bad window path name ".!listedtoplevel.!frame.text"
|
||||
# which is normally prevented by after_cancel.
|
||||
## def test_openshell(self):
|
||||
## pyshell.use_subprocess = False
|
||||
## ps = pyshell.PyShellFileList(self.root).open_shell()
|
||||
## self.assertIsInstance(ps, pyshell.PyShell)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
352
third_party/python/Lib/idlelib/idle_test/test_query.py
vendored
Normal file
352
third_party/python/Lib/idlelib/idle_test/test_query.py
vendored
Normal file
|
@ -0,0 +1,352 @@
|
|||
"""Test query, coverage 91%).
|
||||
|
||||
Non-gui tests for Query, SectionName, ModuleName, and HelpSource use
|
||||
dummy versions that extract the non-gui methods and add other needed
|
||||
attributes. GUI tests create an instance of each class and simulate
|
||||
entries and button clicks. Subclass tests only target the new code in
|
||||
the subclass definition.
|
||||
|
||||
The appearance of the widgets is checked by the Query and
|
||||
HelpSource htests. These are run by running query.py.
|
||||
"""
|
||||
from idlelib import query
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
import sys
|
||||
from unittest import mock
|
||||
from idlelib.idle_test.mock_tk import Var
|
||||
|
||||
|
||||
# NON-GUI TESTS
|
||||
|
||||
class QueryTest(unittest.TestCase):
|
||||
"Test Query base class."
|
||||
|
||||
class Dummy_Query:
|
||||
# Test the following Query methods.
|
||||
entry_ok = query.Query.entry_ok
|
||||
ok = query.Query.ok
|
||||
cancel = query.Query.cancel
|
||||
# Add attributes and initialization needed for tests.
|
||||
entry = Var()
|
||||
entry_error = {}
|
||||
def __init__(self, dummy_entry):
|
||||
self.entry.set(dummy_entry)
|
||||
self.entry_error['text'] = ''
|
||||
self.result = None
|
||||
self.destroyed = False
|
||||
def showerror(self, message):
|
||||
self.entry_error['text'] = message
|
||||
def destroy(self):
|
||||
self.destroyed = True
|
||||
|
||||
def test_entry_ok_blank(self):
|
||||
dialog = self.Dummy_Query(' ')
|
||||
self.assertEqual(dialog.entry_ok(), None)
|
||||
self.assertEqual((dialog.result, dialog.destroyed), (None, False))
|
||||
self.assertIn('blank line', dialog.entry_error['text'])
|
||||
|
||||
def test_entry_ok_good(self):
|
||||
dialog = self.Dummy_Query(' good ')
|
||||
Equal = self.assertEqual
|
||||
Equal(dialog.entry_ok(), 'good')
|
||||
Equal((dialog.result, dialog.destroyed), (None, False))
|
||||
Equal(dialog.entry_error['text'], '')
|
||||
|
||||
def test_ok_blank(self):
|
||||
dialog = self.Dummy_Query('')
|
||||
dialog.entry.focus_set = mock.Mock()
|
||||
self.assertEqual(dialog.ok(), None)
|
||||
self.assertTrue(dialog.entry.focus_set.called)
|
||||
del dialog.entry.focus_set
|
||||
self.assertEqual((dialog.result, dialog.destroyed), (None, False))
|
||||
|
||||
def test_ok_good(self):
|
||||
dialog = self.Dummy_Query('good')
|
||||
self.assertEqual(dialog.ok(), None)
|
||||
self.assertEqual((dialog.result, dialog.destroyed), ('good', True))
|
||||
|
||||
def test_cancel(self):
|
||||
dialog = self.Dummy_Query('does not matter')
|
||||
self.assertEqual(dialog.cancel(), None)
|
||||
self.assertEqual((dialog.result, dialog.destroyed), (None, True))
|
||||
|
||||
|
||||
class SectionNameTest(unittest.TestCase):
|
||||
"Test SectionName subclass of Query."
|
||||
|
||||
class Dummy_SectionName:
|
||||
entry_ok = query.SectionName.entry_ok # Function being tested.
|
||||
used_names = ['used']
|
||||
entry = Var()
|
||||
entry_error = {}
|
||||
def __init__(self, dummy_entry):
|
||||
self.entry.set(dummy_entry)
|
||||
self.entry_error['text'] = ''
|
||||
def showerror(self, message):
|
||||
self.entry_error['text'] = message
|
||||
|
||||
def test_blank_section_name(self):
|
||||
dialog = self.Dummy_SectionName(' ')
|
||||
self.assertEqual(dialog.entry_ok(), None)
|
||||
self.assertIn('no name', dialog.entry_error['text'])
|
||||
|
||||
def test_used_section_name(self):
|
||||
dialog = self.Dummy_SectionName('used')
|
||||
self.assertEqual(dialog.entry_ok(), None)
|
||||
self.assertIn('use', dialog.entry_error['text'])
|
||||
|
||||
def test_long_section_name(self):
|
||||
dialog = self.Dummy_SectionName('good'*8)
|
||||
self.assertEqual(dialog.entry_ok(), None)
|
||||
self.assertIn('longer than 30', dialog.entry_error['text'])
|
||||
|
||||
def test_good_section_name(self):
|
||||
dialog = self.Dummy_SectionName(' good ')
|
||||
self.assertEqual(dialog.entry_ok(), 'good')
|
||||
self.assertEqual(dialog.entry_error['text'], '')
|
||||
|
||||
|
||||
class ModuleNameTest(unittest.TestCase):
|
||||
"Test ModuleName subclass of Query."
|
||||
|
||||
class Dummy_ModuleName:
|
||||
entry_ok = query.ModuleName.entry_ok # Function being tested.
|
||||
text0 = ''
|
||||
entry = Var()
|
||||
entry_error = {}
|
||||
def __init__(self, dummy_entry):
|
||||
self.entry.set(dummy_entry)
|
||||
self.entry_error['text'] = ''
|
||||
def showerror(self, message):
|
||||
self.entry_error['text'] = message
|
||||
|
||||
def test_blank_module_name(self):
|
||||
dialog = self.Dummy_ModuleName(' ')
|
||||
self.assertEqual(dialog.entry_ok(), None)
|
||||
self.assertIn('no name', dialog.entry_error['text'])
|
||||
|
||||
def test_bogus_module_name(self):
|
||||
dialog = self.Dummy_ModuleName('__name_xyz123_should_not_exist__')
|
||||
self.assertEqual(dialog.entry_ok(), None)
|
||||
self.assertIn('not found', dialog.entry_error['text'])
|
||||
|
||||
def test_c_source_name(self):
|
||||
dialog = self.Dummy_ModuleName('itertools')
|
||||
self.assertEqual(dialog.entry_ok(), None)
|
||||
self.assertIn('source-based', dialog.entry_error['text'])
|
||||
|
||||
def test_good_module_name(self):
|
||||
dialog = self.Dummy_ModuleName('idlelib')
|
||||
self.assertTrue(dialog.entry_ok().endswith('__init__.py'))
|
||||
self.assertEqual(dialog.entry_error['text'], '')
|
||||
|
||||
|
||||
# 3 HelpSource test classes each test one function.
|
||||
|
||||
orig_platform = query.platform
|
||||
|
||||
class HelpsourceBrowsefileTest(unittest.TestCase):
|
||||
"Test browse_file method of ModuleName subclass of Query."
|
||||
|
||||
class Dummy_HelpSource:
|
||||
browse_file = query.HelpSource.browse_file
|
||||
pathvar = Var()
|
||||
|
||||
def test_file_replaces_path(self):
|
||||
dialog = self.Dummy_HelpSource()
|
||||
# Path is widget entry, either '' or something.
|
||||
# Func return is file dialog return, either '' or something.
|
||||
# Func return should override widget entry.
|
||||
# We need all 4 combinations to test all (most) code paths.
|
||||
for path, func, result in (
|
||||
('', lambda a,b,c:'', ''),
|
||||
('', lambda a,b,c: __file__, __file__),
|
||||
('htest', lambda a,b,c:'', 'htest'),
|
||||
('htest', lambda a,b,c: __file__, __file__)):
|
||||
with self.subTest():
|
||||
dialog.pathvar.set(path)
|
||||
dialog.askfilename = func
|
||||
dialog.browse_file()
|
||||
self.assertEqual(dialog.pathvar.get(), result)
|
||||
|
||||
|
||||
class HelpsourcePathokTest(unittest.TestCase):
|
||||
"Test path_ok method of HelpSource subclass of Query."
|
||||
|
||||
class Dummy_HelpSource:
|
||||
path_ok = query.HelpSource.path_ok
|
||||
path = Var()
|
||||
path_error = {}
|
||||
def __init__(self, dummy_path):
|
||||
self.path.set(dummy_path)
|
||||
self.path_error['text'] = ''
|
||||
def showerror(self, message, widget=None):
|
||||
self.path_error['text'] = message
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
query.platform = orig_platform
|
||||
|
||||
def test_path_ok_blank(self):
|
||||
dialog = self.Dummy_HelpSource(' ')
|
||||
self.assertEqual(dialog.path_ok(), None)
|
||||
self.assertIn('no help file', dialog.path_error['text'])
|
||||
|
||||
def test_path_ok_bad(self):
|
||||
dialog = self.Dummy_HelpSource(__file__ + 'bad-bad-bad')
|
||||
self.assertEqual(dialog.path_ok(), None)
|
||||
self.assertIn('not exist', dialog.path_error['text'])
|
||||
|
||||
def test_path_ok_web(self):
|
||||
dialog = self.Dummy_HelpSource('')
|
||||
Equal = self.assertEqual
|
||||
for url in 'www.py.org', 'http://py.org':
|
||||
with self.subTest():
|
||||
dialog.path.set(url)
|
||||
self.assertEqual(dialog.path_ok(), url)
|
||||
self.assertEqual(dialog.path_error['text'], '')
|
||||
|
||||
def test_path_ok_file(self):
|
||||
dialog = self.Dummy_HelpSource('')
|
||||
for platform, prefix in ('darwin', 'file://'), ('other', ''):
|
||||
with self.subTest():
|
||||
query.platform = platform
|
||||
dialog.path.set(__file__)
|
||||
self.assertEqual(dialog.path_ok(), prefix + __file__)
|
||||
self.assertEqual(dialog.path_error['text'], '')
|
||||
|
||||
|
||||
class HelpsourceEntryokTest(unittest.TestCase):
|
||||
"Test entry_ok method of HelpSource subclass of Query."
|
||||
|
||||
class Dummy_HelpSource:
|
||||
entry_ok = query.HelpSource.entry_ok
|
||||
entry_error = {}
|
||||
path_error = {}
|
||||
def item_ok(self):
|
||||
return self.name
|
||||
def path_ok(self):
|
||||
return self.path
|
||||
|
||||
def test_entry_ok_helpsource(self):
|
||||
dialog = self.Dummy_HelpSource()
|
||||
for name, path, result in ((None, None, None),
|
||||
(None, 'doc.txt', None),
|
||||
('doc', None, None),
|
||||
('doc', 'doc.txt', ('doc', 'doc.txt'))):
|
||||
with self.subTest():
|
||||
dialog.name, dialog.path = name, path
|
||||
self.assertEqual(dialog.entry_ok(), result)
|
||||
|
||||
|
||||
# GUI TESTS
|
||||
|
||||
class QueryGuiTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.dialog = query.Query(root, 'TEST', 'test', _utest=True)
|
||||
cls.dialog.destroy = mock.Mock()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.dialog.destroy
|
||||
del cls.dialog
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.dialog.entry.delete(0, 'end')
|
||||
self.dialog.result = None
|
||||
self.dialog.destroy.reset_mock()
|
||||
|
||||
def test_click_ok(self):
|
||||
dialog = self.dialog
|
||||
dialog.entry.insert(0, 'abc')
|
||||
dialog.button_ok.invoke()
|
||||
self.assertEqual(dialog.result, 'abc')
|
||||
self.assertTrue(dialog.destroy.called)
|
||||
|
||||
def test_click_blank(self):
|
||||
dialog = self.dialog
|
||||
dialog.button_ok.invoke()
|
||||
self.assertEqual(dialog.result, None)
|
||||
self.assertFalse(dialog.destroy.called)
|
||||
|
||||
def test_click_cancel(self):
|
||||
dialog = self.dialog
|
||||
dialog.entry.insert(0, 'abc')
|
||||
dialog.button_cancel.invoke()
|
||||
self.assertEqual(dialog.result, None)
|
||||
self.assertTrue(dialog.destroy.called)
|
||||
|
||||
|
||||
class SectionnameGuiTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
|
||||
def test_click_section_name(self):
|
||||
root = Tk()
|
||||
root.withdraw()
|
||||
dialog = query.SectionName(root, 'T', 't', {'abc'}, _utest=True)
|
||||
Equal = self.assertEqual
|
||||
self.assertEqual(dialog.used_names, {'abc'})
|
||||
dialog.entry.insert(0, 'okay')
|
||||
dialog.button_ok.invoke()
|
||||
self.assertEqual(dialog.result, 'okay')
|
||||
del dialog
|
||||
root.destroy()
|
||||
del root
|
||||
|
||||
|
||||
class ModulenameGuiTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
|
||||
def test_click_module_name(self):
|
||||
root = Tk()
|
||||
root.withdraw()
|
||||
dialog = query.ModuleName(root, 'T', 't', 'idlelib', _utest=True)
|
||||
self.assertEqual(dialog.text0, 'idlelib')
|
||||
self.assertEqual(dialog.entry.get(), 'idlelib')
|
||||
dialog.button_ok.invoke()
|
||||
self.assertTrue(dialog.result.endswith('__init__.py'))
|
||||
del dialog
|
||||
root.destroy()
|
||||
del root
|
||||
|
||||
|
||||
class HelpsourceGuiTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
|
||||
def test_click_help_source(self):
|
||||
root = Tk()
|
||||
root.withdraw()
|
||||
dialog = query.HelpSource(root, 'T', menuitem='__test__',
|
||||
filepath=__file__, _utest=True)
|
||||
Equal = self.assertEqual
|
||||
Equal(dialog.entry.get(), '__test__')
|
||||
Equal(dialog.path.get(), __file__)
|
||||
dialog.button_ok.invoke()
|
||||
prefix = "file://" if sys.platform == 'darwin' else ''
|
||||
Equal(dialog.result, ('__test__', prefix + __file__))
|
||||
del dialog
|
||||
root.destroy()
|
||||
del root
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=False)
|
122
third_party/python/Lib/idlelib/idle_test/test_redirector.py
vendored
Normal file
122
third_party/python/Lib/idlelib/idle_test/test_redirector.py
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
"Test redirector, coverage 100%."
|
||||
|
||||
from idlelib.redirector import WidgetRedirector
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk, Text, TclError
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
|
||||
|
||||
class InitCloseTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.text = Text(cls.root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.text
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
redir = WidgetRedirector(self.text)
|
||||
self.assertEqual(redir.widget, self.text)
|
||||
self.assertEqual(redir.tk, self.text.tk)
|
||||
self.assertRaises(TclError, WidgetRedirector, self.text)
|
||||
redir.close() # restore self.tk, self.text
|
||||
|
||||
def test_close(self):
|
||||
redir = WidgetRedirector(self.text)
|
||||
redir.register('insert', Func)
|
||||
redir.close()
|
||||
self.assertEqual(redir._operations, {})
|
||||
self.assertFalse(hasattr(self.text, 'widget'))
|
||||
|
||||
|
||||
class WidgetRedirectorTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.text = Text(cls.root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.text
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.redir = WidgetRedirector(self.text)
|
||||
self.func = Func()
|
||||
self.orig_insert = self.redir.register('insert', self.func)
|
||||
self.text.insert('insert', 'asdf') # leaves self.text empty
|
||||
|
||||
def tearDown(self):
|
||||
self.text.delete('1.0', 'end')
|
||||
self.redir.close()
|
||||
|
||||
def test_repr(self): # partly for 100% coverage
|
||||
self.assertIn('Redirector', repr(self.redir))
|
||||
self.assertIn('Original', repr(self.orig_insert))
|
||||
|
||||
def test_register(self):
|
||||
self.assertEqual(self.text.get('1.0', 'end'), '\n')
|
||||
self.assertEqual(self.func.args, ('insert', 'asdf'))
|
||||
self.assertIn('insert', self.redir._operations)
|
||||
self.assertIn('insert', self.text.__dict__)
|
||||
self.assertEqual(self.text.insert, self.func)
|
||||
|
||||
def test_original_command(self):
|
||||
self.assertEqual(self.orig_insert.operation, 'insert')
|
||||
self.assertEqual(self.orig_insert.tk_call, self.text.tk.call)
|
||||
self.orig_insert('insert', 'asdf')
|
||||
self.assertEqual(self.text.get('1.0', 'end'), 'asdf\n')
|
||||
|
||||
def test_unregister(self):
|
||||
self.assertIsNone(self.redir.unregister('invalid operation name'))
|
||||
self.assertEqual(self.redir.unregister('insert'), self.func)
|
||||
self.assertNotIn('insert', self.redir._operations)
|
||||
self.assertNotIn('insert', self.text.__dict__)
|
||||
|
||||
def test_unregister_no_attribute(self):
|
||||
del self.text.insert
|
||||
self.assertEqual(self.redir.unregister('insert'), self.func)
|
||||
|
||||
def test_dispatch_intercept(self):
|
||||
self.func.__init__(True)
|
||||
self.assertTrue(self.redir.dispatch('insert', False))
|
||||
self.assertFalse(self.func.args[0])
|
||||
|
||||
def test_dispatch_bypass(self):
|
||||
self.orig_insert('insert', 'asdf')
|
||||
# tk.call returns '' where Python would return None
|
||||
self.assertEqual(self.redir.dispatch('delete', '1.0', 'end'), '')
|
||||
self.assertEqual(self.text.get('1.0', 'end'), '\n')
|
||||
|
||||
def test_dispatch_error(self):
|
||||
self.func.__init__(TclError())
|
||||
self.assertEqual(self.redir.dispatch('insert', False), '')
|
||||
self.assertEqual(self.redir.dispatch('invalid'), '')
|
||||
|
||||
def test_command_dispatch(self):
|
||||
# Test that .__init__ causes redirection of tk calls
|
||||
# through redir.dispatch
|
||||
self.root.call(self.text._w, 'insert', 'hello')
|
||||
self.assertEqual(self.func.args, ('hello',))
|
||||
self.assertEqual(self.text.get('1.0', 'end'), '\n')
|
||||
# Ensure that called through redir .dispatch and not through
|
||||
# self.text.insert by having mock raise TclError.
|
||||
self.func.__init__(TclError())
|
||||
self.assertEqual(self.root.call(self.text._w, 'insert', 'boo'), '')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
294
third_party/python/Lib/idlelib/idle_test/test_replace.py
vendored
Normal file
294
third_party/python/Lib/idlelib/idle_test/test_replace.py
vendored
Normal file
|
@ -0,0 +1,294 @@
|
|||
"Test replace, coverage 78%."
|
||||
|
||||
from idlelib.replace import ReplaceDialog
|
||||
import unittest
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
from tkinter import Tk, Text
|
||||
|
||||
from unittest.mock import Mock
|
||||
from idlelib.idle_test.mock_tk import Mbox
|
||||
import idlelib.searchengine as se
|
||||
|
||||
orig_mbox = se.tkMessageBox
|
||||
showerror = Mbox.showerror
|
||||
|
||||
|
||||
class ReplaceDialogTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
se.tkMessageBox = Mbox
|
||||
cls.engine = se.SearchEngine(cls.root)
|
||||
cls.dialog = ReplaceDialog(cls.root, cls.engine)
|
||||
cls.dialog.bell = lambda: None
|
||||
cls.dialog.ok = Mock()
|
||||
cls.text = Text(cls.root)
|
||||
cls.text.undo_block_start = Mock()
|
||||
cls.text.undo_block_stop = Mock()
|
||||
cls.dialog.text = cls.text
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
se.tkMessageBox = orig_mbox
|
||||
del cls.text, cls.dialog, cls.engine
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.text.insert('insert', 'This is a sample sTring')
|
||||
|
||||
def tearDown(self):
|
||||
self.engine.patvar.set('')
|
||||
self.dialog.replvar.set('')
|
||||
self.engine.wordvar.set(False)
|
||||
self.engine.casevar.set(False)
|
||||
self.engine.revar.set(False)
|
||||
self.engine.wrapvar.set(True)
|
||||
self.engine.backvar.set(False)
|
||||
showerror.title = ''
|
||||
showerror.message = ''
|
||||
self.text.delete('1.0', 'end')
|
||||
|
||||
def test_replace_simple(self):
|
||||
# Test replace function with all options at default setting.
|
||||
# Wrap around - True
|
||||
# Regular Expression - False
|
||||
# Match case - False
|
||||
# Match word - False
|
||||
# Direction - Forwards
|
||||
text = self.text
|
||||
equal = self.assertEqual
|
||||
pv = self.engine.patvar
|
||||
rv = self.dialog.replvar
|
||||
replace = self.dialog.replace_it
|
||||
|
||||
# test accessor method
|
||||
self.engine.setpat('asdf')
|
||||
equal(self.engine.getpat(), pv.get())
|
||||
|
||||
# text found and replaced
|
||||
pv.set('a')
|
||||
rv.set('asdf')
|
||||
replace()
|
||||
equal(text.get('1.8', '1.12'), 'asdf')
|
||||
|
||||
# don't "match word" case
|
||||
text.mark_set('insert', '1.0')
|
||||
pv.set('is')
|
||||
rv.set('hello')
|
||||
replace()
|
||||
equal(text.get('1.2', '1.7'), 'hello')
|
||||
|
||||
# don't "match case" case
|
||||
pv.set('string')
|
||||
rv.set('world')
|
||||
replace()
|
||||
equal(text.get('1.23', '1.28'), 'world')
|
||||
|
||||
# without "regular expression" case
|
||||
text.mark_set('insert', 'end')
|
||||
text.insert('insert', '\nline42:')
|
||||
before_text = text.get('1.0', 'end')
|
||||
pv.set(r'[a-z][\d]+')
|
||||
replace()
|
||||
after_text = text.get('1.0', 'end')
|
||||
equal(before_text, after_text)
|
||||
|
||||
# test with wrap around selected and complete a cycle
|
||||
text.mark_set('insert', '1.9')
|
||||
pv.set('i')
|
||||
rv.set('j')
|
||||
replace()
|
||||
equal(text.get('1.8'), 'i')
|
||||
equal(text.get('2.1'), 'j')
|
||||
replace()
|
||||
equal(text.get('2.1'), 'j')
|
||||
equal(text.get('1.8'), 'j')
|
||||
before_text = text.get('1.0', 'end')
|
||||
replace()
|
||||
after_text = text.get('1.0', 'end')
|
||||
equal(before_text, after_text)
|
||||
|
||||
# text not found
|
||||
before_text = text.get('1.0', 'end')
|
||||
pv.set('foobar')
|
||||
replace()
|
||||
after_text = text.get('1.0', 'end')
|
||||
equal(before_text, after_text)
|
||||
|
||||
# test access method
|
||||
self.dialog.find_it(0)
|
||||
|
||||
def test_replace_wrap_around(self):
|
||||
text = self.text
|
||||
equal = self.assertEqual
|
||||
pv = self.engine.patvar
|
||||
rv = self.dialog.replvar
|
||||
replace = self.dialog.replace_it
|
||||
self.engine.wrapvar.set(False)
|
||||
|
||||
# replace candidate found both after and before 'insert'
|
||||
text.mark_set('insert', '1.4')
|
||||
pv.set('i')
|
||||
rv.set('j')
|
||||
replace()
|
||||
equal(text.get('1.2'), 'i')
|
||||
equal(text.get('1.5'), 'j')
|
||||
replace()
|
||||
equal(text.get('1.2'), 'i')
|
||||
equal(text.get('1.20'), 'j')
|
||||
replace()
|
||||
equal(text.get('1.2'), 'i')
|
||||
|
||||
# replace candidate found only before 'insert'
|
||||
text.mark_set('insert', '1.8')
|
||||
pv.set('is')
|
||||
before_text = text.get('1.0', 'end')
|
||||
replace()
|
||||
after_text = text.get('1.0', 'end')
|
||||
equal(before_text, after_text)
|
||||
|
||||
def test_replace_whole_word(self):
|
||||
text = self.text
|
||||
equal = self.assertEqual
|
||||
pv = self.engine.patvar
|
||||
rv = self.dialog.replvar
|
||||
replace = self.dialog.replace_it
|
||||
self.engine.wordvar.set(True)
|
||||
|
||||
pv.set('is')
|
||||
rv.set('hello')
|
||||
replace()
|
||||
equal(text.get('1.0', '1.4'), 'This')
|
||||
equal(text.get('1.5', '1.10'), 'hello')
|
||||
|
||||
def test_replace_match_case(self):
|
||||
equal = self.assertEqual
|
||||
text = self.text
|
||||
pv = self.engine.patvar
|
||||
rv = self.dialog.replvar
|
||||
replace = self.dialog.replace_it
|
||||
self.engine.casevar.set(True)
|
||||
|
||||
before_text = self.text.get('1.0', 'end')
|
||||
pv.set('this')
|
||||
rv.set('that')
|
||||
replace()
|
||||
after_text = self.text.get('1.0', 'end')
|
||||
equal(before_text, after_text)
|
||||
|
||||
pv.set('This')
|
||||
replace()
|
||||
equal(text.get('1.0', '1.4'), 'that')
|
||||
|
||||
def test_replace_regex(self):
|
||||
equal = self.assertEqual
|
||||
text = self.text
|
||||
pv = self.engine.patvar
|
||||
rv = self.dialog.replvar
|
||||
replace = self.dialog.replace_it
|
||||
self.engine.revar.set(True)
|
||||
|
||||
before_text = text.get('1.0', 'end')
|
||||
pv.set(r'[a-z][\d]+')
|
||||
rv.set('hello')
|
||||
replace()
|
||||
after_text = text.get('1.0', 'end')
|
||||
equal(before_text, after_text)
|
||||
|
||||
text.insert('insert', '\nline42')
|
||||
replace()
|
||||
equal(text.get('2.0', '2.8'), 'linhello')
|
||||
|
||||
pv.set('')
|
||||
replace()
|
||||
self.assertIn('error', showerror.title)
|
||||
self.assertIn('Empty', showerror.message)
|
||||
|
||||
pv.set(r'[\d')
|
||||
replace()
|
||||
self.assertIn('error', showerror.title)
|
||||
self.assertIn('Pattern', showerror.message)
|
||||
|
||||
showerror.title = ''
|
||||
showerror.message = ''
|
||||
pv.set('[a]')
|
||||
rv.set('test\\')
|
||||
replace()
|
||||
self.assertIn('error', showerror.title)
|
||||
self.assertIn('Invalid Replace Expression', showerror.message)
|
||||
|
||||
# test access method
|
||||
self.engine.setcookedpat("?")
|
||||
equal(pv.get(), "\\?")
|
||||
|
||||
def test_replace_backwards(self):
|
||||
equal = self.assertEqual
|
||||
text = self.text
|
||||
pv = self.engine.patvar
|
||||
rv = self.dialog.replvar
|
||||
replace = self.dialog.replace_it
|
||||
self.engine.backvar.set(True)
|
||||
|
||||
text.insert('insert', '\nis as ')
|
||||
|
||||
pv.set('is')
|
||||
rv.set('was')
|
||||
replace()
|
||||
equal(text.get('1.2', '1.4'), 'is')
|
||||
equal(text.get('2.0', '2.3'), 'was')
|
||||
replace()
|
||||
equal(text.get('1.5', '1.8'), 'was')
|
||||
replace()
|
||||
equal(text.get('1.2', '1.5'), 'was')
|
||||
|
||||
def test_replace_all(self):
|
||||
text = self.text
|
||||
pv = self.engine.patvar
|
||||
rv = self.dialog.replvar
|
||||
replace_all = self.dialog.replace_all
|
||||
|
||||
text.insert('insert', '\n')
|
||||
text.insert('insert', text.get('1.0', 'end')*100)
|
||||
pv.set('is')
|
||||
rv.set('was')
|
||||
replace_all()
|
||||
self.assertNotIn('is', text.get('1.0', 'end'))
|
||||
|
||||
self.engine.revar.set(True)
|
||||
pv.set('')
|
||||
replace_all()
|
||||
self.assertIn('error', showerror.title)
|
||||
self.assertIn('Empty', showerror.message)
|
||||
|
||||
pv.set('[s][T]')
|
||||
rv.set('\\')
|
||||
replace_all()
|
||||
|
||||
self.engine.revar.set(False)
|
||||
pv.set('text which is not present')
|
||||
rv.set('foobar')
|
||||
replace_all()
|
||||
|
||||
def test_default_command(self):
|
||||
text = self.text
|
||||
pv = self.engine.patvar
|
||||
rv = self.dialog.replvar
|
||||
replace_find = self.dialog.default_command
|
||||
equal = self.assertEqual
|
||||
|
||||
pv.set('This')
|
||||
rv.set('was')
|
||||
replace_find()
|
||||
equal(text.get('sel.first', 'sel.last'), 'was')
|
||||
|
||||
self.engine.revar.set(True)
|
||||
pv.set('')
|
||||
replace_find()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
29
third_party/python/Lib/idlelib/idle_test/test_rpc.py
vendored
Normal file
29
third_party/python/Lib/idlelib/idle_test/test_rpc.py
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
"Test rpc, coverage 20%."
|
||||
|
||||
from idlelib import rpc
|
||||
import unittest
|
||||
|
||||
|
||||
|
||||
class CodePicklerTest(unittest.TestCase):
|
||||
|
||||
def test_pickle_unpickle(self):
|
||||
def f(): return a + b + c
|
||||
func, (cbytes,) = rpc.pickle_code(f.__code__)
|
||||
self.assertIs(func, rpc.unpickle_code)
|
||||
self.assertIn(b'test_rpc.py', cbytes)
|
||||
code = rpc.unpickle_code(cbytes)
|
||||
self.assertEqual(code.co_names, ('a', 'b', 'c'))
|
||||
|
||||
def test_code_pickler(self):
|
||||
self.assertIn(type((lambda:None).__code__),
|
||||
rpc.CodePickler.dispatch_table)
|
||||
|
||||
def test_dumps(self):
|
||||
def f(): pass
|
||||
# The main test here is that pickling code does not raise.
|
||||
self.assertIn(b'test_rpc.py', rpc.dumps(f.__code__))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
53
third_party/python/Lib/idlelib/idle_test/test_rstrip.py
vendored
Normal file
53
third_party/python/Lib/idlelib/idle_test/test_rstrip.py
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
"Test rstrip, coverage 100%."
|
||||
|
||||
from idlelib import rstrip
|
||||
import unittest
|
||||
from idlelib.idle_test.mock_idle import Editor
|
||||
|
||||
class rstripTest(unittest.TestCase):
|
||||
|
||||
def test_rstrip_line(self):
|
||||
editor = Editor()
|
||||
text = editor.text
|
||||
do_rstrip = rstrip.Rstrip(editor).do_rstrip
|
||||
|
||||
do_rstrip()
|
||||
self.assertEqual(text.get('1.0', 'insert'), '')
|
||||
text.insert('1.0', ' ')
|
||||
do_rstrip()
|
||||
self.assertEqual(text.get('1.0', 'insert'), '')
|
||||
text.insert('1.0', ' \n')
|
||||
do_rstrip()
|
||||
self.assertEqual(text.get('1.0', 'insert'), '\n')
|
||||
|
||||
def test_rstrip_multiple(self):
|
||||
editor = Editor()
|
||||
# Comment above, uncomment 3 below to test with real Editor & Text.
|
||||
#from idlelib.editor import EditorWindow as Editor
|
||||
#from tkinter import Tk
|
||||
#editor = Editor(root=Tk())
|
||||
text = editor.text
|
||||
do_rstrip = rstrip.Rstrip(editor).do_rstrip
|
||||
|
||||
original = (
|
||||
"Line with an ending tab \n"
|
||||
"Line ending in 5 spaces \n"
|
||||
"Linewithnospaces\n"
|
||||
" indented line\n"
|
||||
" indented line with trailing space \n"
|
||||
" ")
|
||||
stripped = (
|
||||
"Line with an ending tab\n"
|
||||
"Line ending in 5 spaces\n"
|
||||
"Linewithnospaces\n"
|
||||
" indented line\n"
|
||||
" indented line with trailing space\n")
|
||||
|
||||
text.insert('1.0', original)
|
||||
do_rstrip()
|
||||
self.assertEqual(text.get('1.0', 'insert'), stripped)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
264
third_party/python/Lib/idlelib/idle_test/test_run.py
vendored
Normal file
264
third_party/python/Lib/idlelib/idle_test/test_run.py
vendored
Normal file
|
@ -0,0 +1,264 @@
|
|||
"Test run, coverage 42%."
|
||||
|
||||
from idlelib import run
|
||||
import unittest
|
||||
from unittest import mock
|
||||
from test.support import captured_stderr
|
||||
|
||||
import io
|
||||
|
||||
class RunTest(unittest.TestCase):
|
||||
|
||||
def test_print_exception_unhashable(self):
|
||||
class UnhashableException(Exception):
|
||||
def __eq__(self, other):
|
||||
return True
|
||||
|
||||
ex1 = UnhashableException('ex1')
|
||||
ex2 = UnhashableException('ex2')
|
||||
try:
|
||||
raise ex2 from ex1
|
||||
except UnhashableException:
|
||||
try:
|
||||
raise ex1
|
||||
except UnhashableException:
|
||||
with captured_stderr() as output:
|
||||
with mock.patch.object(run,
|
||||
'cleanup_traceback') as ct:
|
||||
ct.side_effect = lambda t, e: t
|
||||
run.print_exception()
|
||||
|
||||
tb = output.getvalue().strip().splitlines()
|
||||
self.assertEqual(11, len(tb))
|
||||
self.assertIn('UnhashableException: ex2', tb[3])
|
||||
self.assertIn('UnhashableException: ex1', tb[10])
|
||||
|
||||
|
||||
# PseudoFile tests.
|
||||
|
||||
class S(str):
|
||||
def __str__(self):
|
||||
return '%s:str' % type(self).__name__
|
||||
def __unicode__(self):
|
||||
return '%s:unicode' % type(self).__name__
|
||||
def __len__(self):
|
||||
return 3
|
||||
def __iter__(self):
|
||||
return iter('abc')
|
||||
def __getitem__(self, *args):
|
||||
return '%s:item' % type(self).__name__
|
||||
def __getslice__(self, *args):
|
||||
return '%s:slice' % type(self).__name__
|
||||
|
||||
|
||||
class MockShell:
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
def write(self, *args):
|
||||
self.written.append(args)
|
||||
def readline(self):
|
||||
return self.lines.pop()
|
||||
def close(self):
|
||||
pass
|
||||
def reset(self):
|
||||
self.written = []
|
||||
def push(self, lines):
|
||||
self.lines = list(lines)[::-1]
|
||||
|
||||
|
||||
class PseudeInputFilesTest(unittest.TestCase):
|
||||
|
||||
def test_misc(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoInputFile(shell, 'stdin', 'utf-8')
|
||||
self.assertIsInstance(f, io.TextIOBase)
|
||||
self.assertEqual(f.encoding, 'utf-8')
|
||||
self.assertIsNone(f.errors)
|
||||
self.assertIsNone(f.newlines)
|
||||
self.assertEqual(f.name, '<stdin>')
|
||||
self.assertFalse(f.closed)
|
||||
self.assertTrue(f.isatty())
|
||||
self.assertTrue(f.readable())
|
||||
self.assertFalse(f.writable())
|
||||
self.assertFalse(f.seekable())
|
||||
|
||||
def test_unsupported(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoInputFile(shell, 'stdin', 'utf-8')
|
||||
self.assertRaises(OSError, f.fileno)
|
||||
self.assertRaises(OSError, f.tell)
|
||||
self.assertRaises(OSError, f.seek, 0)
|
||||
self.assertRaises(OSError, f.write, 'x')
|
||||
self.assertRaises(OSError, f.writelines, ['x'])
|
||||
|
||||
def test_read(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoInputFile(shell, 'stdin', 'utf-8')
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.read(), 'one\ntwo\n')
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.read(-1), 'one\ntwo\n')
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.read(None), 'one\ntwo\n')
|
||||
shell.push(['one\n', 'two\n', 'three\n', ''])
|
||||
self.assertEqual(f.read(2), 'on')
|
||||
self.assertEqual(f.read(3), 'e\nt')
|
||||
self.assertEqual(f.read(10), 'wo\nthree\n')
|
||||
|
||||
shell.push(['one\n', 'two\n'])
|
||||
self.assertEqual(f.read(0), '')
|
||||
self.assertRaises(TypeError, f.read, 1.5)
|
||||
self.assertRaises(TypeError, f.read, '1')
|
||||
self.assertRaises(TypeError, f.read, 1, 1)
|
||||
|
||||
def test_readline(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoInputFile(shell, 'stdin', 'utf-8')
|
||||
shell.push(['one\n', 'two\n', 'three\n', 'four\n'])
|
||||
self.assertEqual(f.readline(), 'one\n')
|
||||
self.assertEqual(f.readline(-1), 'two\n')
|
||||
self.assertEqual(f.readline(None), 'three\n')
|
||||
shell.push(['one\ntwo\n'])
|
||||
self.assertEqual(f.readline(), 'one\n')
|
||||
self.assertEqual(f.readline(), 'two\n')
|
||||
shell.push(['one', 'two', 'three'])
|
||||
self.assertEqual(f.readline(), 'one')
|
||||
self.assertEqual(f.readline(), 'two')
|
||||
shell.push(['one\n', 'two\n', 'three\n'])
|
||||
self.assertEqual(f.readline(2), 'on')
|
||||
self.assertEqual(f.readline(1), 'e')
|
||||
self.assertEqual(f.readline(1), '\n')
|
||||
self.assertEqual(f.readline(10), 'two\n')
|
||||
|
||||
shell.push(['one\n', 'two\n'])
|
||||
self.assertEqual(f.readline(0), '')
|
||||
self.assertRaises(TypeError, f.readlines, 1.5)
|
||||
self.assertRaises(TypeError, f.readlines, '1')
|
||||
self.assertRaises(TypeError, f.readlines, 1, 1)
|
||||
|
||||
def test_readlines(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoInputFile(shell, 'stdin', 'utf-8')
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.readlines(), ['one\n', 'two\n'])
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.readlines(-1), ['one\n', 'two\n'])
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.readlines(None), ['one\n', 'two\n'])
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.readlines(0), ['one\n', 'two\n'])
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.readlines(3), ['one\n'])
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertEqual(f.readlines(4), ['one\n', 'two\n'])
|
||||
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertRaises(TypeError, f.readlines, 1.5)
|
||||
self.assertRaises(TypeError, f.readlines, '1')
|
||||
self.assertRaises(TypeError, f.readlines, 1, 1)
|
||||
|
||||
def test_close(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoInputFile(shell, 'stdin', 'utf-8')
|
||||
shell.push(['one\n', 'two\n', ''])
|
||||
self.assertFalse(f.closed)
|
||||
self.assertEqual(f.readline(), 'one\n')
|
||||
f.close()
|
||||
self.assertFalse(f.closed)
|
||||
self.assertEqual(f.readline(), 'two\n')
|
||||
self.assertRaises(TypeError, f.close, 1)
|
||||
|
||||
|
||||
class PseudeOutputFilesTest(unittest.TestCase):
|
||||
|
||||
def test_misc(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoOutputFile(shell, 'stdout', 'utf-8')
|
||||
self.assertIsInstance(f, io.TextIOBase)
|
||||
self.assertEqual(f.encoding, 'utf-8')
|
||||
self.assertIsNone(f.errors)
|
||||
self.assertIsNone(f.newlines)
|
||||
self.assertEqual(f.name, '<stdout>')
|
||||
self.assertFalse(f.closed)
|
||||
self.assertTrue(f.isatty())
|
||||
self.assertFalse(f.readable())
|
||||
self.assertTrue(f.writable())
|
||||
self.assertFalse(f.seekable())
|
||||
|
||||
def test_unsupported(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoOutputFile(shell, 'stdout', 'utf-8')
|
||||
self.assertRaises(OSError, f.fileno)
|
||||
self.assertRaises(OSError, f.tell)
|
||||
self.assertRaises(OSError, f.seek, 0)
|
||||
self.assertRaises(OSError, f.read, 0)
|
||||
self.assertRaises(OSError, f.readline, 0)
|
||||
|
||||
def test_write(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoOutputFile(shell, 'stdout', 'utf-8')
|
||||
f.write('test')
|
||||
self.assertEqual(shell.written, [('test', 'stdout')])
|
||||
shell.reset()
|
||||
f.write('t\xe8st')
|
||||
self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
|
||||
shell.reset()
|
||||
|
||||
f.write(S('t\xe8st'))
|
||||
self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
|
||||
self.assertEqual(type(shell.written[0][0]), str)
|
||||
shell.reset()
|
||||
|
||||
self.assertRaises(TypeError, f.write)
|
||||
self.assertEqual(shell.written, [])
|
||||
self.assertRaises(TypeError, f.write, b'test')
|
||||
self.assertRaises(TypeError, f.write, 123)
|
||||
self.assertEqual(shell.written, [])
|
||||
self.assertRaises(TypeError, f.write, 'test', 'spam')
|
||||
self.assertEqual(shell.written, [])
|
||||
|
||||
def test_writelines(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoOutputFile(shell, 'stdout', 'utf-8')
|
||||
f.writelines([])
|
||||
self.assertEqual(shell.written, [])
|
||||
shell.reset()
|
||||
f.writelines(['one\n', 'two'])
|
||||
self.assertEqual(shell.written,
|
||||
[('one\n', 'stdout'), ('two', 'stdout')])
|
||||
shell.reset()
|
||||
f.writelines(['on\xe8\n', 'tw\xf2'])
|
||||
self.assertEqual(shell.written,
|
||||
[('on\xe8\n', 'stdout'), ('tw\xf2', 'stdout')])
|
||||
shell.reset()
|
||||
|
||||
f.writelines([S('t\xe8st')])
|
||||
self.assertEqual(shell.written, [('t\xe8st', 'stdout')])
|
||||
self.assertEqual(type(shell.written[0][0]), str)
|
||||
shell.reset()
|
||||
|
||||
self.assertRaises(TypeError, f.writelines)
|
||||
self.assertEqual(shell.written, [])
|
||||
self.assertRaises(TypeError, f.writelines, 123)
|
||||
self.assertEqual(shell.written, [])
|
||||
self.assertRaises(TypeError, f.writelines, [b'test'])
|
||||
self.assertRaises(TypeError, f.writelines, [123])
|
||||
self.assertEqual(shell.written, [])
|
||||
self.assertRaises(TypeError, f.writelines, [], [])
|
||||
self.assertEqual(shell.written, [])
|
||||
|
||||
def test_close(self):
|
||||
shell = MockShell()
|
||||
f = run.PseudoOutputFile(shell, 'stdout', 'utf-8')
|
||||
self.assertFalse(f.closed)
|
||||
f.write('test')
|
||||
f.close()
|
||||
self.assertTrue(f.closed)
|
||||
self.assertRaises(ValueError, f.write, 'x')
|
||||
self.assertEqual(shell.written, [('test', 'stdout')])
|
||||
f.close()
|
||||
self.assertRaises(TypeError, f.close, 1)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
33
third_party/python/Lib/idlelib/idle_test/test_runscript.py
vendored
Normal file
33
third_party/python/Lib/idlelib/idle_test/test_runscript.py
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
"Test runscript, coverage 16%."
|
||||
|
||||
from idlelib import runscript
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
from idlelib.editor import EditorWindow
|
||||
|
||||
|
||||
class ScriptBindingTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.update_idletasks()
|
||||
for id in cls.root.tk.call('after', 'info'):
|
||||
cls.root.after_cancel(id) # Need for EditorWindow.
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
ew = EditorWindow(root=self.root)
|
||||
sb = runscript.ScriptBinding(ew)
|
||||
ew._close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
27
third_party/python/Lib/idlelib/idle_test/test_scrolledlist.py
vendored
Normal file
27
third_party/python/Lib/idlelib/idle_test/test_scrolledlist.py
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
"Test scrolledlist, coverage 38%."
|
||||
|
||||
from idlelib.scrolledlist import ScrolledList
|
||||
import unittest
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
from tkinter import Tk
|
||||
|
||||
|
||||
class ScrolledListTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = Tk()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
|
||||
def test_init(self):
|
||||
ScrolledList(self.root)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
80
third_party/python/Lib/idlelib/idle_test/test_search.py
vendored
Normal file
80
third_party/python/Lib/idlelib/idle_test/test_search.py
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
"Test search, coverage 69%."
|
||||
|
||||
from idlelib import search
|
||||
import unittest
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
from tkinter import Tk, Text, BooleanVar
|
||||
from idlelib import searchengine
|
||||
|
||||
# Does not currently test the event handler wrappers.
|
||||
# A usage test should simulate clicks and check highlighting.
|
||||
# Tests need to be coordinated with SearchDialogBase tests
|
||||
# to avoid duplication.
|
||||
|
||||
|
||||
class SearchDialogTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = Tk()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.engine = searchengine.SearchEngine(self.root)
|
||||
self.dialog = search.SearchDialog(self.root, self.engine)
|
||||
self.dialog.bell = lambda: None
|
||||
self.text = Text(self.root)
|
||||
self.text.insert('1.0', 'Hello World!')
|
||||
|
||||
def test_find_again(self):
|
||||
# Search for various expressions
|
||||
text = self.text
|
||||
|
||||
self.engine.setpat('')
|
||||
self.assertFalse(self.dialog.find_again(text))
|
||||
self.dialog.bell = lambda: None
|
||||
|
||||
self.engine.setpat('Hello')
|
||||
self.assertTrue(self.dialog.find_again(text))
|
||||
|
||||
self.engine.setpat('Goodbye')
|
||||
self.assertFalse(self.dialog.find_again(text))
|
||||
|
||||
self.engine.setpat('World!')
|
||||
self.assertTrue(self.dialog.find_again(text))
|
||||
|
||||
self.engine.setpat('Hello World!')
|
||||
self.assertTrue(self.dialog.find_again(text))
|
||||
|
||||
# Regular expression
|
||||
self.engine.revar = BooleanVar(self.root, True)
|
||||
self.engine.setpat('W[aeiouy]r')
|
||||
self.assertTrue(self.dialog.find_again(text))
|
||||
|
||||
def test_find_selection(self):
|
||||
# Select some text and make sure it's found
|
||||
text = self.text
|
||||
# Add additional line to find
|
||||
self.text.insert('2.0', 'Hello World!')
|
||||
|
||||
text.tag_add('sel', '1.0', '1.4') # Select 'Hello'
|
||||
self.assertTrue(self.dialog.find_selection(text))
|
||||
|
||||
text.tag_remove('sel', '1.0', 'end')
|
||||
text.tag_add('sel', '1.6', '1.11') # Select 'World!'
|
||||
self.assertTrue(self.dialog.find_selection(text))
|
||||
|
||||
text.tag_remove('sel', '1.0', 'end')
|
||||
text.tag_add('sel', '1.0', '1.11') # Select 'Hello World!'
|
||||
self.assertTrue(self.dialog.find_selection(text))
|
||||
|
||||
# Remove additional line
|
||||
text.delete('2.0', 'end')
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=2)
|
156
third_party/python/Lib/idlelib/idle_test/test_searchbase.py
vendored
Normal file
156
third_party/python/Lib/idlelib/idle_test/test_searchbase.py
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
"Test searchbase, coverage 98%."
|
||||
# The only thing not covered is inconsequential --
|
||||
# testing skipping of suite when self.needwrapbutton is false.
|
||||
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk, Frame ##, BooleanVar, StringVar
|
||||
from idlelib import searchengine as se
|
||||
from idlelib import searchbase as sdb
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
## from idlelib.idle_test.mock_tk import Var
|
||||
|
||||
# The ## imports above & following could help make some tests gui-free.
|
||||
# However, they currently make radiobutton tests fail.
|
||||
##def setUpModule():
|
||||
## # Replace tk objects used to initialize se.SearchEngine.
|
||||
## se.BooleanVar = Var
|
||||
## se.StringVar = Var
|
||||
##
|
||||
##def tearDownModule():
|
||||
## se.BooleanVar = BooleanVar
|
||||
## se.StringVar = StringVar
|
||||
|
||||
|
||||
class SearchDialogBaseTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.engine = se.SearchEngine(self.root) # None also seems to work
|
||||
self.dialog = sdb.SearchDialogBase(root=self.root, engine=self.engine)
|
||||
|
||||
def tearDown(self):
|
||||
self.dialog.close()
|
||||
|
||||
def test_open_and_close(self):
|
||||
# open calls create_widgets, which needs default_command
|
||||
self.dialog.default_command = None
|
||||
|
||||
# Since text parameter of .open is not used in base class,
|
||||
# pass dummy 'text' instead of tk.Text().
|
||||
self.dialog.open('text')
|
||||
self.assertEqual(self.dialog.top.state(), 'normal')
|
||||
self.dialog.close()
|
||||
self.assertEqual(self.dialog.top.state(), 'withdrawn')
|
||||
|
||||
self.dialog.open('text', searchphrase="hello")
|
||||
self.assertEqual(self.dialog.ent.get(), 'hello')
|
||||
self.dialog.close()
|
||||
|
||||
def test_create_widgets(self):
|
||||
self.dialog.create_entries = Func()
|
||||
self.dialog.create_option_buttons = Func()
|
||||
self.dialog.create_other_buttons = Func()
|
||||
self.dialog.create_command_buttons = Func()
|
||||
|
||||
self.dialog.default_command = None
|
||||
self.dialog.create_widgets()
|
||||
|
||||
self.assertTrue(self.dialog.create_entries.called)
|
||||
self.assertTrue(self.dialog.create_option_buttons.called)
|
||||
self.assertTrue(self.dialog.create_other_buttons.called)
|
||||
self.assertTrue(self.dialog.create_command_buttons.called)
|
||||
|
||||
def test_make_entry(self):
|
||||
equal = self.assertEqual
|
||||
self.dialog.row = 0
|
||||
self.dialog.top = self.root
|
||||
entry, label = self.dialog.make_entry("Test:", 'hello')
|
||||
equal(label['text'], 'Test:')
|
||||
|
||||
self.assertIn(entry.get(), 'hello')
|
||||
egi = entry.grid_info()
|
||||
equal(int(egi['row']), 0)
|
||||
equal(int(egi['column']), 1)
|
||||
equal(int(egi['rowspan']), 1)
|
||||
equal(int(egi['columnspan']), 1)
|
||||
equal(self.dialog.row, 1)
|
||||
|
||||
def test_create_entries(self):
|
||||
self.dialog.top = self.root
|
||||
self.dialog.row = 0
|
||||
self.engine.setpat('hello')
|
||||
self.dialog.create_entries()
|
||||
self.assertIn(self.dialog.ent.get(), 'hello')
|
||||
|
||||
def test_make_frame(self):
|
||||
self.dialog.row = 0
|
||||
self.dialog.top = self.root
|
||||
frame, label = self.dialog.make_frame()
|
||||
self.assertEqual(label, '')
|
||||
self.assertIsInstance(frame, Frame)
|
||||
|
||||
frame, label = self.dialog.make_frame('testlabel')
|
||||
self.assertEqual(label['text'], 'testlabel')
|
||||
self.assertIsInstance(frame, Frame)
|
||||
|
||||
def btn_test_setup(self, meth):
|
||||
self.dialog.top = self.root
|
||||
self.dialog.row = 0
|
||||
return meth()
|
||||
|
||||
def test_create_option_buttons(self):
|
||||
e = self.engine
|
||||
for state in (0, 1):
|
||||
for var in (e.revar, e.casevar, e.wordvar, e.wrapvar):
|
||||
var.set(state)
|
||||
frame, options = self.btn_test_setup(
|
||||
self.dialog.create_option_buttons)
|
||||
for spec, button in zip (options, frame.pack_slaves()):
|
||||
var, label = spec
|
||||
self.assertEqual(button['text'], label)
|
||||
self.assertEqual(var.get(), state)
|
||||
|
||||
def test_create_other_buttons(self):
|
||||
for state in (False, True):
|
||||
var = self.engine.backvar
|
||||
var.set(state)
|
||||
frame, others = self.btn_test_setup(
|
||||
self.dialog.create_other_buttons)
|
||||
buttons = frame.pack_slaves()
|
||||
for spec, button in zip(others, buttons):
|
||||
val, label = spec
|
||||
self.assertEqual(button['text'], label)
|
||||
if val == state:
|
||||
# hit other button, then this one
|
||||
# indexes depend on button order
|
||||
self.assertEqual(var.get(), state)
|
||||
|
||||
def test_make_button(self):
|
||||
self.dialog.top = self.root
|
||||
self.dialog.buttonframe = Frame(self.dialog.top)
|
||||
btn = self.dialog.make_button('Test', self.dialog.close)
|
||||
self.assertEqual(btn['text'], 'Test')
|
||||
|
||||
def test_create_command_buttons(self):
|
||||
self.dialog.top = self.root
|
||||
self.dialog.create_command_buttons()
|
||||
# Look for close button command in buttonframe
|
||||
closebuttoncommand = ''
|
||||
for child in self.dialog.buttonframe.winfo_children():
|
||||
if child['text'] == 'close':
|
||||
closebuttoncommand = child['command']
|
||||
self.assertIn('close', closebuttoncommand)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=2)
|
330
third_party/python/Lib/idlelib/idle_test/test_searchengine.py
vendored
Normal file
330
third_party/python/Lib/idlelib/idle_test/test_searchengine.py
vendored
Normal file
|
@ -0,0 +1,330 @@
|
|||
"Test searchengine, coverage 99%."
|
||||
|
||||
from idlelib import searchengine as se
|
||||
import unittest
|
||||
# from test.support import requires
|
||||
from tkinter import BooleanVar, StringVar, TclError # ,Tk, Text
|
||||
import tkinter.messagebox as tkMessageBox
|
||||
from idlelib.idle_test.mock_tk import Var, Mbox
|
||||
from idlelib.idle_test.mock_tk import Text as mockText
|
||||
import re
|
||||
|
||||
# With mock replacements, the module does not use any gui widgets.
|
||||
# The use of tk.Text is avoided (for now, until mock Text is improved)
|
||||
# by patching instances with an index function returning what is needed.
|
||||
# This works because mock Text.get does not use .index.
|
||||
# The tkinter imports are used to restore searchengine.
|
||||
|
||||
def setUpModule():
|
||||
# Replace s-e module tkinter imports other than non-gui TclError.
|
||||
se.BooleanVar = Var
|
||||
se.StringVar = Var
|
||||
se.tkMessageBox = Mbox
|
||||
|
||||
def tearDownModule():
|
||||
# Restore 'just in case', though other tests should also replace.
|
||||
se.BooleanVar = BooleanVar
|
||||
se.StringVar = StringVar
|
||||
se.tkMessageBox = tkMessageBox
|
||||
|
||||
|
||||
class Mock:
|
||||
def __init__(self, *args, **kwargs): pass
|
||||
|
||||
class GetTest(unittest.TestCase):
|
||||
# SearchEngine.get returns singleton created & saved on first call.
|
||||
def test_get(self):
|
||||
saved_Engine = se.SearchEngine
|
||||
se.SearchEngine = Mock # monkey-patch class
|
||||
try:
|
||||
root = Mock()
|
||||
engine = se.get(root)
|
||||
self.assertIsInstance(engine, se.SearchEngine)
|
||||
self.assertIs(root._searchengine, engine)
|
||||
self.assertIs(se.get(root), engine)
|
||||
finally:
|
||||
se.SearchEngine = saved_Engine # restore class to module
|
||||
|
||||
class GetLineColTest(unittest.TestCase):
|
||||
# Test simple text-independent helper function
|
||||
def test_get_line_col(self):
|
||||
self.assertEqual(se.get_line_col('1.0'), (1, 0))
|
||||
self.assertEqual(se.get_line_col('1.11'), (1, 11))
|
||||
|
||||
self.assertRaises(ValueError, se.get_line_col, ('1.0 lineend'))
|
||||
self.assertRaises(ValueError, se.get_line_col, ('end'))
|
||||
|
||||
class GetSelectionTest(unittest.TestCase):
|
||||
# Test text-dependent helper function.
|
||||
## # Need gui for text.index('sel.first/sel.last/insert').
|
||||
## @classmethod
|
||||
## def setUpClass(cls):
|
||||
## requires('gui')
|
||||
## cls.root = Tk()
|
||||
##
|
||||
## @classmethod
|
||||
## def tearDownClass(cls):
|
||||
## cls.root.destroy()
|
||||
## del cls.root
|
||||
|
||||
def test_get_selection(self):
|
||||
# text = Text(master=self.root)
|
||||
text = mockText()
|
||||
text.insert('1.0', 'Hello World!')
|
||||
|
||||
# fix text.index result when called in get_selection
|
||||
def sel(s):
|
||||
# select entire text, cursor irrelevant
|
||||
if s == 'sel.first': return '1.0'
|
||||
if s == 'sel.last': return '1.12'
|
||||
raise TclError
|
||||
text.index = sel # replaces .tag_add('sel', '1.0, '1.12')
|
||||
self.assertEqual(se.get_selection(text), ('1.0', '1.12'))
|
||||
|
||||
def mark(s):
|
||||
# no selection, cursor after 'Hello'
|
||||
if s == 'insert': return '1.5'
|
||||
raise TclError
|
||||
text.index = mark # replaces .mark_set('insert', '1.5')
|
||||
self.assertEqual(se.get_selection(text), ('1.5', '1.5'))
|
||||
|
||||
|
||||
class ReverseSearchTest(unittest.TestCase):
|
||||
# Test helper function that searches backwards within a line.
|
||||
def test_search_reverse(self):
|
||||
Equal = self.assertEqual
|
||||
line = "Here is an 'is' test text."
|
||||
prog = re.compile('is')
|
||||
Equal(se.search_reverse(prog, line, len(line)).span(), (12, 14))
|
||||
Equal(se.search_reverse(prog, line, 14).span(), (12, 14))
|
||||
Equal(se.search_reverse(prog, line, 13).span(), (5, 7))
|
||||
Equal(se.search_reverse(prog, line, 7).span(), (5, 7))
|
||||
Equal(se.search_reverse(prog, line, 6), None)
|
||||
|
||||
|
||||
class SearchEngineTest(unittest.TestCase):
|
||||
# Test class methods that do not use Text widget.
|
||||
|
||||
def setUp(self):
|
||||
self.engine = se.SearchEngine(root=None)
|
||||
# Engine.root is only used to create error message boxes.
|
||||
# The mock replacement ignores the root argument.
|
||||
|
||||
def test_is_get(self):
|
||||
engine = self.engine
|
||||
Equal = self.assertEqual
|
||||
|
||||
Equal(engine.getpat(), '')
|
||||
engine.setpat('hello')
|
||||
Equal(engine.getpat(), 'hello')
|
||||
|
||||
Equal(engine.isre(), False)
|
||||
engine.revar.set(1)
|
||||
Equal(engine.isre(), True)
|
||||
|
||||
Equal(engine.iscase(), False)
|
||||
engine.casevar.set(1)
|
||||
Equal(engine.iscase(), True)
|
||||
|
||||
Equal(engine.isword(), False)
|
||||
engine.wordvar.set(1)
|
||||
Equal(engine.isword(), True)
|
||||
|
||||
Equal(engine.iswrap(), True)
|
||||
engine.wrapvar.set(0)
|
||||
Equal(engine.iswrap(), False)
|
||||
|
||||
Equal(engine.isback(), False)
|
||||
engine.backvar.set(1)
|
||||
Equal(engine.isback(), True)
|
||||
|
||||
def test_setcookedpat(self):
|
||||
engine = self.engine
|
||||
engine.setcookedpat(r'\s')
|
||||
self.assertEqual(engine.getpat(), r'\s')
|
||||
engine.revar.set(1)
|
||||
engine.setcookedpat(r'\s')
|
||||
self.assertEqual(engine.getpat(), r'\\s')
|
||||
|
||||
def test_getcookedpat(self):
|
||||
engine = self.engine
|
||||
Equal = self.assertEqual
|
||||
|
||||
Equal(engine.getcookedpat(), '')
|
||||
engine.setpat('hello')
|
||||
Equal(engine.getcookedpat(), 'hello')
|
||||
engine.wordvar.set(True)
|
||||
Equal(engine.getcookedpat(), r'\bhello\b')
|
||||
engine.wordvar.set(False)
|
||||
|
||||
engine.setpat(r'\s')
|
||||
Equal(engine.getcookedpat(), r'\\s')
|
||||
engine.revar.set(True)
|
||||
Equal(engine.getcookedpat(), r'\s')
|
||||
|
||||
def test_getprog(self):
|
||||
engine = self.engine
|
||||
Equal = self.assertEqual
|
||||
|
||||
engine.setpat('Hello')
|
||||
temppat = engine.getprog()
|
||||
Equal(temppat.pattern, re.compile('Hello', re.IGNORECASE).pattern)
|
||||
engine.casevar.set(1)
|
||||
temppat = engine.getprog()
|
||||
Equal(temppat.pattern, re.compile('Hello').pattern, 0)
|
||||
|
||||
engine.setpat('')
|
||||
Equal(engine.getprog(), None)
|
||||
engine.setpat('+')
|
||||
engine.revar.set(1)
|
||||
Equal(engine.getprog(), None)
|
||||
self.assertEqual(Mbox.showerror.message,
|
||||
'Error: nothing to repeat at position 0\nPattern: +')
|
||||
|
||||
def test_report_error(self):
|
||||
showerror = Mbox.showerror
|
||||
Equal = self.assertEqual
|
||||
pat = '[a-z'
|
||||
msg = 'unexpected end of regular expression'
|
||||
|
||||
Equal(self.engine.report_error(pat, msg), None)
|
||||
Equal(showerror.title, 'Regular expression error')
|
||||
expected_message = ("Error: " + msg + "\nPattern: [a-z")
|
||||
Equal(showerror.message, expected_message)
|
||||
|
||||
Equal(self.engine.report_error(pat, msg, 5), None)
|
||||
Equal(showerror.title, 'Regular expression error')
|
||||
expected_message += "\nOffset: 5"
|
||||
Equal(showerror.message, expected_message)
|
||||
|
||||
|
||||
class SearchTest(unittest.TestCase):
|
||||
# Test that search_text makes right call to right method.
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
## requires('gui')
|
||||
## cls.root = Tk()
|
||||
## cls.text = Text(master=cls.root)
|
||||
cls.text = mockText()
|
||||
test_text = (
|
||||
'First line\n'
|
||||
'Line with target\n'
|
||||
'Last line\n')
|
||||
cls.text.insert('1.0', test_text)
|
||||
cls.pat = re.compile('target')
|
||||
|
||||
cls.engine = se.SearchEngine(None)
|
||||
cls.engine.search_forward = lambda *args: ('f', args)
|
||||
cls.engine.search_backward = lambda *args: ('b', args)
|
||||
|
||||
## @classmethod
|
||||
## def tearDownClass(cls):
|
||||
## cls.root.destroy()
|
||||
## del cls.root
|
||||
|
||||
def test_search(self):
|
||||
Equal = self.assertEqual
|
||||
engine = self.engine
|
||||
search = engine.search_text
|
||||
text = self.text
|
||||
pat = self.pat
|
||||
|
||||
engine.patvar.set(None)
|
||||
#engine.revar.set(pat)
|
||||
Equal(search(text), None)
|
||||
|
||||
def mark(s):
|
||||
# no selection, cursor after 'Hello'
|
||||
if s == 'insert': return '1.5'
|
||||
raise TclError
|
||||
text.index = mark
|
||||
Equal(search(text, pat), ('f', (text, pat, 1, 5, True, False)))
|
||||
engine.wrapvar.set(False)
|
||||
Equal(search(text, pat), ('f', (text, pat, 1, 5, False, False)))
|
||||
engine.wrapvar.set(True)
|
||||
engine.backvar.set(True)
|
||||
Equal(search(text, pat), ('b', (text, pat, 1, 5, True, False)))
|
||||
engine.backvar.set(False)
|
||||
|
||||
def sel(s):
|
||||
if s == 'sel.first': return '2.10'
|
||||
if s == 'sel.last': return '2.16'
|
||||
raise TclError
|
||||
text.index = sel
|
||||
Equal(search(text, pat), ('f', (text, pat, 2, 16, True, False)))
|
||||
Equal(search(text, pat, True), ('f', (text, pat, 2, 10, True, True)))
|
||||
engine.backvar.set(True)
|
||||
Equal(search(text, pat), ('b', (text, pat, 2, 10, True, False)))
|
||||
Equal(search(text, pat, True), ('b', (text, pat, 2, 16, True, True)))
|
||||
|
||||
|
||||
class ForwardBackwardTest(unittest.TestCase):
|
||||
# Test that search_forward method finds the target.
|
||||
## @classmethod
|
||||
## def tearDownClass(cls):
|
||||
## cls.root.destroy()
|
||||
## del cls.root
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.engine = se.SearchEngine(None)
|
||||
## requires('gui')
|
||||
## cls.root = Tk()
|
||||
## cls.text = Text(master=cls.root)
|
||||
cls.text = mockText()
|
||||
# search_backward calls index('end-1c')
|
||||
cls.text.index = lambda index: '4.0'
|
||||
test_text = (
|
||||
'First line\n'
|
||||
'Line with target\n'
|
||||
'Last line\n')
|
||||
cls.text.insert('1.0', test_text)
|
||||
cls.pat = re.compile('target')
|
||||
cls.res = (2, (10, 16)) # line, slice indexes of 'target'
|
||||
cls.failpat = re.compile('xyz') # not in text
|
||||
cls.emptypat = re.compile(r'\w*') # empty match possible
|
||||
|
||||
def make_search(self, func):
|
||||
def search(pat, line, col, wrap, ok=0):
|
||||
res = func(self.text, pat, line, col, wrap, ok)
|
||||
# res is (line, matchobject) or None
|
||||
return (res[0], res[1].span()) if res else res
|
||||
return search
|
||||
|
||||
def test_search_forward(self):
|
||||
# search for non-empty match
|
||||
Equal = self.assertEqual
|
||||
forward = self.make_search(self.engine.search_forward)
|
||||
pat = self.pat
|
||||
Equal(forward(pat, 1, 0, True), self.res)
|
||||
Equal(forward(pat, 3, 0, True), self.res) # wrap
|
||||
Equal(forward(pat, 3, 0, False), None) # no wrap
|
||||
Equal(forward(pat, 2, 10, False), self.res)
|
||||
|
||||
Equal(forward(self.failpat, 1, 0, True), None)
|
||||
Equal(forward(self.emptypat, 2, 9, True, ok=True), (2, (9, 9)))
|
||||
#Equal(forward(self.emptypat, 2, 9, True), self.res)
|
||||
# While the initial empty match is correctly ignored, skipping
|
||||
# the rest of the line and returning (3, (0,4)) seems buggy - tjr.
|
||||
Equal(forward(self.emptypat, 2, 10, True), self.res)
|
||||
|
||||
def test_search_backward(self):
|
||||
# search for non-empty match
|
||||
Equal = self.assertEqual
|
||||
backward = self.make_search(self.engine.search_backward)
|
||||
pat = self.pat
|
||||
Equal(backward(pat, 3, 5, True), self.res)
|
||||
Equal(backward(pat, 2, 0, True), self.res) # wrap
|
||||
Equal(backward(pat, 2, 0, False), None) # no wrap
|
||||
Equal(backward(pat, 2, 16, False), self.res)
|
||||
|
||||
Equal(backward(self.failpat, 3, 9, True), None)
|
||||
Equal(backward(self.emptypat, 2, 10, True, ok=True), (2, (9,9)))
|
||||
# Accepted because 9 < 10, not because ok=True.
|
||||
# It is not clear that ok=True is useful going back - tjr
|
||||
Equal(backward(self.emptypat, 2, 9, True), (2, (5, 9)))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
509
third_party/python/Lib/idlelib/idle_test/test_squeezer.py
vendored
Normal file
509
third_party/python/Lib/idlelib/idle_test/test_squeezer.py
vendored
Normal file
|
@ -0,0 +1,509 @@
|
|||
from collections import namedtuple
|
||||
from tkinter import Text, Tk
|
||||
import unittest
|
||||
from unittest.mock import Mock, NonCallableMagicMock, patch, sentinel, ANY
|
||||
from test.support import requires
|
||||
|
||||
from idlelib.config import idleConf
|
||||
from idlelib.squeezer import count_lines_with_wrapping, ExpandingButton, \
|
||||
Squeezer
|
||||
from idlelib import macosx
|
||||
from idlelib.textview import view_text
|
||||
from idlelib.tooltip import Hovertip
|
||||
from idlelib.pyshell import PyShell
|
||||
|
||||
|
||||
SENTINEL_VALUE = sentinel.SENTINEL_VALUE
|
||||
|
||||
|
||||
def get_test_tk_root(test_instance):
|
||||
"""Helper for tests: Create a root Tk object."""
|
||||
requires('gui')
|
||||
root = Tk()
|
||||
root.withdraw()
|
||||
|
||||
def cleanup_root():
|
||||
root.update_idletasks()
|
||||
root.destroy()
|
||||
test_instance.addCleanup(cleanup_root)
|
||||
|
||||
return root
|
||||
|
||||
|
||||
class CountLinesTest(unittest.TestCase):
|
||||
"""Tests for the count_lines_with_wrapping function."""
|
||||
def check(self, expected, text, linewidth, tabwidth):
|
||||
return self.assertEqual(
|
||||
expected,
|
||||
count_lines_with_wrapping(text, linewidth, tabwidth),
|
||||
)
|
||||
|
||||
def test_count_empty(self):
|
||||
"""Test with an empty string."""
|
||||
self.assertEqual(count_lines_with_wrapping(""), 0)
|
||||
|
||||
def test_count_begins_with_empty_line(self):
|
||||
"""Test with a string which begins with a newline."""
|
||||
self.assertEqual(count_lines_with_wrapping("\ntext"), 2)
|
||||
|
||||
def test_count_ends_with_empty_line(self):
|
||||
"""Test with a string which ends with a newline."""
|
||||
self.assertEqual(count_lines_with_wrapping("text\n"), 1)
|
||||
|
||||
def test_count_several_lines(self):
|
||||
"""Test with several lines of text."""
|
||||
self.assertEqual(count_lines_with_wrapping("1\n2\n3\n"), 3)
|
||||
|
||||
def test_tab_width(self):
|
||||
"""Test with various tab widths and line widths."""
|
||||
self.check(expected=1, text='\t' * 1, linewidth=8, tabwidth=4)
|
||||
self.check(expected=1, text='\t' * 2, linewidth=8, tabwidth=4)
|
||||
self.check(expected=2, text='\t' * 3, linewidth=8, tabwidth=4)
|
||||
self.check(expected=2, text='\t' * 4, linewidth=8, tabwidth=4)
|
||||
self.check(expected=3, text='\t' * 5, linewidth=8, tabwidth=4)
|
||||
|
||||
# test longer lines and various tab widths
|
||||
self.check(expected=4, text='\t' * 10, linewidth=12, tabwidth=4)
|
||||
self.check(expected=10, text='\t' * 10, linewidth=12, tabwidth=8)
|
||||
self.check(expected=2, text='\t' * 4, linewidth=10, tabwidth=3)
|
||||
|
||||
# test tabwidth=1
|
||||
self.check(expected=2, text='\t' * 9, linewidth=5, tabwidth=1)
|
||||
self.check(expected=2, text='\t' * 10, linewidth=5, tabwidth=1)
|
||||
self.check(expected=3, text='\t' * 11, linewidth=5, tabwidth=1)
|
||||
|
||||
# test for off-by-one errors
|
||||
self.check(expected=2, text='\t' * 6, linewidth=12, tabwidth=4)
|
||||
self.check(expected=3, text='\t' * 6, linewidth=11, tabwidth=4)
|
||||
self.check(expected=2, text='\t' * 6, linewidth=13, tabwidth=4)
|
||||
|
||||
|
||||
class SqueezerTest(unittest.TestCase):
|
||||
"""Tests for the Squeezer class."""
|
||||
def make_mock_editor_window(self):
|
||||
"""Create a mock EditorWindow instance."""
|
||||
editwin = NonCallableMagicMock()
|
||||
# isinstance(editwin, PyShell) must be true for Squeezer to enable
|
||||
# auto-squeezing; in practice this will always be true
|
||||
editwin.__class__ = PyShell
|
||||
return editwin
|
||||
|
||||
def make_squeezer_instance(self, editor_window=None):
|
||||
"""Create an actual Squeezer instance with a mock EditorWindow."""
|
||||
if editor_window is None:
|
||||
editor_window = self.make_mock_editor_window()
|
||||
return Squeezer(editor_window)
|
||||
|
||||
def test_count_lines(self):
|
||||
"""Test Squeezer.count_lines() with various inputs.
|
||||
|
||||
This checks that Squeezer.count_lines() calls the
|
||||
count_lines_with_wrapping() function with the appropriate parameters.
|
||||
"""
|
||||
for tabwidth, linewidth in [(4, 80), (1, 79), (8, 80), (3, 120)]:
|
||||
self._test_count_lines_helper(linewidth=linewidth,
|
||||
tabwidth=tabwidth)
|
||||
|
||||
def _prepare_mock_editwin_for_count_lines(self, editwin,
|
||||
linewidth, tabwidth):
|
||||
"""Prepare a mock EditorWindow object for Squeezer.count_lines."""
|
||||
CHAR_WIDTH = 10
|
||||
BORDER_WIDTH = 2
|
||||
PADDING_WIDTH = 1
|
||||
|
||||
# Prepare all the required functionality on the mock EditorWindow object
|
||||
# so that the calculations in Squeezer.count_lines() can run.
|
||||
editwin.get_tk_tabwidth.return_value = tabwidth
|
||||
editwin.text.winfo_width.return_value = \
|
||||
linewidth * CHAR_WIDTH + 2 * (BORDER_WIDTH + PADDING_WIDTH)
|
||||
text_opts = {
|
||||
'border': BORDER_WIDTH,
|
||||
'padx': PADDING_WIDTH,
|
||||
'font': None,
|
||||
}
|
||||
editwin.text.cget = lambda opt: text_opts[opt]
|
||||
|
||||
# monkey-path tkinter.font.Font with a mock object, so that
|
||||
# Font.measure('0') returns CHAR_WIDTH
|
||||
mock_font = Mock()
|
||||
def measure(char):
|
||||
if char == '0':
|
||||
return CHAR_WIDTH
|
||||
raise ValueError("measure should only be called on '0'!")
|
||||
mock_font.return_value.measure = measure
|
||||
patcher = patch('idlelib.squeezer.Font', mock_font)
|
||||
patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
def _test_count_lines_helper(self, linewidth, tabwidth):
|
||||
"""Helper for test_count_lines."""
|
||||
editwin = self.make_mock_editor_window()
|
||||
self._prepare_mock_editwin_for_count_lines(editwin, linewidth, tabwidth)
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
|
||||
mock_count_lines = Mock(return_value=SENTINEL_VALUE)
|
||||
text = 'TEXT'
|
||||
with patch('idlelib.squeezer.count_lines_with_wrapping',
|
||||
mock_count_lines):
|
||||
self.assertIs(squeezer.count_lines(text), SENTINEL_VALUE)
|
||||
mock_count_lines.assert_called_with(text, linewidth, tabwidth)
|
||||
|
||||
def test_init(self):
|
||||
"""Test the creation of Squeezer instances."""
|
||||
editwin = self.make_mock_editor_window()
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
self.assertIs(squeezer.editwin, editwin)
|
||||
self.assertEqual(squeezer.expandingbuttons, [])
|
||||
|
||||
def test_write_no_tags(self):
|
||||
"""Test Squeezer's overriding of the EditorWindow's write() method."""
|
||||
editwin = self.make_mock_editor_window()
|
||||
for text in ['', 'TEXT', 'LONG TEXT' * 1000, 'MANY_LINES\n' * 100]:
|
||||
editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE)
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
|
||||
self.assertEqual(squeezer.editwin.write(text, ()), SENTINEL_VALUE)
|
||||
self.assertEqual(orig_write.call_count, 1)
|
||||
orig_write.assert_called_with(text, ())
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 0)
|
||||
|
||||
def test_write_not_stdout(self):
|
||||
"""Test Squeezer's overriding of the EditorWindow's write() method."""
|
||||
for text in ['', 'TEXT', 'LONG TEXT' * 1000, 'MANY_LINES\n' * 100]:
|
||||
editwin = self.make_mock_editor_window()
|
||||
editwin.write.return_value = SENTINEL_VALUE
|
||||
orig_write = editwin.write
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
|
||||
self.assertEqual(squeezer.editwin.write(text, "stderr"),
|
||||
SENTINEL_VALUE)
|
||||
self.assertEqual(orig_write.call_count, 1)
|
||||
orig_write.assert_called_with(text, "stderr")
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 0)
|
||||
|
||||
def test_write_stdout(self):
|
||||
"""Test Squeezer's overriding of the EditorWindow's write() method."""
|
||||
editwin = self.make_mock_editor_window()
|
||||
self._prepare_mock_editwin_for_count_lines(editwin,
|
||||
linewidth=80, tabwidth=8)
|
||||
|
||||
for text in ['', 'TEXT']:
|
||||
editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE)
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
squeezer.auto_squeeze_min_lines = 50
|
||||
|
||||
self.assertEqual(squeezer.editwin.write(text, "stdout"),
|
||||
SENTINEL_VALUE)
|
||||
self.assertEqual(orig_write.call_count, 1)
|
||||
orig_write.assert_called_with(text, "stdout")
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 0)
|
||||
|
||||
for text in ['LONG TEXT' * 1000, 'MANY_LINES\n' * 100]:
|
||||
editwin.write = orig_write = Mock(return_value=SENTINEL_VALUE)
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
squeezer.auto_squeeze_min_lines = 50
|
||||
|
||||
self.assertEqual(squeezer.editwin.write(text, "stdout"), None)
|
||||
self.assertEqual(orig_write.call_count, 0)
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 1)
|
||||
|
||||
def test_auto_squeeze(self):
|
||||
"""Test that the auto-squeezing creates an ExpandingButton properly."""
|
||||
root = get_test_tk_root(self)
|
||||
text_widget = Text(root)
|
||||
text_widget.mark_set("iomark", "1.0")
|
||||
|
||||
editwin = self.make_mock_editor_window()
|
||||
editwin.text = text_widget
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
squeezer.auto_squeeze_min_lines = 5
|
||||
squeezer.count_lines = Mock(return_value=6)
|
||||
|
||||
editwin.write('TEXT\n'*6, "stdout")
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), '\n')
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 1)
|
||||
|
||||
def test_squeeze_current_text_event(self):
|
||||
"""Test the squeeze_current_text event."""
|
||||
root = get_test_tk_root(self)
|
||||
|
||||
# squeezing text should work for both stdout and stderr
|
||||
for tag_name in ["stdout", "stderr"]:
|
||||
text_widget = Text(root)
|
||||
text_widget.mark_set("iomark", "1.0")
|
||||
|
||||
editwin = self.make_mock_editor_window()
|
||||
editwin.text = editwin.per.bottom = text_widget
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
squeezer.count_lines = Mock(return_value=6)
|
||||
|
||||
# prepare some text in the Text widget
|
||||
text_widget.insert("1.0", "SOME\nTEXT\n", tag_name)
|
||||
text_widget.mark_set("insert", "1.0")
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
|
||||
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 0)
|
||||
|
||||
# test squeezing the current text
|
||||
retval = squeezer.squeeze_current_text_event(event=Mock())
|
||||
self.assertEqual(retval, "break")
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), '\n\n')
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 1)
|
||||
self.assertEqual(squeezer.expandingbuttons[0].s, 'SOME\nTEXT')
|
||||
|
||||
# test that expanding the squeezed text works and afterwards the
|
||||
# Text widget contains the original text
|
||||
squeezer.expandingbuttons[0].expand(event=Mock())
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 0)
|
||||
|
||||
def test_squeeze_current_text_event_no_allowed_tags(self):
|
||||
"""Test that the event doesn't squeeze text without a relevant tag."""
|
||||
root = get_test_tk_root(self)
|
||||
|
||||
text_widget = Text(root)
|
||||
text_widget.mark_set("iomark", "1.0")
|
||||
|
||||
editwin = self.make_mock_editor_window()
|
||||
editwin.text = editwin.per.bottom = text_widget
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
squeezer.count_lines = Mock(return_value=6)
|
||||
|
||||
# prepare some text in the Text widget
|
||||
text_widget.insert("1.0", "SOME\nTEXT\n", "TAG")
|
||||
text_widget.mark_set("insert", "1.0")
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
|
||||
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 0)
|
||||
|
||||
# test squeezing the current text
|
||||
retval = squeezer.squeeze_current_text_event(event=Mock())
|
||||
self.assertEqual(retval, "break")
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), 'SOME\nTEXT\n\n')
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 0)
|
||||
|
||||
def test_squeeze_text_before_existing_squeezed_text(self):
|
||||
"""Test squeezing text before existing squeezed text."""
|
||||
root = get_test_tk_root(self)
|
||||
|
||||
text_widget = Text(root)
|
||||
text_widget.mark_set("iomark", "1.0")
|
||||
|
||||
editwin = self.make_mock_editor_window()
|
||||
editwin.text = editwin.per.bottom = text_widget
|
||||
squeezer = self.make_squeezer_instance(editwin)
|
||||
squeezer.count_lines = Mock(return_value=6)
|
||||
|
||||
# prepare some text in the Text widget and squeeze it
|
||||
text_widget.insert("1.0", "SOME\nTEXT\n", "stdout")
|
||||
text_widget.mark_set("insert", "1.0")
|
||||
squeezer.squeeze_current_text_event(event=Mock())
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 1)
|
||||
|
||||
# test squeezing the current text
|
||||
text_widget.insert("1.0", "MORE\nSTUFF\n", "stdout")
|
||||
text_widget.mark_set("insert", "1.0")
|
||||
retval = squeezer.squeeze_current_text_event(event=Mock())
|
||||
self.assertEqual(retval, "break")
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), '\n\n\n')
|
||||
self.assertEqual(len(squeezer.expandingbuttons), 2)
|
||||
self.assertTrue(text_widget.compare(
|
||||
squeezer.expandingbuttons[0],
|
||||
'<',
|
||||
squeezer.expandingbuttons[1],
|
||||
))
|
||||
|
||||
GetOptionSignature = namedtuple('GetOptionSignature',
|
||||
'configType section option default type warn_on_default raw')
|
||||
@classmethod
|
||||
def _make_sig(cls, configType, section, option, default=sentinel.NOT_GIVEN,
|
||||
type=sentinel.NOT_GIVEN,
|
||||
warn_on_default=sentinel.NOT_GIVEN,
|
||||
raw=sentinel.NOT_GIVEN):
|
||||
return cls.GetOptionSignature(configType, section, option, default,
|
||||
type, warn_on_default, raw)
|
||||
|
||||
@classmethod
|
||||
def get_GetOption_signature(cls, mock_call_obj):
|
||||
args, kwargs = mock_call_obj[-2:]
|
||||
return cls._make_sig(*args, **kwargs)
|
||||
|
||||
def test_reload(self):
|
||||
"""Test the reload() class-method."""
|
||||
self.assertIsInstance(Squeezer.auto_squeeze_min_lines, int)
|
||||
idleConf.SetOption('main', 'PyShell', 'auto-squeeze-min-lines', '42')
|
||||
Squeezer.reload()
|
||||
self.assertEqual(Squeezer.auto_squeeze_min_lines, 42)
|
||||
|
||||
|
||||
class ExpandingButtonTest(unittest.TestCase):
|
||||
"""Tests for the ExpandingButton class."""
|
||||
# In these tests the squeezer instance is a mock, but actual tkinter
|
||||
# Text and Button instances are created.
|
||||
def make_mock_squeezer(self):
|
||||
"""Helper for tests: Create a mock Squeezer object."""
|
||||
root = get_test_tk_root(self)
|
||||
squeezer = Mock()
|
||||
squeezer.editwin.text = Text(root)
|
||||
|
||||
# Set default values for the configuration settings
|
||||
squeezer.auto_squeeze_min_lines = 50
|
||||
return squeezer
|
||||
|
||||
@patch('idlelib.squeezer.Hovertip', autospec=Hovertip)
|
||||
def test_init(self, MockHovertip):
|
||||
"""Test the simplest creation of an ExpandingButton."""
|
||||
squeezer = self.make_mock_squeezer()
|
||||
text_widget = squeezer.editwin.text
|
||||
|
||||
expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
|
||||
self.assertEqual(expandingbutton.s, 'TEXT')
|
||||
|
||||
# check that the underlying tkinter.Button is properly configured
|
||||
self.assertEqual(expandingbutton.master, text_widget)
|
||||
self.assertTrue('50 lines' in expandingbutton.cget('text'))
|
||||
|
||||
# check that the text widget still contains no text
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), '\n')
|
||||
|
||||
# check that the mouse events are bound
|
||||
self.assertIn('<Double-Button-1>', expandingbutton.bind())
|
||||
right_button_code = '<Button-%s>' % ('2' if macosx.isAquaTk() else '3')
|
||||
self.assertIn(right_button_code, expandingbutton.bind())
|
||||
|
||||
# check that ToolTip was called once, with appropriate values
|
||||
self.assertEqual(MockHovertip.call_count, 1)
|
||||
MockHovertip.assert_called_with(expandingbutton, ANY, hover_delay=ANY)
|
||||
|
||||
# check that 'right-click' appears in the tooltip text
|
||||
tooltip_text = MockHovertip.call_args[0][1]
|
||||
self.assertIn('right-click', tooltip_text.lower())
|
||||
|
||||
def test_expand(self):
|
||||
"""Test the expand event."""
|
||||
squeezer = self.make_mock_squeezer()
|
||||
expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
|
||||
|
||||
# insert the button into the text widget
|
||||
# (this is normally done by the Squeezer class)
|
||||
text_widget = expandingbutton.text
|
||||
text_widget.window_create("1.0", window=expandingbutton)
|
||||
|
||||
# set base_text to the text widget, so that changes are actually made
|
||||
# to it (by ExpandingButton) and we can inspect these changes afterwards
|
||||
expandingbutton.base_text = expandingbutton.text
|
||||
|
||||
# trigger the expand event
|
||||
retval = expandingbutton.expand(event=Mock())
|
||||
self.assertEqual(retval, None)
|
||||
|
||||
# check that the text was inserted into the text widget
|
||||
self.assertEqual(text_widget.get('1.0', 'end'), 'TEXT\n')
|
||||
|
||||
# check that the 'TAGS' tag was set on the inserted text
|
||||
text_end_index = text_widget.index('end-1c')
|
||||
self.assertEqual(text_widget.get('1.0', text_end_index), 'TEXT')
|
||||
self.assertEqual(text_widget.tag_nextrange('TAGS', '1.0'),
|
||||
('1.0', text_end_index))
|
||||
|
||||
# check that the button removed itself from squeezer.expandingbuttons
|
||||
self.assertEqual(squeezer.expandingbuttons.remove.call_count, 1)
|
||||
squeezer.expandingbuttons.remove.assert_called_with(expandingbutton)
|
||||
|
||||
def test_expand_dangerous_oupput(self):
|
||||
"""Test that expanding very long output asks user for confirmation."""
|
||||
squeezer = self.make_mock_squeezer()
|
||||
text = 'a' * 10**5
|
||||
expandingbutton = ExpandingButton(text, 'TAGS', 50, squeezer)
|
||||
expandingbutton.set_is_dangerous()
|
||||
self.assertTrue(expandingbutton.is_dangerous)
|
||||
|
||||
# insert the button into the text widget
|
||||
# (this is normally done by the Squeezer class)
|
||||
text_widget = expandingbutton.text
|
||||
text_widget.window_create("1.0", window=expandingbutton)
|
||||
|
||||
# set base_text to the text widget, so that changes are actually made
|
||||
# to it (by ExpandingButton) and we can inspect these changes afterwards
|
||||
expandingbutton.base_text = expandingbutton.text
|
||||
|
||||
# patch the message box module to always return False
|
||||
with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox:
|
||||
mock_msgbox.askokcancel.return_value = False
|
||||
mock_msgbox.askyesno.return_value = False
|
||||
|
||||
# trigger the expand event
|
||||
retval = expandingbutton.expand(event=Mock())
|
||||
|
||||
# check that the event chain was broken and no text was inserted
|
||||
self.assertEqual(retval, 'break')
|
||||
self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), '')
|
||||
|
||||
# patch the message box module to always return True
|
||||
with patch('idlelib.squeezer.tkMessageBox') as mock_msgbox:
|
||||
mock_msgbox.askokcancel.return_value = True
|
||||
mock_msgbox.askyesno.return_value = True
|
||||
|
||||
# trigger the expand event
|
||||
retval = expandingbutton.expand(event=Mock())
|
||||
|
||||
# check that the event chain wasn't broken and the text was inserted
|
||||
self.assertEqual(retval, None)
|
||||
self.assertEqual(expandingbutton.text.get('1.0', 'end-1c'), text)
|
||||
|
||||
def test_copy(self):
|
||||
"""Test the copy event."""
|
||||
# testing with the actual clipboard proved problematic, so this test
|
||||
# replaces the clipboard manipulation functions with mocks and checks
|
||||
# that they are called appropriately
|
||||
squeezer = self.make_mock_squeezer()
|
||||
expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
|
||||
expandingbutton.clipboard_clear = Mock()
|
||||
expandingbutton.clipboard_append = Mock()
|
||||
|
||||
# trigger the copy event
|
||||
retval = expandingbutton.copy(event=Mock())
|
||||
self.assertEqual(retval, None)
|
||||
|
||||
# check that the expanding button called clipboard_clear() and
|
||||
# clipboard_append('TEXT') once each
|
||||
self.assertEqual(expandingbutton.clipboard_clear.call_count, 1)
|
||||
self.assertEqual(expandingbutton.clipboard_append.call_count, 1)
|
||||
expandingbutton.clipboard_append.assert_called_with('TEXT')
|
||||
|
||||
def test_view(self):
|
||||
"""Test the view event."""
|
||||
squeezer = self.make_mock_squeezer()
|
||||
expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
|
||||
expandingbutton.selection_own = Mock()
|
||||
|
||||
with patch('idlelib.squeezer.view_text', autospec=view_text)\
|
||||
as mock_view_text:
|
||||
# trigger the view event
|
||||
expandingbutton.view(event=Mock())
|
||||
|
||||
# check that the expanding button called view_text
|
||||
self.assertEqual(mock_view_text.call_count, 1)
|
||||
|
||||
# check that the proper text was passed
|
||||
self.assertEqual(mock_view_text.call_args[0][2], 'TEXT')
|
||||
|
||||
def test_rmenu(self):
|
||||
"""Test the context menu."""
|
||||
squeezer = self.make_mock_squeezer()
|
||||
expandingbutton = ExpandingButton('TEXT', 'TAGS', 50, squeezer)
|
||||
with patch('tkinter.Menu') as mock_Menu:
|
||||
mock_menu = Mock()
|
||||
mock_Menu.return_value = mock_menu
|
||||
mock_event = Mock()
|
||||
mock_event.x = 10
|
||||
mock_event.y = 10
|
||||
expandingbutton.context_menu_event(event=mock_event)
|
||||
self.assertEqual(mock_menu.add_command.call_count,
|
||||
len(expandingbutton.rmenu_specs))
|
||||
for label, *data in expandingbutton.rmenu_specs:
|
||||
mock_menu.add_command.assert_any_call(label=label, command=ANY)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
47
third_party/python/Lib/idlelib/idle_test/test_stackviewer.py
vendored
Normal file
47
third_party/python/Lib/idlelib/idle_test/test_stackviewer.py
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
"Test stackviewer, coverage 63%."
|
||||
|
||||
from idlelib import stackviewer
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
from idlelib.tree import TreeNode, ScrolledCanvas
|
||||
import sys
|
||||
|
||||
|
||||
class StackBrowserTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
svs = stackviewer.sys
|
||||
try:
|
||||
abc
|
||||
except NameError:
|
||||
svs.last_type, svs.last_value, svs.last_traceback = (
|
||||
sys.exc_info())
|
||||
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
svs = stackviewer.sys
|
||||
del svs.last_traceback, svs.last_type, svs.last_value
|
||||
|
||||
cls.root.update_idletasks()
|
||||
## for id in cls.root.tk.call('after', 'info'):
|
||||
## cls.root.after_cancel(id) # Need for EditorWindow.
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
sb = stackviewer.StackBrowser(self.root)
|
||||
isi = self.assertIsInstance
|
||||
isi(stackviewer.sc, ScrolledCanvas)
|
||||
isi(stackviewer.item, stackviewer.StackTreeItem)
|
||||
isi(stackviewer.node, TreeNode)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
41
third_party/python/Lib/idlelib/idle_test/test_statusbar.py
vendored
Normal file
41
third_party/python/Lib/idlelib/idle_test/test_statusbar.py
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
"Test statusbar, coverage 100%."
|
||||
|
||||
from idlelib import statusbar
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
bar = statusbar.MultiStatusBar(self.root)
|
||||
self.assertEqual(bar.labels, {})
|
||||
|
||||
def test_set_label(self):
|
||||
bar = statusbar.MultiStatusBar(self.root)
|
||||
bar.set_label('left', text='sometext', width=10)
|
||||
self.assertIn('left', bar.labels)
|
||||
left = bar.labels['left']
|
||||
self.assertEqual(left['text'], 'sometext')
|
||||
self.assertEqual(left['width'], 10)
|
||||
bar.set_label('left', text='revised text')
|
||||
self.assertEqual(left['text'], 'revised text')
|
||||
bar.set_label('right', text='correct text')
|
||||
self.assertEqual(bar.labels['right']['text'], 'correct text')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
236
third_party/python/Lib/idlelib/idle_test/test_text.py
vendored
Normal file
236
third_party/python/Lib/idlelib/idle_test/test_text.py
vendored
Normal file
|
@ -0,0 +1,236 @@
|
|||
''' Test mock_tk.Text class against tkinter.Text class
|
||||
|
||||
Run same tests with both by creating a mixin class.
|
||||
'''
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from _tkinter import TclError
|
||||
|
||||
class TextTest(object):
|
||||
"Define items common to both sets of tests."
|
||||
|
||||
hw = 'hello\nworld' # Several tests insert this after initialization.
|
||||
hwn = hw+'\n' # \n present at initialization, before insert
|
||||
|
||||
# setUpClass defines cls.Text and maybe cls.root.
|
||||
# setUp defines self.text from Text and maybe root.
|
||||
|
||||
def test_init(self):
|
||||
self.assertEqual(self.text.get('1.0'), '\n')
|
||||
self.assertEqual(self.text.get('end'), '')
|
||||
|
||||
def test_index_empty(self):
|
||||
index = self.text.index
|
||||
|
||||
for dex in (-1.0, 0.3, '1.-1', '1.0', '1.0 lineend', '1.end', '1.33',
|
||||
'insert'):
|
||||
self.assertEqual(index(dex), '1.0')
|
||||
|
||||
for dex in 'end', 2.0, '2.1', '33.44':
|
||||
self.assertEqual(index(dex), '2.0')
|
||||
|
||||
def test_index_data(self):
|
||||
index = self.text.index
|
||||
self.text.insert('1.0', self.hw)
|
||||
|
||||
for dex in -1.0, 0.3, '1.-1', '1.0':
|
||||
self.assertEqual(index(dex), '1.0')
|
||||
|
||||
for dex in '1.0 lineend', '1.end', '1.33':
|
||||
self.assertEqual(index(dex), '1.5')
|
||||
|
||||
for dex in 'end', '33.44':
|
||||
self.assertEqual(index(dex), '3.0')
|
||||
|
||||
def test_get(self):
|
||||
get = self.text.get
|
||||
Equal = self.assertEqual
|
||||
self.text.insert('1.0', self.hw)
|
||||
|
||||
Equal(get('end'), '')
|
||||
Equal(get('end', 'end'), '')
|
||||
Equal(get('1.0'), 'h')
|
||||
Equal(get('1.0', '1.1'), 'h')
|
||||
Equal(get('1.0', '1.3'), 'hel')
|
||||
Equal(get('1.1', '1.3'), 'el')
|
||||
Equal(get('1.0', '1.0 lineend'), 'hello')
|
||||
Equal(get('1.0', '1.10'), 'hello')
|
||||
Equal(get('1.0 lineend'), '\n')
|
||||
Equal(get('1.1', '2.3'), 'ello\nwor')
|
||||
Equal(get('1.0', '2.5'), self.hw)
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
Equal(get('0.0', '5.0'), self.hwn)
|
||||
|
||||
def test_insert(self):
|
||||
insert = self.text.insert
|
||||
get = self.text.get
|
||||
Equal = self.assertEqual
|
||||
|
||||
insert('1.0', self.hw)
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
|
||||
insert('1.0', '') # nothing
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
|
||||
insert('1.0', '*')
|
||||
Equal(get('1.0', 'end'), '*hello\nworld\n')
|
||||
|
||||
insert('1.0 lineend', '*')
|
||||
Equal(get('1.0', 'end'), '*hello*\nworld\n')
|
||||
|
||||
insert('2.3', '*')
|
||||
Equal(get('1.0', 'end'), '*hello*\nwor*ld\n')
|
||||
|
||||
insert('end', 'x')
|
||||
Equal(get('1.0', 'end'), '*hello*\nwor*ldx\n')
|
||||
|
||||
insert('1.4', 'x\n')
|
||||
Equal(get('1.0', 'end'), '*helx\nlo*\nwor*ldx\n')
|
||||
|
||||
def test_no_delete(self):
|
||||
# if index1 == 'insert' or 'end' or >= end, there is no deletion
|
||||
delete = self.text.delete
|
||||
get = self.text.get
|
||||
Equal = self.assertEqual
|
||||
self.text.insert('1.0', self.hw)
|
||||
|
||||
delete('insert')
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
|
||||
delete('end')
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
|
||||
delete('insert', 'end')
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
|
||||
delete('insert', '5.5')
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
|
||||
delete('1.4', '1.0')
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
|
||||
delete('1.4', '1.4')
|
||||
Equal(get('1.0', 'end'), self.hwn)
|
||||
|
||||
def test_delete_char(self):
|
||||
delete = self.text.delete
|
||||
get = self.text.get
|
||||
Equal = self.assertEqual
|
||||
self.text.insert('1.0', self.hw)
|
||||
|
||||
delete('1.0')
|
||||
Equal(get('1.0', '1.end'), 'ello')
|
||||
|
||||
delete('1.0', '1.1')
|
||||
Equal(get('1.0', '1.end'), 'llo')
|
||||
|
||||
# delete \n and combine 2 lines into 1
|
||||
delete('1.end')
|
||||
Equal(get('1.0', '1.end'), 'lloworld')
|
||||
|
||||
self.text.insert('1.3', '\n')
|
||||
delete('1.10')
|
||||
Equal(get('1.0', '1.end'), 'lloworld')
|
||||
|
||||
self.text.insert('1.3', '\n')
|
||||
delete('1.3', '2.0')
|
||||
Equal(get('1.0', '1.end'), 'lloworld')
|
||||
|
||||
def test_delete_slice(self):
|
||||
delete = self.text.delete
|
||||
get = self.text.get
|
||||
Equal = self.assertEqual
|
||||
self.text.insert('1.0', self.hw)
|
||||
|
||||
delete('1.0', '1.0 lineend')
|
||||
Equal(get('1.0', 'end'), '\nworld\n')
|
||||
|
||||
delete('1.0', 'end')
|
||||
Equal(get('1.0', 'end'), '\n')
|
||||
|
||||
self.text.insert('1.0', self.hw)
|
||||
delete('1.0', '2.0')
|
||||
Equal(get('1.0', 'end'), 'world\n')
|
||||
|
||||
delete('1.0', 'end')
|
||||
Equal(get('1.0', 'end'), '\n')
|
||||
|
||||
self.text.insert('1.0', self.hw)
|
||||
delete('1.2', '2.3')
|
||||
Equal(get('1.0', 'end'), 'held\n')
|
||||
|
||||
def test_multiple_lines(self): # insert and delete
|
||||
self.text.insert('1.0', 'hello')
|
||||
|
||||
self.text.insert('1.3', '1\n2\n3\n4\n5')
|
||||
self.assertEqual(self.text.get('1.0', 'end'), 'hel1\n2\n3\n4\n5lo\n')
|
||||
|
||||
self.text.delete('1.3', '5.1')
|
||||
self.assertEqual(self.text.get('1.0', 'end'), 'hello\n')
|
||||
|
||||
def test_compare(self):
|
||||
compare = self.text.compare
|
||||
Equal = self.assertEqual
|
||||
# need data so indexes not squished to 1,0
|
||||
self.text.insert('1.0', 'First\nSecond\nThird\n')
|
||||
|
||||
self.assertRaises(TclError, compare, '2.2', 'op', '2.2')
|
||||
|
||||
for op, less1, less0, equal, greater0, greater1 in (
|
||||
('<', True, True, False, False, False),
|
||||
('<=', True, True, True, False, False),
|
||||
('>', False, False, False, True, True),
|
||||
('>=', False, False, True, True, True),
|
||||
('==', False, False, True, False, False),
|
||||
('!=', True, True, False, True, True),
|
||||
):
|
||||
Equal(compare('1.1', op, '2.2'), less1, op)
|
||||
Equal(compare('2.1', op, '2.2'), less0, op)
|
||||
Equal(compare('2.2', op, '2.2'), equal, op)
|
||||
Equal(compare('2.3', op, '2.2'), greater0, op)
|
||||
Equal(compare('3.3', op, '2.2'), greater1, op)
|
||||
|
||||
|
||||
class MockTextTest(TextTest, unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
from idlelib.idle_test.mock_tk import Text
|
||||
cls.Text = Text
|
||||
|
||||
def setUp(self):
|
||||
self.text = self.Text()
|
||||
|
||||
|
||||
def test_decode(self):
|
||||
# test endflags (-1, 0) not tested by test_index (which uses +1)
|
||||
decode = self.text._decode
|
||||
Equal = self.assertEqual
|
||||
self.text.insert('1.0', self.hw)
|
||||
|
||||
Equal(decode('end', -1), (2, 5))
|
||||
Equal(decode('3.1', -1), (2, 5))
|
||||
Equal(decode('end', 0), (2, 6))
|
||||
Equal(decode('3.1', 0), (2, 6))
|
||||
|
||||
|
||||
class TkTextTest(TextTest, unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
from tkinter import Tk, Text
|
||||
cls.Text = Text
|
||||
cls.root = Tk()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.text = self.Text(self.root)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=False)
|
181
third_party/python/Lib/idlelib/idle_test/test_textview.py
vendored
Normal file
181
third_party/python/Lib/idlelib/idle_test/test_textview.py
vendored
Normal file
|
@ -0,0 +1,181 @@
|
|||
"""Test textview, coverage 100%.
|
||||
|
||||
Since all methods and functions create (or destroy) a ViewWindow, which
|
||||
is a widget containing a widget, etcetera, all tests must be gui tests.
|
||||
Using mock Text would not change this. Other mocks are used to retrieve
|
||||
information about calls.
|
||||
"""
|
||||
from idlelib import textview as tv
|
||||
import unittest
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
|
||||
import os
|
||||
from tkinter import Tk
|
||||
from tkinter.ttk import Button
|
||||
from idlelib.idle_test.mock_idle import Func
|
||||
from idlelib.idle_test.mock_tk import Mbox_func
|
||||
|
||||
def setUpModule():
|
||||
global root
|
||||
root = Tk()
|
||||
root.withdraw()
|
||||
|
||||
def tearDownModule():
|
||||
global root
|
||||
root.update_idletasks()
|
||||
root.destroy()
|
||||
del root
|
||||
|
||||
# If we call ViewWindow or wrapper functions with defaults
|
||||
# modal=True, _utest=False, test hangs on call to wait_window.
|
||||
# Have also gotten tk error 'can't invoke "event" command'.
|
||||
|
||||
|
||||
class VW(tv.ViewWindow): # Used in ViewWindowTest.
|
||||
transient = Func()
|
||||
grab_set = Func()
|
||||
wait_window = Func()
|
||||
|
||||
|
||||
# Call wrapper class VW with mock wait_window.
|
||||
class ViewWindowTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
VW.transient.__init__()
|
||||
VW.grab_set.__init__()
|
||||
VW.wait_window.__init__()
|
||||
|
||||
def test_init_modal(self):
|
||||
view = VW(root, 'Title', 'test text')
|
||||
self.assertTrue(VW.transient.called)
|
||||
self.assertTrue(VW.grab_set.called)
|
||||
self.assertTrue(VW.wait_window.called)
|
||||
view.ok()
|
||||
|
||||
def test_init_nonmodal(self):
|
||||
view = VW(root, 'Title', 'test text', modal=False)
|
||||
self.assertFalse(VW.transient.called)
|
||||
self.assertFalse(VW.grab_set.called)
|
||||
self.assertFalse(VW.wait_window.called)
|
||||
view.ok()
|
||||
|
||||
def test_ok(self):
|
||||
view = VW(root, 'Title', 'test text', modal=False)
|
||||
view.destroy = Func()
|
||||
view.ok()
|
||||
self.assertTrue(view.destroy.called)
|
||||
del view.destroy # Unmask real function.
|
||||
view.destroy()
|
||||
|
||||
|
||||
class TextFrameTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = root = Tk()
|
||||
root.withdraw()
|
||||
cls.frame = tv.TextFrame(root, 'test text')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
del cls.frame
|
||||
cls.root.update_idletasks()
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_line1(self):
|
||||
get = self.frame.text.get
|
||||
self.assertEqual(get('1.0', '1.end'), 'test text')
|
||||
|
||||
|
||||
# Call ViewWindow with modal=False.
|
||||
class ViewFunctionTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.orig_error = tv.showerror
|
||||
tv.showerror = Mbox_func()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
tv.showerror = cls.orig_error
|
||||
del cls.orig_error
|
||||
|
||||
def test_view_text(self):
|
||||
view = tv.view_text(root, 'Title', 'test text', modal=False)
|
||||
self.assertIsInstance(view, tv.ViewWindow)
|
||||
self.assertIsInstance(view.viewframe, tv.ViewFrame)
|
||||
view.viewframe.ok()
|
||||
|
||||
def test_view_file(self):
|
||||
view = tv.view_file(root, 'Title', __file__, 'ascii', modal=False)
|
||||
self.assertIsInstance(view, tv.ViewWindow)
|
||||
self.assertIsInstance(view.viewframe, tv.ViewFrame)
|
||||
get = view.viewframe.textframe.text.get
|
||||
self.assertIn('Test', get('1.0', '1.end'))
|
||||
view.ok()
|
||||
|
||||
def test_bad_file(self):
|
||||
# Mock showerror will be used; view_file will return None.
|
||||
view = tv.view_file(root, 'Title', 'abc.xyz', 'ascii', modal=False)
|
||||
self.assertIsNone(view)
|
||||
self.assertEqual(tv.showerror.title, 'File Load Error')
|
||||
|
||||
def test_bad_encoding(self):
|
||||
p = os.path
|
||||
fn = p.abspath(p.join(p.dirname(__file__), '..', 'CREDITS.txt'))
|
||||
view = tv.view_file(root, 'Title', fn, 'ascii', modal=False)
|
||||
self.assertIsNone(view)
|
||||
self.assertEqual(tv.showerror.title, 'Unicode Decode Error')
|
||||
|
||||
def test_nowrap(self):
|
||||
view = tv.view_text(root, 'Title', 'test', modal=False, wrap='none')
|
||||
text_widget = view.viewframe.textframe.text
|
||||
self.assertEqual(text_widget.cget('wrap'), 'none')
|
||||
|
||||
|
||||
# Call ViewWindow with _utest=True.
|
||||
class ButtonClickTest(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.view = None
|
||||
self.called = False
|
||||
|
||||
def tearDown(self):
|
||||
if self.view:
|
||||
self.view.destroy()
|
||||
|
||||
def test_view_text_bind_with_button(self):
|
||||
def _command():
|
||||
self.called = True
|
||||
self.view = tv.view_text(root, 'TITLE_TEXT', 'COMMAND', _utest=True)
|
||||
button = Button(root, text='BUTTON', command=_command)
|
||||
button.invoke()
|
||||
self.addCleanup(button.destroy)
|
||||
|
||||
self.assertEqual(self.called, True)
|
||||
self.assertEqual(self.view.title(), 'TITLE_TEXT')
|
||||
self.assertEqual(self.view.viewframe.textframe.text.get('1.0', '1.end'),
|
||||
'COMMAND')
|
||||
|
||||
def test_view_file_bind_with_button(self):
|
||||
def _command():
|
||||
self.called = True
|
||||
self.view = tv.view_file(root, 'TITLE_FILE', __file__,
|
||||
encoding='ascii', _utest=True)
|
||||
button = Button(root, text='BUTTON', command=_command)
|
||||
button.invoke()
|
||||
self.addCleanup(button.destroy)
|
||||
|
||||
self.assertEqual(self.called, True)
|
||||
self.assertEqual(self.view.title(), 'TITLE_FILE')
|
||||
get = self.view.viewframe.textframe.text.get
|
||||
with open(__file__) as f:
|
||||
self.assertEqual(get('1.0', '1.end'), f.readline().strip())
|
||||
f.readline()
|
||||
self.assertEqual(get('3.0', '3.end'), f.readline().strip())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
146
third_party/python/Lib/idlelib/idle_test/test_tooltip.py
vendored
Normal file
146
third_party/python/Lib/idlelib/idle_test/test_tooltip.py
vendored
Normal file
|
@ -0,0 +1,146 @@
|
|||
from idlelib.tooltip import TooltipBase, Hovertip
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
|
||||
from functools import wraps
|
||||
import time
|
||||
from tkinter import Button, Tk, Toplevel
|
||||
import unittest
|
||||
|
||||
|
||||
def setUpModule():
|
||||
global root
|
||||
root = Tk()
|
||||
|
||||
def root_update():
|
||||
global root
|
||||
root.update()
|
||||
|
||||
def tearDownModule():
|
||||
global root
|
||||
root.update_idletasks()
|
||||
root.destroy()
|
||||
del root
|
||||
|
||||
def add_call_counting(func):
|
||||
@wraps(func)
|
||||
def wrapped_func(*args, **kwargs):
|
||||
wrapped_func.call_args_list.append((args, kwargs))
|
||||
return func(*args, **kwargs)
|
||||
wrapped_func.call_args_list = []
|
||||
return wrapped_func
|
||||
|
||||
|
||||
def _make_top_and_button(testobj):
|
||||
global root
|
||||
top = Toplevel(root)
|
||||
testobj.addCleanup(top.destroy)
|
||||
top.title("Test tooltip")
|
||||
button = Button(top, text='ToolTip test button')
|
||||
button.pack()
|
||||
testobj.addCleanup(button.destroy)
|
||||
top.lift()
|
||||
return top, button
|
||||
|
||||
|
||||
class ToolTipBaseTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.top, self.button = _make_top_and_button(self)
|
||||
|
||||
def test_base_class_is_unusable(self):
|
||||
global root
|
||||
top = Toplevel(root)
|
||||
self.addCleanup(top.destroy)
|
||||
|
||||
button = Button(top, text='ToolTip test button')
|
||||
button.pack()
|
||||
self.addCleanup(button.destroy)
|
||||
|
||||
with self.assertRaises(NotImplementedError):
|
||||
tooltip = TooltipBase(button)
|
||||
tooltip.showtip()
|
||||
|
||||
|
||||
class HovertipTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.top, self.button = _make_top_and_button(self)
|
||||
|
||||
def test_showtip(self):
|
||||
tooltip = Hovertip(self.button, 'ToolTip text')
|
||||
self.addCleanup(tooltip.hidetip)
|
||||
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
tooltip.showtip()
|
||||
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
|
||||
def test_showtip_twice(self):
|
||||
tooltip = Hovertip(self.button, 'ToolTip text')
|
||||
self.addCleanup(tooltip.hidetip)
|
||||
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
tooltip.showtip()
|
||||
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
orig_tipwindow = tooltip.tipwindow
|
||||
tooltip.showtip()
|
||||
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
self.assertIs(tooltip.tipwindow, orig_tipwindow)
|
||||
|
||||
def test_hidetip(self):
|
||||
tooltip = Hovertip(self.button, 'ToolTip text')
|
||||
self.addCleanup(tooltip.hidetip)
|
||||
tooltip.showtip()
|
||||
tooltip.hidetip()
|
||||
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
|
||||
def test_showtip_on_mouse_enter_no_delay(self):
|
||||
tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None)
|
||||
self.addCleanup(tooltip.hidetip)
|
||||
tooltip.showtip = add_call_counting(tooltip.showtip)
|
||||
root_update()
|
||||
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
self.button.event_generate('<Enter>', x=0, y=0)
|
||||
root_update()
|
||||
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
self.assertGreater(len(tooltip.showtip.call_args_list), 0)
|
||||
|
||||
def test_showtip_on_mouse_enter_hover_delay(self):
|
||||
tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=50)
|
||||
self.addCleanup(tooltip.hidetip)
|
||||
tooltip.showtip = add_call_counting(tooltip.showtip)
|
||||
root_update()
|
||||
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
self.button.event_generate('<Enter>', x=0, y=0)
|
||||
root_update()
|
||||
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
time.sleep(0.1)
|
||||
root_update()
|
||||
self.assertTrue(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
self.assertGreater(len(tooltip.showtip.call_args_list), 0)
|
||||
|
||||
def test_hidetip_on_mouse_leave(self):
|
||||
tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=None)
|
||||
self.addCleanup(tooltip.hidetip)
|
||||
tooltip.showtip = add_call_counting(tooltip.showtip)
|
||||
root_update()
|
||||
self.button.event_generate('<Enter>', x=0, y=0)
|
||||
root_update()
|
||||
self.button.event_generate('<Leave>', x=0, y=0)
|
||||
root_update()
|
||||
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
self.assertGreater(len(tooltip.showtip.call_args_list), 0)
|
||||
|
||||
def test_dont_show_on_mouse_leave_before_delay(self):
|
||||
tooltip = Hovertip(self.button, 'ToolTip text', hover_delay=50)
|
||||
self.addCleanup(tooltip.hidetip)
|
||||
tooltip.showtip = add_call_counting(tooltip.showtip)
|
||||
root_update()
|
||||
self.button.event_generate('<Enter>', x=0, y=0)
|
||||
root_update()
|
||||
self.button.event_generate('<Leave>', x=0, y=0)
|
||||
root_update()
|
||||
time.sleep(0.1)
|
||||
root_update()
|
||||
self.assertFalse(tooltip.tipwindow and tooltip.tipwindow.winfo_viewable())
|
||||
self.assertEqual(tooltip.showtip.call_args_list, [])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
33
third_party/python/Lib/idlelib/idle_test/test_tree.py
vendored
Normal file
33
third_party/python/Lib/idlelib/idle_test/test_tree.py
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
"Test tree. coverage 56%."
|
||||
|
||||
from idlelib import tree
|
||||
import unittest
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
from tkinter import Tk
|
||||
|
||||
|
||||
class TreeTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
# Start with code slightly adapted from htest.
|
||||
sc = tree.ScrolledCanvas(
|
||||
self.root, bg="white", highlightthickness=0, takefocus=1)
|
||||
sc.frame.pack(expand=1, fill="both", side='left')
|
||||
item = tree.FileTreeItem(tree.ICONDIR)
|
||||
node = tree.TreeNode(sc.canvas, None, item)
|
||||
node.expand()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
135
third_party/python/Lib/idlelib/idle_test/test_undo.py
vendored
Normal file
135
third_party/python/Lib/idlelib/idle_test/test_undo.py
vendored
Normal file
|
@ -0,0 +1,135 @@
|
|||
"Test undo, coverage 77%."
|
||||
# Only test UndoDelegator so far.
|
||||
|
||||
from idlelib.undo import UndoDelegator
|
||||
import unittest
|
||||
from test.support import requires
|
||||
requires('gui')
|
||||
|
||||
from unittest.mock import Mock
|
||||
from tkinter import Text, Tk
|
||||
from idlelib.percolator import Percolator
|
||||
|
||||
|
||||
class UndoDelegatorTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.root = Tk()
|
||||
cls.text = Text(cls.root)
|
||||
cls.percolator = Percolator(cls.text)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.percolator.redir.close()
|
||||
del cls.percolator, cls.text
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def setUp(self):
|
||||
self.delegator = UndoDelegator()
|
||||
self.delegator.bell = Mock()
|
||||
self.percolator.insertfilter(self.delegator)
|
||||
|
||||
def tearDown(self):
|
||||
self.percolator.removefilter(self.delegator)
|
||||
self.text.delete('1.0', 'end')
|
||||
self.delegator.resetcache()
|
||||
|
||||
def test_undo_event(self):
|
||||
text = self.text
|
||||
|
||||
text.insert('insert', 'foobar')
|
||||
text.insert('insert', 'h')
|
||||
text.event_generate('<<undo>>')
|
||||
self.assertEqual(text.get('1.0', 'end'), '\n')
|
||||
|
||||
text.insert('insert', 'foo')
|
||||
text.insert('insert', 'bar')
|
||||
text.delete('1.2', '1.4')
|
||||
text.insert('insert', 'hello')
|
||||
text.event_generate('<<undo>>')
|
||||
self.assertEqual(text.get('1.0', '1.4'), 'foar')
|
||||
text.event_generate('<<undo>>')
|
||||
self.assertEqual(text.get('1.0', '1.6'), 'foobar')
|
||||
text.event_generate('<<undo>>')
|
||||
self.assertEqual(text.get('1.0', '1.3'), 'foo')
|
||||
text.event_generate('<<undo>>')
|
||||
self.delegator.undo_event('event')
|
||||
self.assertTrue(self.delegator.bell.called)
|
||||
|
||||
def test_redo_event(self):
|
||||
text = self.text
|
||||
|
||||
text.insert('insert', 'foo')
|
||||
text.insert('insert', 'bar')
|
||||
text.delete('1.0', '1.3')
|
||||
text.event_generate('<<undo>>')
|
||||
text.event_generate('<<redo>>')
|
||||
self.assertEqual(text.get('1.0', '1.3'), 'bar')
|
||||
text.event_generate('<<redo>>')
|
||||
self.assertTrue(self.delegator.bell.called)
|
||||
|
||||
def test_dump_event(self):
|
||||
"""
|
||||
Dump_event cannot be tested directly without changing
|
||||
environment variables. So, test statements in dump_event
|
||||
indirectly
|
||||
"""
|
||||
text = self.text
|
||||
d = self.delegator
|
||||
|
||||
text.insert('insert', 'foo')
|
||||
text.insert('insert', 'bar')
|
||||
text.delete('1.2', '1.4')
|
||||
self.assertTupleEqual((d.pointer, d.can_merge), (3, True))
|
||||
text.event_generate('<<undo>>')
|
||||
self.assertTupleEqual((d.pointer, d.can_merge), (2, False))
|
||||
|
||||
def test_get_set_saved(self):
|
||||
# test the getter method get_saved
|
||||
# test the setter method set_saved
|
||||
# indirectly test check_saved
|
||||
d = self.delegator
|
||||
|
||||
self.assertTrue(d.get_saved())
|
||||
self.text.insert('insert', 'a')
|
||||
self.assertFalse(d.get_saved())
|
||||
d.saved_change_hook = Mock()
|
||||
|
||||
d.set_saved(True)
|
||||
self.assertEqual(d.pointer, d.saved)
|
||||
self.assertTrue(d.saved_change_hook.called)
|
||||
|
||||
d.set_saved(False)
|
||||
self.assertEqual(d.saved, -1)
|
||||
self.assertTrue(d.saved_change_hook.called)
|
||||
|
||||
def test_undo_start_stop(self):
|
||||
# test the undo_block_start and undo_block_stop methods
|
||||
text = self.text
|
||||
|
||||
text.insert('insert', 'foo')
|
||||
self.delegator.undo_block_start()
|
||||
text.insert('insert', 'bar')
|
||||
text.insert('insert', 'bar')
|
||||
self.delegator.undo_block_stop()
|
||||
self.assertEqual(text.get('1.0', '1.3'), 'foo')
|
||||
|
||||
# test another code path
|
||||
self.delegator.undo_block_start()
|
||||
text.insert('insert', 'bar')
|
||||
self.delegator.undo_block_stop()
|
||||
self.assertEqual(text.get('1.0', '1.3'), 'foo')
|
||||
|
||||
def test_addcmd(self):
|
||||
text = self.text
|
||||
# when number of undo operations exceeds max_undo
|
||||
self.delegator.max_undo = max_undo = 10
|
||||
for i in range(max_undo + 10):
|
||||
text.insert('insert', 'foo')
|
||||
self.assertLessEqual(len(self.delegator.undolist), max_undo)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2, exit=False)
|
73
third_party/python/Lib/idlelib/idle_test/test_warning.py
vendored
Normal file
73
third_party/python/Lib/idlelib/idle_test/test_warning.py
vendored
Normal file
|
@ -0,0 +1,73 @@
|
|||
'''Test warnings replacement in pyshell.py and run.py.
|
||||
|
||||
This file could be expanded to include traceback overrides
|
||||
(in same two modules). If so, change name.
|
||||
Revise if output destination changes (http://bugs.python.org/issue18318).
|
||||
Make sure warnings module is left unaltered (http://bugs.python.org/issue18081).
|
||||
'''
|
||||
from idlelib import run
|
||||
from idlelib import pyshell as shell
|
||||
import unittest
|
||||
from test.support import captured_stderr
|
||||
import warnings
|
||||
|
||||
# Try to capture default showwarning before Idle modules are imported.
|
||||
showwarning = warnings.showwarning
|
||||
# But if we run this file within idle, we are in the middle of the run.main loop
|
||||
# and default showwarnings has already been replaced.
|
||||
running_in_idle = 'idle' in showwarning.__name__
|
||||
|
||||
# The following was generated from pyshell.idle_formatwarning
|
||||
# and checked as matching expectation.
|
||||
idlemsg = '''
|
||||
Warning (from warnings module):
|
||||
File "test_warning.py", line 99
|
||||
Line of code
|
||||
UserWarning: Test
|
||||
'''
|
||||
shellmsg = idlemsg + ">>> "
|
||||
|
||||
|
||||
class RunWarnTest(unittest.TestCase):
|
||||
|
||||
@unittest.skipIf(running_in_idle, "Does not work when run within Idle.")
|
||||
def test_showwarnings(self):
|
||||
self.assertIs(warnings.showwarning, showwarning)
|
||||
run.capture_warnings(True)
|
||||
self.assertIs(warnings.showwarning, run.idle_showwarning_subproc)
|
||||
run.capture_warnings(False)
|
||||
self.assertIs(warnings.showwarning, showwarning)
|
||||
|
||||
def test_run_show(self):
|
||||
with captured_stderr() as f:
|
||||
run.idle_showwarning_subproc(
|
||||
'Test', UserWarning, 'test_warning.py', 99, f, 'Line of code')
|
||||
# The following uses .splitlines to erase line-ending differences
|
||||
self.assertEqual(idlemsg.splitlines(), f.getvalue().splitlines())
|
||||
|
||||
|
||||
class ShellWarnTest(unittest.TestCase):
|
||||
|
||||
@unittest.skipIf(running_in_idle, "Does not work when run within Idle.")
|
||||
def test_showwarnings(self):
|
||||
self.assertIs(warnings.showwarning, showwarning)
|
||||
shell.capture_warnings(True)
|
||||
self.assertIs(warnings.showwarning, shell.idle_showwarning)
|
||||
shell.capture_warnings(False)
|
||||
self.assertIs(warnings.showwarning, showwarning)
|
||||
|
||||
def test_idle_formatter(self):
|
||||
# Will fail if format changed without regenerating idlemsg
|
||||
s = shell.idle_formatwarning(
|
||||
'Test', UserWarning, 'test_warning.py', 99, 'Line of code')
|
||||
self.assertEqual(idlemsg, s)
|
||||
|
||||
def test_shell_show(self):
|
||||
with captured_stderr() as f:
|
||||
shell.idle_showwarning(
|
||||
'Test', UserWarning, 'test_warning.py', 99, f, 'Line of code')
|
||||
self.assertEqual(shellmsg.splitlines(), f.getvalue().splitlines())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
45
third_party/python/Lib/idlelib/idle_test/test_window.py
vendored
Normal file
45
third_party/python/Lib/idlelib/idle_test/test_window.py
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
"Test window, coverage 47%."
|
||||
|
||||
from idlelib import window
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
|
||||
|
||||
class WindowListTest(unittest.TestCase):
|
||||
|
||||
def test_init(self):
|
||||
wl = window.WindowList()
|
||||
self.assertEqual(wl.dict, {})
|
||||
self.assertEqual(wl.callbacks, [])
|
||||
|
||||
# Further tests need mock Window.
|
||||
|
||||
|
||||
class ListedToplevelTest(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
window.registry = set()
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
window.registry = window.WindowList()
|
||||
cls.root.update_idletasks()
|
||||
## for id in cls.root.tk.call('after', 'info'):
|
||||
## cls.root.after_cancel(id) # Need for EditorWindow.
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
|
||||
win = window.ListedToplevel(self.root)
|
||||
self.assertIn(win, window.registry)
|
||||
self.assertEqual(win.focused_widget, win)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
39
third_party/python/Lib/idlelib/idle_test/test_zoomheight.py
vendored
Normal file
39
third_party/python/Lib/idlelib/idle_test/test_zoomheight.py
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
"Test zoomheight, coverage 66%."
|
||||
# Some code is system dependent.
|
||||
|
||||
from idlelib import zoomheight
|
||||
import unittest
|
||||
from test.support import requires
|
||||
from tkinter import Tk
|
||||
from idlelib.editor import EditorWindow
|
||||
|
||||
|
||||
class Test(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
requires('gui')
|
||||
cls.root = Tk()
|
||||
cls.root.withdraw()
|
||||
cls.editwin = EditorWindow(root=cls.root)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.editwin._close()
|
||||
cls.root.update_idletasks()
|
||||
for id in cls.root.tk.call('after', 'info'):
|
||||
cls.root.after_cancel(id) # Need for EditorWindow.
|
||||
cls.root.destroy()
|
||||
del cls.root
|
||||
|
||||
def test_init(self):
|
||||
zoom = zoomheight.ZoomHeight(self.editwin)
|
||||
self.assertIs(zoom.editwin, self.editwin)
|
||||
|
||||
def test_zoom_height_event(self):
|
||||
zoom = zoomheight.ZoomHeight(self.editwin)
|
||||
zoom.zoom_height_event()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(verbosity=2)
|
Loading…
Add table
Add a link
Reference in a new issue