]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-89360: Fix ValueError in IDLE MultiCall event_delete (#152738)
authorSerhiy Storchaka <storchaka@gmail.com>
Wed, 1 Jul 2026 16:22:03 +0000 (19:22 +0300)
committerGitHub <noreply@github.com>
Wed, 1 Jul 2026 16:22:03 +0000 (12:22 -0400)
Deleting a key binding for a sequence not bound to the virtual event no
longer raises a ValueError; the discrepancy is now ignored.

Lib/idlelib/idle_test/test_multicall.py
Lib/idlelib/multicall.py
Misc/NEWS.d/next/IDLE/2026-07-01-14-00-00.gh-issue-89360.mUlTiC.rst [new file with mode: 0644]

index 7d73761cfdfee828da3f021f49ffda0afab780bb..fcce2030579f4be860e4e9a396fa9414f0f5ff5a 100644 (file)
@@ -43,6 +43,22 @@ class MultiCallTest(unittest.TestCase):
         mctext = self.mc(self.root)
         self.assertIs(mctext.yview.__func__, Text.yview)
 
+    def test_event_delete_unbound_sequence(self):
+        # gh-89360: deleting a sequence that was not added to a virtual
+        # event is ignored instead of raising ValueError.
+        mctext = self.mc(self.root)
+        mctext.event_add('<<tester>>', '<Control-Key-a>')
+        info = mctext.event_info('<<tester>>')
+        self.assertEqual(len(info), 1)
+
+        # A different sequence, never added: a no-op, not an error.
+        mctext.event_delete('<<tester>>', '<Control-Key-b>')
+        self.assertEqual(mctext.event_info('<<tester>>'), info)
+
+        # The added sequence can still be deleted normally.
+        mctext.event_delete('<<tester>>', '<Control-Key-a>')
+        self.assertNotIn(info[0], mctext.event_info('<<tester>>'))
+
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)
index 41f81813113062167b813f1400aff15ad140afc3..95f4fee7fbe740ad59247520c96da679cdc3074c 100644 (file)
@@ -386,10 +386,11 @@ def MultiCallCreator(widget):
                 if triplet is None:
                     #print("Tkinter event_delete: %s" % seq, file=sys.__stderr__)
                     widget.event_delete(self, virtual, seq)
-                else:
+                elif triplet in triplets:
                     if func is not None:
                         self.__binders[triplet[1]].unbind(triplet, func)
                     triplets.remove(triplet)
+                # Else the sequence is not bound; ignore it (gh-89360).
 
         def event_info(self, virtual=None):
             if virtual is None or virtual not in self.__eventinfo:
diff --git a/Misc/NEWS.d/next/IDLE/2026-07-01-14-00-00.gh-issue-89360.mUlTiC.rst b/Misc/NEWS.d/next/IDLE/2026-07-01-14-00-00.gh-issue-89360.mUlTiC.rst
new file mode 100644 (file)
index 0000000..9e3023f
--- /dev/null
@@ -0,0 +1,3 @@
+Fix a rare crash in the IDLE editor when the completion window is closed:
+deleting a key binding for a sequence that is not bound to the virtual
+event is now ignored instead of raising a ``ValueError``.