https://github.com/python/cpython/commit/c2d275202830651e91c779c66213bd5ed4610144
commit: c2d275202830651e91c779c66213bd5ed4610144
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: terryjreedy <[email protected]>
date: 2026-07-01T16:49:12Z
summary:

[3.15] gh-89360: Fix ValueError in IDLE MultiCall event_delete (GH-152738) 
(#152802)

gh-89360: Fix ValueError in IDLE MultiCall event_delete (GH-152738)

Deleting a key binding for a sequence not bound to the virtual event no
longer raises a ValueError; the discrepancy is now ignored.
(cherry picked from commit ea7619faeacf310ba1b2ef41ad07966ce2aae11f)

Co-authored-by: Serhiy Storchaka <[email protected]>

files:
A Misc/NEWS.d/next/IDLE/2026-07-01-14-00-00.gh-issue-89360.mUlTiC.rst
M Lib/idlelib/idle_test/test_multicall.py
M Lib/idlelib/multicall.py

diff --git a/Lib/idlelib/idle_test/test_multicall.py 
b/Lib/idlelib/idle_test/test_multicall.py
index 7d73761cfdfee8..fcce2030579f4b 100644
--- a/Lib/idlelib/idle_test/test_multicall.py
+++ b/Lib/idlelib/idle_test/test_multicall.py
@@ -43,6 +43,22 @@ def test_yview(self):
         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)
diff --git a/Lib/idlelib/multicall.py b/Lib/idlelib/multicall.py
index 41f81813113062..95f4fee7fbe740 100644
--- a/Lib/idlelib/multicall.py
+++ b/Lib/idlelib/multicall.py
@@ -386,10 +386,11 @@ def event_delete(self, virtual, *sequences):
                 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
index 00000000000000..9e3023f8228233
--- /dev/null
+++ b/Misc/NEWS.d/next/IDLE/2026-07-01-14-00-00.gh-issue-89360.mUlTiC.rst
@@ -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``.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to