Tomographer  v5.4
Tomographer C++ Framework Documentation
exc.h
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2016 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  * Copyright (c) 2017 Caltech, Institute for Quantum Information and Matter, Philippe Faist
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 #ifndef TOMOGRAPHERPY_EXC_H
29 #define TOMOGRAPHERPY_EXC_H
30 
31 #include <exception>
32 #include <stdexcept>
33 
34 #include <tomographerpy/common.h>
35 
36 
37 namespace tpy {
38 
39 
40 #ifndef TOMOGRAPHER_PARSED_BY_DOXYGEN
41 
42 // implementation
44 
45 #else
46 // fake code for Doxygen
47 
52 class TomographerCxxError : public std::runtime_error { }; // fake
53 
54 #endif
55 
56 
57 
58 namespace tomo_internal {
59 
60 // (Adapted from \c "pybind11::exception<Type>" in \c "pybind11/include/pybind11.h"
61 // sources.)
62 template<typename Type>
63 class TOMOGRAPHER_EXPORT ExceptionWithDocstring : public py::object {
64 public:
65  ExceptionWithDocstring(py::handle scope, const char *name, PyObject *baseTypeObj = PyExc_Exception,
66  std::string docstring = std::string()) {
67  std::string full_name = scope.attr("__name__").cast<std::string>() +
68  std::string(".") + name;
69  m_ptr = PyErr_NewExceptionWithDoc(const_cast<char*>(full_name.c_str()),
70  const_cast<char*>(docstring.c_str()),
71  baseTypeObj,
72  NULL);
73  if (py::hasattr(scope, name)) {
74  py::pybind11_fail("Error during initialization: multiple incompatible "
75  "definitions with name \"" + std::string(name) + "\"");
76  }
77  scope.attr(name) = *this;
78  }
79 
80  // Sets the current python exception to this exception object with the given message
81  void operator()(const char *message) {
82  PyErr_SetString(m_ptr, message);
83  }
84 };
85 } // namespace tomo_internal
86 
92 template <typename CppException>
94  py::handle scope,
95  const char *name,
96  PyObject *base = PyExc_Exception,
97  std::string docstring = std::string()
98  ) {
99  static tomo_internal::ExceptionWithDocstring<CppException> ex(scope, name, base, docstring);
100  py::register_exception_translator([](std::exception_ptr p) {
101  if (!p) return;
102  try {
104  } catch (const CppException &e) {
105  ex(e.what());
106  }
107  });
108  return ex;
109 }
110 
111 
112 
116 {
117 private:
118  PyObject *ptype;
119  PyObject *pvalue;
120  PyObject *ptraceback;
121  const std::string msg;
122 public:
123 
125  : ptype(NULL), pvalue(NULL), ptraceback(NULL),
126  msg("<catch tpy::PyFetchedException and call restorePyException() to set Python exception>")
127  {
128  PyErr_Fetch(&ptype, &pvalue, &ptraceback) ;
129  }
130 
132  : ptype(copy.ptype),
133  pvalue(copy.pvalue),
134  ptraceback(copy.ptraceback)
135  {
136  }
137 
138  void restorePyException()
139  {
140  PyErr_Restore(ptype, pvalue, ptraceback);
141  ptype = NULL;
142  pvalue = NULL;
143  ptraceback = NULL;
144  }
145 
146  const char * what() const noexcept { return msg.c_str(); }
147 };
148 
149 
150 
151 } // namespace tpy
152 
153 
154 #endif
STL class.
tomo_internal::ExceptionWithDocstring< CppException > & registerExceptionWithDocstring(py::handle scope, const char *name, PyObject *base=PyExc_Exception, std::string docstring=std::string())
Helper to register in Python a C++ exception with a docstring.
Definition: exc.h:93
T what(T... args)
Helper for catching exceptions in a thread and re-raising them.
Definition: exc.h:115
Base exception class for errors in the tomographer python module.
Definition: exc.h:52
STL class.
T c_str(T... args)
#define TOMOGRAPHER_DEFINE_MSG_EXCEPTION_BASE(ClassName, ErrPrefix, BaseClass)
Define a simple exception class.
Definition: cxxutil.h:730
C++ Classes and Utilities for Python Modules.
Definition: common.h:89
T rethrow_exception(T... args)