]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.11] gh-103737: IDLE - Remove unneeded .keys() for dict iteration (GH-110960) ...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 18 Oct 2023 08:40:39 +0000 (10:40 +0200)
committerGitHub <noreply@github.com>
Wed, 18 Oct 2023 08:40:39 +0000 (08:40 +0000)
gh-103737: IDLE - Remove unneeded .keys() for dict iteration (GH-110960)

Add comments where .keys() is needed.
Leave debugger usages along because situation is unclear as indicated in expanded comment.
Most testing is manual.
(cherry picked from commit baefbb21d91db2d950706737a6ebee9b2eff5c2d)

Co-authored-by: Terry Jan Reedy <tjreedy@udel.edu>
Lib/idlelib/config.py
Lib/idlelib/configdialog.py
Lib/idlelib/debugger.py
Lib/idlelib/debugobj.py
Lib/idlelib/idle_test/test_config.py
Lib/idlelib/idle_test/test_debugobj.py
Lib/idlelib/pyshell.py
Lib/idlelib/stackviewer.py

index 2b09d79470b47c48dde916301dabfcb036e7c31e..898efeb4dd15508ac82cb076ebc17705bd32eed5 100644 (file)
@@ -597,7 +597,9 @@ class IdleConf:
         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>'],
@@ -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)
@@ -889,7 +891,7 @@ def _dump():  # htest # (not really, but ignore in coverage)
 
     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 +910,6 @@ if __name__ == '__main__':
     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.
index cda7966d558a51c20ca9def0e4ef7687fef3558a..d56afe8a807fea1e6c656efd523a9d77ef94be87 100644 (file)
@@ -211,14 +211,8 @@ class ConfigDialog(Toplevel):
                   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 @@ class ConfigDialog(Toplevel):
         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()
@@ -583,6 +576,8 @@ class HighPage(Frame):
                 (*)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 +760,7 @@ class HighPage(Frame):
             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()
@@ -1477,12 +1472,13 @@ class KeysPage(Frame):
             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]:
index 452c62b42655b3b121445fb5b5e33c0b8fd0d251..a92bb98d908d462cd8709e9f3c74f9c10adbfe78 100644 (file)
@@ -509,7 +509,7 @@ class NamespaceViewer:
             # 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)
             ###
index 71d01c7070df54c843ae44392bea96d10667b775..032b686f379378b3cf7c3084799386f41b656a5b 100644 (file)
@@ -93,7 +93,8 @@ class SequenceTreeItem(ObjectTreeItem):
 
 class DictTreeItem(SequenceTreeItem):
     def keys(self):
-        keys = list(self.object.keys())
+        # TODO return sorted(self.object)
+        keys = list(self.object)
         try:
             keys.sort()
         except:
index 08ed76fe288294c8bf782d73807cc0b328dce3fd..a746f1538a62b00f57bb05b75d37ea566546c05c 100644 (file)
@@ -274,8 +274,8 @@ class IdleConfTest(unittest.TestCase):
                 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():
index 131ce22b8bb69b001a76648e0f8ca48659d9fab7..90ace4e1bc4f9ef8ca24028c4c01b985412fdc6d 100644 (file)
@@ -37,7 +37,7 @@ class SequenceTreeItemTest(unittest.TestCase):
 
     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 @@ class DictTreeItemTest(unittest.TestCase):
 
     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__':
index 3141b477eff181713bde248cdd422a702bb28bde..0a7ee59f730a561595b40138072faef51a4fbd29 100755 (executable)
@@ -747,10 +747,11 @@ class ModifiedInterpreter(InteractiveInterpreter):
             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"
index 7b00c4cdb7d0338b4e977dbcdda7d8f55a10b462..4858cc682a4f453566aa14813be9f914776e260c 100644 (file)
@@ -99,7 +99,7 @@ class VariablesTreeItem(ObjectTreeItem):
 
     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: