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
16namespace CPyCppyy {
17
18//= CPyCppyy exception object proxy construction/destruction =================
19static 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//----------------------------------------------------------------------------
51static 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//----------------------------------------------------------------------------
101static 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//----------------------------------------------------------------------------
112static 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//----------------------------------------------------------------------------
136static 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//----------------------------------------------------------------------------
148static PyObject* ep_richcompare(CPPExcInstance* self, PyObject* other, int op)
149{
150 return PyObject_RichCompare(self->fCppInstance, other, op);
151}
152
153//----------------------------------------------------------------------------
154static int ep_nonzero(CPPExcInstance* self)
155{
156 if (self->fCppInstance)
157 return PyObject_IsTrue(self->fCppInstance);
158
159 return 0;
160}
161
162//-----------------------------------------------------------------------------
163static 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 ======================================
226PyTypeObject 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
#define CPyCppyy_PyText_Append
Definition: CPyCppyy.h:104
#define CPyCppyy_PyText_Check
Definition: CPyCppyy.h:95
#define PyVarObject_HEAD_INIT(type, size)
Definition: CPyCppyy.h:215
_object PyObject
Definition: PyMethodBase.h:42
PyObject * gUnderlying
Definition: PyStrings.cxx:31
Set of helper functions that are invoked from the pythonizors, on the Python side.
PyTypeObject CPPExcInstance_Type
static PyObject * ep_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
static PyObject * ep_repr(CPPExcInstance *self)
static int ep_clear(CPPExcInstance *pyobj)
static void ep_dealloc(CPPExcInstance *pyobj)
static PyNumberMethods ep_as_number
static int ep_traverse(CPPExcInstance *pyobj, visitproc visit, void *args)
static int ep_setattro(CPPExcInstance *self, PyObject *attr, PyObject *value)
static PyObject * ep_getattro(CPPExcInstance *self, PyObject *attr)
static PyObject * ep_richcompare(CPPExcInstance *self, PyObject *other, int op)
static PyObject * ep_str(CPPExcInstance *self)
static int ep_nonzero(CPPExcInstance *self)
static const char * what
Definition: stlLoader.cc:6