From ee3e42434de2563967d80b0d60f6589a7e2aba80 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Wed, 10 May 2023 22:11:30 +0200 Subject: [PATCH] Handle exceptions in numpy::array_view<...>::set(). set() can throw an exception; we must check for that to properly get that exception propagated to the python side; otherwise we get a SystemError ("method ... returned a result with an exception set"). Example repro: ``` from pylab import * gca().add_collection(mpl.collections.LineCollection(rand(2, 2, 2), array=0)) ``` (Here the C extension method receives a single tuple (rgba) color rather than an array of tuple (rgba) colors.) I'd rather not explicitly test for the exception being raised (a ValueError) because if switching to pybind11 one naturally gets a broadcast of the scalar value into a correctly dimensionalized array; indeed mplcairo handles the above example just fine. --- src/py_converters.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/py_converters.cpp b/src/py_converters.cpp index cd4013bb30ad..d8aa384cd08b 100644 --- a/src/py_converters.cpp +++ b/src/py_converters.cpp @@ -510,8 +510,8 @@ int convert_points(PyObject *obj, void *pointsp) if (obj == NULL || obj == Py_None) { return 1; } - points->set(obj); - if (points->size() && !check_trailing_shape(*points, "points", 2)) { + if (!points->set(obj) + || points->size() && !check_trailing_shape(*points, "points", 2)) { return 0; } return 1; @@ -523,8 +523,8 @@ int convert_transforms(PyObject *obj, void *transp) if (obj == NULL || obj == Py_None) { return 1; } - trans->set(obj); - if (trans->size() && !check_trailing_shape(*trans, "transforms", 3, 3)) { + if (!trans->set(obj) + || trans->size() && !check_trailing_shape(*trans, "transforms", 3, 3)) { return 0; } return 1; @@ -536,8 +536,8 @@ int convert_bboxes(PyObject *obj, void *bboxp) if (obj == NULL || obj == Py_None) { return 1; } - bbox->set(obj); - if (bbox->size() && !check_trailing_shape(*bbox, "bbox array", 2, 2)) { + if (!bbox->set(obj) + || bbox->size() && !check_trailing_shape(*bbox, "bbox array", 2, 2)) { return 0; } return 1; @@ -549,8 +549,8 @@ int convert_colors(PyObject *obj, void *colorsp) if (obj == NULL || obj == Py_None) { return 1; } - colors->set(obj); - if (colors->size() && !check_trailing_shape(*colors, "colors", 4)) { + if (!colors->set(obj) + || colors->size() && !check_trailing_shape(*colors, "colors", 4)) { return 0; } return 1;