The Gaudi Framework  master (37c0b60a)
genconfuser Namespace Reference

Functions

def _inheritsfrom (derived, basenames)
 
def loadConfigurableDb (build_dir=None, project_name=None)
 
def getConfigurableUsers (modulename, root, mayNotExist=False)
 
def main ()
 

Variables

 VERBOSE
 
 verbose
 
 retcode
 

Function Documentation

◆ _inheritsfrom()

def genconfuser._inheritsfrom (   derived,
  basenames 
)
private
Check if any of the class names in 'basenames' is anywhere in the base
classes of the class 'derived'.
If 'derived' _is_ one in 'basenames', returns False.

'basenames' can be a string or an iterable (of strings).

Definition at line 33 of file genconfuser.py.

33 def _inheritsfrom(derived, basenames):
34  """
35  Check if any of the class names in 'basenames' is anywhere in the base
36  classes of the class 'derived'.
37  If 'derived' _is_ one in 'basenames', returns False.
38 
39  'basenames' can be a string or an iterable (of strings).
40  """
41  if isinstance(basenames, str):
42  basenames = (basenames,)
43  for b in derived.__bases__:
44  if b.__name__ in basenames:
45  return True
46  else:
47  if _inheritsfrom(b, basenames):
48  return True
49  return False
50 
51 

◆ getConfigurableUsers()

def genconfuser.getConfigurableUsers (   modulename,
  root,
  mayNotExist = False 
)
Find in the module 'modulename' all the classes that derive from ConfigurableUser.
Return the list of the names.
The flag mayNotExist is used to choose the level of the logging message in case
the requested module does not exist.

Definition at line 109 of file genconfuser.py.

109 def getConfigurableUsers(modulename, root, mayNotExist=False):
110  """
111  Find in the module 'modulename' all the classes that derive from ConfigurableUser.
112  Return the list of the names.
113  The flag mayNotExist is used to choose the level of the logging message in case
114  the requested module does not exist.
115  """
116  # remember the old system path
117  oldpath = list(sys.path)
118  # we need to hack the sys.path to add the first part of the module name after root
119  moduleelements = modulename.split(".")
120  if len(moduleelements) > 1:
121  moddir = os.sep.join([root] + moduleelements[:-1])
122  else:
123  moddir = root
124  # this is the name of the submodule to import
125  shortmodname = moduleelements[-1]
126  # check if the module file actually exists
127  if not os.path.exists(os.path.join(moddir, shortmodname) + ".py"):
128  msg = "Module %s does not exist" % modulename
129  if mayNotExist:
130  logging.verbose(msg)
131  else:
132  logging.error(msg)
133  # no file -> do not try to import
134  return []
135  # prepend moddir to the path
136  sys.path.insert(0, moddir)
137  logging.verbose("sys.path prepended with %r", sys.path[0])
138 
139  logging.info("Looking for ConfigurableUser in %r", modulename)
140  g, l = {}, {}
141  try:
142  logging.verbose("importing %s", shortmodname)
143  exec("import %s as mod" % shortmodname, g, l)
144  finally:
145  # restore old sys.path
146  logging.verbose("restoring old sys.path")
147  sys.path = oldpath
148  mod = l["mod"]
149  if "__all__" in dir(mod) and mod.__all__:
150  all = mod.__all__
151  else:
152  all = [n for n in dir(mod) if not n.startswith("_")]
153  result = []
154  for name in all:
155  cfg = cfgDb.get(name)
156  if cfg and cfg["module"] != modulename:
157  # This name comes from another module
158  logging.verbose("Object %r already found in module %r", name, cfg["module"])
159  continue
160  t = getattr(mod, name)
161  if isinstance(t, type) and _inheritsfrom(
162  t, ("ConfigurableUser", "SuperAlgorithm")
163  ):
164  result.append(name)
165  logging.verbose("Found %r", result)
166  return result
167 
168 

◆ loadConfigurableDb()

def genconfuser.loadConfigurableDb (   build_dir = None,
  project_name = None 
)
Equivalent to GaudiKernel.ConfigurableDb.loadConfigurableDb(), but does a
deep search and executes the '*.confdb' files instead of importing them.

Definition at line 52 of file genconfuser.py.

