7__author__ =
"Sebastien Binet"
17 if platform.system() ==
"Linux":
18 if lib[:3] !=
"lib": lib =
"lib"+lib
19 if lib[-3:] !=
".so": lib = lib+
".so"
24 'ElementLinkInt_p1' :
'ElementLink_p1<unsigned int>',
25 'basic_string<char>' :
'string',
26 'std::basic_string<char>' :
'string',
27 'vector<basic_string<char> >' :
'vector<string>',
29 'INavigable4MomentumCollection' :
'DataVector<INavigable4Momentum>',
30 'IParticleContainer' :
'DataVector<IParticle>',
34 'INavigable4MomentumCollection' :
'DataVector<INavigable4Momentum>',
35 'IParticleContainer' :
'DataVector<IParticle>',
39 'char',
'unsigned char',
'signed char',
41 'short int',
'short signed',
'short signed int',
42 'short',
'unsigned short',
'signed short',
43 'int',
'unsigned int',
50 'long signed',
'signed long',
70_is_stl_sequence = re.compile (
r'std::(?P<ContType>.*?)'
71 r'<(?P<TemplateArg>.*?)'
72 r',\s*?std::allocator<\2> >')
73_is_stl_mapping = re.compile (
r'std::map<'
74 r'(?P<TemplateArg1>.*?),\s*?'
75 r'(?P<TemplateArg2>.*?)'
76 r',\s*?std::allocator<\2> >')
82def _get_native_libname(libname):
83 """ return the OS-native name from an OS-indenpendent one """
85 if plat.count(
'linux')>0:
86 lib_prefix,lib_suffix =
'lib',
'.so'
88 lib_prefix,lib_suffix =
'',
'.dll'
89 elif plat ==
'darwin':
90 lib_prefix,lib_suffix =
'lib',
'.dylib'
92 raise RuntimeError (
"sorry platform [%s] is not (yet?) supported"%plat)
93 _sys_libname = libname
94 if not _sys_libname.startswith (lib_prefix):
95 _sys_libname =
''.join([lib_prefix,_sys_libname])
96 if not _sys_libname.endswith (lib_suffix):
97 _sys_libname =
''.join([_sys_libname, lib_suffix])
100def load_library (libname):
102 Helper method to load a library by its natural name, not the OS-native name.
103 But if the OS-native name is given, it is safely handled too.
105 >>> load_library ('AthenaServices')
106 >>> load_library ('AthenaServicesDict')
108 _sys_libname = _get_native_libname(libname)
110 return ctypes.cdll.LoadLibrary (_sys_libname)
114 Helper function to find the (full)path to a library given its natural name.
115 @return None on failure
118 >>> find_library('AthenaServices')
119 '/afs/cern.ch/.../AtlasCore/[release]/InstallArea/.../libAthenaServices.so
128 _sys_libname = _get_native_libname(libname)
130 if os.name !=
'posix':
131 raise RuntimeError(
'sorry OS [%s] is not supported' % os.name)
133 if 'LD_LIBRARY_PATH' in os.environ:
134 for d
in os.environ[
'LD_LIBRARY_PATH'].
split(os.pathsep):
135 lib = os.path.join(d, _sys_libname)
136 if os.path.exists(lib):
141def _is_rootcint_dict (libname):
142 """helper function to reject rootcint libraries entries from rootmap
143 files (which appeared w/ ROOT v21/22)
144 It seems all of them (and on all platforms) are named like:
145 vector<char>: vector.dll
147 if libname ==
".dll":
149 pat = re.compile(
r'\w*?.dll')
150 return not (libname.startswith(
"lib"))
and \
151 not (pat.match (libname)
is None)
155 The repository of 'rootmap' files (location, content,...)
160 import PyUtils.RootUtils
as ru
161 ROOT = ru.import_root()
162 self._cxx = ROOT.Ath.DsoDb.instance()
164 def _to_py(self, cxx):
166 kk = self._cxx.py_keys_from(cxx)
167 vv = self._cxx.py_vals_from(cxx)
168 for i
in range(kk.size()):
169 dd[kk[i]] = list(vv[i])
174 return self._to_py(self._cxx.db())
178 return self._to_py(self._cxx.pf())
180 def has_type(self, typename):
181 return self._cxx.has_type(typename)
183 def load_type(self, typename):
184 return self._cxx.load_type(typename)
186 def capabilities(self, libname):
187 return list(self._cxx.capabilities(libname))
189 def duplicates(self, libname, pedantic=False):
190 return self._to_py(self._cxx.duplicates(libname, pedantic))
192 def dict_duplicates(self, pedantic=False):
193 return self._to_py(self._cxx.dict_duplicates(pedantic))
195 dictDuplicates = dict_duplicates
197 def pf_duplicates(self, pedantic=False):
198 return self._to_py(self._cxx.pf_duplicates(pedantic))
200 pfDuplicates = pf_duplicates
202 def libs(self, detailed=False):
203 return list(self._cxx.libs(detailed))
205 def content(self, pedantic):
206 return self._to_py(self._cxx.content(pedantic))
210 return list(self._cxx.dso_files())
214 return self.dso_files
216def _to_rootmap_name(typename):
218 helper method to massage a typename into something understandable
221 typename = typename.replace(
', ',
',')
223 if typename
in _cpp_builtins:
226 if typename
in _aliases.keys():
227 t = _aliases[typename]
228 return _to_rootmap_name(t)
230 if _is_stl_sequence.match(typename):
233 _m = _is_stl_sequence.match(typename)
234 _m_type = _m.group(
'TemplateArg')
236 _m_type = _to_rootmap_name(_m_type.strip())
237 if _m_type.endswith(
'>'):
239 typename =
'std::%s<%s>' % (_m.group(
'ContType'),
242 typename = typename.replace(
'std::basic_string<char> ',
244 typename = typename.replace(
'std::basic_string<char>',
246 typename = typename.replace(
'std::',
'')
247 typename = typename.replace(
'> >',
'>->')
248 typename = typename.replace(
' >',
'>')
249 typename = typename.replace(
'>->',
'> >')
252def _to_rflx_name (typename):
253 """helper method to massage a typename into something understandable
254 by reflex (which doesn't understand the same thing than rootmaps).
256 typename = typename.replace(
', ',
',')
258 if typename
in _cpp_builtins:
261 if typename
in _typedefs.keys():
262 t = _typedefs[typename]
263 return _to_rflx_name(t)
265 if _is_stl_sequence.match(typename):
268 _m = _is_stl_sequence.match (typename)
269 _m_type = _m.group(
'TemplateArg')
271 _m_type = _to_rflx_name (_m_type.strip())
272 if _m_type.endswith(
'>'):
274 typename =
'std::%s<%s>' % (_m.group(
'ContType'), _m_type)
275 typename = typename.replace(
'std::string>',
276 'std::basic_string<char> >')
277 typename = typename.replace(
'std::string',
278 'std::basic_string<char>')
283 The repository of 'rootmap' files (location, content,...)
287 PluginNamespace =
"__pf__"
289 def __init__(self, name = "DsoDb"):
290 object.__init__(self)
295 import PyUtils.Logging
as _L
296 self.msg = _L.logging.getLogger(
'DsoDb')
298 self.dsoPath = os.environ[
'LD_LIBRARY_PATH']
299 self.__buildRepository()
302 def __buildRepository(self):
304 self.dsoFiles =
set()
305 dsoPath = [p
for p
in self.dsoPath.
split( os.pathsep )
306 if not p.startswith(os.environ[
'ROOTSYS'])]
308 if not os.path.exists(path):
continue
311 dir_content = os.listdir(path)
315 dir_content = os.listdir(path)
316 except Exception
as err:
317 msg.warning(
"caught:\n%s", err)
318 if dir_content
is None:
319 msg.warning(
"could not run os.listdir on [%s]", path)
321 dsoFiles = [ f
for f
in dir_content
322 if f.endswith(self.RootMap) ]
323 for dsoFile
in dsoFiles:
324 dsoFile = os.path.join( path, dsoFile )
325 if os.path.exists(dsoFile):
327 self.dsoFiles.
add(dsoFile)
328 for line
in open(dsoFile,
'r'):
331 if len(line) <= 0
or line[0] ==
"#":
338 dsoKey, libName = line[0], line[1]
339 except Exception
as err:
341 'could not parse %s:%i', dsoFile, line_nbr
344 '(some) reflex-dicts may fail to be auto-loaded'
353 if dsoKey.startswith( self.PluginNamespace ):
357 if dsoKey
not in db: db[dsoKey] = list()
358 if _is_rootcint_dict (libName):
361 libName = os.path.join(path,
_libName(libName))
362 db[dsoKey].append(libName)
369 s = os.linesep.join( [
370 "+--- %s ---" % self.name,
371 "|nbr of lib components: %i" % len(self.db.keys()),
372 "|nbr of pf components: %i" % len(self.pf.keys()),
373 "|nbr of dso files: %i" % len(self.dsoFiles),
374 "|nbr of known libs: %i" % len(self.libs()),
375 "+-------------------------"
380 def __dups(self, db, pedantic):
383 if len(db[k]) == 1:
continue
384 if pedantic: libs = db[k]
389 if os.path.basename(lib)
not in baseLibs:
391 baseLibs.add(os.path.basename(lib))
395 dups[k] = [ lib
for lib
in libs ]
398 def duplicates(self, libName, pedantic = False):
399 caps = self.capabilities(libName)
401 for dupDb
in [ self.dictDuplicates(pedantic),
402 self.pfDuplicates(pedantic) ]:
405 if k
not in dups: dups[k] = []
406 dups[k] += [ lib
for lib
in dupDb[k]
407 if libName
not in os.path.basename(lib) ]
409 for k
in dups.keys():
413 def dictDuplicates(self, pedantic = False):
414 return self.__dups(self.db, pedantic)
416 def pfDuplicates(self, pedantic = False):
417 return self.__dups(self.pf, pedantic)
419 def capabilities(self, libName):
422 for db
in [self.db, self.pf]:
424 if libName
in [ os.path.basename(lib)
for lib
in db[k] ]:
426 caps = [ cap
for cap
in caps ]
429 print (
"::: ERROR: No such library [%s] in dsoDb !!" % libName)
430 raise ValueError (
"")
433 def libs(self, detailedDump = False):
434 if detailedDump: fct =
lambda x : x
435 else: fct = os.path.basename
437 for db
in [self.pf, self.db]:
441 libs = [ lib
for lib
in libs ]
445 def content(self, pedantic):
447 for db
in [self.pf, self.db]:
449 if pedantic: libs = db[k]
454 if os.path.basename(lib)
not in baseLibs:
456 baseLibs.add(os.path.basename(lib))
459 d[k] = [ lib
for lib
in libs ]
462 def _to_rootmap_name(self, typename):
464 helper method to massage a typename into something understandable
467 return _to_rootmap_name(typename)
469 def _to_rflx_name (self, typename):
470 """helper method to massage a typename into something understandable
471 by reflex (which doesn't understand the same thing than rootmaps).
473 return _to_rflx_name(typename)
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
bool add(const std::string &hname, TKey *tobj)
std::string replace(std::string s, const std::string &s2, const std::string &s3)
std::vector< std::string > split(const std::string &s, const std::string &t=":")