Make it easier to add new binding of builtin Python exceptions

This commit is contained in:
Dean Moldovan 2016-09-10 14:43:28 +02:00
parent 135ba8deaf
commit f69071ca4b
2 changed files with 20 additions and 18 deletions

View File

@ -54,11 +54,7 @@ PYBIND11_NOINLINE inline internals &get_internals() {
try { try {
if (p) std::rethrow_exception(p); if (p) std::rethrow_exception(p);
} catch (error_already_set &e) { e.restore(); return; } catch (error_already_set &e) { e.restore(); return;
} catch (const index_error &e) { PyErr_SetString(PyExc_IndexError, e.what()); return; } catch (const builtin_exception &e) { e.set_error(); return;
} catch (const key_error &e) { PyErr_SetString(PyExc_KeyError, e.what()); return;
} catch (const value_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
} catch (const type_error &e) { PyErr_SetString(PyExc_TypeError, e.what()); return;
} catch (const stop_iteration &e) { PyErr_SetString(PyExc_StopIteration, e.what()); return;
} catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return; } catch (const std::bad_alloc &e) { PyErr_SetString(PyExc_MemoryError, e.what()); return;
} catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; } catch (const std::domain_error &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;
} catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return; } catch (const std::invalid_argument &e) { PyErr_SetString(PyExc_ValueError, e.what()); return;

View File

@ -399,21 +399,27 @@ private:
PyObject *type, *value, *trace; PyObject *type, *value, *trace;
}; };
#define PYBIND11_RUNTIME_EXCEPTION(name) \ /// C++ bindings of builtin Python exceptions
class name : public std::runtime_error { public: \ class builtin_exception : public std::runtime_error {
name(const std::string &w) : std::runtime_error(w) { }; \ public:
name(const char *s) : std::runtime_error(s) { }; \ using std::runtime_error::runtime_error;
name() : std::runtime_error("") { } \ virtual void set_error() const = 0; /// Set the error using the Python C API
};
#define PYBIND11_RUNTIME_EXCEPTION(name, type) \
class name : public builtin_exception { public: \
using builtin_exception::builtin_exception; \
name() : name("") { } \
void set_error() const override { PyErr_SetString(type, what()); } \
}; };
// C++ bindings of core Python exceptions PYBIND11_RUNTIME_EXCEPTION(stop_iteration, PyExc_StopIteration)
PYBIND11_RUNTIME_EXCEPTION(stop_iteration) PYBIND11_RUNTIME_EXCEPTION(index_error, PyExc_IndexError)
PYBIND11_RUNTIME_EXCEPTION(index_error) PYBIND11_RUNTIME_EXCEPTION(key_error, PyExc_KeyError)
PYBIND11_RUNTIME_EXCEPTION(key_error) PYBIND11_RUNTIME_EXCEPTION(value_error, PyExc_ValueError)
PYBIND11_RUNTIME_EXCEPTION(value_error) PYBIND11_RUNTIME_EXCEPTION(type_error, PyExc_TypeError)
PYBIND11_RUNTIME_EXCEPTION(type_error) PYBIND11_RUNTIME_EXCEPTION(cast_error, PyExc_RuntimeError) /// Thrown when pybind11::cast or handle::call fail due to a type casting error
PYBIND11_RUNTIME_EXCEPTION(cast_error) /// Thrown when pybind11::cast or handle::call fail due to a type casting error PYBIND11_RUNTIME_EXCEPTION(reference_cast_error, PyExc_RuntimeError) /// Used internally
PYBIND11_RUNTIME_EXCEPTION(reference_cast_error) /// Used internally
[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const char *reason) { throw std::runtime_error(reason); } [[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const char *reason) { throw std::runtime_error(reason); }
[[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const std::string &reason) { throw std::runtime_error(reason); } [[noreturn]] PYBIND11_NOINLINE inline void pybind11_fail(const std::string &reason) { throw std::runtime_error(reason); }