Logo ROOT  
Reference Guide
CPPExcInstance.cxx
Go to the documentation of this file.
1 // Bindings
2 #include "CPyCppyy.h"
3 #include "CPPExcInstance.h"
4 #include "PyStrings.h"
5 
6 
7 //______________________________________________________________________________
8 // Python-side exception proxy objects
9 // ===================================
10 //
11 // Python exceptions need to derive from PyException as it expects a set of
12 // specific data members. This class exists so that general CPPInstances need
13 // not carry that overhead. In use, it forwards to the embedded CPPInstance.
14 
15 
16 namespace CPyCppyy {
17 
18 //= CPyCppyy exception object proxy construction/destruction =================
19 static PyObject* ep_new(PyTypeObject* subtype, PyObject* args, PyObject* kwds)
20 {
21 // Create a new exception object proxy (holder only).
22  PyObject* pyobj = ((PyTypeObject*)PyExc_Exception)->tp_new(subtype, nullptr, nullptr);
23  if (!pyobj)
24  return nullptr;
25 
26  CPPExcInstance* excobj = (CPPExcInstance*)pyobj;
27  excobj->fTopMessage = nullptr;
28  if (args) {
29  PyObject* ulc = PyObject_GetAttr((PyObject*)subtype, PyStrings::gUnderlying);
30  excobj->fCppInstance = PyType_Type.tp_call(ulc, args, kwds);
31  if (!excobj->fCppInstance) {
32  // if this fails, then the contruction may have been attempted from a string
33  // (e.g. from PyErr_Format); if so, drop the proxy and use fTopMessage instead
34  PyErr_Clear();
35  if (PyTuple_GET_SIZE(args) == 1) {
36  PyObject* msg = PyTuple_GET_ITEM(args, 0);
37  if (CPyCppyy_PyText_Check(msg)) {
38  Py_INCREF(msg);
39  excobj->fTopMessage = msg;
40  }
41  }
42  }
43  Py_DECREF(ulc);
44  } else
45  excobj->fCppInstance = nullptr;
46 
47  return pyobj;
48 }
49 
50 //----------------------------------------------------------------------------
51 static int ep_traverse(CPPExcInstance* pyobj, visitproc visit, void* args)
52 {
53 // Garbage collector traverse of held python member objects.
54  ((PyTypeObject*)PyExc_Exception)->tp_traverse((PyObject*)pyobj, visit, args);
55 
56  if (pyobj->fCppInstance)
57  visit(pyobj->fCppInstance, args);
58 
59  if (pyobj->fTopMessage)
60  visit(pyobj->fTopMessage, args);
61 
62  return 0;
63 }
64 
65 //----------------------------------------------------------------------------
67 {
68  if (self->fCppInstance) {
69  PyObject* what = PyObject_CallMethod((PyObject*)self, (char*)"what", nullptr);
70  if (what) {
71  if (self->fTopMessage) {
72  Py_INCREF(self->fTopMessage);
73  PyObject* top = self->fTopMessage;
75  Py_DECREF(what);
76  what = top;
77  }
78  return what;
79  }
80  PyErr_Clear();
81  return PyObject_Str(self->fCppInstance);
82  }
83 
84  if (self->fTopMessage) {
85  Py_INCREF(self->fTopMessage);
86  return self->fTopMessage;
87  }
88 
89  return PyType_Type.tp_str((PyObject*)self);
90 }
91 
92 //----------------------------------------------------------------------------
94 {
95  if (self->fCppInstance)
96  return PyObject_Repr(self->fCppInstance);
97  return PyType_Type.tp_repr((PyObject*)self);
98 }
99 
100 //----------------------------------------------------------------------------
101 static void ep_dealloc(CPPExcInstance* pyobj)
102 {
103  PyObject* tmp1 = pyobj->fCppInstance;
104  PyObject* tmp2 = pyobj->fTopMessage;
105 
106  ((PyTypeObject*)PyExc_Exception)->tp_dealloc((PyObject*)pyobj);
107  Py_CLEAR(tmp1);
108  Py_CLEAR(tmp2);
109 }
110 
111 //----------------------------------------------------------------------------
112 static int ep_clear(CPPExcInstance* pyobj)
113 {
114 // Garbage collector clear of held python member objects.
115  ((PyTypeObject*)PyExc_Exception)->tp_clear((PyObject*)pyobj);
116 
117  Py_CLEAR(pyobj->fCppInstance);
118  Py_CLEAR(pyobj->fTopMessage);
119 
120  return 0;
121 }
122 
123 //= forwarding methods =======================================================
125 {
126  if (self->fCppInstance) {
127  PyObject* res = PyObject_GetAttr(self->fCppInstance, attr);
128  if (res) return res;
129  PyErr_Clear();
130  }
131 
132  return ((PyTypeObject*)PyExc_Exception)->tp_getattro((PyObject*)self, attr);
133 }
134 
135 //----------------------------------------------------------------------------
136 static int ep_setattro(CPPExcInstance* self, PyObject* attr, PyObject* value)
137 {
138  if (self->fCppInstance) {
139  int res = PyObject_SetAttr(self->fCppInstance, attr, value);
140  if (!res) return res;
141  PyErr_Clear();
142  }
143 
144  return ((PyTypeObject*)PyExc_Exception)->tp_setattro((PyObject*)self, attr, value);
145 }
146 
147 //----------------------------------------------------------------------------
148 static PyObject* ep_richcompare(CPPExcInstance* self, PyObject* other, int op)
149 {
150  return PyObject_RichCompare(self->fCppInstance, other, op);
151 }
152 
153 //----------------------------------------------------------------------------
154 static int ep_nonzero(CPPExcInstance* self)
155 {
156  if (self->fCppInstance)
157  return PyObject_IsTrue(self->fCppInstance);
158 
159  return 0;
160 }
161 
162 //-----------------------------------------------------------------------------
163 static PyNumberMethods ep_as_number = {
164  0, // nb_add
165  0, // nb_subtract
166  0, // nb_multiply
167 #if PY_VERSION_HEX < 0x03000000
168  0, // nb_divide
169 #endif
170  0, // nb_remainder
171  0, // nb_divmod
172  0, // nb_power
173  0, // nb_negative
174  0, // nb_positive
175  0, // nb_absolute
176  (inquiry)ep_nonzero, // nb_bool (nb_nonzero in p2)
177  0, // nb_invert
178  0, // nb_lshift
179  0, // nb_rshift
180  0, // nb_and
181  0, // nb_xor
182  0, // nb_or
183 #if PY_VERSION_HEX < 0x03000000
184  0, // nb_coerce
185 #endif
186  0, // nb_int
187  0, // nb_long (nb_reserved in p3)
188  0, // nb_float
189 #if PY_VERSION_HEX < 0x03000000
190  0, // nb_oct
191  0, // nb_hex
192 #endif
193  0, // nb_inplace_add
194  0, // nb_inplace_subtract
195  0, // nb_inplace_multiply
196 #if PY_VERSION_HEX < 0x03000000
197  0, // nb_inplace_divide
198 #endif
199  0, // nb_inplace_remainder
200  0, // nb_inplace_power
201  0, // nb_inplace_lshift
202  0, // nb_inplace_rshift
203  0, // nb_inplace_and
204  0, // nb_inplace_xor
205  0 // nb_inplace_or
206 #if PY_VERSION_HEX >= 0x02020000
207  , 0 // nb_floor_divide
208 #if PY_VERSION_HEX < 0x03000000
209  , 0 // nb_true_divide
210 #else
211  , 0 // nb_true_divide
212 #endif
213  , 0 // nb_inplace_floor_divide
214  , 0 // nb_inplace_true_divide
215 #endif
216 #if PY_VERSION_HEX >= 0x02050000
217  , 0 // nb_index
218 #endif
219 #if PY_VERSION_HEX >= 0x03050000
220  , 0 // nb_matrix_multiply
221  , 0 // nb_inplace_matrix_multiply
222 #endif
223 };
224 
225 //= CPyCppyy exception object proxy type ======================================
226 PyTypeObject CPPExcInstance_Type = {
227  PyVarObject_HEAD_INIT(&PyType_Type, 0)
228  (char*)"cppyy.CPPExcInstance", // tp_name
229  sizeof(CPPExcInstance), // tp_basicsize
230  0, // tp_itemsize
231  (destructor)ep_dealloc, // tp_dealloc
232  0, // tp_print
233  0, // tp_getattr
234  0, // tp_setattr
235  0, // tp_compare
236  (reprfunc)ep_repr, // tp_repr
237  &ep_as_number, // tp_as_number
238  0, // tp_as_sequence
239  0, // tp_as_mapping
240  0, // tp_hash
241  0, // tp_call
242  (reprfunc)ep_str, // tp_str
243  (getattrofunc)ep_getattro, // tp_getattro
244  (setattrofunc)ep_setattro, // tp_setattro
245  0, // tp_as_buffer
246  Py_TPFLAGS_DEFAULT |
247  Py_TPFLAGS_BASETYPE |
248  Py_TPFLAGS_BASE_EXC_SUBCLASS |
249  Py_TPFLAGS_HAVE_GC |
250  Py_TPFLAGS_CHECKTYPES, // tp_flags
251  (char*)"cppyy exception object proxy (internal)", // tp_doc
252  (traverseproc)ep_traverse, // tp_traverse
253  (inquiry)ep_clear, // tp_clear
254  (richcmpfunc)ep_richcompare, // tp_richcompare
255  0, // tp_weaklistoffset
256  0, // tp_iter
257  0, // tp_iternext
258  0, // tp_methods
259  0, // tp_members
260  0, // tp_getset
261  (PyTypeObject*)PyExc_Exception, // tp_base
262  0, // tp_dict
263  0, // tp_descr_get
264  0, // tp_descr_set
265  0, // tp_dictoffset
266  0, // tp_init
267  0, // tp_alloc
268  (newfunc)ep_new, // tp_new
269  0, // tp_free
270  0, // tp_is_gc
271  0, // tp_bases
272  0, // tp_mro
273  0, // tp_cache
274  0, // tp_subclasses
275  0 // tp_weaklist
276 #if PY_VERSION_HEX >= 0x02030000
277  , 0 // tp_del
278 #endif
279 #if PY_VERSION_HEX >= 0x02060000
280  , 0 // tp_version_tag
281 #endif
282 #if PY_VERSION_HEX >= 0x03040000
283  , 0 // tp_finalize
284 #endif
285 };
286 
287 } // namespace CPyCppyy
static PyObject * ep_repr(CPPExcInstance *self)
static int ep_traverse(CPPExcInstance *pyobj, visitproc visit, void *args)
static PyObject * ep_str(CPPExcInstance *self)
static PyNumberMethods ep_as_number
#define PyVarObject_HEAD_INIT(type, size)
Definition: CPyCppyy.h:207
static PyObject * ep_getattro(CPPExcInstance *self, PyObject *attr)
PyObject * gUnderlying
Definition: PyStrings.cxx:31
static void ep_dealloc(CPPExcInstance *pyobj)
static const char * what
Definition: stlLoader.cc:6
static PyObject * ep_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
static PyObject * ep_richcompare(CPPExcInstance *self, PyObject *other, int op)
_object PyObject
Definition: PyMethodBase.h:41
#define CPyCppyy_PyText_Append
Definition: CPyCppyy.h:104
static int ep_clear(CPPExcInstance *pyobj)
PyTypeObject CPPExcInstance_Type
static int ep_setattro(CPPExcInstance *self, PyObject *attr, PyObject *value)
static int ep_nonzero(CPPExcInstance *self)
#define CPyCppyy_PyText_Check
Definition: CPyCppyy.h:95