ATLAS Offline Software
Loading...
Searching...
No Matches
PyAthena::PyComponentMgr Class Reference

#include <PyComponentMgr.h>

Inheritance diagram for PyAthena::PyComponentMgr:
Collaboration diagram for PyAthena::PyComponentMgr:

Public Member Functions

 PyComponentMgr (const std::string &name, ISvcLocator *pSvcLocator)
 Constructor with parameters:
virtual ~PyComponentMgr ()
 Destructor:
virtual StatusCode initialize () override
 Gaudi Service Implementation.
virtual StatusCode finalize () override
virtual PyObjectpyObject (IPyComponent *component) override
 Retrieve a python object from the python world.

Private Types

typedef std::unordered_map< std::string, PyObject * > PyComponents_t

Private Member Functions

 PyComponentMgr ()=delete

Private Attributes

PyObjectm_dict
 The dictionary of python components' description It should be of the form: { 'name' : { 'package' : "MyAnaPkg", 'class' : "MyAlg", 'pyprops' : { 'OutputLevel' : 1, ..., } }, }.
PyComponents_t m_components
 A fast look-up hash-map for python components { 'name' : PyObject* } PyObject* is NULL if not yet instantiated Note that we own the PyObjects.

Friends

class SvcFactory< PyAthena::PyComponentMgr >

Detailed Description

Definition at line 35 of file PyComponentMgr.h.

Member Typedef Documentation

◆ PyComponents_t

typedef std::unordered_map<std::string, PyObject*> PyAthena::PyComponentMgr::PyComponents_t
private

Definition at line 84 of file PyComponentMgr.h.

Constructor & Destructor Documentation

◆ PyComponentMgr() [1/2]

PyComponentMgr::PyComponentMgr ( const std::string & name,
ISvcLocator * pSvcLocator )

Constructor with parameters:

Definition at line 72 of file PyComponentMgr.cxx.

73 :
74 base_class ( name, pSvcLocator ),
75 m_dict ( nullptr ),
77{
78 //
79 // Property declaration
80 //
81 //declareProperty( "Property", m_nProperty, "descr" );
82
83}
PyComponents_t m_components
A fast look-up hash-map for python components { 'name' : PyObject* } PyObject* is NULL if not yet ins...
PyObject * m_dict
The dictionary of python components' description It should be of the form: { 'name' : { 'package' : "...

◆ ~PyComponentMgr()

PyComponentMgr::~PyComponentMgr ( )
virtual

Destructor:

Definition at line 87 of file PyComponentMgr.cxx.

88{
89 ATH_MSG_DEBUG("Calling destructor");
90
91 // we own the repository of instances' description
92 if ( m_dict ) {
93 RootUtils::PyGILStateEnsure ensure;
94 Py_DECREF( m_dict );
95 m_dict = nullptr;
96 }
97
98 // as well as the one of corresponding instances
99 if ( m_components.size() ) {
100 RootUtils::PyGILStateEnsure ensure;
101 for ( PyComponents_t::iterator
102 i = m_components.begin(),
103 iEnd = m_components.end();
104 i != iEnd;
105 ++i ) {
106 ATH_MSG_VERBOSE("__del__(" << i->first << ")...");
107 Py_XDECREF( i->second );
108 }
109 }
110
111}
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)

◆ PyComponentMgr() [2/2]

PyAthena::PyComponentMgr::PyComponentMgr ( )
privatedelete

Member Function Documentation

◆ finalize()

StatusCode PyComponentMgr::finalize ( )
overridevirtual

Definition at line 198 of file PyComponentMgr.cxx.

199{
200 ATH_MSG_INFO("Finalizing " << name() << "...");
201 return StatusCode::SUCCESS;
202}
#define ATH_MSG_INFO(x)

◆ initialize()

StatusCode PyComponentMgr::initialize ( )
overridevirtual

Gaudi Service Implementation.

Definition at line 116 of file PyComponentMgr.cxx.

