Skip to content

Commit

Permalink
gh-103737: IDLE - Remove unneeded .keys() for dict iteration (#110960)
Browse files Browse the repository at this point in the history
Add comments where .keys() is needed.
Leave debugger usages along because situation is unclear as indicated in expanded comment.
Most testing is manual.
  • Loading branch information
terryjreedy committed Oct 18, 2023
1 parent 77dbd95 commit baefbb2
Show file tree
Hide file tree
Showing 8 changed files with 28 additions and 26 deletions.
10 changes: 7 additions & 3 deletions Lib/idlelib/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,9 @@ def GetCoreKeys(self, keySetName=None):
problem getting any core binding there will be an 'ultimate last
resort fallback' to the CUA-ish bindings defined here.
"""
# TODO: = dict(sorted([(v-event, keys), ...]))?
keyBindings={
# vitual-event: list of key events.
'<<copy>>': ['<Control-c>', '<Control-C>'],
'<<cut>>': ['<Control-x>', '<Control-X>'],
'<<paste>>': ['<Control-v>', '<Control-V>'],
Expand Down Expand Up @@ -880,7 +882,7 @@ def _dump(): # htest # (not really, but ignore in coverage)
line, crc = 0, 0

def sprint(obj):
global line, crc
nonlocal line, crc
txt = str(obj)
line += 1
crc = crc32(txt.encode(encoding='utf-8'), crc)
Expand All @@ -889,7 +891,7 @@ def sprint(obj):

def dumpCfg(cfg):
print('\n', cfg, '\n') # Cfg has variable '0xnnnnnnnn' address.
for key in sorted(cfg.keys()):
for key in sorted(cfg):
sections = cfg[key].sections()
sprint(key)
sprint(sections)
Expand All @@ -908,4 +910,6 @@ def dumpCfg(cfg):
from unittest import main
main('idlelib.idle_test.test_config', verbosity=2, exit=False)

# Run revised _dump() as htest?
_dump()
# Run revised _dump() (700+ lines) as htest? More sorting.
# Perhaps as window with tabs for textviews, making it config viewer.
22 changes: 9 additions & 13 deletions Lib/idlelib/configdialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,8 @@ def help(self):
contents=help_common+help_pages.get(page, ''))

def deactivate_current_config(self):
"""Remove current key bindings.
Iterate over window instances defined in parent and remove
the keybindings.
"""
# Before a config is saved, some cleanup of current
# config must be done - remove the previous keybindings.
win_instances = self.parent.instance_dict.keys()
for instance in win_instances:
"""Remove current key bindings in current windows."""
for instance in self.parent.instance_dict:
instance.RemoveKeybindings()

def activate_config_changes(self):
Expand All @@ -227,8 +221,7 @@ def activate_config_changes(self):
Dynamically update the current parent window instances
with some of the configuration changes.
"""
win_instances = self.parent.instance_dict.keys()
for instance in win_instances:
for instance in self.parent.instance_dict:
instance.ResetColorizer()
instance.ResetFont()
instance.set_notabs_indentwidth()
Expand Down Expand Up @@ -583,6 +576,8 @@ def create_page_highlight(self):
(*)theme_message: Label
"""
self.theme_elements = {
# Display_name: ('internal_name, sort_number').
# TODO: remove sort_number unneeded with dict ordering.
'Normal Code or Text': ('normal', '00'),
'Code Context': ('context', '01'),
'Python Keywords': ('keyword', '02'),
Expand Down Expand Up @@ -765,7 +760,7 @@ def load_theme_cfg(self):
self.builtinlist.SetMenu(item_list, item_list[0])
self.set_theme_type()
# Load theme element option menu.
theme_names = list(self.theme_elements.keys())
theme_names = list(self.theme_elements)
theme_names.sort(key=lambda x: self.theme_elements[x][1])
self.targetlist.SetMenu(theme_names, theme_names[0])
self.paint_theme_sample()
Expand Down Expand Up @@ -1477,12 +1472,13 @@ def load_keys_list(self, keyset_name):
reselect = True
list_index = self.bindingslist.index(ANCHOR)
keyset = idleConf.GetKeySet(keyset_name)
bind_names = list(keyset.keys())
# 'set' is dict mapping virtual event to list of key events.
bind_names = list(keyset)
bind_names.sort()
self.bindingslist.delete(0, END)
for bind_name in bind_names:
key = ' '.join(keyset[bind_name])
bind_name = bind_name[2:-2] # Trim off the angle brackets.
bind_name = bind_name[2:-2] # Trim double angle brackets.
if keyset_name in changes['keys']:
# Handle any unsaved changes to this key set.
if bind_name in changes['keys'][keyset_name]:
Expand Down
2 changes: 1 addition & 1 deletion Lib/idlelib/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ def load_dict(self, dict, force=0, rpc_client=None):
# There is also an obscure bug in sorted(dict) where the
# interpreter gets into a loop requesting non-existing dict[0],
# dict[1], dict[2], etc from the debugger_r.DictProxy.
###
# TODO recheck above; see debugger_r 159ff, debugobj 60.
keys_list = dict.keys()
names = sorted(keys_list)
###
Expand Down
3 changes: 2 additions & 1 deletion Lib/idlelib/debugobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ def setfunction(value, key=key, object=self.object):

class DictTreeItem(SequenceTreeItem):
def keys(self):
keys = list(self.object.keys())
# TODO return sorted(self.object)
keys = list(self.object)
try:
keys.sort()
except:
Expand Down
4 changes: 2 additions & 2 deletions Lib/idlelib/idle_test/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ def test_create_config_handlers(self):
conf.CreateConfigHandlers()

# Check keys are equal
self.assertCountEqual(conf.defaultCfg.keys(), conf.config_types)
self.assertCountEqual(conf.userCfg.keys(), conf.config_types)
self.assertCountEqual(conf.defaultCfg, conf.config_types)
self.assertCountEqual(conf.userCfg, conf.config_types)

# Check conf parser are correct type
for default_parser in conf.defaultCfg.values():
Expand Down
4 changes: 2 additions & 2 deletions Lib/idlelib/idle_test/test_debugobj.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_isexpandable(self):

def test_keys(self):
ti = debugobj.SequenceTreeItem('label', 'abc')
self.assertEqual(list(ti.keys()), [0, 1, 2])
self.assertEqual(list(ti.keys()), [0, 1, 2]) # keys() is a range.


class DictTreeItemTest(unittest.TestCase):
Expand All @@ -50,7 +50,7 @@ def test_isexpandable(self):

def test_keys(self):
ti = debugobj.DictTreeItem('label', {1:1, 0:0, 2:2})
self.assertEqual(ti.keys(), [0, 1, 2])
self.assertEqual(ti.keys(), [0, 1, 2]) # keys() is a sorted list.


if __name__ == '__main__':
Expand Down
7 changes: 4 additions & 3 deletions Lib/idlelib/pyshell.py
Original file line number Diff line number Diff line change
Expand Up @@ -747,10 +747,11 @@ def showtraceback(self):
self.tkconsole.open_stack_viewer()

def checklinecache(self):
c = linecache.cache
for key in list(c.keys()):
"Remove keys other than '<pyshell#n>'."
cache = linecache.cache
for key in list(cache): # Iterate list because mutate cache.
if key[:1] + key[-1:] != "<>":
del c[key]
del cache[key]

def runcommand(self, code):
"Run the code without invoking the debugger"
Expand Down
2 changes: 1 addition & 1 deletion Lib/idlelib/stackviewer.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def IsExpandable(self):

def GetSubList(self):
sublist = []
for key in self.object.keys():
for key in self.object.keys(): # self.object not necessarily dict.
try:
value = self.object[key]
except KeyError:
Expand Down

0 comments on commit baefbb2

Please sign in to comment.