diff --git a/Lib/idlelib/idle_test/test_multicall.py b/Lib/idlelib/idle_test/test_multicall.py index 7d73761cfdfee82..fcce2030579f4be 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('<>', '') + info = mctext.event_info('<>') + self.assertEqual(len(info), 1) + + # A different sequence, never added: a no-op, not an error. + mctext.event_delete('<>', '') + self.assertEqual(mctext.event_info('<>'), info) + + # The added sequence can still be deleted normally. + mctext.event_delete('<>', '') + self.assertNotIn(info[0], mctext.event_info('<>')) + if __name__ == '__main__': unittest.main(verbosity=2) diff --git a/Lib/idlelib/multicall.py b/Lib/idlelib/multicall.py index 41f818131130621..95f4fee7fbe740a 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 000000000000000..9e3023f8228233f --- /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``.