ATLAS Offline Software
PyAthena.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
2 
3 # @file: PyAthena.py
4 # @purpose: a set of Python classes for PyAthena
5 # @author: Sebastien Binet <binet@cern.ch>
6 
7 from __future__ import print_function
8 
9 __doc__ = """Module containing a set of Python base classes for PyAthena"""
10 __version__ = "$Revision: 1.16 $"
11 __author__ = "Sebastien Binet <binet@cern.ch>"
12 
13 
14 __all__ = []
15 __pseudo_all__ = [ 'StatusCode',
16  'Alg',
17  'Svc',
18  'AlgTool',
19  'Aud',
20  'AthFilterAlgorithm',
21  'services',
22  'algs'
23  ]
24 
25 
26 def _get_native_libname(libname):
27  """ return the OS-native name from an OS-indenpendent one """
28  import sys
29  plat = sys.platform
30  if plat.count('linux')>0:
31  lib_prefix,lib_suffix = 'lib', '.so'
32  elif plat == 'win32':
33  lib_prefix,lib_suffix = '', '.dll'
34  elif plat == 'darwin':
35  lib_prefix,lib_suffix = 'lib','.dylib'
36  else:
37  raise RuntimeError ("sorry platform [%s] is not (yet?) supported"%plat)
38  _sys_libname = libname
39  if not _sys_libname.startswith (lib_prefix):
40  _sys_libname = ''.join([lib_prefix,_sys_libname])
41  if not _sys_libname.endswith (lib_suffix):
42  _sys_libname = ''.join([_sys_libname, lib_suffix])
43  return _sys_libname
44 
45 def load_library (libname):
46  """
47  Helper method to load a library by its natural name, not the OS-native name.
48  But if the OS-native name is given, it is safely handled too. Note that there's
49  a problem on MacOSX, for which the OS-native name ends with .dylib, but for
50  which ATLAS builds .so libraries. Override the OS-native name (which should probably
51  be replaced by two attempts; one with the .dylib and the other with .so)
52  usage:
53  >>> load_library ('AthenaServices')
54  >>> load_library ('AthenaServicesDict')
55  """
56  _sys_libname = _get_native_libname(libname)
57  from sys import platform
58  if platform == 'darwin':
59  _sys_libname = _sys_libname.replace('.dylib', '.so')
60  import ctypes
61  return ctypes.cdll.LoadLibrary (_sys_libname)
62 
63 def find_library(libname):
64  """
65  Helper function to find the (full)path to a library given its natural name.
66  @return None on failure
67 
68  usage:
69  >>> find_library('AthenaServices')
70  '/afs/cern.ch/.../AtlasCore/[release]/InstallArea/.../libAthenaServices.so
71  """
72  import os
73 
79  _sys_libname = _get_native_libname(libname)
80  # FIXME: REALLY not portable...
81  if os.name != 'posix':
82  raise RuntimeError('sorry OS [%s] is not supported' % os.name)
83 
84  if 'LD_LIBRARY_PATH' in os.environ:
85  for d in os.environ['LD_LIBRARY_PATH'].split(os.pathsep):
86  lib = os.path.join(d, _sys_libname)
87  if os.path.exists(lib):
88  return lib
89  return
90 
91 def reload_module (modname):
92  """
93  Helper method to reload a python module by name.
94  This is useful in the usual following case:
95  >>> from Foo import MyAlg
96  >>> assert (not 'Foo' in dir())
97  >>> reload(Foo) # won't work
98  >>> PyAthena.reload_module ('Foo') # will work
99  >>> PyAthena.reload_module (Foo) # will work too
100  """
101  import sys, types
102  from imp import reload
103  if isinstance (modname, types.ModuleType):
104  modname = modname.__name__
105  if modname in sys.modules:
106  return reload (sys.modules[modname])
107  raise ValueError('no module [%s] could be found'%modname)
108 
109 def py_reload (*args):
110  """simple minded function to reload objects, methods and modules
111 
112  example of usage:
113  >>> # edit and modify the execute methods of some PyAthena.Alg
114  ... # class, then load back that definition
115  >>> PyAthena.py_reload (alg1.execute, alg2.execute)
116  >>> PyAthena.py_reload (alg1.execute)
117  >>> alg1.execute() # will use the new definition
118  >>> theApp.nextEvent() # will also use the new definitions
119  ... # of both alg1 and alg2
120  """
121  import types, sys
122  from imp import reload
123  for i,arg in enumerate(args):
124  if isinstance (arg, types.ModuleType):
125 
126  reload (arg)
127  elif isinstance (arg, types.StringType):
128  # no-op
129  continue
130  elif isinstance (arg, types.MethodType):
131 
133  modname = arg.im_self.__class__.__module__
134  module = reload (sys.modules[modname])
135  obj = arg.im_self
136  klass = getattr (module, obj.__class__.__name__)
137  # update the object with the new fct definition
138  fct_name = arg.im_func.__name__
139  new_fct = getattr (klass, fct_name)
140  #new_fct.im_class = klass
141 
142  setattr (obj, fct_name,
143  new_fct.__get__(obj))
144  elif hasattr (arg, '__class__'):
145 
147  modname = arg.__class__.__module__
148  module = reload (sys.modules[modname])
149  # get the class, in case new methods appeared...
150  klass = getattr (module, arg.__class__.__name__)
151  from AthenaCommon.Configurable import Configurable
152  cfg_methods = dir(Configurable)
153  d = (k for k in dir(klass)
154  if not k.startswith('__') and k not in cfg_methods)
155  for k in d:
156  if not hasattr (arg, k):
157  v = getattr (klass, k)
158  try:
159  v = v.__get__ (arg)
160  except AttributeError:
161  # 'handle' not-yet-set gaudi properties
162  continue
163  setattr (arg, k, v.__get__(arg))
164  # FIXME: should we remove methods which disappeared ?
165  v = getattr (arg, k)
166 
169  py_reload (v)
170  else:
171  print ("*** unhandled type: [%s] (arg #%i) ***" % (type(arg),i))
172  pass
173  return
174 
175 
176 from AthenaPython import PyAthenaComps
177 from AthenaPython.Bindings import _PyAthenaBindingsCatalog as _pycat
178 
179 
180 import types
181 class ModuleFacade(types.ModuleType):
182  """a helper class to allow easy retrieval of automatically generated
183  configurables (stolen from PyRoot)
184  """
185  def __init__( self, module ):
186  types.ModuleType.__init__(self, module.__name__)
187  self.__dict__[ 'module' ] = module
188  self.__dict__[ '__doc__' ] = module.__doc__
189  self.__dict__[ '__name__' ] = module.__name__
190  self.__dict__[ '__file__' ] = module.__file__
191 
192  from .Bindings import py_svc
193  self.__dict__ ['py_svc'] = py_svc
194 
195  from .Bindings import py_tool
196  self.__dict__ ['py_tool'] = py_tool
197 
198  from .Bindings import py_alg
199  self.__dict__ ['py_alg'] = py_alg
200 
201  self.__dict__ ['load_library'] = load_library
202  self.__dict__ ['find_library'] = find_library
203  self.__dict__ ['reload_module'] = reload_module
204  self.__dict__ ['py_reload'] = py_reload
205 
206  def __getattr__(self, k):
207  if k in self.__dict__:
208  return self.__dict__.get(k)
209  if k.startswith('__'):
210  return types.ModuleType.__getattribute__(self, k)
211  if k in __pseudo_all__: v = getattr(PyAthenaComps, k)
212  else: v = _pycat.init(k)
213  object.__getattribute__(self, '__dict__')[k] = v
214  return v
215 
216 import sys
217 sys.modules[ __name__ ] = ModuleFacade( sys.modules[ __name__ ] )
218 del ModuleFacade
python.PyAthena._get_native_libname
def _get_native_libname(libname)
helpers
Definition: PyAthena.py:26
python.PyAthena.ModuleFacade
Definition: PyAthena.py:181
python.PyAthena.find_library
def find_library(libname)
Definition: PyAthena.py:63
python.PyAthena.ModuleFacade.__init__
def __init__(self, module)
Definition: PyAthena.py:185
Configurable
athena/gaudi ----------------------------------------------------------—
python.PyAthena.load_library
def load_library(libname)
Definition: PyAthena.py:45
beamspotman.dir
string dir
Definition: beamspotman.py:623
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.PyAthena.py_reload
def py_reload(*args)
Definition: PyAthena.py:109
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
python.PyAthena.ModuleFacade.__getattr__
def __getattr__(self, k)
Definition: PyAthena.py:206
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.PyAthena.reload_module
def reload_module(modname)
Definition: PyAthena.py:91