mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
[3.12] gh-66819: More IDLE htest updates(2) (GH-112642) (#112643)
Examine and update spec -- callable pairs.
Revise run method.
(cherry picked from commit 3855b45874
)
Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
This commit is contained in:
parent
f5965c2385
commit
ee3ef7f196
9 changed files with 70 additions and 69 deletions
|
@ -254,5 +254,6 @@ if __name__ == "__main__":
|
||||||
if len(sys.argv) == 1: # If pass file on command line, unittest fails.
|
if len(sys.argv) == 1: # If pass file on command line, unittest fails.
|
||||||
from unittest import main
|
from unittest import main
|
||||||
main('idlelib.idle_test.test_browser', verbosity=2, exit=False)
|
main('idlelib.idle_test.test_browser', verbosity=2, exit=False)
|
||||||
|
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
run(_module_browser)
|
run(_module_browser)
|
||||||
|
|
|
@ -120,7 +120,7 @@ def make_objecttreeitem(labeltext, object, setfunction=None):
|
||||||
return c(labeltext, object, setfunction)
|
return c(labeltext, object, setfunction)
|
||||||
|
|
||||||
|
|
||||||
def _object_browser(parent): # htest #
|
def _debug_object_browser(parent): # htest #
|
||||||
import sys
|
import sys
|
||||||
from tkinter import Toplevel
|
from tkinter import Toplevel
|
||||||
top = Toplevel(parent)
|
top = Toplevel(parent)
|
||||||
|
@ -140,4 +140,4 @@ if __name__ == '__main__':
|
||||||
main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False)
|
main('idlelib.idle_test.test_debugobj', verbosity=2, exit=False)
|
||||||
|
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
run(_object_browser)
|
run(_debug_object_browser)
|
||||||
|
|
|
@ -8,14 +8,15 @@ the master window to end testing.
|
||||||
|
|
||||||
In a tested module, let X be a global name bound to a callable (class or
|
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
|
function) whose .__name__ attribute is also X (the usual situation). The
|
||||||
first parameter of X must be 'parent'. When called, the parent argument
|
first parameter of X must be 'parent' or 'master'. When called, the
|
||||||
will be the root window. X must create a child Toplevel(parent) window
|
first argument will be the root window. X must create a child
|
||||||
(or subclass thereof). The Toplevel may be a test widget or dialog, in
|
Toplevel(parent/master) (or subclass thereof). The Toplevel may be a
|
||||||
which case the callable is the corresponding class. Or the Toplevel may
|
test widget or dialog, in which case the callable is the corresponding
|
||||||
contain the widget to be tested or set up a context in which a test
|
class. Or the Toplevel may contain the widget to be tested or set up a
|
||||||
widget is invoked. In this latter case, the callable is a wrapper
|
context in which a test widget is invoked. In this latter case, the
|
||||||
function that sets up the Toplevel and other objects. Wrapper function
|
callable is a wrapper function that sets up the Toplevel and other
|
||||||
names, such as _editor_window', should start with '_' and be lowercase.
|
objects. Wrapper function names, such as _editor_window', should start
|
||||||
|
with '_' and be lowercase.
|
||||||
|
|
||||||
|
|
||||||
End the module with
|
End the module with
|
||||||
|
@ -117,12 +118,20 @@ CustomRun_spec = {
|
||||||
'file': 'query',
|
'file': 'query',
|
||||||
'kwds': {'title': 'Customize query.py Run',
|
'kwds': {'title': 'Customize query.py Run',
|
||||||
'_htest': True},
|
'_htest': True},
|
||||||
'msg': "Enter with <Return> or [Run]. Print valid entry to Shell\n"
|
'msg': "Enter with <Return> or [OK]. Print valid entry to Shell\n"
|
||||||
"Arguments are parsed into a list\n"
|
"Arguments are parsed into a list\n"
|
||||||
"Mode is currently restart True or False\n"
|
"Mode is currently restart True or False\n"
|
||||||
"Close dialog with valid entry, <Escape>, [Cancel], [X]"
|
"Close dialog with valid entry, <Escape>, [Cancel], [X]"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_debug_object_browser_spec = {
|
||||||
|
'file': 'debugobj',
|
||||||
|
'kwds': {},
|
||||||
|
'msg': "Double click on items up to the lowest level.\n"
|
||||||
|
"Attributes of the objects and related information "
|
||||||
|
"will be displayed side-by-side at each level."
|
||||||
|
}
|
||||||
|
|
||||||
# TODO Improve message
|
# TODO Improve message
|
||||||
_dyn_option_menu_spec = {
|
_dyn_option_menu_spec = {
|
||||||
'file': 'dynoption',
|
'file': 'dynoption',
|
||||||
|
@ -178,7 +187,7 @@ HelpSource_spec = {
|
||||||
"Any url ('www...', 'http...') is accepted.\n"
|
"Any url ('www...', 'http...') is accepted.\n"
|
||||||
"Test Browse with and without path, as cannot unittest.\n"
|
"Test Browse with and without path, as cannot unittest.\n"
|
||||||
"[Ok] or <Return> prints valid entry to shell\n"
|
"[Ok] or <Return> prints valid entry to shell\n"
|
||||||
"[Cancel] or <Escape> prints None to shell"
|
"<Escape>, [Cancel], or [X] prints None to shell"
|
||||||
}
|
}
|
||||||
|
|
||||||
_io_binding_spec = {
|
_io_binding_spec = {
|
||||||
|
@ -199,17 +208,17 @@ _linenumbers_drag_scrolling_spec = {
|
||||||
'kwds': {},
|
'kwds': {},
|
||||||
'msg': textwrap.dedent("""\
|
'msg': textwrap.dedent("""\
|
||||||
1. Click on the line numbers and drag down below the edge of the
|
1. Click on the line numbers and drag down below the edge of the
|
||||||
window, moving the mouse a bit and then leaving it there for a while.
|
window, moving the mouse a bit and then leaving it there for a
|
||||||
The text and line numbers should gradually scroll down, with the
|
while. The text and line numbers should gradually scroll down,
|
||||||
selection updated continuously.
|
with the selection updated continuously.
|
||||||
|
|
||||||
2. With the lines still selected, click on a line number above the
|
2. With the lines still selected, click on a line number above
|
||||||
selected lines. Only the line whose number was clicked should be
|
or below the selected lines. Only the line whose number was
|
||||||
selected.
|
clicked should be selected.
|
||||||
|
|
||||||
3. Repeat step #1, dragging to above the window. The text and line
|
3. Repeat step #1, dragging to above the window. The text and
|
||||||
numbers should gradually scroll up, with the selection updated
|
line numbers should gradually scroll up, with the selection
|
||||||
continuously.
|
updated continuously.
|
||||||
|
|
||||||
4. Repeat step #2, clicking a line number below the selection."""),
|
4. Repeat step #2, clicking a line number below the selection."""),
|
||||||
}
|
}
|
||||||
|
@ -217,42 +226,33 @@ _linenumbers_drag_scrolling_spec = {
|
||||||
_multi_call_spec = {
|
_multi_call_spec = {
|
||||||
'file': 'multicall',
|
'file': 'multicall',
|
||||||
'kwds': {},
|
'kwds': {},
|
||||||
'msg': "The following actions should trigger a print to console or IDLE"
|
'msg': "The following should trigger a print to console or IDLE Shell.\n"
|
||||||
" Shell.\nEntering and leaving the text area, key entry, "
|
"Entering and leaving the text area, key entry, <Control-Key>,\n"
|
||||||
"<Control-Key>,\n<Alt-Key-a>, <Control-Key-a>, "
|
"<Alt-Key-a>, <Control-Key-a>, <Alt-Control-Key-a>, \n"
|
||||||
"<Alt-Control-Key-a>, \n<Control-Button-1>, <Alt-Button-1> and "
|
"<Control-Button-1>, <Alt-Button-1> and focusing elsewhere."
|
||||||
"focusing out of the window\nare sequences to be tested."
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_module_browser_spec = {
|
_module_browser_spec = {
|
||||||
'file': 'browser',
|
'file': 'browser',
|
||||||
'kwds': {},
|
'kwds': {},
|
||||||
'msg': "Inspect names of module, class(with superclass if "
|
'msg': textwrap.dedent("""
|
||||||
"applicable), methods and functions.\nToggle nested items.\n"
|
"Inspect names of module, class(with superclass if applicable),
|
||||||
"Double clicking on items prints a traceback for an exception "
|
"methods and functions. Toggle nested items. Double clicking
|
||||||
"that is ignored."
|
"on items prints a traceback for an exception that is ignored.""")
|
||||||
}
|
}
|
||||||
|
|
||||||
_multistatus_bar_spec = {
|
_multistatus_bar_spec = {
|
||||||
'file': 'statusbar',
|
'file': 'statusbar',
|
||||||
'kwds': {},
|
'kwds': {},
|
||||||
'msg': "Ensure presence of multi-status bar below text area.\n"
|
'msg': "Ensure presence of multi-status bar below text area.\n"
|
||||||
"Click 'Update Status' to change the multi-status text"
|
"Click 'Update Status' to change the status text"
|
||||||
}
|
}
|
||||||
|
|
||||||
_object_browser_spec = {
|
PathBrowser_spec = {
|
||||||
'file': 'debugobj',
|
|
||||||
'kwds': {},
|
|
||||||
'msg': "Double click on items up to the lowest level.\n"
|
|
||||||
"Attributes of the objects and related information "
|
|
||||||
"will be displayed side-by-side at each level."
|
|
||||||
}
|
|
||||||
|
|
||||||
_path_browser_spec = {
|
|
||||||
'file': 'pathbrowser',
|
'file': 'pathbrowser',
|
||||||
'kwds': {},
|
'kwds': {'_htest': True},
|
||||||
'msg': "Test for correct display of all paths in sys.path.\n"
|
'msg': "Test for correct display of all paths in sys.path.\n"
|
||||||
"Toggle nested items up to the lowest level.\n"
|
"Toggle nested items out to the lowest level.\n"
|
||||||
"Double clicking on an item prints a traceback\n"
|
"Double clicking on an item prints a traceback\n"
|
||||||
"for an exception that is ignored."
|
"for an exception that is ignored."
|
||||||
}
|
}
|
||||||
|
@ -367,11 +367,12 @@ _widget_redirector_spec = {
|
||||||
}
|
}
|
||||||
|
|
||||||
def run(*tests):
|
def run(*tests):
|
||||||
|
"Run callables in tests."
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
root.title('IDLE htest')
|
root.title('IDLE htest')
|
||||||
root.resizable(0, 0)
|
root.resizable(0, 0)
|
||||||
|
|
||||||
# a scrollable Label like constant width text widget.
|
# A scrollable Label-like constant width text widget.
|
||||||
frameLabel = tk.Frame(root, padx=10)
|
frameLabel = tk.Frame(root, padx=10)
|
||||||
frameLabel.pack()
|
frameLabel.pack()
|
||||||
text = tk.Text(frameLabel, wrap='word')
|
text = tk.Text(frameLabel, wrap='word')
|
||||||
|
@ -381,45 +382,44 @@ def run(*tests):
|
||||||
scrollbar.pack(side='right', fill='y', expand=False)
|
scrollbar.pack(side='right', fill='y', expand=False)
|
||||||
text.pack(side='left', fill='both', expand=True)
|
text.pack(side='left', fill='both', expand=True)
|
||||||
|
|
||||||
test_list = [] # List of tuples of the form (spec, callable widget)
|
test_list = [] # Make list of (spec, callable) tuples.
|
||||||
if tests:
|
if tests:
|
||||||
for test in tests:
|
for test in tests:
|
||||||
test_spec = globals()[test.__name__ + '_spec']
|
test_spec = globals()[test.__name__ + '_spec']
|
||||||
test_spec['name'] = test.__name__
|
test_spec['name'] = test.__name__
|
||||||
test_list.append((test_spec, test))
|
test_list.append((test_spec, test))
|
||||||
else:
|
else:
|
||||||
for k, d in globals().items():
|
for key, dic in globals().items():
|
||||||
if k.endswith('_spec'):
|
if key.endswith('_spec'):
|
||||||
test_name = k[:-5]
|
test_name = key[:-5]
|
||||||
test_spec = d
|
test_spec = dic
|
||||||
test_spec['name'] = test_name
|
test_spec['name'] = test_name
|
||||||
mod = import_module('idlelib.' + test_spec['file'])
|
mod = import_module('idlelib.' + test_spec['file'])
|
||||||
test = getattr(mod, test_name)
|
test = getattr(mod, test_name)
|
||||||
test_list.append((test_spec, test))
|
test_list.append((test_spec, test))
|
||||||
|
test_list.reverse() # So can pop in proper order in next_test.
|
||||||
|
|
||||||
test_name = tk.StringVar(root)
|
test_name = tk.StringVar(root)
|
||||||
callable_object = None
|
callable_object = None
|
||||||
test_kwds = None
|
test_kwds = None
|
||||||
|
|
||||||
def next_test():
|
def next_test():
|
||||||
|
|
||||||
nonlocal test_name, callable_object, test_kwds
|
nonlocal test_name, callable_object, test_kwds
|
||||||
if len(test_list) == 1:
|
if len(test_list) == 1:
|
||||||
next_button.pack_forget()
|
next_button.pack_forget()
|
||||||
test_spec, callable_object = test_list.pop()
|
test_spec, callable_object = test_list.pop()
|
||||||
test_kwds = test_spec['kwds']
|
test_kwds = test_spec['kwds']
|
||||||
test_kwds['parent'] = root
|
|
||||||
test_name.set('Test ' + test_spec['name'])
|
test_name.set('Test ' + test_spec['name'])
|
||||||
|
|
||||||
text.configure(state='normal') # enable text editing
|
text['state'] = 'normal' # Enable text replacement.
|
||||||
text.delete('1.0', 'end')
|
text.delete('1.0', 'end')
|
||||||
text.insert("1.0", test_spec['msg'])
|
text.insert("1.0", test_spec['msg'])
|
||||||
text.configure(state='disabled') # preserve read-only property
|
text['state'] = 'disabled' # Restore read-only property.
|
||||||
|
|
||||||
def run_test(_=None):
|
def run_test(_=None):
|
||||||
widget = callable_object(**test_kwds)
|
widget = callable_object(root, **test_kwds)
|
||||||
try:
|
try:
|
||||||
print(widget.result)
|
print(widget.result) # Only true for query classes(?).
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -396,10 +396,11 @@ class IOBinding:
|
||||||
def _io_binding(parent): # htest #
|
def _io_binding(parent): # htest #
|
||||||
from tkinter import Toplevel, Text
|
from tkinter import Toplevel, Text
|
||||||
|
|
||||||
root = Toplevel(parent)
|
top = Toplevel(parent)
|
||||||
root.title("Test IOBinding")
|
top.title("Test IOBinding")
|
||||||
x, y = map(int, parent.geometry().split('+')[1:])
|
x, y = map(int, parent.geometry().split('+')[1:])
|
||||||
root.geometry("+%d+%d" % (x, y + 175))
|
top.geometry("+%d+%d" % (x, y + 175))
|
||||||
|
|
||||||
class MyEditWin:
|
class MyEditWin:
|
||||||
def __init__(self, text):
|
def __init__(self, text):
|
||||||
self.text = text
|
self.text = text
|
||||||
|
@ -423,7 +424,7 @@ def _io_binding(parent): # htest #
|
||||||
def savecopy(self, event):
|
def savecopy(self, event):
|
||||||
self.text.event_generate("<<save-copy-of-window-as-file>>")
|
self.text.event_generate("<<save-copy-of-window-as-file>>")
|
||||||
|
|
||||||
text = Text(root)
|
text = Text(top)
|
||||||
text.pack()
|
text.pack()
|
||||||
text.focus_set()
|
text.focus_set()
|
||||||
editwin = MyEditWin(text)
|
editwin = MyEditWin(text)
|
||||||
|
|
|
@ -421,6 +421,8 @@ def _multi_call(parent): # htest #
|
||||||
top.geometry("+%d+%d" % (x, y + 175))
|
top.geometry("+%d+%d" % (x, y + 175))
|
||||||
text = MultiCallCreator(tkinter.Text)(top)
|
text = MultiCallCreator(tkinter.Text)(top)
|
||||||
text.pack()
|
text.pack()
|
||||||
|
text.focus_set()
|
||||||
|
|
||||||
def bindseq(seq, n=[0]):
|
def bindseq(seq, n=[0]):
|
||||||
def handler(event):
|
def handler(event):
|
||||||
print(seq)
|
print(seq)
|
||||||
|
|
|
@ -99,13 +99,9 @@ class DirBrowserTreeItem(TreeItem):
|
||||||
return sorted
|
return sorted
|
||||||
|
|
||||||
|
|
||||||
def _path_browser(parent): # htest #
|
|
||||||
PathBrowser(parent, _htest=True)
|
|
||||||
parent.mainloop()
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
from unittest import main
|
from unittest import main
|
||||||
main('idlelib.idle_test.test_pathbrowser', verbosity=2, exit=False)
|
main('idlelib.idle_test.test_pathbrowser', verbosity=2, exit=False)
|
||||||
|
|
||||||
from idlelib.idle_test.htest import run
|
from idlelib.idle_test.htest import run
|
||||||
run(_path_browser)
|
run(PathBrowser)
|
||||||
|
|
|
@ -368,7 +368,7 @@ class CustomRun(Query):
|
||||||
sticky='we')
|
sticky='we')
|
||||||
|
|
||||||
def cli_args_ok(self):
|
def cli_args_ok(self):
|
||||||
"Validity check and parsing for command line arguments."
|
"Return command line arg list or None if error."
|
||||||
cli_string = self.entry.get().strip()
|
cli_string = self.entry.get().strip()
|
||||||
try:
|
try:
|
||||||
cli_args = shlex.split(cli_string, posix=True)
|
cli_args = shlex.split(cli_string, posix=True)
|
||||||
|
|
|
@ -517,13 +517,13 @@ class ShellSidebar(BaseSideBar):
|
||||||
def _linenumbers_drag_scrolling(parent): # htest #
|
def _linenumbers_drag_scrolling(parent): # htest #
|
||||||
from idlelib.idle_test.test_sidebar import Dummy_editwin
|
from idlelib.idle_test.test_sidebar import Dummy_editwin
|
||||||
|
|
||||||
toplevel = tk.Toplevel(parent)
|
top = tk.Toplevel(parent)
|
||||||
text_frame = tk.Frame(toplevel)
|
text_frame = tk.Frame(top)
|
||||||
text_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
text_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||||
text_frame.rowconfigure(1, weight=1)
|
text_frame.rowconfigure(1, weight=1)
|
||||||
text_frame.columnconfigure(1, weight=1)
|
text_frame.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
font = idleConf.GetFont(toplevel, 'main', 'EditorWindow')
|
font = idleConf.GetFont(top, 'main', 'EditorWindow')
|
||||||
text = tk.Text(text_frame, width=80, height=24, wrap=tk.NONE, font=font)
|
text = tk.Text(text_frame, width=80, height=24, wrap=tk.NONE, font=font)
|
||||||
text.grid(row=1, column=1, sticky=tk.NSEW)
|
text.grid(row=1, column=1, sticky=tk.NSEW)
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@ def _multistatus_bar(parent): # htest #
|
||||||
x, y = map(int, parent.geometry().split('+')[1:])
|
x, y = map(int, parent.geometry().split('+')[1:])
|
||||||
top.geometry("+%d+%d" %(x, y + 175))
|
top.geometry("+%d+%d" %(x, y + 175))
|
||||||
top.title("Test multistatus bar")
|
top.title("Test multistatus bar")
|
||||||
|
|
||||||
frame = Frame(top)
|
frame = Frame(top)
|
||||||
text = Text(frame, height=5, width=40)
|
text = Text(frame, height=5, width=40)
|
||||||
text.pack()
|
text.pack()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue