Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Lib/.ruff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ select = [
"ctypes/__init__.py" = ["F401"] # Re-exports from _ctypes
"ensurepip/__init__.py" = ["F401"] # `import zlib` availability check
"idlelib/idle_test/htest.py" = ["F401"] # Import for Windows DPI side effect
"idlelib/idle_test/template.py" = ["F401"] # Placeholder import, see README.txt
"idlelib/idle_test/test_iomenu.py" = ["F401"] # Imports checked for existence
"importlib/_abc.py" = ["F401"] # Bootstrap-sensitive _bootstrap import
"importlib/machinery.py" = ["F401"] # NamespacePath re-export
Expand Down
1 change: 1 addition & 0 deletions Lib/idlelib/idle_test/template.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"Test , coverage %."

from idlelib import zzdummy
import unittest
from test.support import requires
from tkinter import Tk
Expand Down
60 changes: 43 additions & 17 deletions Lib/idlelib/idle_test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -454,9 +454,6 @@ def test_get_extension_keys(self):
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('''
Expand Down Expand Up @@ -491,19 +488,27 @@ def test_get_keybinding(self):
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
try:
# Ensure that platform isn't darwin
sys.platform = 'some-linux'
self.assertEqual(conf.GetCurrentKeySet(),
conf.GetKeySet(conf.CurrentKeys()))

# On darwin, '<Alt-' is replaced with '<Option-'. Add an
# extension binding, as the default key sets have no Alt keys.
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',
'<Alt-Shift-Key-F12>')
self.assertEqual(conf.GetKeySet(conf.CurrentKeys())['<<newfoo>>'],
['<Alt-Shift-Key-F12>'])
sys.platform = 'darwin'
self.assertEqual(conf.GetCurrentKeySet()['<<newfoo>>'],
['<Option-Shift-Key-F12>'])
finally:
# Restore platform
sys.platform = current_platform

def test_get_keyset(self):
conf = self.mock_config()
Expand Down Expand Up @@ -762,8 +767,29 @@ 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.
self.assertFalse(changes.save_all())
self.assertFalse(usermain.has_option('Indent', 'use-spaces'))
self.assertEqual(changes, self.empty)

# TODO: test that save_all calls usercfg Saves.
def test_save_all_saves_files(self):
eq = self.assertEqual
changes = self.changes
for parser in testcfg.values():
parser.Save = Func()
try:
# 'main', 'highlight' and 'keys' are saved even if unchanged.
self.assertFalse(changes.save_all())
eq([testcfg[cfgtype].Save.called
for cfgtype in ('main', 'highlight', 'keys', 'extensions')],
[1, 1, 1, 0])
# A changed configuration type is saved too.
changes.add_option('extensions', 'Esec', 'eitem', 'eval')
self.assertTrue(changes.save_all())
eq(testcfg['extensions'].Save.called, 1)
finally:
for parser in testcfg.values():
del parser.Save
userextn.remove_section('Esec')

def test_delete_section(self):
changes = self.load()
Expand Down
138 changes: 132 additions & 6 deletions Lib/idlelib/idle_test/test_configdialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Half the class creates dialog, half works with user customizations.
"""
from idlelib import configdialog
from idlelib.editor import EditorWindow
from test.support import requires
requires('gui')
import unittest
Expand Down Expand Up @@ -51,12 +52,27 @@ def tearDownModule():


class ConfigDialogTest(unittest.TestCase):
# The methods tested here are mocked out in the tests below.

def setUp(self):
self.parent = dialog.parent
self.instance = mock.create_autospec(EditorWindow, instance=True)
dialog.parent = mock.Mock(instance_dict={self.instance: []})

def tearDown(self):
dialog.parent = self.parent

def test_deactivate_current_config(self):
pass
dialog.deactivate_current_config()
self.instance.RemoveKeybindings.assert_called_once_with()

def activate_config_changes(self):
pass
def test_activate_config_changes(self):
dialog.activate_config_changes()
for name in ('ResetColorizer', 'ResetFont', 'set_notabs_indentwidth',
'ApplyKeybindings', 'reset_help_menu_entries',
'update_cursor_blink'):
with self.subTest(name=name):
getattr(self.instance, name).assert_called_once_with()


class ButtonTest(unittest.TestCase):
Expand Down Expand Up @@ -1295,13 +1311,123 @@ def test_context(self):
self.assertEqual(extpage, {'CodeContext': {'maxlines': '1'}})


#unittest.skip("Nothing here yet TODO")
class ExtPageTest(unittest.TestCase):
"""Test that the help source list works correctly."""
"""Test that the extension page works correctly.

The page loads the options of each extension from the default and
user config files, displays those of the selected extension, and
saves the changed ones to the user config file. ZzDummy is the
only extension shipped with IDLE.
"""
@classmethod
def setUpClass(cls):
page = dialog.extpage
page = cls.page = dialog.extpage
dialog.note.select(page)
page.update()

def setUp(self):
# Restore the option vars changed by the previous test.
self.page.load_extensions()

def tearDown(self):
self.page.ext_userCfg.remove_section('ZzDummy')

def test_load_extensions(self):
eq = self.assertEqual
extensions = self.page.extensions
eq(list(extensions), sorted(idleConf.GetExtensions(active_only=False)))
opts = extensions['ZzDummy']
# The 'enable' options come first, the others follow, both sorted.
eq([opt['name'] for opt in opts],
['enable', 'enable_editor', 'enable_shell', 'z-text'])
eq([opt['type'] for opt in opts], ['bool', 'bool', 'bool', None])
eq([opt['default'] for opt in opts], ['False', 'True', 'False', 'Z'])
eq([opt['value'] for opt in opts], [False, True, False, 'Z'])
for opt in opts:
with self.subTest(name=opt['name']):
eq(opt['var'].get(), str(opt['value']))

def test_load_extensions_enable_first(self):
# The 'enable' options come first even if they sort last.
page = self.page
page.ext_userCfg.SetOption('ZzDummy', 'a-text', 'A')
page.load_extensions()
self.assertEqual([opt['name'] for opt in page.extensions['ZzDummy']],
['enable', 'enable_editor', 'enable_shell',
'a-text', 'z-text'])

def test_load_extensions_user_value(self):
# A user option overrides the default value, but not the default.
page = self.page
page.ext_userCfg.SetOption('ZzDummy', 'z-text', 'user')
page.load_extensions()
opt = page.extensions['ZzDummy'][-1]
self.assertEqual(opt['name'], 'z-text')
self.assertEqual(opt['default'], 'Z')
self.assertEqual(opt['value'], 'user')
self.assertEqual(opt['var'].get(), 'user')

def test_extension_selected(self):
eq = self.assertEqual
page = self.page
frame = page.config_frame['ZzDummy']
# Deselecting hides the options of the current extension.
page.extension_list.selection_clear(0, 'end')
page.extension_selected(None)
eq(page.current_extension, None)
eq(page.details_frame.cget('text'), '')
eq(frame.winfo_manager(), '')
# Selecting shows the options of the selected extension.
page.extension_list.selection_set(0)
page.extension_selected(None)
eq(page.current_extension, 'ZzDummy')
eq(page.details_frame.cget('text'), 'ZzDummy')
eq(frame.winfo_manager(), 'grid')

def test_set_extension_value_changed(self):
page = self.page
opt = page.extensions['ZzDummy'][-1] # z-text, default 'Z'.
opt['var'].set('user')
self.assertTrue(page.set_extension_value('ZzDummy', opt))
self.assertEqual(page.ext_userCfg.Get('ZzDummy', 'z-text'), 'user')
# Saving the same value again is not a change.
self.assertFalse(page.set_extension_value('ZzDummy', opt))

def test_set_extension_value_default(self):
page = self.page
opt = page.extensions['ZzDummy'][-1]
# The default value is not saved in the user config file.
opt['var'].set('Z')
self.assertFalse(page.set_extension_value('ZzDummy', opt))
self.assertFalse(page.ext_userCfg.has_option('ZzDummy', 'z-text'))
# Setting it back to the default removes the user option.
page.ext_userCfg.SetOption('ZzDummy', 'z-text', 'user')
self.assertTrue(page.set_extension_value('ZzDummy', opt))
self.assertFalse(page.ext_userCfg.has_option('ZzDummy', 'z-text'))

def test_set_extension_value_empty(self):
# An empty value is replaced with the default.
page = self.page
opt = page.extensions['ZzDummy'][-1]
opt['var'].set(' ')
self.assertFalse(page.set_extension_value('ZzDummy', opt))
self.assertEqual(opt['var'].get(), 'Z')

def test_save_all_changed_extensions(self):
page = self.page
page.ext_userCfg.Save = Func()
try:
# Nothing is saved if nothing is changed.
page.save_all_changed_extensions()
self.assertEqual(page.ext_userCfg.Save.called, 0)
page.extensions['ZzDummy'][0]['var'].set('True')
page.extensions['ZzDummy'][-1]['var'].set('user')
page.save_all_changed_extensions()
self.assertEqual(page.ext_userCfg.Save.called, 1)
self.assertEqual(page.ext_userCfg.Get('ZzDummy', 'enable'), 'True')
self.assertEqual(page.ext_userCfg.Get('ZzDummy', 'z-text'), 'user')
finally:
del page.ext_userCfg.Save


class HelpSourceTest(unittest.TestCase):
Expand Down
57 changes: 54 additions & 3 deletions Lib/idlelib/idle_test/test_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,11 +219,13 @@ def setUpClass(cls):
cls.root = Tk()
cls.root.withdraw()
cls.window = Editor(root=cls.root)
cls.text = cls.window.text
cls.window.rmenu = cls.DummyRMenu

@classmethod
def tearDownClass(cls):
cls.window._close()
del cls.window
del cls.window, cls.text
cls.root.update_idletasks()
for id in cls.root.after_info():
cls.root.after_cancel(id)
Expand All @@ -233,8 +235,57 @@ def tearDownClass(cls):
class DummyRMenu:
def tk_popup(x, y): pass

def test_rclick(self):
pass
def click(self, x=0, y=0):
"""Simulate a right click at the (x, y) pixel of the text.

Return the index of the clicked character, as computed by the
widget itself. It cannot be computed here, because the geometry
of the text is unknown while its window is not mapped.
"""
index = self.text.index(f'@{x},{y}')
Event = namedtuple('Event', ['x', 'y', 'x_root', 'y_root'])
event = Event(x, y, x_root=0, y_root=0)
self.assertEqual(self.window.right_menu_event(event), 'break')
return index

def test_rclick_no_selection(self):
text = self.text
insert(text, 'one two three')
index = self.click()
self.assertEqual(text.tag_ranges('sel'), ())
self.assertEqual(text.index('insert'), index)

def test_rclick_outside_selection(self):
text = self.text
insert(text, 'one two three')
# The selection does not contain the clicked character.
text.tag_add('sel', '1.5', '1.8')
text.mark_set('insert', '1.8')
index = self.click()
self.assertEqual(text.tag_ranges('sel'), ())
self.assertEqual(text.index('insert'), index)

def test_rclick_inside_selection(self):
text = self.text
insert(text, 'one two three')
# The selection contains the clicked character.
index = text.index('@0,0')
text.tag_add('sel', index, f'{index}+3c')
text.mark_set('insert', 'end-1c')
self.click()
self.assertEqual(text.index('sel.first'), index)
self.assertEqual(text.index('sel.last'), text.index(f'{index}+3c'))
self.assertEqual(text.index('insert'), text.index('end-1c'))

def test_rmenu_check_copy(self):
text = self.text
insert(text, 'one two three')
eq = self.assertEqual
eq(self.window.rmenu_check_copy(), 'disabled')
eq(self.window.rmenu_check_cut(), 'disabled')
text.tag_add('sel', '1.0', '1.3')
eq(self.window.rmenu_check_copy(), 'normal')
eq(self.window.rmenu_check_cut(), 'normal')


if __name__ == '__main__':
Expand Down
Loading
Loading