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