52 def loadConfigurableDb(build_dir=None, project_name=None):
53  """
54  Equivalent to GaudiKernel.ConfigurableDb.loadConfigurableDb(), but does a
55  deep search and executes the '*.confdb' files instead of importing them.
56  """
57  log = GaudiKernel.ConfigurableDb.log
58  from os.path import join as path_join
59 
60  # look for the confdb files in all the reasonable places
61  # - CMake builds
62  confDbFiles = []
63  for path in sys.path:
64  confDbFiles += [
65  f for f in glob(path_join(path, "*", "*.confdb")) if os.path.isfile(f)
66  ]
67  # - new-style CMake builds (look for all .confdb in the build tree)
68  if build_dir:
69  for root, _, files in os.walk(build_dir):
70  confDbFiles += [
71  os.path.join(root, f) for f in files if f.endswith(".confdb")
72  ]
73  # - used projects and local merged file
74  pathlist = os.getenv("LD_LIBRARY_PATH", "").split(os.pathsep)
75  for path in filter(os.path.isdir, pathlist):
76  confDbFiles += [
77  f
78  for f in [
79  path_join(path, f) for f in os.listdir(path) if f.endswith(".confdb")
80  ]
81  ]
82  # - get the list of ignored files
83  ignored_files = set(os.environ.get("CONFIGURABLE_DB_IGNORE", "").split(","))
84  # - load the confdb files
85  for confDb in set(confDbFiles):
86  if confDb in ignored_files or (
87  project_name
88  and os.path.basename(confDb) == ("{}.confdb".format(project_name))
89  ):
90  # skip ignored files and the project's own confdb
91  log.debug("\t-ignoring [%s]", confDb)
92  # make sure we count also <project_name>.confdb for GaudiKernel
93  ignored_files.add(confDb)
94  continue
95  log.debug("\t-loading [%s]...", confDb)
96  try:
97  cfgDb._loadModule(confDb)
98  except Exception as err:
99  # It may happen that the file is found but not completely
100  # written, usually during parallel builds, but we do not care.
101  log.warning("Could not load file [%s] !", confDb)
102  log.warning("Reason: %s", err)
103  # top up with the regular merged confDb (for the used projects)
104  # (make sure GaudiKernel gets the right exclusions)
105  os.environ["CONFIGURABLE_DB_IGNORE"] = ",".join(ignored_files)
107 
108 

◆ main()

def genconfuser.main ( )

Definition at line 169 of file genconfuser.py.

