enable
enable copied to clipboard
libc++abi exception when running demo enable/enable/examples/demo/savage/buttons_on_canvas when running python3.11
Description:
When running demo enable/enable/examples/demo/savage/buttons_on_canvas, a exception will happen in libc++:
2023-04-06 11:25:18.884 Python[3819:77967] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to /var/folders/2z/kylzj9s92y71cxscmljmpqrh0000gt/T/org.python.python.savedState
libc++abi: terminating with uncaught exception of type kiva::$_0
zsh: abort python3.11 enable/examples/demo/savage/buttons_on_canvas.py
Replication step: python enable/examples/demo/savage/buttons_on_canvas.py
Environment: MacOS, python3.11 or python3.8 (with or without EDM)
Packages Installed:
Package Version Editable project location
------------------ ----------- --------------------------------------
chaco 5.1.0 /Users/cyliu/Documents/3.11_test/chaco
configobj 5.0.8
enable 5.4.0.dev32
fonttools 4.39.2
joblib 1.2.0
numpy 1.24.2
pandas 1.5.3
Pillow 9.4.0
pip 22.3.1
PyAudio 0.2.13
pyface 7.4.4
pygarrayimage 1.0
pyglet 2.0.5
Pygments 2.14.0
pyparsing 3.0.9
PySide6 6.4.3
PySide6-Addons 6.4.3
PySide6-Essentials 6.4.3
python-dateutil 2.8.2
pytz 2023.2
reportlab 3.6.12
scikit-learn 1.2.2
scipy 1.10.1
setuptools 65.6.3
shiboken6 6.4.3
six 1.16.0
threadpoolctl 3.1.0
traits 6.4.1
traitsui 8.0.0.dev0
The error seems to happen in demo.configure_traits() (enable/examples/demo/savage/buttons_on_canvas.py, Line 181). Evidence: When I add prints above and below it, only the first print (1) will print out:
demo = ButtonCanvasView()
if __name__ == "__main__":
print("1")
demo.configure_traits()
print("2")
After further locating using the same print method, the error is found inside the following part of the traits/traits/has_traits.py (line 2163-2172). This is a class from traitsui:
rc = toolkit().view_application(
context,
self.trait_view(view),
kind,
handler,
id,
scrollable,
args,
)
We can exclude the possibility that the error comes from toolkit() construction function (traitsui/traitsui/toolkit.py line 80), since the print can successfully pass this function. The inspect tool points to the overrided view_application function in traitsui/qt4/toolkit.py using the following code (in line 2164 of traits/traits/has_traits.py)
print(inspect.getsourcefile(toolkit().view_application))
Further print tests leads to
traitsui/qt4/view_application.py (line 59-110)
def view_application(context, view, kind, handler, id, scrollable, args):
"""Creates a stand-alone PyQt application to display a specified traits UI
View.
Parameters
----------
context : object or dictionary
A single object or a dictionary of string/object pairs, whose trait
attributes are to be edited. If not specified, the current object is
used.
view : view object
A View object that defines a user interface for editing trait attribute
values.
kind : string
The type of user interface window to create. See the
**traitsui.view.kind_trait** trait for values and
their meanings. If *kind* is unspecified or None, the **kind**
attribute of the View object is used.
handler : Handler object
A handler object used for event handling in the dialog box. If
None, the default handler for Traits UI is used.
scrollable : Boolean
Indicates whether the dialog box should be scrollable. When set to
True, scroll bars appear on the dialog box if it is not large enough
to display all of the items in the view at one time.
"""
if (kind == "panel") or ((kind is None) and (view.kind == "panel")):
kind = "modal"
app = QtGui.QApplication.instance()
if app is None or not is_event_loop_running_qt4(app):
return ViewApplication(
context, view, kind, handler, id, scrollable, args
).ui.result
ui = view.ui(
context,
kind=kind,
handler=handler,
id=id,
scrollable=scrollable,
args=args,
)
# If the UI has not been closed yet, we need to keep a reference to
# it until it does close.
if not ui.destroyed:
KEEP_ALIVE_UIS.add(ui)
ui.on_trait_change(on_ui_destroyed, "destroyed")
return ui.result
Is there no stack trace? Most of the code you're referencing here is nowhere near kiva.
@homosapien-lcy It may be worth trying to run this under faulthandler to see if that gives useful output: https://docs.python.org/3/library/faulthandler.html.
As John noted the code you have linked here is just generic GUI wrapper code that starts and runs a TraitsUI application and so is not helpful in diagnosing the issue - or likely at fault (by the way, github allows you to highlight and copy permanent links to other code stored in github, which is a nicer way of linking in issues). As Mark suggests, run with faulthandler to get a better idea of the issue.
Thanks for the comments! Looking into faulthandler now
Looking into faulthandler now
For the quick version: just use python -X faulthandler enable/examples/demo/savage/buttons_on_canvas.py instead of python enable/examples/demo/savage/buttons_on_canvas.py
Thanks! I got much more information from the error message. It seems the problem comes from kiva/agg/agg.py", line 1183 in clip_to_rect:
Traceback (most recent call last):
File "/Users/cyliu/Documents/3.11_test/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 22, in <module>
from enable.api import BaseTool, Component, ComponentEditor, Container
ModuleNotFoundError: No module named 'enable'
(py311) (base) cyliu@aus552cyliu enable % python3.11 -X faulthandler enable/examples/demo/savage/buttons_on_canvas.py
2023-04-06 17:31:16.778 Python[11186:238536] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to /var/folders/2z/kylzj9s92y71cxscmljmpqrh0000gt/T/org.python.python.savedState
libc++abi: terminating with uncaught exception of type kiva::$_0
Fatal Python error: Aborted
Current thread 0x0000000119235600 (most recent call first):
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/kiva/agg/agg.py", line 1183 in clip_to_rect
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/enable/savage/svg/backends/kiva/renderer.py", line 218 in set_on_gc
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/enable/savage/svg/backends/kiva/renderer.py", line 534 in gradientPath
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/enable/savage/svg/document.py", line 1119 in render
File "/Users/cyliu/Documents/3.11_test/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 79 in _draw_svg_document
File "/Users/cyliu/Documents/3.11_test/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 59 in draw
File "/Users/cyliu/Documents/3.11_test/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 99 in draw
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/enable/abstract_window.py", line 536 in _paint
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/enable/qt4/base_window.py", line 90 in paintEvent
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/enable/qt4/base_window.py", line 255 in paintEvent
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/pyface/util/guisupport.py", line 155 in start_event_loop_qt4
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/traitsui/qt4/view_application.py", line 138 in __init__
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/traitsui/qt4/view_application.py", line 92 in view_application
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/traitsui/qt4/toolkit.py", line 237 in view_application
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/traits/has_traits.py", line 2164 in configure_traits
File "/Users/cyliu/Documents/3.11_test/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 181 in <module>
Extension modules: traits.ctraits, numpy.core._multiarray_umath, numpy.core._multiarray_tests, numpy.linalg._umath_linalg, numpy.fft._pocketfft_internal, numpy.random._common, numpy.random.bit_generator, numpy.random._bounded_integers, numpy.random._mt19937, numpy.random.mtrand, numpy.random._philox, numpy.random._pcg64, numpy.random._sfc64, numpy.random._generator, kiva._cython_speedups, kiva._marker_renderer, xxsubtype, shiboken6.Shiboken, PySide6.QtCore, PySide6.QtGui, PySide6.QtWidgets, PySide6.QtPrintSupport, PySide6.QtNetwork, PySide6.QtWebChannel, PySide6.QtWebEngineCore, PySide6.QtWebEngineWidgets, PySide6.QtSvg, kiva.agg._agg, kiva.agg._plat_support, PySide6.QtOpenGL, PySide6.QtOpenGLWidgets (total: 31)
zsh: abort python3.11 -X faulthandler enable/examples/demo/savage/buttons_on_canvas.py
Ahh... that's the level of detail we needed. Here's the relevant C++ code: https://github.com/enthought/enable/blob/ccb76800a11f1d0d2f6618bbf6a6498839ed62cb/kiva/agg/src/kiva_graphics_context.h#L862-L917
Yes, there is an else clause where an exception is thrown, but I don't think that's the exception here. In order for this->state.use_rect_clipping() to be false, this->state.clipping_path must be non-empty, but that appears to be an unimplemented feature in kiva's AGG backend. this->state.clipping_path is always empty:
https://github.com/enthought/enable/blob/ccb76800a11f1d0d2f6618bbf6a6498839ed62cb/kiva/agg/src/kiva_graphics_context.h#L787-L789
I suspect, but do not know, that bad values are being passed as the clipping rect and that big block of code is throwing an exception somewhere.
One thing to try is to see what happens when using a backend other than old Agg. Something like:
ETS_TOOLKIT=qt.qpainter python -X faulthandler enable/examples/demo/savage/buttons_on_canvas.py
or
ETS_TOOLKIT=qt.celiagg python -X faulthandler enable/examples/demo/savage/buttons_on_canvas.py
ETS_TOOLKIT=qt.qpainter python -X faulthandler enable/examples/demo/savage/buttons_on_canvas.py
After test, I found qt.qpainter can run with no error.
But the qt.celiagg will yield the following error:
Traceback (most recent call last):
File "/Users/cyliu/Documents/3.11_test/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 23, in <module>
from enable.savage.svg.backends.kiva.renderer import Renderer as KivaRenderer
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/enable/savage/svg/backends/kiva/renderer.py", line 36, in <module>
class CompiledPath(KivaCompiledPath):
File "/Users/cyliu/.venvs/py311/lib/python3.11/site-packages/enable/savage/svg/backends/kiva/renderer.py", line 38, in CompiledPath
AddPath = KivaCompiledPath.add_path
^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: type object 'Unimplemented' has no attribute 'add_path
After more tests:
if sys.platform == "darwin":
print('in darwin')
if self.spreadMethod != "pad":
warnings.warn(
"spreadMethod %r is not supported. Using 'pad'"
% self.spreadMethod
)
if bbox is not None:
print("in clip")
print("bbox", bbox)
gc.clip_to_rect(*bbox)
The bbox inputted that caused unimplemented error seems normal:
in darwin
in clip
bbox [0.0, 0.0, 72.0, 16.0]
in darwin
in clip
bbox [0.0, 0.0, 104.00238, 120.0]
in darwin
in clip
bbox [0.0, 0.0, 77.351562, 25.5921935]
in darwin
in clip
bbox [0.0, 0.0, 84.556527, 32.353364]
libc++abi: terminating with uncaught exception of type kiva::$_0
Fatal Python error: Aborted
Indeed, even if I pin the bbox value to all 0s (enable/savage/svg/backends/kiva/renderer.py, line 195-235)
def set_on_gc(self, gc, bbox=None):
# Apply transforms
if self.transforms is not None:
for func, f_args in self.transforms:
if isinstance(f_args, tuple):
func(gc, *f_args)
else:
func(gc, f_args)
x1 = self.x1
x2 = self.x2
y1 = self.y1
y2 = self.y2
if sys.platform == "darwin":
if self.spreadMethod != "pad":
warnings.warn(
"spreadMethod %r is not supported. Using 'pad'"
% self.spreadMethod
)
if bbox is not None:
bbox = [0, 0, 0, 0]
gc.clip_to_rect(*bbox)
else:
print("Alert, None!!!")
else:
if self.units == "objectBoundingBox" and bbox is not None:
x1 = (bbox[2] + bbox[0]) * x1
y1 = (bbox[3] + bbox[1]) * y1
x2 = (bbox[2] + bbox[0]) * x2
y2 = (bbox[3] + bbox[1]) * y2
self.bbox_transform(gc, bbox)
stops = np.transpose(self.stops)
gc.linear_gradient(
x1, y1, x2, y2, stops, self.spreadMethod, self.units
)
I print the *args out before it is past into the C++ code
def clip_to_rect(self, *args):
print("in clip_to_rect", *args)
return _agg.GraphicsContextArray_clip_to_rect(self, *args)
The program will still failed in the end, even though it didn't raised error with the same input in the first few calls:
2023-04-10 14:45:13.649 Python[7063:125720] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to /var/folders/2z/kylzj9s92y71cxscmljmpqrh0000gt/T/org.python.python.savedState
in clip_to_rect 0.0 0.0 108.0 120.0
in clip_to_rect 0.0 0.0 106.25 118.28572
in clip_to_rect 0 0 0 0
in clip_to_rect 0.0 0.0 108.0 120.0
in clip_to_rect 0.0 0.0 106.25 118.28572
in clip_to_rect 0 0 0 0
in clip_to_rect 0 0 0 0
in clip_to_rect 0 0 0 0
in clip_to_rect 0 0 0 0
in clip_to_rect 0 0 0 0
in clip_to_rect 0 0 0 0
in clip_to_rect 0 0 0 0
libc++abi: terminating with uncaught exception of type kiva::$_0
Fatal Python error: Aborted
Current thread 0x0000000109f83600 (most recent call first):
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/kiva/agg/agg.py", line 1184 in clip_to_rect
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/savage/svg/backends/kiva/renderer.py", line 219 in set_on_gc
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/savage/svg/backends/kiva/renderer.py", line 537 in gradientPath
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/savage/svg/document.py", line 1119 in render
File "/Users/cyliu/Documents/3.11_test_2/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 79 in _draw_svg_document
File "/Users/cyliu/Documents/3.11_test_2/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 59 in draw
File "/Users/cyliu/Documents/3.11_test_2/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 99 in draw
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/abstract_window.py", line 536 in _paint
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/qt4/base_window.py", line 90 in paintEvent
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/enable/qt4/base_window.py", line 255 in paintEvent
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/pyface/util/guisupport.py", line 156 in start_event_loop_qt4
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/traitsui/qt4/view_application.py", line 138 in __init__
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/traitsui/qt4/view_application.py", line 92 in view_application
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/traitsui/qt4/toolkit.py", line 237 in view_application
File "/Users/cyliu/.venvs/py311_test_2/lib/python3.11/site-packages/traits/has_traits.py", line 2164 in configure_traits
File "/Users/cyliu/Documents/3.11_test_2/enable/enable/examples/demo/savage/buttons_on_canvas.py", line 181 in <module>
Extension modules: traits.ctraits, numpy.core._multiarray_umath, numpy.core._multiarray_tests, numpy.linalg._umath_linalg, numpy.fft._pocketfft_internal, numpy.random._common, numpy.random.bit_generator, numpy.random._bounded_integers, numpy.random._mt19937, numpy.random.mtrand, numpy.random._philox, numpy.random._pcg64, numpy.random._sfc64, numpy.random._generator, kiva._cython_speedups, kiva._marker_renderer, xxsubtype, shiboken6.Shiboken, PySide6.QtCore, PySide6.QtGui, PySide6.QtWidgets, PySide6.QtPrintSupport, PySide6.QtNetwork, PySide6.QtWebChannel, PySide6.QtWebEngineCore, PySide6.QtWebEngineWidgets, kiva.agg._agg, kiva.agg._plat_support, PySide6.QtOpenGL, PySide6.QtOpenGLWidgets, kiwisolver._cext, PySide6.QtSvg, PySide6.QtSvgWidgets (total: 33)
zsh: abort python3.11 -X faulthandler enable/examples/demo/savage/buttons_on_canvas.py
I tested it with edm on Python 3.8 and Linux (enable 5.3) and it works as expected. The issue seems to be OS-X specific.