1
/* This file is part of MAUS: http://micewww.pp.rl.ac.uk/projects/maus
3
* MAUS is free software: you can redistribute it and/or modify
4
* it under the terms of the GNU General Public License as published by
5
* the Free Software Foundation, either version 3 of the License, or
6
* (at your option) any later version.
8
* MAUS is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with MAUS. If not, see <http://www.gnu.org/licenses/>.
17
#ifndef _SRC_COMMON_CPP_API_PYWRAPOUTPUTBASE_INL_
18
#define _SRC_COMMON_CPP_API_PYWRAPOUTPUTBASE_INL_
22
#include "structmember.h" // python PyMemberDef
24
#include "src/common_cpp/Utils/JsonWrapper.hh"
25
#include "src/common_cpp/DataStructure/Data.hh"
26
#include "src/common_cpp/Utils/CppErrorHandler.hh"
29
template <class OUTPUTCLASS>
30
PyObject* PyWrapOutputBase<OUTPUTCLASS>::birth(PyObject* self,
33
PyWrappedOutput* py_output = reinterpret_cast<PyWrappedOutput*>(self);
34
if (!py_output->output) {
35
PyErr_SetString(PyExc_ValueError, "self was not initialised properly");
39
static char *kwlist[] = {const_cast<char*>("datacards"), NULL};
42
if (!PyArg_ParseTupleAndKeywords(args, kwds, "s|", kwlist, &cards)) {
45
std::string config(cards);
47
py_output->output->birth(config);
48
} catch (std::exception& exc) {
49
PyErr_SetString(PyExc_ValueError, (&exc)->what());
52
PyErr_SetString(PyExc_SystemError, "Caught an unknown error during birth");
59
template <class OUTPUTCLASS>
60
PyObject* PyWrapOutputBase<OUTPUTCLASS>::death(PyObject* self,
63
PyWrappedOutput* py_output = reinterpret_cast<PyWrappedOutput*>(self);
64
if (!py_output->output) {
65
PyErr_SetString(PyExc_ValueError, "self was not initialised properly");
69
py_output->output->death();
70
} catch (std::exception& exc) {
71
PyErr_SetString(PyExc_ValueError, (&exc)->what());
74
PyErr_SetString(PyExc_SystemError, "Caught an unknown error during birth");
81
template <class OUTPUTCLASS>
82
PyObject* PyWrapOutputBase<OUTPUTCLASS>::save(PyObject* self,
85
PyWrappedOutput* py_output = reinterpret_cast<PyWrappedOutput*>(self);
86
if (!py_output->output) {
87
PyErr_SetString(PyExc_ValueError, "self was not initialised properly");
91
static char *kwlist[] = {const_cast<char*>("data"), NULL};
94
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|", kwlist, &data_in)) {
97
// data_out should be Py_NONE or NULL (error)
98
PyObject* data_out = py_output->output->save_pyobj(data_in);
102
template <class OUTPUTCLASS>
103
PyObject* PyWrapOutputBase<OUTPUTCLASS>::_new(PyTypeObject* type, PyObject *args, PyObject *kwds) {
104
PyWrappedOutput* self = reinterpret_cast<PyWrappedOutput*>(type->tp_alloc(type, 0));
106
return reinterpret_cast<PyObject*>(self);
109
template <class OUTPUTCLASS>
110
std::string PyWrapOutputBase<OUTPUTCLASS>::_birth_docstring =
111
std::string("Initialise the outputter based on datacards\n\n")+
112
std::string(" - datacards: string representation of the control variables\n");
114
template <class OUTPUTCLASS>
115
std::string PyWrapOutputBase<OUTPUTCLASS>::_save_docstring =
116
std::string("Save the data\n\n")+
117
std::string(" - data: a parsable event, either in json, string or MAUS\n")+
118
std::string(" native representation. Can be a MAUS.Data, MAUS.JobHeader,\n")+
119
std::string(" MAUS.RunHeader, MAUS.RunFooter or MAUS.JobFooter object\n");
121
template <class OUTPUTCLASS>
122
std::string PyWrapOutputBase<OUTPUTCLASS>::_death_docstring =
123
std::string("Deinitialise the outputter ready for the next run\n");
125
template <class OUTPUTCLASS>
126
std::string PyWrapOutputBase<OUTPUTCLASS>::_class_docstring =
127
std::string("Class for saving the MAUS data.\n\n")+
128
std::string(" def __init__(self)\n")+
129
std::string(" Initialise the class\n");
132
template <class OUTPUTCLASS>
133
int PyWrapOutputBase<OUTPUTCLASS>::_init(PyWrappedOutput* self, PyObject *args, PyObject *kwds) {
134
if (self->output == NULL)
135
self->output = new OUTPUTCLASS();
136
if (self->can_convert == NULL) {
137
self->can_convert = Py_True;
138
Py_INCREF(self->can_convert);
143
template <class OUTPUTCLASS>
144
void PyWrapOutputBase<OUTPUTCLASS>::_dealloc(PyWrappedOutput* self) {
145
if (self->output != NULL)
147
Py_DECREF(self->can_convert);
150
template <class OUTPUTCLASS>
151
PyMemberDef PyWrapOutputBase<OUTPUTCLASS>::_members[] = {
152
{const_cast<char*>("can_convert"),
153
T_OBJECT_EX, offsetof(PyWrappedOutput, can_convert), 0,
155
"Returns true if the module can do conversions, else false (or non-existent)"
157
{NULL} /* Sentinel */
161
template <class OUTPUTCLASS>
162
PyMethodDef PyWrapOutputBase<OUTPUTCLASS>::_methods[] = {
163
{"birth", (PyCFunction)birth,
164
METH_VARARGS|METH_KEYWORDS, _birth_docstring.c_str()},
165
{"death", (PyCFunction)death,
166
METH_VARARGS|METH_KEYWORDS, _death_docstring.c_str()},
167
{"save", (PyCFunction)save,
168
METH_VARARGS|METH_KEYWORDS, _save_docstring.c_str()},
172
template <class OUTPUTCLASS>
173
PyMethodDef PyWrapOutputBase<OUTPUTCLASS>::_module_methods[] = {
174
{NULL} /* Sentinel */
177
template <class OUTPUTCLASS>
178
std::string PyWrapOutputBase<OUTPUTCLASS>::_class_name = "";
179
template <class OUTPUTCLASS>
180
std::string PyWrapOutputBase<OUTPUTCLASS>::_module_name = "";
181
template <class OUTPUTCLASS>
182
std::string PyWrapOutputBase<OUTPUTCLASS>::_path_name = "";
185
template <class OUTPUTCLASS>
186
PyTypeObject PyWrapOutputBase<OUTPUTCLASS>::_class_type = {
187
PyObject_HEAD_INIT(NULL)
189
_path_name.c_str(), /*tp_name*/
190
sizeof(PyWrappedOutput), /*tp_basicsize*/
192
(destructor)_dealloc, /*tp_dealloc*/
199
0, /*tp_as_sequence*/
207
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
208
_class_docstring.c_str(), /* tp_doc */
211
0, /* tp_richcompare */
212
0, /* tp_weaklistoffset */
215
PyWrapOutputBase<OUTPUTCLASS>::_methods, /* tp_methods */
216
PyWrapOutputBase<OUTPUTCLASS>::_members, /* tp_members */
220
0, /* tp_descr_get */
221
0, /* tp_descr_set */
222
0, /* tp_dictoffset */
223
(initproc)_init, /* tp_init */
228
template <class OUTPUTCLASS>
229
void PyWrapOutputBase<OUTPUTCLASS>::PyWrapOutputBaseModInit(
230
std::string class_name,
231
std::string class_docstring,
232
std::string birth_docstring,
233
std::string death_docstring,
234
std::string save_docstring) {
235
if (class_docstring != "")
236
_class_docstring = class_docstring;
237
if (birth_docstring != "")
238
_birth_docstring = birth_docstring;
239
if (death_docstring != "")
240
_death_docstring = death_docstring;
241
if (save_docstring != "")
242
_save_docstring = save_docstring;
243
_methods[0].ml_doc = _birth_docstring.c_str();
244
_methods[1].ml_doc = _save_docstring.c_str();
245
_methods[2].ml_doc = _death_docstring.c_str();
247
_class_type.tp_doc = _class_docstring.c_str();
248
// Static so allocates c_str() memory for lifetime of the program
249
_class_name = class_name;
250
_module_name = "_"+_class_name;
251
_path_name = "_"+_class_name+"."+_class_name;
252
_class_type.tp_name = _path_name.c_str();
255
if (PyType_Ready(&_class_type) < 0)
258
module = Py_InitModule3(_module_name.c_str(), _module_methods,
259
"Please import the class directly from the MAUS module.");
263
PyTypeObject* obj_class_type = &_class_type;
264
Py_INCREF(obj_class_type);
265
PyModule_AddObject(module,
267
reinterpret_cast<PyObject*>(obj_class_type));