117{
118 ATH_MSG_INFO("Initializing " << name() << "...");
119
120 const std::string pyModuleName = "AthenaPython.Configurables";
121
122 // import the module holding the dictionary of component instances
123 RootUtils::PyGILStateEnsure ensure;
124 ATH_MSG_DEBUG("Importing module [" << pyModuleName << "]...");
125 PyObject* module = PyImport_ImportModule( const_cast<char*>(pyModuleName.c_str()) );
126 if ( !module || !PyModule_Check( module ) ) {
127 ATH_MSG_ERROR("Could not import [" << pyModuleName << "] !!");
128 Py_XDECREF (module);
129 throw CPyCppyy::PyException();
130 }
131
132 const std::string pyClassName = "PyComponents";
133 PyObject* pyClass = 0;
134 pyClass = PyDict_GetItemString( PyModule_GetDict( module ),
135 const_cast<char*>( pyClassName.c_str() ) );
136
137 // borrowed ref. so ->increment
138 Py_XINCREF( pyClass );
139
140 if ( !pyClass ) {
141 ATH_MSG_ERROR("Could not retrieve class [" << pyClassName
142 << "] from module [" << pyModuleName << "] !!");
143 Py_XDECREF(pyClass);
144 Py_DECREF (module);
145 return StatusCode::FAILURE;
146 }
147
148 m_dict = PyObject_GetAttrString( pyClass,
149 const_cast<char*>( "instances" ) );
150 if ( !m_dict || !PyDict_Check( m_dict ) ) {
151 ATH_MSG_ERROR("Could not retrieve attribute [instances] from class ["
152 << pyClassName << "] !!");
153 Py_DECREF (pyClass);
154 Py_DECREF (module);
155 return StatusCode::FAILURE;
156 }
157 Py_DECREF(pyClass);
158
159 // install the fancy attribute getter for PyComponents to automatically
160 // retrieve an initialized component.
161 // see bug #46668
162 {
163 PyObject* fancy_attr = 0;
164 fancy_attr = PyDict_GetItemString(PyModule_GetDict(module),
165 (char*)"_install_fancy_attrs");
166 // borrowed ref => increment
167 Py_XINCREF(fancy_attr);
168 if (!fancy_attr) {
169 PyErr_Clear();
171 ("could not retrieve function [_install_fancy_attrs] from module ["
172 << pyModuleName << "]");
173 } else {
174 PyObject* ret = PyObject_CallFunction(fancy_attr, NULL);
175 Py_XDECREF(ret);
176 }
177 Py_XDECREF(fancy_attr);
178 }
179 Py_DECREF (module);
180
181 // make sure the PyROOT fixes are installed
182 const std::string pyRootFixes = "RootUtils.PyROOTFixes";
183 ATH_MSG_DEBUG("Importing module [" << pyRootFixes << "]...");
184 PyObject *rootFixes = 0;
185 rootFixes = PyImport_ImportModule(const_cast<char*>(pyRootFixes.c_str()));
186 if ( !rootFixes || !PyModule_Check( rootFixes ) ) {
187 PyErr_Print();
188 PyErr_Clear();
189 ATH_MSG_WARNING("Could not import [" << pyRootFixes << "] !!"
190 << endmsg
191 << "Some problem may appear with some C++->python binded classes (YMMV)");
192 }
193 Py_XDECREF(rootFixes);
194 return StatusCode::SUCCESS;
195}
#define endmsg
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
_object PyObject

◆ pyObject()

PyObject * PyComponentMgr::pyObject ( IPyComponent * component)
overridevirtual

Retrieve a python object from the python world.

this returns a NEW reference to that python object.

Hum... remove ? or not ? leaving the objects on the python side may allow easier retrieval from py-components...

Definition at line 206 of file PyComponentMgr.cxx.

207{
208 const std::string& name = cppComp->name();
209
210 // Check if we already have instantiated that component
211 RootUtils::PyGILStateEnsure ensure;
212 PyComponents_t::iterator comp = m_components.find( name );
213 if ( comp != m_components.end() && comp->second ) {
214 Py_INCREF (comp->second);
215 return comp->second;
216 }
217 m_components[name] = static_cast<PyObject*>( NULL );
218
219 // Check we have a valid dict.
220 if ( !m_dict || !PyDict_Check(m_dict) ) {
221 ATH_MSG_ERROR("Invalid repository of Python components !!");
222 Py_INCREF( Py_None );
223 return Py_None;
224 }
225
226 PyObject* o = PyDict_GetItemString( m_dict,
227 const_cast<char*>(name.c_str()) );
228 // borrowed ref -> incr
229 Py_XINCREF( o );
230
231 // Check we have a valid dict.
232 if ( !o ) {
233 ATH_MSG_ERROR("No such python component [" << name
234 << "] or invalid item !!");
235 Py_XDECREF( o );
236 throw CPyCppyy::PyException();
237 }
238 m_components[name] = o;
239
243// // remove the object from the python dict
244// if ( PyDict_DelItemString( m_dict, const_cast<char*>(name.c_str()) ) ) {
245// ATH_MSG_ERROR("Could not remove [" << name << "] from PyComponents.instances !!");
246// throw PyROOT::TPyException();
247// }
248
249 // now we tell the PyObject which C++ object it is the cousin of.
250 if ( !cppComp->setPyAttr(o) ) {
251 ATH_MSG_WARNING("Could not connect the C++ object ["
252 << cppComp->typeName() << "/" << cppComp->name()
253 << "] with its python cousin !");
254 }
255
256 removePyGen();
257
258 Py_INCREF(o);
259 return o;
260}

◆ SvcFactory< PyAthena::PyComponentMgr >

friend class SvcFactory< PyAthena::PyComponentMgr >
friend

Definition at line 35 of file PyComponentMgr.h.

Member Data Documentation

◆ m_components

PyComponents_t PyAthena::PyComponentMgr::m_components
private

A fast look-up hash-map for python components { 'name' : PyObject* } PyObject* is NULL if not yet instantiated Note that we own the PyObjects.

Definition at line 90 of file PyComponentMgr.h.

◆ m_dict

PyObject* PyAthena::PyComponentMgr::m_dict
private

The dictionary of python components' description It should be of the form: { 'name' : { 'package' : "MyAnaPkg", 'class' : "MyAlg", 'pyprops' : { 'OutputLevel' : 1, ..., } }, }.

Definition at line 82 of file PyComponentMgr.h.


The documentation for this class was generated from the following files: