Skip to content

Commit a215d91

Browse files
PR: Make infowidget a property to prevent errors when it's garbage collected (IPython console) (#23845)
Co-authored-by: Carlos Cordoba <[email protected]>
1 parent 03decbb commit a215d91

File tree

1 file changed

+43
-25
lines changed

1 file changed

+43
-25
lines changed

spyder/plugins/ipythonconsole/widgets/main_widget.py

+43-25
Original file line numberDiff line numberDiff line change
@@ -327,18 +327,10 @@ def __init__(self, name=None, plugin=None, parent=None):
327327

328328
# Info widget
329329
if self.enable_infowidget:
330-
from spyder.widgets.browser import FrameWebView
331-
332-
self.infowidget = FrameWebView(self)
333-
if WEBENGINE:
334-
self.infowidget.page().setBackgroundColor(
335-
QColor(MAIN_BG_COLOR))
336-
else:
337-
self.infowidget.setStyleSheet(
338-
"background:{}".format(MAIN_BG_COLOR))
339-
layout.addWidget(self.infowidget)
330+
self._infowidget = self._create_info_widget()
331+
layout.addWidget(self._infowidget)
340332
else:
341-
self.infowidget = None
333+
self._infowidget = None
342334

343335
# Label to inform users how to get out of the pager
344336
self.pager_label = QLabel(_("Press <b>Q</b> to exit pager"), self)
@@ -1093,6 +1085,19 @@ def change_client_mpl_conf(o=_options, c=client):
10931085

10941086
# ---- Private methods
10951087
# -------------------------------------------------------------------------
1088+
def _create_info_widget(self):
1089+
from spyder.widgets.browser import FrameWebView
1090+
1091+
infowidget = FrameWebView(self)
1092+
if WEBENGINE:
1093+
infowidget.page().setBackgroundColor(
1094+
QColor(MAIN_BG_COLOR))
1095+
else:
1096+
infowidget.setStyleSheet(
1097+
"background:{}".format(MAIN_BG_COLOR)
1098+
)
1099+
return infowidget
1100+
10961101
def _change_client_conf(self, client, client_conf_func, value):
10971102
"""
10981103
Change a client configuration option, taking into account if it is
@@ -1358,6 +1363,8 @@ def _update_environment_menu(self):
13581363
# Render consoles menu and submenus
13591364
self.console_environment_menu.render()
13601365

1366+
# ---- Public API
1367+
# -------------------------------------------------------------------------
13611368
def find_connection_file(self, connection_file):
13621369
"""Fix connection file path."""
13631370
cf_path = osp.dirname(connection_file)
@@ -1382,16 +1389,34 @@ def find_connection_file(self, connection_file):
13821389

13831390
return connection_file
13841391

1385-
# ---- Public API
1386-
# -------------------------------------------------------------------------
1392+
@property
1393+
def infowidget(self):
1394+
"""
1395+
This is necessary to prevent an error when, in some situations, Python
1396+
garbage collects _infowidget.
1397+
1398+
Notes
1399+
-----
1400+
* See spyder-ide/spyder#21509 and spyder-ide/spyder#23529
1401+
"""
1402+
try:
1403+
# We need to call a method to detect if the object was garbage
1404+
# collected and trigger the RuntimeError we want to catch here.
1405+
self._infowidget.isVisible()
1406+
return self._infowidget
1407+
except RuntimeError:
1408+
self._infowidget = self._create_info_widget()
1409+
return self._infowidget
1410+
except AttributeError:
1411+
return None
13871412

13881413
# ---- General
13891414
# -------------------------------------------------------------------------
13901415
def update_font(self, font, app_font):
13911416
self._font = font
13921417
self._app_font = app_font
13931418

1394-
if self.enable_infowidget:
1419+
if self.enable_infowidget and self.infowidget is not None:
13951420
self.infowidget.set_font(app_font)
13961421

13971422
for client in self.clients:
@@ -1425,18 +1450,11 @@ def refresh_container(self, give_focus=False):
14251450
client.set_info_page()
14261451
client.shellwidget.hide()
14271452
client.layout.addWidget(self.infowidget)
1428-
self.infowidget.show()
1453+
if self.infowidget is not None:
1454+
self.infowidget.show()
14291455
else:
1430-
if self.enable_infowidget:
1431-
try:
1432-
self.infowidget.hide()
1433-
except RuntimeError:
1434-
# Needed to handle the possible scenario where the
1435-
# `infowidget` (`FrameWebView`) related C/C++ object
1436-
# has been already deleted when trying to hide it.
1437-
# See spyder-ider/spyder#21509
1438-
self.enable_infowidget = False
1439-
self.infowidget = None
1456+
if self.enable_infowidget and self.infowidget is not None:
1457+
self.infowidget.hide()
14401458
client.shellwidget.show()
14411459

14421460
# Get reference for the control widget of the selected tab

0 commit comments

Comments
 (0)