From 7bb15ecbba8d99928466f0fdf9016cdf6fcbcc0a Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Sun, 23 Apr 2023 23:53:54 -0400 Subject: [PATCH 1/8] gh-103737: IDLE - Removes unneeded .keys() for dict iteration. Comment some of non-dict .keys() returns. config: remove .keys(), fix dump, add comments. debugobj: remove one .keys() test_config: remove .keys() test_debugobj: comment .keys() returns --- Lib/idlelib/config.py | 8 +++++--- Lib/idlelib/debugobj.py | 3 ++- Lib/idlelib/idle_test/test_config.py | 4 ++-- Lib/idlelib/idle_test/test_debugobj.py | 4 ++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 2b09d79470b47c..91926fba1ac91f 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -880,7 +880,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) @@ -889,7 +889,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) @@ -908,4 +908,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. diff --git a/Lib/idlelib/debugobj.py b/Lib/idlelib/debugobj.py index 5a4c9978842035..59816f190288a8 100644 --- a/Lib/idlelib/debugobj.py +++ b/Lib/idlelib/debugobj.py @@ -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: diff --git a/Lib/idlelib/idle_test/test_config.py b/Lib/idlelib/idle_test/test_config.py index 697fda527968de..c7edd2f91acfc8 100644 --- a/Lib/idlelib/idle_test/test_config.py +++ b/Lib/idlelib/idle_test/test_config.py @@ -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(): diff --git a/Lib/idlelib/idle_test/test_debugobj.py b/Lib/idlelib/idle_test/test_debugobj.py index 131ce22b8bb69b..90ace4e1bc4f9e 100644 --- a/Lib/idlelib/idle_test/test_debugobj.py +++ b/Lib/idlelib/idle_test/test_debugobj.py @@ -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): @@ -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__': From d5ffa71b57ee684e4d85c3b651d28745dadb411b Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Mon, 24 Apr 2023 00:11:01 -0400 Subject: [PATCH 2/8] Leave .keys() alone debugger: must verify note, added TODO debugger_r: must verify note pyshell: dict changed in iteration stackviewer: object possibly not dict --- Lib/idlelib/debugger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/debugger.py b/Lib/idlelib/debugger.py index ccd03e46e16147..e634a2e753b072 100644 --- a/Lib/idlelib/debugger.py +++ b/Lib/idlelib/debugger.py @@ -508,7 +508,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. keys_list = dict.keys() names = sorted(keys_list) ### From f2afbe9bbf8b67b130daf53bbafa9237ed339ed1 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 17 Oct 2023 00:44:41 -0400 Subject: [PATCH 3/8] Expand debugger recheck comment with cross references. --- Lib/idlelib/debugger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/debugger.py b/Lib/idlelib/debugger.py index a4b9336d78b8e7..a92bb98d908d46 100644 --- a/Lib/idlelib/debugger.py +++ b/Lib/idlelib/debugger.py @@ -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. + # TODO recheck above; see debugger_r 159ff, debugobj 60. keys_list = dict.keys() names = sorted(keys_list) ### From b81b49054df8d423a33435d872e9f6bd3df3134c Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 17 Oct 2023 00:46:15 -0400 Subject: [PATCH 4/8] pyshell: remove '.keys()'. Expand 'c' to 'cache'. --- Lib/idlelib/pyshell.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index 6028700356b171..7a2707935b60c9 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -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 ''." + 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" From 43cc81a1f83d7524cfef4399bfcd2d7f59356454 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 17 Oct 2023 01:01:20 -0400 Subject: [PATCH 5/8] configdialog HighPage theme_elements is dict. Tested without .keys(). Add note about removing sort numbers later. --- Lib/idlelib/configdialog.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index cda7966d558a51..7dad69443687c6 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -583,6 +583,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'), @@ -765,7 +767,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() From bbca9a158f362cee59fc1efa94dcedfc1b75c111 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 17 Oct 2023 01:36:28 -0400 Subject: [PATCH 6/8] configdialog KeysPage keyset is dict Tested Keys action-keys list still present and sorted. --- Lib/idlelib/config.py | 2 ++ Lib/idlelib/configdialog.py | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Lib/idlelib/config.py b/Lib/idlelib/config.py index 91926fba1ac91f..898efeb4dd1550 100644 --- a/Lib/idlelib/config.py +++ b/Lib/idlelib/config.py @@ -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. '<>': ['', ''], '<>': ['', ''], '<>': ['', ''], diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 7dad69443687c6..6224e129a2b346 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -1479,12 +1479,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]: From 8bae238e7f6945377cdfc435f6975cba8b570e1d Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 17 Oct 2023 02:06:41 -0400 Subject: [PATCH 7/8] configdialog apply key changes: remove .keys() editor.py 1028 already has 'for instance in ... instance_dict. Also tested that can change keys. --- Lib/idlelib/configdialog.py | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Lib/idlelib/configdialog.py b/Lib/idlelib/configdialog.py index 6224e129a2b346..d56afe8a807fea 100644 --- a/Lib/idlelib/configdialog.py +++ b/Lib/idlelib/configdialog.py @@ -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): @@ -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() From 510f89963a07c5b7efb7b463e8be63026d5fb436 Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Tue, 17 Oct 2023 02:07:31 -0400 Subject: [PATCH 8/8] stackviewer: object not necessarily dict. --- Lib/idlelib/stackviewer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/idlelib/stackviewer.py b/Lib/idlelib/stackviewer.py index 7b00c4cdb7d033..4858cc682a4f45 100644 --- a/Lib/idlelib/stackviewer.py +++ b/Lib/idlelib/stackviewer.py @@ -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: