From 9671f6842cd34ffbbb5f96ad96603055dbfbdaef Mon Sep 17 00:00:00 2001 From: Tal Einat <532281+taleinat@users.noreply.github.com> Date: Thu, 27 May 2021 18:24:22 +0300 Subject: [PATCH 1/2] bpo-41611: IDLE: Catch TclError exceptions in AutoCompleteWindow.winconfig_event() Due to the event sometimes being triggered after some delay, the completion list window may no longer exist when the handler is called. Therefore it is necessary to catch potential TclError exceptions in the handler's code. Signed-off-by: Tal Einat <532281+taleinat@users.noreply.github.com> --- Lib/idlelib/autocomplete_w.py | 65 +++++++++++-------- .../2021-05-27-18-22-46.bpo-41611.jOKpfc.rst | 1 + 2 files changed, 39 insertions(+), 27 deletions(-) create mode 100644 Misc/NEWS.d/next/IDLE/2021-05-27-18-22-46.bpo-41611.jOKpfc.rst diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index 4676822a697034..981d253348b341 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -242,37 +242,48 @@ def winconfig_event(self, event): self.is_configuring = True if not self.is_active(): return - # Position the completion list window - text = self.widget - text.see(self.startindex) - x, y, cx, cy = text.bbox(self.startindex) - acw = self.autocompletewindow - if platform.system().startswith('Windows'): - # On Windows an update() call is needed for the completion list - # window to be created, so that we can fetch its width and - # height. However, this is not needed on other platforms (tested - # on Ubuntu and macOS) but at one point began causing freezes on - # macOS. See issues 37849 and 41611. - acw.update() - acw_width, acw_height = acw.winfo_width(), acw.winfo_height() - text_width, text_height = text.winfo_width(), text.winfo_height() - new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) - new_y = text.winfo_rooty() + y - if (text_height - (y + cy) >= acw_height # enough height below - or y < acw_height): # not enough height above - # place acw below current line - new_y += cy - else: - # place acw above current line - new_y -= acw_height - acw.wm_geometry("+%d+%d" % (new_x, new_y)) - acw.update_idletasks() + + # Due to the event sometimes being triggered after some + # delay, the completion list window may no longer exist when the + # handler is called. Therefore it is necessary to catch potential + # TclError exceptions in the handler's code. See: bpo-41611. + try: + # Position the completion list window + text = self.widget + text.see(self.startindex) + x, y, cx, cy = text.bbox(self.startindex) + acw = self.autocompletewindow + if platform.system().startswith('Windows'): + # On Windows an update() call is needed for the completion + # list window to be created, so that we can fetch its width + # and height. However, this is not needed on other platforms + # (tested on Ubuntu and macOS) but at one point began + # causing freezes on macOS. See issues 37849 and 41611. + acw.update() + acw_width, acw_height = acw.winfo_width(), acw.winfo_height() + text_width, text_height = text.winfo_width(), text.winfo_height() + new_x = text.winfo_rootx() + min(x, max(0, text_width - acw_width)) + new_y = text.winfo_rooty() + y + if (text_height - (y + cy) >= acw_height # enough height below + or y < acw_height): # not enough height above + # place acw below current line + new_y += cy + else: + # place acw above current line + new_y -= acw_height + acw.wm_geometry("+%d+%d" % (new_x, new_y)) + acw.update_idletasks() + except TclError: + pass if platform.system().startswith('Windows'): - # See issue 15786. When on Windows platform, Tk will misbehave + # See issue 15786. When on Windows platform, Tk will misbehave # to call winconfig_event multiple times, we need to prevent this, # otherwise mouse button double click will not be able to used. - acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) + try: + acw.unbind(WINCONFIG_SEQUENCE, self.winconfigid) + except TclError: + pass self.winconfigid = None self.is_configuring = False diff --git a/Misc/NEWS.d/next/IDLE/2021-05-27-18-22-46.bpo-41611.jOKpfc.rst b/Misc/NEWS.d/next/IDLE/2021-05-27-18-22-46.bpo-41611.jOKpfc.rst new file mode 100644 index 00000000000000..a80c9f7c5a73b6 --- /dev/null +++ b/Misc/NEWS.d/next/IDLE/2021-05-27-18-22-46.bpo-41611.jOKpfc.rst @@ -0,0 +1 @@ +Avoid uncaught exceptions in ``AutoCompleteWindow.winconfig_event()``. From d4ffbb8b9ff0d3262c5e2773eada55daab22b05f Mon Sep 17 00:00:00 2001 From: Terry Jan Reedy Date: Thu, 27 May 2021 15:18:13 -0400 Subject: [PATCH 2/2] Update autocomplete_w.py Condense comment. --- Lib/idlelib/autocomplete_w.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Lib/idlelib/autocomplete_w.py b/Lib/idlelib/autocomplete_w.py index 981d253348b341..2e3f9c14a19814 100644 --- a/Lib/idlelib/autocomplete_w.py +++ b/Lib/idlelib/autocomplete_w.py @@ -243,10 +243,8 @@ def winconfig_event(self, event): if not self.is_active(): return - # Due to the event sometimes being triggered after some - # delay, the completion list window may no longer exist when the - # handler is called. Therefore it is necessary to catch potential - # TclError exceptions in the handler's code. See: bpo-41611. + # Since the event may occur after the completion window is gone, + # catch potential TclError exceptions when accessing acw. See: bpo-41611. try: # Position the completion list window text = self.widget