ATLAS Offline Software
Public Member Functions | Private Types | Private Member Functions | Private Attributes | Friends | List of all members
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: More...
 
virtual ~PyComponentMgr ()
 Destructor: More...
 
virtual StatusCode initialize () override
 Gaudi Service Implementation. More...
 
virtual StatusCode finalize () override
 
virtual PyObjectpyObject (IPyComponent *component) override
 Retrieve a python object from the python world. More...
 

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, ..., } }, }. More...
 
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. More...
 

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 ),
76  m_components( )
77 {
78  //
79  // Property declaration
80  //
81  //declareProperty( "Property", m_nProperty, "descr" );
82 
83 }

◆ ~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 ) {
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() ) {
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 }

◆ 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 }

◆ 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
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 }

◆ 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
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 }

Friends And Related Function Documentation

◆ SvcFactory< PyAthena::PyComponentMgr >

friend class SvcFactory< PyAthena::PyComponentMgr >
friend

Definition at line 30 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:
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
RootUtils::PyException
CPyCppyy::PyException PyException
Definition: Utility.h:24
plotting.yearwise_luminosity_vs_mu.comp
comp
Definition: yearwise_luminosity_vs_mu.py:23
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
PyAthena::PyComponentMgr::m_components
PyComponents_t m_components
A fast look-up hash-map for python components { 'name' : PyObject* } PyObject* is NULL if not yet ins...
Definition: PyComponentMgr.h:90
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
RootUtils::PyGILStateEnsure
Definition: PyAthenaGILStateEnsure.h:20
PyAthena::PyComponentMgr::m_dict
PyObject * m_dict
The dictionary of python components' description It should be of the form: { 'name' : { 'package' : "...
Definition: PyComponentMgr.h:82
python.PyAthena.module
module
Definition: PyAthena.py:131
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
endmsg
#define endmsg
Definition: AnalysisConfig_Ntuple.cxx:63
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:221
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
PyObject
_object PyObject
Definition: IPyComponent.h:26