169 def main():
170  from optparse import OptionParser
171 
172  parser = OptionParser(
173  prog=os.path.basename(sys.argv[0]),
174  usage="%prog [options] <PackageName> [<Module1> ...]",
175  )
176  parser.add_option(
177  "-o",
178  "--output",
179  action="store",
180  type="string",
181  help="output file for confDb data [default = '../genConfDir/<PackageName>_user_confDb.py'].",
182  )
183  parser.add_option(
184  "-r",
185  "--root",
186  action="store",
187  type="string",
188  help="root directory of the python modules [default = '../python'].",
189  )
190  parser.add_option(
191  "-v", "--verbose", action="store_true", help="print some debugging information"
192  )
193  parser.add_option(
194  "--debug", action="store_true", help="print more debugging information"
195  )
196  parser.add_option(
197  "--build-dir",
198  action="store",
199  help="build directory where to look for .confdb files (search all subdirectories)",
200  )
201  parser.add_option(
202  "--project-name",
203  action="store",
204  help="name of the current project (used to exclude spurious versions of the .confdb file for the current project)",
205  )
206  parser.set_defaults(root=os.path.join("..", "python"))
207 
208  opts, args = parser.parse_args()
209 
210  if opts.debug:
211  log_level = logging.DEBUG
212  elif opts.verbose:
213  log_level = logging.VERBOSE
214  else:
215  log_level = logging.INFO if os.environ.get("VERBOSE") else logging.WARNING
216  logging.basicConfig(
217  format="%(levelname)s: %(message)s", stream=sys.stdout, level=log_level
218  )
219 
220  if len(args) < 1:
221  parser.error("PackageName is required")
222 
223  package_name = args.pop(0)
224 
225  usingConvention = False
226  if not args:
227  # use the conventional module name <package>.Configuration
228  args = [package_name + ".Configuration"]
229  usingConvention = True
230 
231  genConfDir = os.path.join("..", os.environ.get("CMTCONFIG", ""), "genConfDir")
232  if not os.path.exists(genConfDir):
233  genConfDir = os.path.join("..", "genConfDir")
234 
235  if not opts.output:
236  outputfile = os.path.join(genConfDir, package_name + "_user.confdb")
237  else:
238  outputfile = opts.output
239 
240  # We can disable the error on missing configurables only if we can import Gaudi.Configurables
241  # It must be done at this point because it may conflict with logging.basicConfig
242  try:
243  import Gaudi.Configurables
244 
245  Gaudi.Configurables.ignoreMissingConfigurables = True
246  except ImportError:
247  pass
248  # load configurables database to avoid fake duplicates
249  loadConfigurableDb(opts.build_dir, opts.project_name)
250  # ensure that local configurables are in the database
251  try:
252  # Add the local python directories to the python path to be able to import the local
253  # configurables
254  sys.path.insert(0, genConfDir)
255  sys.path.insert(0, os.path.join("..", "python"))
256  localConfDb = os.path.join(genConfDir, package_name, package_name + ".confdb")
257  if os.path.exists(localConfDb):
258  cfgDb._loadModule(localConfDb)
259  # Extend the search path of the package module to find the configurables
260  package_module = __import__(package_name)
261  package_module.__path__.insert(0, os.path.join(genConfDir, package_name))
262  except Exception:
263  pass # ignore failures (not important)
264 
265  # Collecting ConfigurableUser specializations
266  cus = {}
267  for mod in args:
268  lst = None
269  try:
270  lst = getConfigurableUsers(mod, root=opts.root, mayNotExist=usingConvention)
271  except ImportError:
272  import traceback
273 
274  logging.error(
275  "Cannot import module %r:\n%s", mod, traceback.format_exc().rstrip()
276  ) # I remove the trailing '\n'
277  return 2
278  if lst:
279  cus[mod] = lst
280  # Add the configurables to the database as fake entries to avoid duplicates
281  for m in lst:
282  cfgDb.add(configurable=m, package="None", module="None", lib="None")
283  elif not usingConvention:
284  logging.warning(
285  "Specified module %r does not contain ConfigurableUser specializations",
286  mod,
287  )
288 
289  if cus:
290  logging.info("ConfigurableUser found:\n%s", pformat(cus))
291  # header
292  output = """## -*- ascii -*-
293 # db file automatically generated by %s on: %s
294 """ % (
295  parser.prog,
296  time.asctime(),
297  )
298 
299  for mod in cus:
300  for cu in cus[mod]:
301  output += "%s %s %s\n" % (mod, "None", cu)
302 
303  # trailer
304  output += "## %s\n" % package_name
305  elif usingConvention:
306  logging.info("No ConfigurableUser found")
307  output = (
308  "# db file automatically generated by %s on: %s\n"
309  "# No ConfigurableUser specialization in %s\n"
310  ) % (parser.prog, time.asctime(), package_name)
311  else:
312  logging.error("No ConfigurableUser specialization found")
313  return 1
314 
315  # create the destination directory if not there
316  output_dir = os.path.dirname(outputfile)
317  try:
318  logging.info("Creating directory %r", output_dir)
319  os.makedirs(output_dir, 0o755)
320  except OSError as err:
321  import errno
322 
323  if err.errno == errno.EEXIST:
324  # somebody already - perhaps concurrently - created that dir.
325  pass
326  else:
327  raise
328 
329  # write output to file
330  logging.verbose("Writing confDb data to %r", outputfile)
331  open(outputfile, "w").write(output)
332  return 0
333 
334 

Variable Documentation

◆ retcode

genconfuser.retcode

Definition at line 336 of file genconfuser.py.

◆ VERBOSE

genconfuser.VERBOSE

Definition at line 26 of file genconfuser.py.

◆ verbose

genconfuser.verbose

Definition at line 28 of file genconfuser.py.

GaudiKernel.ConfigurableDb.loadConfigurableDb
def loadConfigurableDb()
Definition: ConfigurableDb.py:113
genconfuser._inheritsfrom
def _inheritsfrom(derived, basenames)
Definition: genconfuser.py:33
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
genconfuser.main
def main()
Definition: genconfuser.py:169
genconfuser.getConfigurableUsers
def getConfigurableUsers(modulename, root, mayNotExist=False)
Definition: genconfuser.py:109
genconfuser.loadConfigurableDb
def loadConfigurableDb(build_dir=None, project_name=None)
Definition: genconfuser.py:52