Tests nested (e.g. C++ -> Python -> C++) exception handling
(capture)
| 204 | |
| 205 | @pytest.mark.xfail("env.GRAALPY", reason="TODO should get fixed on GraalPy side") |
| 206 | def test_nested_throws(capture): |
| 207 | """Tests nested (e.g. C++ -> Python -> C++) exception handling""" |
| 208 | |
| 209 | def throw_myex(): |
| 210 | raise m.MyException("nested error") |
| 211 | |
| 212 | def throw_myex5(): |
| 213 | raise m.MyException5("nested error 5") |
| 214 | |
| 215 | # In the comments below, the exception is caught in the first step, thrown in the last step |
| 216 | |
| 217 | # C++ -> Python |
| 218 | with capture: |
| 219 | m.try_catch(m.MyException5, throw_myex5) |
| 220 | assert str(capture).startswith("MyException5: nested error 5") |
| 221 | |
| 222 | # Python -> C++ -> Python |
| 223 | with pytest.raises(m.MyException) as excinfo: |
| 224 | m.try_catch(m.MyException5, throw_myex) |
| 225 | assert str(excinfo.value) == "nested error" |
| 226 | |
| 227 | def pycatch(exctype, f, *args): # noqa: ARG001 |
| 228 | try: |
| 229 | f(*args) |
| 230 | except m.MyException as e: |
| 231 | print(e) |
| 232 | |
| 233 | # C++ -> Python -> C++ -> Python |
| 234 | with capture: |
| 235 | m.try_catch( |
| 236 | m.MyException5, |
| 237 | pycatch, |
| 238 | m.MyException, |
| 239 | m.try_catch, |
| 240 | m.MyException, |
| 241 | throw_myex5, |
| 242 | ) |
| 243 | assert str(capture).startswith("MyException5: nested error 5") |
| 244 | |
| 245 | # C++ -> Python -> C++ |
| 246 | with capture: |
| 247 | m.try_catch(m.MyException, pycatch, m.MyException5, m.throws4) |
| 248 | assert capture == "this error is rethrown" |
| 249 | |
| 250 | # Python -> C++ -> Python -> C++ |
| 251 | with pytest.raises(m.MyException5) as excinfo: |
| 252 | m.try_catch(m.MyException, pycatch, m.MyException, m.throws5) |
| 253 | assert str(excinfo.value) == "this is a helper-defined translated exception" |
| 254 | |
| 255 | |
| 256 | # TODO: Investigate this crash, see pybind/pybind11#5062 for background |