From ec8dd7aaa0627bf28632fd6e551edfcecde33695 Mon Sep 17 00:00:00 2001 From: Carlos Mastalli Date: Thu, 23 Nov 2023 23:50:04 +0000 Subject: [PATCH] [exception] Extended exception and added python bindings --- bindings/python/crocoddyl/core/core.cpp | 1 + bindings/python/crocoddyl/core/core.hpp | 1 + .../python/crocoddyl/core/utils/exception.hpp | 45 +++++++++++++++++++ .../python/crocoddyl/core/utils/excepton.cpp | 27 +++++++++++ include/crocoddyl/core/utils/exception.hpp | 9 +++- src/core/utils/exception.cpp | 8 +++- 6 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 bindings/python/crocoddyl/core/utils/exception.hpp create mode 100644 bindings/python/crocoddyl/core/utils/excepton.cpp diff --git a/bindings/python/crocoddyl/core/core.cpp b/bindings/python/crocoddyl/core/core.cpp index e178414f61..3aae5f7022 100644 --- a/bindings/python/crocoddyl/core/core.cpp +++ b/bindings/python/crocoddyl/core/core.cpp @@ -72,6 +72,7 @@ void exposeCore() { exposeSolverIpopt(); #endif exposeCallbacks(); + exposeException(); exposeStopWatch(); } diff --git a/bindings/python/crocoddyl/core/core.hpp b/bindings/python/crocoddyl/core/core.hpp index 6688cf2a32..ef885c9050 100644 --- a/bindings/python/crocoddyl/core/core.hpp +++ b/bindings/python/crocoddyl/core/core.hpp @@ -74,6 +74,7 @@ void exposeSolverIntro(); void exposeSolverIpopt(); #endif void exposeCallbacks(); +void exposeException(); void exposeStopWatch(); void exposeCore(); diff --git a/bindings/python/crocoddyl/core/utils/exception.hpp b/bindings/python/crocoddyl/core/utils/exception.hpp new file mode 100644 index 0000000000..a097cbc528 --- /dev/null +++ b/bindings/python/crocoddyl/core/utils/exception.hpp @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////// +// BSD 3-Clause License +// +// Copyright (C) 2023-2023, Heriot-Watt University +// Copyright note valid unless otherwise stated in individual files. +// All rights reserved. +/////////////////////////////////////////////////////////////////////////////// + +#ifndef BINDINGS_PYTHON_CROCODDYL_CORE_EXCEPTION_HPP_ +#define BINDINGS_PYTHON_CROCODDYL_CORE_EXCEPTION_HPP_ + +#include "crocoddyl/core/utils/exception.hpp" +#include "python/crocoddyl/core/core.hpp" + +namespace crocoddyl { +namespace python { + +static PyObject* createExceptionClass(const char* name, + PyObject* base_type = PyExc_Exception) { + const std::string scope_name = + bp::extract(bp::scope().attr("__name__")); + const std::string qualified_name = scope_name + "." + name; + PyObject* type = PyErr_NewException(qualified_name.c_str(), base_type, 0); + if (!type) { + bp::throw_error_already_set(); + } + bp::scope().attr(name) = bp::handle<>(bp::borrowed(type)); + return type; +} + +PyObject* ExceptionType = NULL; +void translateException(Exception const& e) { + bp::object exc_t(bp::handle<>(bp::borrowed(ExceptionType))); + exc_t.attr("cause") = + bp::object(e); // add the wrapped exception to the Python exception + exc_t.attr("what") = bp::object(e.what()); // for convenience + PyErr_SetString( + ExceptionType, + e.what()); // the string is used by print(exception) in python +} + +} // namespace python +} // namespace crocoddyl + +#endif // BINDINGS_PYTHON_CROCODDYL_CORE_EXCEPTION_HPP_ diff --git a/bindings/python/crocoddyl/core/utils/excepton.cpp b/bindings/python/crocoddyl/core/utils/excepton.cpp new file mode 100644 index 0000000000..799ad1442e --- /dev/null +++ b/bindings/python/crocoddyl/core/utils/excepton.cpp @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////// +// BSD 3-Clause License +// +// Copyright (C) 2023-2023, Heriot-Watt University +// Copyright note valid unless otherwise stated in individual files. +// All rights reserved. +/////////////////////////////////////////////////////////////////////////////// + +#include "python/crocoddyl/core/utils/exception.hpp" + +namespace crocoddyl { +namespace python { + +void exposeException() { + bp::class_ ExceptionClass( + "Exception", bp::init( + bp::args("self", "msg", "file", "func", "line"), + "Initialize the Crocoddyl's exception.")); + ExceptionClass.add_property("message", &Exception::getMessage) + .add_property("extra_data", &Exception::getExtraData); + + ExceptionType = createExceptionClass("Exception"); + bp::register_exception_translator(&translateException); +} + +} // namespace python +} // namespace crocoddyl diff --git a/include/crocoddyl/core/utils/exception.hpp b/include/crocoddyl/core/utils/exception.hpp index 25a1553788..06a4d7759f 100644 --- a/include/crocoddyl/core/utils/exception.hpp +++ b/include/crocoddyl/core/utils/exception.hpp @@ -1,7 +1,8 @@ /////////////////////////////////////////////////////////////////////////////// // BSD 3-Clause License // -// Copyright (C) 2019-2020, University of Edinburgh, LAAS-CNRS +// Copyright (C) 2019-2023, University of Edinburgh, LAAS-CNRS, +// Heriot-Watt University // Copyright note valid unless otherwise stated in individual files. // All rights reserved. /////////////////////////////////////////////////////////////////////////////// @@ -43,6 +44,12 @@ class Exception : public std::exception { virtual ~Exception() NOEXCEPT; virtual const char *what() const NOEXCEPT; + std::string getMessage() const; + std::string getExtraData() const; + + private: + std::string exception_msg_; + std::string extra_data_; std::string msg_; }; diff --git a/src/core/utils/exception.cpp b/src/core/utils/exception.cpp index c1ad7c02ca..921dba118c 100644 --- a/src/core/utils/exception.cpp +++ b/src/core/utils/exception.cpp @@ -1,7 +1,7 @@ /////////////////////////////////////////////////////////////////////////////// // BSD 3-Clause License // -// Copyright (C) 2019-2020, University of Edinburgh +// Copyright (C) 2019-2023, University of Edinburgh, Heriot-Watt University // Copyright note valid unless otherwise stated in individual files. // All rights reserved. /////////////////////////////////////////////////////////////////////////////// @@ -18,10 +18,16 @@ Exception::Exception(const std::string &msg, const char *file, const char *func, ss << line << "\n"; ss << msg; msg_ = ss.str(); + exception_msg_ = msg; + extra_data_ = file; } Exception::~Exception() NOEXCEPT {} const char *Exception::what() const NOEXCEPT { return msg_.c_str(); } +std::string Exception::getMessage() const { return exception_msg_; } + +std::string Exception::getExtraData() const { return extra_data_; } + } // namespace crocoddyl