ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Control
RootUtils
src
pyroot
PyROOTPickle.cxx
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3
*/
4
11
12
// Called from python, so only excuted single-threaded (GIL).
13
#include "
CxxUtils/checker_macros.h
"
14
ATLAS_NO_CHECK_FILE_THREAD_SAFETY
;
15
16
17
#include "
RootUtils/PyROOTPickle.h
"
18
#include "
RootUtils/PyGetString.h
"
19
#include "
Utility.h
"
20
#include "Python.h"
21
#include "TClass.h"
22
#include "TBufferFile.h"
23
#include "TPython.h"
24
25
26
//- data _______________________________________________________________________
27
static
PyObject
*
gExpand
= 0;
28
29
30
namespace
RootUtils
{
31
36
PyObject
*
CPPInstanceReduce
(
PyObject
* self,
PyObject
* )
37
{
38
// Turn the object proxy instance into a character stream and return for
39
// pickle, together with the callable object that can restore the stream
40
// into the object proxy instance.
41
42
void
* vself = TPython::CPPInstance_AsVoidPtr( self );
// checks type
43
if
( ! vself ) {
44
PyErr_SetString( PyExc_TypeError,
45
"__reduce__ requires an object proxy instance as first argument"
);
46
return
0;
47
}
48
49
PyObject
* nattr = PyObject_GetAttrString( (
PyObject
*)self->ob_type, (
char
*)
"__name__"
);
50
PyObject
* pyname = PyObject_Str( nattr );
51
Py_DECREF( nattr );
52
53
std::string klassname =
PyGetString
( pyname ).first;
54
TClass* klass = TClass::GetClass( klassname.c_str() );
55
56
// no cast is needed, but WriteObject taking a TClass argument is protected,
57
// so use WriteObjectAny()
58
TBufferFile buf( TBuffer::kWrite );
59
if
( buf.WriteObjectAny( vself, klass ) != 1 ) {
60
PyErr_Format( PyExc_IOError,
61
"could not stream object of type %s"
, klassname.c_str() );
62
Py_DECREF( pyname );
63
return
0;
64
}
65
66
// use a string for the serialized result, as a python buffer will not copy
67
// the buffer contents; use a string for the class name, used when casting
68
// on reading back in
69
PyObject
* res2 = PyTuple_New( 2 );
70
PyTuple_SET_ITEM( res2, 0, PyUnicode_FromStringAndSize( buf.Buffer(), buf.Length() ) );
71
PyTuple_SET_ITEM( res2, 1, pyname );
72
73
PyObject
* result = PyTuple_New( 2 );
74
Py_INCREF(
gExpand
);
75
PyTuple_SET_ITEM( result, 0,
gExpand
);
76
PyTuple_SET_ITEM( result, 1, res2 );
77
78
return
result;
79
}
80
81
86
PyObject
*
CPPInstanceExpand
(
PyObject
*,
PyObject
* args )
87
{
88
// This method is a helper for (un)pickling of CPPInstance instances.
89
PyObject
* pybuf = 0;
90
const
char
* clname = 0;
91
if
( ! PyArg_ParseTuple( args,
const_cast<
char
*
>
(
"O!s:__expand__"
),
92
&PyUnicode_Type, &pybuf, &clname ) )
93
return
0;
94
95
// use the PyString macros to by-pass error checking; do not adopt the buffer,
96
// as the local TBufferFile can go out of scope (there is no copying)
97
TBufferFile buf( TBuffer::kRead,
98
PyUnicode_GET_LENGTH( pybuf ),
99
(
char
*)
PyGetString
( pybuf ).first.c_str(),
100
kFALSE );
101
102
void
* result = buf.ReadObjectAny( 0 );
103
return
TPython::CPPInstance_FromVoidPtr( result, clname );
104
}
105
106
112
void
PyROOTPickle::Initialize
(
PyObject
* libpyroot_pymodule,
PyObject
* cppinstance_pytype )
113
{
114
Py_INCREF( libpyroot_pymodule );
115
PyTypeObject* pytype =
reinterpret_cast<
PyTypeObject*
>
(cppinstance_pytype);
116
117
// Don't change this name to CPPInstance since it's saved in pickles.
118
static
PyMethodDef s_pdefExp = { (
char
*)
"_ObjectProxy__expand__"
,
119
(PyCFunction)
CPPInstanceExpand
, METH_VARARGS, (
char
*)
"internal function"
};
120
121
PyObject
* pymname = PyUnicode_FromString( PyModule_GetName( libpyroot_pymodule ) );
122
gExpand
= PyCFunction_NewEx( &s_pdefExp, NULL, pymname );
123
Py_DECREF( pymname );
124
Bool_t isOk = PyObject_SetAttrString( libpyroot_pymodule, s_pdefExp.ml_name,
gExpand
) == 0;
125
Py_DECREF(
gExpand
);
// is moderately risky, but Weakref not allowed (?)
126
127
if
( ! isOk ) {
128
Py_DECREF( libpyroot_pymodule );
129
PyErr_SetString( PyExc_TypeError,
"could not add expand function to libPyROOT"
);
130
return
;
131
}
132
133
static
PyMethodDef s_pdefRed = { (
char
*)
"__reduce__"
,
134
(PyCFunction)
CPPInstanceReduce
, METH_NOARGS, (
char
*)
"internal function"
};
135
136
PyObject
* descr = PyDescr_NewMethod( pytype, &s_pdefRed );
137
isOk = PyDict_SetItemString( pytype->tp_dict, s_pdefRed.ml_name, descr) == 0;
138
Py_DECREF( descr );
139
if
( ! isOk ) {
140
Py_DECREF( libpyroot_pymodule );
141
PyErr_SetString( PyExc_TypeError,
"could not add __reduce__ function to CPPInstance"
);
142
return
;
143
}
144
145
Py_DECREF( libpyroot_pymodule );
146
}
147
148
149
}
// namespace RootUtils
PyObject
_object PyObject
Definition
IPyComponent.h:27
PyGetString.h
Convert python string -> C++ string for py2 and py3.
gExpand
static PyObject * gExpand
Definition
PyROOTPickle.cxx:27
PyROOTPickle.h
Port pickling functionality while awaiting newer release.
Utility.h
Utility code originally from pyroot.
checker_macros.h
Define macros for attributes used to control the static checker.
ATLAS_NO_CHECK_FILE_THREAD_SAFETY
#define ATLAS_NO_CHECK_FILE_THREAD_SAFETY
Definition
checker_macros.h:209
RootUtils::PyROOTPickle::Initialize
static void Initialize(PyObject *libpyroot_pymodule, PyObject *objectproxy_pytype)
Install the pickling of ObjectProxy's functionality.
Definition
PyROOTPickle.cxx:112
RootUtils
Definition
ILogger.h:20
RootUtils::CPPInstanceReduce
PyObject * CPPInstanceReduce(PyObject *self, PyObject *)
PyROOT object proxy pickle support.
Definition
PyROOTPickle.cxx:36
RootUtils::CPPInstanceExpand
PyObject * CPPInstanceExpand(PyObject *, PyObject *args)
Helper for (un)pickling of CPPInstance's.
Definition
PyROOTPickle.cxx:86
RootUtils::PyGetString
std::pair< std::string, bool > PyGetString(PyObject *s)
Convert python string -> C++ string for py2 and py3.
Definition
PyGetString.h:40
Generated on
for ATLAS Offline Software by
1.17.0