Line data Source code
1 : // SPDX-License-Identifier: BSD-3-Clause 2 : // Copyright (c) 2023 Scipp contributors (https://github.com/scipp) 3 : /// @file 4 : /// @author Simon Heybrock 5 : 6 : #include "scipp/core/except.h" 7 : #include "pybind11.h" 8 : #include "scipp/dataset/except.h" 9 : #include "scipp/units/except.h" 10 : #include "scipp/variable/except.h" 11 : 12 : namespace py = pybind11; 13 : 14 : namespace { 15 : /// Translate an exception into a standard Python exception. 16 : template <class CppException, class PyException> 17 12 : void register_with_builtin_exception(const PyException &py_exception) { 18 : // Pybind11 does not like it when the lambda captures something, 19 : // so 'pass' py_exception via a static variable. 20 12 : static auto pyexc = py_exception; 21 4454 : py::register_exception_translator([](std::exception_ptr p) { 22 : try { 23 72097 : if (p) 24 144194 : std::rethrow_exception(p); 25 76539 : } catch (const CppException &e) { 26 4442 : PyErr_SetString(pyexc, e.what()); 27 : } 28 : }); 29 12 : } 30 : 31 : template <class CppException> 32 30 : void register_exception(py::handle scope, const char *name, py::handle base, 33 : const char *doc) { 34 30 : auto exc = py::register_exception<CppException>(scope, name, base); 35 30 : exc.doc() = doc; 36 30 : } 37 : } // namespace 38 : 39 3 : void init_exceptions(py::module &m) { 40 : using namespace scipp; 41 : 42 3 : register_exception<except::BinEdgeError>( 43 : m, "BinEdgeError", PyExc_RuntimeError, 44 : "Inappropriate bin-edge coordinate."); 45 3 : register_exception<except::BinnedDataError>(m, "BinnedDataError", 46 : PyExc_RuntimeError, 47 : "Incorrect use of binned data."); 48 3 : register_exception<except::CoordMismatchError>( 49 : m, "CoordError", PyExc_RuntimeError, 50 : "Bad coordinate values or mismatching coordinates."); 51 3 : register_exception<except::DataArrayError>( 52 : m, "DataArrayError", PyExc_RuntimeError, 53 : "Incorrect use of scipp.DataArray."); 54 3 : register_exception<except::DatasetError>( 55 : m, "DatasetError", PyExc_RuntimeError, "Incorrect use of scipp.Dataset."); 56 3 : register_exception<except::DimensionError>( 57 : m, "DimensionError", PyExc_RuntimeError, 58 : "Inappropriate dimension labels and/or shape."); 59 3 : register_exception<except::TypeError>(m, "DTypeError", PyExc_TypeError, 60 : "Inappropriate dtype."); 61 3 : register_exception<except::UnitError>(m, "UnitError", PyExc_RuntimeError, 62 : "Inappropriate unit."); 63 3 : register_exception<except::VariableError>(m, "VariableError", 64 : PyExc_RuntimeError, 65 : "Incorrect use of scipp.Variable."); 66 3 : register_exception<except::VariancesError>( 67 : m, "VariancesError", PyExc_RuntimeError, 68 : "Variances used where they are not supported or not used where they are " 69 : "required."); 70 : 71 3 : register_with_builtin_exception<except::SizeError>(PyExc_ValueError); 72 3 : register_with_builtin_exception<except::SliceError>(PyExc_IndexError); 73 3 : register_with_builtin_exception<except::NotFoundError>(PyExc_KeyError); 74 3 : register_with_builtin_exception<except::NotImplementedError>( 75 : PyExc_NotImplementedError); 76 3 : }