##// END OF EJS Templates
Handle OSError cases where traceback frames occur from built files (#13964)...
Handle OSError cases where traceback frames occur from built files (#13964) I've been using the `_render_traceback_` method of the traceback object, provided by the `IPython.core.interactiveshell.InteractiveShell` object that you created, in the `showtraceback` method. Thanks to this, I was able to create better error messages. I appreciate it. The following issue is related to the use of this method. ```python try: # Exception classes can customise their traceback - we # use this in IPython.parallel for exceptions occurring # in the engines. This should return a list of strings. if hasattr(value, "_render_traceback_"): stb = value._render_traceback_() else: stb = self.InteractiveTB.structured_traceback( etype, value, tb, tb_offset=tb_offset ) ``` I noticed that in the recent `8.11` version, code was added to generate a traceback when the source code is too long. In this case, if the `etb.tb_frame` object is a built file or something similar, the `inspect.getsourcelines(etb.tb_frame)` method may raise an error. So I implemented a change to set the `max_len` to the minimum value and avoid the following condition when an `OSError` occurs. I think this approach can handle cases where errors occur while using the `inspect.getsourcelines()` method. If there is anything I have done wrong or any procedures I should follow, please let me know. I would greatly appreciate it if you could leave a comment and I will make the necessary changes immediately. Thank you.

File last commit:

r28021:b332fd1a
r28196:92027083 merge
Show More
qt_for_kernel.py
124 lines | 3.4 KiB | text/x-python | PythonLexer
""" Import Qt in a manner suitable for an IPython kernel.
This is the import used for the `gui=qt` or `matplotlib=qt` initialization.
Import Priority:
if Qt has been imported anywhere else:
use that
if matplotlib has been imported and doesn't support v2 (<= 1.0.1):
use PyQt4 @v1
Next, ask QT_API env variable
if QT_API not set:
ask matplotlib what it's using. If Qt4Agg or Qt5Agg, then use the
version matplotlib is configured with
else: (matplotlib said nothing)
# this is the default path - nobody told us anything
try in this order:
PyQt default version, PySide, PyQt5
else:
use what QT_API says
Note that %gui's implementation will always set a `QT_API`, see
`IPython.terminal.pt_inputhooks.get_inputhook_name_and_func`
"""
# NOTE: This is no longer an external, third-party module, and should be
# considered part of IPython. For compatibility however, it is being kept in
# IPython/external.
import os
import sys
from IPython.external.qt_loaders import (
load_qt,
loaded_api,
enum_factory,
# QT6
QT_API_PYQT6,
QT_API_PYSIDE6,
# QT5
QT_API_PYQT5,
QT_API_PYSIDE2,
# QT4
QT_API_PYQT,
QT_API_PYSIDE,
# default
QT_API_PYQT_DEFAULT,
)
_qt_apis = (
# QT6
QT_API_PYQT6,
QT_API_PYSIDE6,
# QT5
QT_API_PYQT5,
QT_API_PYSIDE2,
# default
QT_API_PYQT_DEFAULT,
)
def matplotlib_options(mpl):
"""Constraints placed on an imported matplotlib."""
if mpl is None:
return
backend = mpl.rcParams.get('backend', None)
if backend == 'Qt4Agg':
mpqt = mpl.rcParams.get('backend.qt4', None)
if mpqt is None:
return None
if mpqt.lower() == 'pyside':
return [QT_API_PYSIDE]
elif mpqt.lower() == 'pyqt4':
return [QT_API_PYQT_DEFAULT]
elif mpqt.lower() == 'pyqt4v2':
return [QT_API_PYQT]
raise ImportError("unhandled value for backend.qt4 from matplotlib: %r" %
mpqt)
elif backend == 'Qt5Agg':
mpqt = mpl.rcParams.get('backend.qt5', None)
if mpqt is None:
return None
if mpqt.lower() == 'pyqt5':
return [QT_API_PYQT5]
raise ImportError("unhandled value for backend.qt5 from matplotlib: %r" %
mpqt)
def get_options():
"""Return a list of acceptable QT APIs, in decreasing order of preference."""
#already imported Qt somewhere. Use that
loaded = loaded_api()
if loaded is not None:
return [loaded]
mpl = sys.modules.get("matplotlib", None)
if mpl is not None and tuple(mpl.__version__.split(".")) < ("1", "0", "2"):
# 1.0.1 only supports PyQt4 v1
return [QT_API_PYQT_DEFAULT]
qt_api = os.environ.get('QT_API', None)
if qt_api is None:
#no ETS variable. Ask mpl, then use default fallback path
return matplotlib_options(mpl) or [
QT_API_PYQT_DEFAULT,
QT_API_PYQT6,
QT_API_PYSIDE6,
QT_API_PYQT5,
QT_API_PYSIDE2,
]
elif qt_api not in _qt_apis:
raise RuntimeError("Invalid Qt API %r, valid values are: %r" %
(qt_api, ', '.join(_qt_apis)))
else:
return [qt_api]
api_opts = get_options()
QtCore, QtGui, QtSvg, QT_API = load_qt(api_opts)
enum_helper = enum_factory(QT_API, QtCore)