Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
8b22c0aa
Kaydet (Commit)
8b22c0aa
authored
Tem 08, 2016
tarafından
Terry Jan Reedy
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Issue #27380: IDLE: add query.HelpSource class and tests.
Remove modules that are combined in new module.
üst
d6402a40
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
329 additions
and
355 deletions
+329
-355
config_help.py
Lib/idlelib/config_help.py
+0
-170
configdialog.py
Lib/idlelib/configdialog.py
+9
-8
htest.py
Lib/idlelib/idle_test/htest.py
+17
-13
test_config_help.py
Lib/idlelib/idle_test/test_config_help.py
+0
-106
test_query.py
Lib/idlelib/idle_test/test_query.py
+179
-25
query.py
Lib/idlelib/query.py
+124
-33
No files found.
Lib/idlelib/config_help.py
deleted
100644 → 0
Dosyayı görüntüle @
d6402a40
"Dialog to specify or edit the parameters for a user configured help source."
import
os
import
sys
from
tkinter
import
*
import
tkinter.messagebox
as
tkMessageBox
import
tkinter.filedialog
as
tkFileDialog
class
GetHelpSourceDialog
(
Toplevel
):
def
__init__
(
self
,
parent
,
title
,
menuItem
=
''
,
filePath
=
''
,
_htest
=
False
):
"""Get menu entry and url/ local file location for Additional Help
User selects a name for the Help resource and provides a web url
or a local file as its source. The user can enter a url or browse
for the file.
_htest - bool, change box location when running htest
"""
Toplevel
.
__init__
(
self
,
parent
)
self
.
configure
(
borderwidth
=
5
)
self
.
resizable
(
height
=
FALSE
,
width
=
FALSE
)
self
.
title
(
title
)
self
.
transient
(
parent
)
self
.
grab_set
()
self
.
protocol
(
"WM_DELETE_WINDOW"
,
self
.
cancel
)
self
.
parent
=
parent
self
.
result
=
None
self
.
create_widgets
()
self
.
menu
.
set
(
menuItem
)
self
.
path
.
set
(
filePath
)
self
.
withdraw
()
#hide while setting geometry
#needs to be done here so that the winfo_reqwidth is valid
self
.
update_idletasks
()
#centre dialog over parent. below parent if running htest.
self
.
geometry
(
"+
%
d+
%
d"
%
(
parent
.
winfo_rootx
()
+
(
parent
.
winfo_width
()
/
2
-
self
.
winfo_reqwidth
()
/
2
),
parent
.
winfo_rooty
()
+
((
parent
.
winfo_height
()
/
2
-
self
.
winfo_reqheight
()
/
2
)
if
not
_htest
else
150
)))
self
.
deiconify
()
#geometry set, unhide
self
.
bind
(
'<Return>'
,
self
.
ok
)
self
.
wait_window
()
def
create_widgets
(
self
):
self
.
menu
=
StringVar
(
self
)
self
.
path
=
StringVar
(
self
)
self
.
fontSize
=
StringVar
(
self
)
self
.
frameMain
=
Frame
(
self
,
borderwidth
=
2
,
relief
=
GROOVE
)
self
.
frameMain
.
pack
(
side
=
TOP
,
expand
=
TRUE
,
fill
=
BOTH
)
labelMenu
=
Label
(
self
.
frameMain
,
anchor
=
W
,
justify
=
LEFT
,
text
=
'Menu Item:'
)
self
.
entryMenu
=
Entry
(
self
.
frameMain
,
textvariable
=
self
.
menu
,
width
=
30
)
self
.
entryMenu
.
focus_set
()
labelPath
=
Label
(
self
.
frameMain
,
anchor
=
W
,
justify
=
LEFT
,
text
=
'Help File Path: Enter URL or browse for file'
)
self
.
entryPath
=
Entry
(
self
.
frameMain
,
textvariable
=
self
.
path
,
width
=
40
)
self
.
entryMenu
.
focus_set
()
labelMenu
.
pack
(
anchor
=
W
,
padx
=
5
,
pady
=
3
)
self
.
entryMenu
.
pack
(
anchor
=
W
,
padx
=
5
,
pady
=
3
)
labelPath
.
pack
(
anchor
=
W
,
padx
=
5
,
pady
=
3
)
self
.
entryPath
.
pack
(
anchor
=
W
,
padx
=
5
,
pady
=
3
)
browseButton
=
Button
(
self
.
frameMain
,
text
=
'Browse'
,
width
=
8
,
command
=
self
.
browse_file
)
browseButton
.
pack
(
pady
=
3
)
frameButtons
=
Frame
(
self
)
frameButtons
.
pack
(
side
=
BOTTOM
,
fill
=
X
)
self
.
buttonOk
=
Button
(
frameButtons
,
text
=
'OK'
,
width
=
8
,
default
=
ACTIVE
,
command
=
self
.
ok
)
self
.
buttonOk
.
grid
(
row
=
0
,
column
=
0
,
padx
=
5
,
pady
=
5
)
self
.
buttonCancel
=
Button
(
frameButtons
,
text
=
'Cancel'
,
width
=
8
,
command
=
self
.
cancel
)
self
.
buttonCancel
.
grid
(
row
=
0
,
column
=
1
,
padx
=
5
,
pady
=
5
)
def
browse_file
(
self
):
filetypes
=
[
(
"HTML Files"
,
"*.htm *.html"
,
"TEXT"
),
(
"PDF Files"
,
"*.pdf"
,
"TEXT"
),
(
"Windows Help Files"
,
"*.chm"
),
(
"Text Files"
,
"*.txt"
,
"TEXT"
),
(
"All Files"
,
"*"
)]
path
=
self
.
path
.
get
()
if
path
:
dir
,
base
=
os
.
path
.
split
(
path
)
else
:
base
=
None
if
sys
.
platform
[:
3
]
==
'win'
:
dir
=
os
.
path
.
join
(
os
.
path
.
dirname
(
sys
.
executable
),
'Doc'
)
if
not
os
.
path
.
isdir
(
dir
):
dir
=
os
.
getcwd
()
else
:
dir
=
os
.
getcwd
()
opendialog
=
tkFileDialog
.
Open
(
parent
=
self
,
filetypes
=
filetypes
)
file
=
opendialog
.
show
(
initialdir
=
dir
,
initialfile
=
base
)
if
file
:
self
.
path
.
set
(
file
)
def
menu_ok
(
self
):
"Simple validity check for a sensible menu item name"
menu_ok
=
True
menu
=
self
.
menu
.
get
()
menu
.
strip
()
if
not
menu
:
tkMessageBox
.
showerror
(
title
=
'Menu Item Error'
,
message
=
'No menu item specified'
,
parent
=
self
)
self
.
entryMenu
.
focus_set
()
menu_ok
=
False
elif
len
(
menu
)
>
30
:
tkMessageBox
.
showerror
(
title
=
'Menu Item Error'
,
message
=
'Menu item too long:'
'
\n
Limit 30 characters.'
,
parent
=
self
)
self
.
entryMenu
.
focus_set
()
menu_ok
=
False
return
menu_ok
def
path_ok
(
self
):
"Simple validity check for menu file path"
path_ok
=
True
path
=
self
.
path
.
get
()
path
.
strip
()
if
not
path
:
#no path specified
tkMessageBox
.
showerror
(
title
=
'File Path Error'
,
message
=
'No help file path specified.'
,
parent
=
self
)
self
.
entryPath
.
focus_set
()
path_ok
=
False
elif
path
.
startswith
((
'www.'
,
'http'
)):
pass
else
:
if
path
[:
5
]
==
'file:'
:
path
=
path
[
5
:]
if
not
os
.
path
.
exists
(
path
):
tkMessageBox
.
showerror
(
title
=
'File Path Error'
,
message
=
'Help file path does not exist.'
,
parent
=
self
)
self
.
entryPath
.
focus_set
()
path_ok
=
False
return
path_ok
def
ok
(
self
,
event
=
None
):
if
self
.
menu_ok
()
and
self
.
path_ok
():
self
.
result
=
(
self
.
menu
.
get
()
.
strip
(),
self
.
path
.
get
()
.
strip
())
if
sys
.
platform
==
'darwin'
:
path
=
self
.
result
[
1
]
if
path
.
startswith
((
'www'
,
'file:'
,
'http:'
,
'https:'
)):
pass
else
:
# Mac Safari insists on using the URI form for local files
self
.
result
=
list
(
self
.
result
)
self
.
result
[
1
]
=
"file://"
+
path
self
.
destroy
()
def
cancel
(
self
,
event
=
None
):
self
.
result
=
None
self
.
destroy
()
if
__name__
==
'__main__'
:
import
unittest
unittest
.
main
(
'idlelib.idle_test.test_config_help'
,
verbosity
=
2
,
exit
=
False
)
from
idlelib.idle_test.htest
import
run
run
(
GetHelpSourceDialog
)
Lib/idlelib/configdialog.py
Dosyayı görüntüle @
8b22c0aa
...
...
@@ -18,8 +18,7 @@ import tkinter.font as tkFont
from
idlelib.config
import
idleConf
from
idlelib.dynoption
import
DynOptionMenu
from
idlelib.config_key
import
GetKeysDialog
from
idlelib.query
import
SectionName
from
idlelib.config_help
import
GetHelpSourceDialog
from
idlelib.query
import
SectionName
,
HelpSource
from
idlelib.tabbedpages
import
TabbedPageSet
from
idlelib.textview
import
view_text
from
idlelib
import
macosx
...
...
@@ -940,7 +939,8 @@ class ConfigDialog(Toplevel):
self
.
buttonHelpListRemove
.
config
(
state
=
DISABLED
)
def
HelpListItemAdd
(
self
):
helpSource
=
GetHelpSourceDialog
(
self
,
'New Help Source'
)
.
result
helpSource
=
HelpSource
(
self
,
'New Help Source'
,
)
.
result
if
helpSource
:
self
.
userHelpList
.
append
((
helpSource
[
0
],
helpSource
[
1
]))
self
.
listHelp
.
insert
(
END
,
helpSource
[
0
])
...
...
@@ -950,11 +950,12 @@ class ConfigDialog(Toplevel):
def
HelpListItemEdit
(
self
):
itemIndex
=
self
.
listHelp
.
index
(
ANCHOR
)
helpSource
=
self
.
userHelpList
[
itemIndex
]
newHelpSource
=
GetHelpSourceDialog
(
self
,
'Edit Help Source'
,
menuItem
=
helpSource
[
0
],
filePath
=
helpSource
[
1
])
.
result
if
(
not
newHelpSource
)
or
(
newHelpSource
==
helpSource
):
return
#no changes
newHelpSource
=
HelpSource
(
self
,
'Edit Help Source'
,
menuitem
=
helpSource
[
0
],
filepath
=
helpSource
[
1
],
)
.
result
if
newHelpSource
and
newHelpSource
!=
helpSource
:
self
.
userHelpList
[
itemIndex
]
=
newHelpSource
self
.
listHelp
.
delete
(
itemIndex
)
self
.
listHelp
.
insert
(
itemIndex
,
newHelpSource
[
0
])
...
...
Lib/idlelib/idle_test/htest.py
Dosyayı görüntüle @
8b22c0aa
...
...
@@ -137,18 +137,6 @@ _editor_window_spec = {
"Best to close editor first."
}
GetHelpSourceDialog_spec
=
{
'file'
:
'config_help'
,
'kwds'
:
{
'title'
:
'Get helpsource'
,
'_htest'
:
True
},
'msg'
:
"Enter menu item name and help file path
\n
"
"<nothing> and more than 30 chars are invalid menu item names.
\n
"
"<nothing>, file does not exist are invalid path items.
\n
"
"Test for incomplete web address for help file path.
\n
"
"A valid entry will be printed to shell with [0k].
\n
"
"[Cancel] will print None to shell"
,
}
# Update once issue21519 is resolved.
GetKeysDialog_spec
=
{
'file'
:
'config_key'
,
...
...
@@ -175,6 +163,22 @@ _grep_dialog_spec = {
"should open that file
\n
in 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
"
"A valid entry will be printed to shell with [0k]
\n
"
"or <return>. [Cancel] will print None to shell"
}
_io_binding_spec
=
{
'file'
:
'iomenu'
,
'kwds'
:
{},
...
...
@@ -241,7 +245,7 @@ Query_spec = {
'_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, [Cancel] or [X]"
,
"Close dialog with valid entry, [Cancel] or [X]"
}
...
...
Lib/idlelib/idle_test/test_config_help.py
deleted
100644 → 0
Dosyayı görüntüle @
d6402a40
"""Unittests for idlelib.config_help.py"""
import
unittest
from
idlelib.idle_test.mock_tk
import
Var
,
Mbox
,
Entry
from
idlelib
import
config_help
as
help_dialog_module
help_dialog
=
help_dialog_module
.
GetHelpSourceDialog
class
Dummy_help_dialog
:
# Mock for testing the following methods of help_dialog
menu_ok
=
help_dialog
.
menu_ok
path_ok
=
help_dialog
.
path_ok
ok
=
help_dialog
.
ok
cancel
=
help_dialog
.
cancel
# Attributes, constant or variable, needed for tests
menu
=
Var
()
entryMenu
=
Entry
()
path
=
Var
()
entryPath
=
Entry
()
result
=
None
destroyed
=
False
def
destroy
(
self
):
self
.
destroyed
=
True
# menu_ok and path_ok call Mbox.showerror if menu and path are not ok.
orig_mbox
=
help_dialog_module
.
tkMessageBox
showerror
=
Mbox
.
showerror
class
ConfigHelpTest
(
unittest
.
TestCase
):
dialog
=
Dummy_help_dialog
()
@classmethod
def
setUpClass
(
cls
):
help_dialog_module
.
tkMessageBox
=
Mbox
@classmethod
def
tearDownClass
(
cls
):
help_dialog_module
.
tkMessageBox
=
orig_mbox
def
test_blank_menu
(
self
):
self
.
dialog
.
menu
.
set
(
''
)
self
.
assertFalse
(
self
.
dialog
.
menu_ok
())
self
.
assertEqual
(
showerror
.
title
,
'Menu Item Error'
)
self
.
assertIn
(
'No'
,
showerror
.
message
)
def
test_long_menu
(
self
):
self
.
dialog
.
menu
.
set
(
'hello'
*
10
)
self
.
assertFalse
(
self
.
dialog
.
menu_ok
())
self
.
assertEqual
(
showerror
.
title
,
'Menu Item Error'
)
self
.
assertIn
(
'long'
,
showerror
.
message
)
def
test_good_menu
(
self
):
self
.
dialog
.
menu
.
set
(
'help'
)
showerror
.
title
=
'No Error'
# should not be called
self
.
assertTrue
(
self
.
dialog
.
menu_ok
())
self
.
assertEqual
(
showerror
.
title
,
'No Error'
)
def
test_blank_path
(
self
):
self
.
dialog
.
path
.
set
(
''
)
self
.
assertFalse
(
self
.
dialog
.
path_ok
())
self
.
assertEqual
(
showerror
.
title
,
'File Path Error'
)
self
.
assertIn
(
'No'
,
showerror
.
message
)
def
test_invalid_file_path
(
self
):
self
.
dialog
.
path
.
set
(
'foobar'
*
100
)
self
.
assertFalse
(
self
.
dialog
.
path_ok
())
self
.
assertEqual
(
showerror
.
title
,
'File Path Error'
)
self
.
assertIn
(
'not exist'
,
showerror
.
message
)
def
test_invalid_url_path
(
self
):
self
.
dialog
.
path
.
set
(
'ww.foobar.com'
)
self
.
assertFalse
(
self
.
dialog
.
path_ok
())
self
.
assertEqual
(
showerror
.
title
,
'File Path Error'
)
self
.
assertIn
(
'not exist'
,
showerror
.
message
)
self
.
dialog
.
path
.
set
(
'htt.foobar.com'
)
self
.
assertFalse
(
self
.
dialog
.
path_ok
())
self
.
assertEqual
(
showerror
.
title
,
'File Path Error'
)
self
.
assertIn
(
'not exist'
,
showerror
.
message
)
def
test_good_path
(
self
):
self
.
dialog
.
path
.
set
(
'https://docs.python.org'
)
showerror
.
title
=
'No Error'
# should not be called
self
.
assertTrue
(
self
.
dialog
.
path_ok
())
self
.
assertEqual
(
showerror
.
title
,
'No Error'
)
def
test_ok
(
self
):
self
.
dialog
.
destroyed
=
False
self
.
dialog
.
menu
.
set
(
'help'
)
self
.
dialog
.
path
.
set
(
'https://docs.python.org'
)
self
.
dialog
.
ok
()
self
.
assertEqual
(
self
.
dialog
.
result
,
(
'help'
,
'https://docs.python.org'
))
self
.
assertTrue
(
self
.
dialog
.
destroyed
)
def
test_cancel
(
self
):
self
.
dialog
.
destroyed
=
False
self
.
dialog
.
cancel
()
self
.
assertEqual
(
self
.
dialog
.
result
,
None
)
self
.
assertTrue
(
self
.
dialog
.
destroyed
)
if
__name__
==
'__main__'
:
unittest
.
main
(
verbosity
=
2
,
exit
=
False
)
Lib/idlelib/idle_test/test_query.py
Dosyayı görüntüle @
8b22c0aa
"""Test idlelib.query.
Coverage: 100
%
.
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.
Coverage: 94
%
(100
%
for Query and SectionName).
6 of 8 missing are ModuleName exceptions I don't know how to trigger.
"""
from
test.support
import
requires
from
tkinter
import
Tk
...
...
@@ -9,21 +19,9 @@ from unittest import mock
from
idlelib.idle_test.mock_tk
import
Var
,
Mbox_func
from
idlelib
import
query
Query
=
query
.
Query
class
Dummy_Query
:
# Mock for testing the following methods Query
entry_ok
=
Query
.
entry_ok
ok
=
Query
.
ok
cancel
=
Query
.
cancel
# Attributes, constant or variable, needed for tests
entry
=
Var
()
result
=
None
destroyed
=
False
def
destroy
(
self
):
self
.
destroyed
=
True
# Mock entry.showerror messagebox so don't need click to continue
# when entry_ok and path_ok methods call it to display errors.
# entry_ok calls modal messagebox.showerror if entry is not ok.
# Mock showerrer so don't need to click to continue.
orig_showerror
=
query
.
showerror
showerror
=
Mbox_func
()
# Instance has __call__ method.
...
...
@@ -34,7 +32,23 @@ def tearDownModule():
query
.
showerror
=
orig_showerror
# 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 needed for the tests.
entry
=
Var
()
result
=
None
destroyed
=
False
def
destroy
(
self
):
self
.
destroyed
=
True
dialog
=
Dummy_Query
()
def
setUp
(
self
):
...
...
@@ -42,7 +56,7 @@ class QueryTest(unittest.TestCase):
self
.
dialog
.
result
=
None
self
.
dialog
.
destroyed
=
False
def
test_
blank_entry
(
self
):
def
test_
entry_ok_blank
(
self
):
dialog
=
self
.
dialog
Equal
=
self
.
assertEqual
dialog
.
entry
.
set
(
' '
)
...
...
@@ -51,7 +65,7 @@ class QueryTest(unittest.TestCase):
Equal
(
showerror
.
title
,
'Entry Error'
)
self
.
assertIn
(
'Blank'
,
showerror
.
message
)
def
test_
good_entry
(
self
):
def
test_
entry_ok_good
(
self
):
dialog
=
self
.
dialog
Equal
=
self
.
assertEqual
dialog
.
entry
.
set
(
' good '
)
...
...
@@ -59,7 +73,17 @@ class QueryTest(unittest.TestCase):
Equal
((
dialog
.
result
,
dialog
.
destroyed
),
(
None
,
False
))
Equal
(
showerror
.
title
,
None
)
def
test_ok
(
self
):
def
test_ok_blank
(
self
):
dialog
=
self
.
dialog
Equal
=
self
.
assertEqual
dialog
.
entry
.
set
(
''
)
dialog
.
entry
.
focus_set
=
mock
.
Mock
()
Equal
(
dialog
.
ok
(),
None
)
self
.
assertTrue
(
dialog
.
entry
.
focus_set
.
called
)
del
dialog
.
entry
.
focus_set
Equal
((
dialog
.
result
,
dialog
.
destroyed
),
(
None
,
False
))
def
test_ok_good
(
self
):
dialog
=
self
.
dialog
Equal
=
self
.
assertEqual
dialog
.
entry
.
set
(
'good'
)
...
...
@@ -73,12 +97,14 @@ class QueryTest(unittest.TestCase):
Equal
((
dialog
.
result
,
dialog
.
destroyed
),
(
None
,
True
))
class
Dummy_SectionName
:
entry_ok
=
query
.
SectionName
.
entry_ok
# Test override.
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
()
class
SectionNameTest
(
unittest
.
TestCase
):
dialog
=
Dummy_SectionName
()
def
setUp
(
self
):
...
...
@@ -116,12 +142,14 @@ class SectionNameTest(unittest.TestCase):
Equal
(
showerror
.
title
,
None
)
class
Dummy_ModuleName
:
entry_ok
=
query
.
ModuleName
.
entry_ok
# Test override
class
ModuleNameTest
(
unittest
.
TestCase
):
"Test ModuleName subclass of Query."
class
Dummy_ModuleName
:
entry_ok
=
query
.
ModuleName
.
entry_ok
# Funtion being tested.
text0
=
''
entry
=
Var
()
class
ModuleNameTest
(
unittest
.
TestCase
):
dialog
=
Dummy_ModuleName
()
def
setUp
(
self
):
...
...
@@ -159,13 +187,119 @@ class ModuleNameTest(unittest.TestCase):
Equal
(
showerror
.
title
,
None
)
# 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
()
dialog
=
Dummy_HelpSource
()
def
test_file_replaces_path
(
self
):
# Path is widget entry, file is file dialog return.
dialog
=
self
.
dialog
for
path
,
func
,
result
in
(
# We need all combination to test all (most) code paths.
(
''
,
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 ModuleName subclass of Query."
class
Dummy_HelpSource
:
path_ok
=
query
.
HelpSource
.
path_ok
path
=
Var
()
dialog
=
Dummy_HelpSource
()
@classmethod
def
tearDownClass
(
cls
):
query
.
platform
=
orig_platform
def
setUp
(
self
):
showerror
.
title
=
None
def
test_path_ok_blank
(
self
):
dialog
=
self
.
dialog
Equal
=
self
.
assertEqual
dialog
.
path
.
set
(
' '
)
Equal
(
dialog
.
path_ok
(),
None
)
Equal
(
showerror
.
title
,
'File Path Error'
)
self
.
assertIn
(
'No help'
,
showerror
.
message
)
def
test_path_ok_bad
(
self
):
dialog
=
self
.
dialog
Equal
=
self
.
assertEqual
dialog
.
path
.
set
(
__file__
+
'bad-bad-bad'
)
Equal
(
dialog
.
path_ok
(),
None
)
Equal
(
showerror
.
title
,
'File Path Error'
)
self
.
assertIn
(
'not exist'
,
showerror
.
message
)
def
test_path_ok_web
(
self
):
dialog
=
self
.
dialog
Equal
=
self
.
assertEqual
for
url
in
'www.py.org'
,
'http://py.org'
:
with
self
.
subTest
():
dialog
.
path
.
set
(
url
)
Equal
(
dialog
.
path_ok
(),
url
)
Equal
(
showerror
.
title
,
None
)
def
test_path_ok_file
(
self
):
dialog
=
self
.
dialog
Equal
=
self
.
assertEqual
for
platform
,
prefix
in
(
'darwin'
,
'file://'
),
(
'other'
,
''
):
with
self
.
subTest
():
query
.
platform
=
platform
dialog
.
path
.
set
(
__file__
)
Equal
(
dialog
.
path_ok
(),
prefix
+
__file__
)
Equal
(
showerror
.
title
,
None
)
class
HelpsourceEntryokTest
(
unittest
.
TestCase
):
"Test entry_ok method of ModuleName subclass of Query."
class
Dummy_HelpSource
:
entry_ok
=
query
.
HelpSource
.
entry_ok
def
item_ok
(
self
):
return
self
.
name
def
path_ok
(
self
):
return
self
.
path
dialog
=
Dummy_HelpSource
()
def
test_entry_ok_helpsource
(
self
):
dialog
=
self
.
dialog
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
(
self
.
dialog
.
entry_ok
(),
result
)
# GUI TESTS
class
QueryGuiTest
(
unittest
.
TestCase
):
@classmethod
def
setUpClass
(
cls
):
requires
(
'gui'
)
cls
.
root
=
root
=
Tk
()
cls
.
dialog
=
Query
(
root
,
'TEST'
,
'test'
,
_utest
=
True
)
cls
.
dialog
=
query
.
Query
(
root
,
'TEST'
,
'test'
,
_utest
=
True
)
cls
.
dialog
.
destroy
=
mock
.
Mock
()
@classmethod
...
...
@@ -238,5 +372,25 @@ class ModulenameGuiTest(unittest.TestCase):
del
root
class
HelpsourceGuiTest
(
unittest
.
TestCase
):
@classmethod
def
setUpClass
(
cls
):
requires
(
'gui'
)
def
test_click_help_source
(
self
):
root
=
Tk
()
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
()
Equal
(
dialog
.
result
,
(
'__test__'
,
__file__
))
del
dialog
root
.
destroy
()
del
root
if
__name__
==
'__main__'
:
unittest
.
main
(
verbosity
=
2
,
exit
=
False
)
Lib/idlelib/query.py
Dosyayı görüntüle @
8b22c0aa
...
...
@@ -13,10 +13,16 @@ Configdialog uses it for new highlight theme and keybinding set names.
"""
# Query and Section name result from splitting GetCfgSectionNameDialog
# of configSectionNameDialog.py (temporarily config_sec.py) into
# generic and specific parts.
# generic and specific parts. 3.6 only, July 2016.
# ModuleName.entry_ok came from editor.EditorWindow.load_module.
# HelpSource was extracted from configHelpSourceEdit.py (temporarily
# config_help.py), with darwin code moved from ok to path_ok.
import
importlib
import
os
from
sys
import
executable
,
platform
# Platform is set for one test.
from
tkinter
import
Toplevel
,
StringVar
from
tkinter
import
filedialog
from
tkinter.messagebox
import
showerror
from
tkinter.ttk
import
Frame
,
Button
,
Entry
,
Label
...
...
@@ -25,8 +31,8 @@ class Query(Toplevel):
For this base class, accept any non-blank string.
"""
def
__init__
(
self
,
parent
,
title
,
message
,
text0
=
''
,
*
,
_htest
=
False
,
_utest
=
False
):
def
__init__
(
self
,
parent
,
title
,
message
,
*
,
text0
=
''
,
used_names
=
{}
,
_htest
=
False
,
_utest
=
False
):
"""Create popup, do not return until tk widget destroyed.
Additional subclass init must be done before calling this
...
...
@@ -35,10 +41,12 @@ class Query(Toplevel):
title - string, title of popup dialog
message - string, informational message to display
text0 - initial value for entry
used_names - names already in use
_htest - bool, change box location when running htest
_utest - bool, leave window hidden and not modal
"""
Toplevel
.
__init__
(
self
,
parent
)
self
.
withdraw
()
# Hide while configuring, especially geometry.
self
.
configure
(
borderwidth
=
5
)
self
.
resizable
(
height
=
False
,
width
=
False
)
self
.
title
(
title
)
...
...
@@ -49,26 +57,25 @@ class Query(Toplevel):
self
.
parent
=
parent
self
.
message
=
message
self
.
text0
=
text0
self
.
used_names
=
used_names
self
.
create_widgets
()
self
.
update_idletasks
()
#needs to be done here so that the winfo_reqwidth is valid
self
.
withdraw
()
# Hide while configuring, especially geometry.
self
.
geometry
(
self
.
update_idletasks
()
# Needed here for winfo_reqwidth below.
self
.
geometry
(
# Center dialog over parent (or below htest box).
"+
%
d+
%
d"
%
(
parent
.
winfo_rootx
()
+
(
parent
.
winfo_width
()
/
2
-
self
.
winfo_reqwidth
()
/
2
),
parent
.
winfo_rooty
()
+
((
parent
.
winfo_height
()
/
2
-
self
.
winfo_reqheight
()
/
2
)
if
not
_htest
else
150
)
)
)
#centre dialog over parent (or below htest box)
)
)
if
not
_utest
:
self
.
deiconify
()
#
geometry set, unhide
self
.
deiconify
()
#
Unhide now that geometry set.
self
.
wait_window
()
def
create_widgets
(
self
):
# Call from override, if any.
# Bind
widgets needed for entry_ok or unittest to self
.
frame
=
Frame
(
self
,
borderwidth
=
2
,
relief
=
'sunken'
,
)
label
=
Label
(
frame
,
anchor
=
'w'
,
justify
=
'left'
,
# Bind
to self widgets needed for entry_ok or unittest
.
self
.
frame
=
frame
=
Frame
(
self
,
borderwidth
=
2
,
relief
=
'sunken'
,
)
entry
label
=
Label
(
frame
,
anchor
=
'w'
,
justify
=
'left'
,
text
=
self
.
message
)
self
.
entryvar
=
StringVar
(
self
,
self
.
text0
)
self
.
entry
=
Entry
(
frame
,
width
=
30
,
textvariable
=
self
.
entryvar
)
...
...
@@ -81,7 +88,7 @@ class Query(Toplevel):
width
=
8
,
command
=
self
.
cancel
)
frame
.
pack
(
side
=
'top'
,
expand
=
True
,
fill
=
'both'
)
label
.
pack
(
padx
=
5
,
pady
=
5
)
entry
label
.
pack
(
padx
=
5
,
pady
=
5
)
self
.
entry
.
pack
(
padx
=
5
,
pady
=
5
)
buttons
.
pack
(
side
=
'bottom'
)
self
.
button_ok
.
pack
(
side
=
'left'
,
padx
=
5
)
...
...
@@ -93,7 +100,7 @@ class Query(Toplevel):
if
not
entry
:
showerror
(
title
=
'Entry Error'
,
message
=
'Blank line.'
,
parent
=
self
)
return
return
None
return
entry
def
ok
(
self
,
event
=
None
):
# Do not replace.
...
...
@@ -106,7 +113,7 @@ class Query(Toplevel):
self
.
result
=
entry
self
.
destroy
()
else
:
# [Ok]
(but not <Return>) moves focus.
Move it back.
# [Ok]
moves focus. (<Return> does not.)
Move it back.
self
.
entry
.
focus_set
()
def
cancel
(
self
,
event
=
None
):
# Do not replace.
...
...
@@ -117,12 +124,11 @@ class Query(Toplevel):
class
SectionName
(
Query
):
"Get a name for a config file section name."
# Used in ConfigDialog.GetNewKeysName, .GetNewThemeName (837)
def
__init__
(
self
,
parent
,
title
,
message
,
used_names
,
*
,
_htest
=
False
,
_utest
=
False
):
"used_names - collection of strings already in use"
self
.
used_names
=
used_names
Query
.
__init__
(
self
,
parent
,
title
,
message
,
super
()
.
__init__
(
parent
,
title
,
message
,
used_names
=
used_names
,
_htest
=
_htest
,
_utest
=
_utest
)
def
entry_ok
(
self
):
...
...
@@ -131,16 +137,16 @@ class SectionName(Query):
if
not
name
:
showerror
(
title
=
'Name Error'
,
message
=
'No name specified.'
,
parent
=
self
)
return
return
None
elif
len
(
name
)
>
30
:
showerror
(
title
=
'Name Error'
,
message
=
'Name too long. It should be no more than '
+
'30 characters.'
,
parent
=
self
)
return
return
None
elif
name
in
self
.
used_names
:
showerror
(
title
=
'Name Error'
,
message
=
'This name is already in use.'
,
parent
=
self
)
return
return
None
return
name
...
...
@@ -148,48 +154,133 @@ class ModuleName(Query):
"Get a module name for Open Module menu entry."
# Used in open_module (editor.EditorWindow until move to iobinding).
def
__init__
(
self
,
parent
,
title
,
message
,
text0
=
''
,
def
__init__
(
self
,
parent
,
title
,
message
,
text0
,
*
,
_htest
=
False
,
_utest
=
False
):
"""text0 - name selected in text before Open Module invoked"
"""
Query
.
__init__
(
self
,
parent
,
title
,
message
,
text0
=
text0
,
super
()
.
__init__
(
parent
,
title
,
message
,
text0
=
text0
,
_htest
=
_htest
,
_utest
=
_utest
)
def
entry_ok
(
self
):
"Return entered module name as file path or None."
# Moved here from Editor_Window.load_module 2016 July.
name
=
self
.
entry
.
get
()
.
strip
()
if
not
name
:
showerror
(
title
=
'Name Error'
,
message
=
'No name specified.'
,
parent
=
self
)
return
# XXX Ought to insert current file's directory in front of path
return
None
# XXX Ought to insert current file's directory in front of path
.
try
:
spec
=
importlib
.
util
.
find_spec
(
name
)
except
(
ValueError
,
ImportError
)
as
msg
:
showerror
(
"Import Error"
,
str
(
msg
),
parent
=
self
)
return
return
None
if
spec
is
None
:
showerror
(
"Import Error"
,
"module not found"
,
parent
=
self
)
return
return
None
if
not
isinstance
(
spec
.
loader
,
importlib
.
abc
.
SourceLoader
):
showerror
(
"Import Error"
,
"not a source-based module"
,
parent
=
self
)
return
return
None
try
:
file_path
=
spec
.
loader
.
get_filename
(
name
)
except
AttributeError
:
showerror
(
"Import Error"
,
"loader does not support get_filename"
,
parent
=
self
)
return
return
None
return
file_path
class
HelpSource
(
Query
):
"Get menu name and help source for Help menu."
# Used in ConfigDialog.HelpListItemAdd/Edit, (941/9)
def
__init__
(
self
,
parent
,
title
,
*
,
menuitem
=
''
,
filepath
=
''
,
used_names
=
{},
_htest
=
False
,
_utest
=
False
):
"""Get menu entry and url/local file for Additional Help.
User enters a name for the Help resource and a web url or file
name. The user can browse for the file.
"""
self
.
filepath
=
filepath
message
=
'Name for item on Help menu:'
super
()
.
__init__
(
parent
,
title
,
message
,
text0
=
menuitem
,
used_names
=
used_names
,
_htest
=
_htest
,
_utest
=
_utest
)
def
create_widgets
(
self
):
super
()
.
create_widgets
()
frame
=
self
.
frame
pathlabel
=
Label
(
frame
,
anchor
=
'w'
,
justify
=
'left'
,
text
=
'Help File Path: Enter URL or browse for file'
)
self
.
pathvar
=
StringVar
(
self
,
self
.
filepath
)
self
.
path
=
Entry
(
frame
,
textvariable
=
self
.
pathvar
,
width
=
40
)
browse
=
Button
(
frame
,
text
=
'Browse'
,
width
=
8
,
command
=
self
.
browse_file
)
pathlabel
.
pack
(
anchor
=
'w'
,
padx
=
5
,
pady
=
3
)
self
.
path
.
pack
(
anchor
=
'w'
,
padx
=
5
,
pady
=
3
)
browse
.
pack
(
pady
=
3
)
def
askfilename
(
self
,
filetypes
,
initdir
,
initfile
):
# htest #
# Extracted from browse_file so can mock for unittests.
# Cannot unittest as cannot simulate button clicks.
# Test by running htest, such as by running this file.
return
filedialog
.
Open
(
parent
=
self
,
filetypes
=
filetypes
)
\
.
show
(
initialdir
=
initdir
,
initialfile
=
initfile
)
def
browse_file
(
self
):
filetypes
=
[
(
"HTML Files"
,
"*.htm *.html"
,
"TEXT"
),
(
"PDF Files"
,
"*.pdf"
,
"TEXT"
),
(
"Windows Help Files"
,
"*.chm"
),
(
"Text Files"
,
"*.txt"
,
"TEXT"
),
(
"All Files"
,
"*"
)]
path
=
self
.
pathvar
.
get
()
if
path
:
dir
,
base
=
os
.
path
.
split
(
path
)
else
:
base
=
None
if
platform
[:
3
]
==
'win'
:
dir
=
os
.
path
.
join
(
os
.
path
.
dirname
(
executable
),
'Doc'
)
if
not
os
.
path
.
isdir
(
dir
):
dir
=
os
.
getcwd
()
else
:
dir
=
os
.
getcwd
()
file
=
self
.
askfilename
(
filetypes
,
dir
,
base
)
if
file
:
self
.
pathvar
.
set
(
file
)
item_ok
=
SectionName
.
entry_ok
# localize for test override
def
path_ok
(
self
):
"Simple validity check for menu file path"
path
=
self
.
path
.
get
()
.
strip
()
if
not
path
:
#no path specified
showerror
(
title
=
'File Path Error'
,
message
=
'No help file path specified.'
,
parent
=
self
)
return
None
elif
not
path
.
startswith
((
'www.'
,
'http'
)):
if
path
[:
5
]
==
'file:'
:
path
=
path
[
5
:]
if
not
os
.
path
.
exists
(
path
):
showerror
(
title
=
'File Path Error'
,
message
=
'Help file path does not exist.'
,
parent
=
self
)
return
None
if
platform
==
'darwin'
:
# for Mac Safari
path
=
"file://"
+
path
return
path
def
entry_ok
(
self
):
"Return apparently valid (name, path) or None"
name
=
self
.
item_ok
()
path
=
self
.
path_ok
()
return
None
if
name
is
None
or
path
is
None
else
(
name
,
path
)
if
__name__
==
'__main__'
:
import
unittest
unittest
.
main
(
'idlelib.idle_test.test_query'
,
verbosity
=
2
,
exit
=
False
)
from
idlelib.idle_test.htest
import
run
run
(
Query
)
run
(
Query
,
HelpSource
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment