The Gaudi Framework  v36r16 (ea80daf8)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
gaudirun.py
Go to the documentation of this file.
1 #!/usr/bin/env python3
2 
12 
13 from __future__ import print_function
14 
15 import os
16 import sys
17 from tempfile import mkstemp
18 
19 
21  """
22  Remove from the arguments the presence of the profiler and its output in
23  order to relaunch the script w/o infinite loops.
24 
25  >>> getArgsWithoutProfilerInfo(['--profilerName', 'igprof', 'myopts.py'])
26  ['myopts.py']
27 
28  >>> getArgsWithoutProfilerInfo(['--profilerName=igprof', 'myopts.py'])
29  ['myopts.py']
30 
31  >>> getArgsWithoutProfilerInfo(['--profilerName', 'igprof', '--profilerExtraOptions', 'a b c', 'myopts.py'])
32  ['myopts.py']
33 
34  >>> getArgsWithoutProfilerInfo(['--profilerName', 'igprof', '--options', 'a b c', 'myopts.py'])
35  ['--options', 'a b c', 'myopts.py']
36  """
37  newargs = []
38  args = list(args) # make a temp copy
39  while args:
40  o = args.pop(0)
41  if o.startswith("--profile"):
42  if "=" not in o:
43  args.pop(0)
44  else:
45  newargs.append(o)
46  return newargs
47 
48 
49 def setLibraryPreload(newpreload):
50  """Adds a list of libraries to LD_PRELOAD"""
51  preload = os.environ.get("LD_PRELOAD", "")
52  if preload:
53  preload = preload.replace(" ", ":").split(":")
54  else:
55  preload = []
56 
57  for libname in set(preload).intersection(newpreload):
58  logging.warning(
59  "Ignoring preload of library %s because it is " "already in LD_PRELOAD.",
60  libname,
61  )
62 
63  to_load = [libname for libname in newpreload if libname not in set(preload)]
64 
65  if to_load:
66  preload += to_load
67  preload = ":".join(preload)
68  os.environ["LD_PRELOAD"] = preload
69  logging.info("Setting LD_PRELOAD='%s'", preload)
70 
71  return to_load
72 
73 
74 def rationalizepath(path):
75  """
76  Convert the given path to a real path if the pointed file exists, otherwise
77  just normalize it.
78  """
79  path = os.path.normpath(os.path.expandvars(path))
80  if os.path.exists(path):
81  path = os.path.realpath(path)
82  return path
83 
84 
85 # variable used to keep alive the temporary option files extracted
86 # from the .qmt
87 _qmt_tmp_opt_files = []
88 
89 
90 def getArgsFromQmt(qmtfile):
91  """
92  Given a .qmt file, return the command line arguments of the corresponding
93  test.
94  """
95  from xml.etree import ElementTree as ET
96 
97  global _qmt_tmp_opt_files
98  # parse the .qmt file and extract args and options
99  qmt = ET.parse(qmtfile)
100  args = [a.text for a in qmt.findall("argument[@name='args']//text")]
101  options = qmt.find("argument[@name='options']/text")
102 
103  if (
104  options is not None and options.text is not None
105  ): # options need to be dumped in a temporary file
106  import re
107  from tempfile import NamedTemporaryFile
108 
109  if re.search(
110  r"from\s+Gaudi.Configuration\s+import\s+\*"
111  r"|from\s+Configurables\s+import",
112  options.text,
113  ):
114  tmp_opts = NamedTemporaryFile(suffix=".py")
115  else:
116  tmp_opts = NamedTemporaryFile(suffix=".opts")
117  tmp_opts.write(options.text.encode("ascii"))
118  tmp_opts.flush()
119  args.append(tmp_opts.name)
120  _qmt_tmp_opt_files.append(tmp_opts)
121 
122  # relative paths in a .qmt are rooted in the qmtest directory, so
123  # - find where the .qmt lives
124  qmtfile = os.path.abspath(qmtfile)
125  if "qmtest" in qmtfile.split(os.path.sep):
126  # this return the path up to the 'qmtest' entry in qmtfile
127  testdir = qmtfile
128  while os.path.basename(testdir) != "qmtest":
129  testdir = os.path.dirname(testdir)
130  else:
131  testdir = "."
132  # - temporarily switch to that directory and rationalize the paths
133  old_cwd = os.getcwd()
134  os.chdir(testdir)
135  args = [rationalizepath(arg) for arg in args]
136  os.chdir(old_cwd)
137 
138  return args
139 
140 
141 # ---------------------------------------------------------------------
142 if __name__ == "__main__":
143  # ensure that we (and the subprocesses) use the C standard localization
144  if os.environ.get("LC_ALL") != "C":
145  print('# setting LC_ALL to "C"')
146  # !!!!
147  os.environ["LC_ALL"] = "C"
148 
149  from optparse import OptionParser
150 
151  parser = OptionParser(usage="%prog [options] <opts_file|function_id> ...")
152  parser.add_option(
153  "-n",
154  "--dry-run",
155  action="store_true",
156  help="do not run the application, just parse option files",
157  )
158  parser.add_option(
159  "-p",
160  "--pickle-output",
161  action="store",
162  type="string",
163  metavar="FILE",
164  help="DEPRECATED: use '--output file.pkl' instead. Write "
165  "the parsed options as a pickle file (static option "
166  "file)",
167  )
168  parser.add_option(
169  "-v", "--verbose", action="store_true", help="print the parsed options"
170  )
171  parser.add_option(
172  "--old-opts",
173  action="store_true",
174  help="format printed options in old option files style",
175  )
176  parser.add_option(
177  "--all-opts",
178  action="store_true",
179  help="print all the option (even if equal to default)",
180  )
181  # GaudiPython Parallel Mode Option
182  # Argument must be an integer in range [ -1, sys_cpus ]
183  # -1 : All available cpus
184  # 0 : Serial Mode (traditional gaudirun)
185  # n>0 : parallel with n cpus (n <= sys_cpus)
186  parser.add_option(
187  "--ncpus",
188  action="store",
189  type="int",
190  default=0,
191  help="start the application in parallel mode using NCPUS processes. "
192  "0 => serial mode (default), -1 => use all CPUs",
193  )
194 
195  def option_cb(option, opt, value, parser):
196  """Add the option line to a list together with its position in the
197  argument list.
198  """
199  parser.values.options.append((len(parser.largs), value))
200 
201  parser.add_option(
202  "--option",
203  action="callback",
204  callback=option_cb,
205  type="string",
206  nargs=1,
207  help="add a single line (Python) option to the configuration. "
208  "All options lines are executed, one after the other, in "
209  "the same context.",
210  )
211  parser.add_option(
212  "--no-conf-user-apply",
213  action="store_true",
214  help="disable the automatic application of configurable "
215  "users (for backward compatibility)",
216  )
217  parser.add_option(
218  "--old-conf-user-apply",
219  action="store_true",
220  help="use the old logic when applying ConfigurableUsers "
221  "(with bug #103803) [default]",
222  )
223  parser.add_option(
224  "--new-conf-user-apply",
225  action="store_false",
226  dest="old_conf_user_apply",
227  help="use the new (correct) logic when applying "
228  "ConfigurableUsers (fixed bug #103803), can be "
229  "turned on also with the environment variable "
230  "GAUDI_FIXED_APPLY_CONF",
231  )
232  parser.add_option(
233  "-o",
234  "--output",
235  action="store",
236  type="string",
237  help="dump the configuration to a file. The format of "
238  "the options is determined by the extension of the "
239  "file name: .pkl = pickle, .py = python, .opts = "
240  "old style options. The python format cannot be "
241  "used to run the application and it contains the "
242  "same dictionary printed with -v",
243  )
244  parser.add_option(
245  "--post-option",
246  action="append",
247  type="string",
248  dest="post_options",
249  help="Python options to be executed after the ConfigurableUser "
250  "are applied. "
251  "All options lines are executed, one after the other, in "
252  "the same context.",
253  )
254  parser.add_option(
255  "--debug", action="store_true", help="enable some debug print-out"
256  )
257  parser.add_option("--gdb", action="store_true", help="attach gdb")
258  parser.add_option("--printsequence", action="store_true", help="print the sequence")
259  if not sys.platform.startswith("win"):
260  # These options can be used only on unix platforms
261  parser.add_option(
262  "-T",
263  "--tcmalloc",
264  action="store_true",
265  help="Use the Google malloc replacement. The environment "
266  "variable TCMALLOCLIB can be used to specify a different "
267  "name for the library (the default is libtcmalloc.so)",
268  )
269  parser.add_option(
270  "--preload",
271  action="append",
272  help="Allow pre-loading of special libraries (e.g. Google "
273  "profiling libraries).",
274  )
275  # Option to use a profiler
276  parser.add_option(
277  "--profilerName",
278  type="string",
279  help="Select one profiler among: igprofPerf, igprofMem and valgrind<toolname>",
280  )
281 
282  # Option to specify the filename where to collect the profiler's output
283  parser.add_option(
284  "--profilerOutput",
285  type="string",
286  help="Specify the name of the output file for the profiler output",
287  )
288 
289  # Option to specify the filename where to collect the profiler's output
290  parser.add_option(
291  "--profilerExtraOptions",
292  type="string",
293  help="Specify additional options for the profiler. The '--' string should be expressed as '__' (--my-opt becomes __my-opt)",
294  )
295 
296  parser.add_option(
297  "--use-temp-opts",
298  action="store_true",
299  help="when this option is enabled, the options are parsed"
300  " and stored in a temporary file, then the job is "
301  "restarted using that file as input (to save "
302  "memory)",
303  )
304  parser.add_option(
305  "--run-info-file",
306  type="string",
307  help="Save gaudi process information to the file specified (in JSON format)",
308  )
309  parser.add_option(
310  "--application",
311  help="name of the Gaudi::Application to use [default: %default]",
312  )
313 
314  parser.set_defaults(
315  options=[],
316  tcmalloc=False,
317  profilerName="",
318  profilerOutput="",
319  profilerExtraOptions="",
320  preload=[],
321  ncpus=None,
322  # the old logic can be turned off with an env variable
323  old_conf_user_apply="GAUDI_FIXED_APPLY_CONF" not in os.environ,
324  run_info_file=None,
325  application="Gaudi::Application",
326  )
327 
328  # replace .qmt files in the command line with their contained args
329  argv = []
330  for a in sys.argv[1:]:
331  if a.endswith(".qmt") and os.path.exists(a):
332  argv.extend(getArgsFromQmt(a))
333  else:
334  argv.append(a)
335  if argv != sys.argv[1:]:
336  print("# Running", sys.argv[0], "with arguments", argv)
337 
338  opts, args = parser.parse_args(args=argv)
339 
340  # Check consistency of options
341 
342  # Parallel Option ---------------------------------------------------------
343  if opts.ncpus:
344  from multiprocessing import cpu_count
345 
346  sys_cpus = cpu_count()
347  if opts.ncpus > sys_cpus:
348  s = "Invalid value : --ncpus : only %i cpus available" % sys_cpus
349  parser.error(s)
350  elif opts.ncpus < -1:
351  s = "Invalid value : --ncpus must be integer >= -1"
352  parser.error(s)
353  else:
354  # FIXME: is it really needed to set it to None if it is 0 or False?
355  opts.ncpus = None
356 
357  # configure the logging
358  import logging
359 
360  from GaudiKernel.ProcessJobOptions import InstallRootLoggingHandler, PrintOff
361 
362  if opts.old_opts:
363  prefix = "// "
364  else:
365  prefix = "# "
366  level = logging.INFO
367  if opts.debug:
368  level = logging.DEBUG
369  InstallRootLoggingHandler(prefix, level=level, with_time=opts.debug)
370  root_logger = logging.getLogger()
371 
372  # Sanitizer support
373  sanitizers = os.environ.get("PRELOAD_SANITIZER_LIB", "")
374  preload = os.environ.get("LD_PRELOAD", "")
375  if sanitizers:
376  os.environ["PRELOAD_SANITIZER_LIB"] = ""
377  if preload and sanitizers != preload:
378  logging.warning(
379  "Ignoring PRELOAD_SANITIZER_LIB (={}) as LD_PRELOAD (={}) is "
380  "different and takes precedence.".format(sanitizers, preload)
381  )
382  else:
383  for sanitizer in reversed(sanitizers.split(":")):
384  if sanitizer not in preload:
385  opts.preload.insert(0, sanitizer)
386  if opts.profilerName == "jemalloc":
387  logging.warning("jemalloc disabled when using a sanitizer")
388  opts.profilerName = None
389 
390  # tcmalloc support
391  if opts.tcmalloc:
392  # Disable tcmalloc if sanitizer is selected
393  if sanitizers:
394  logging.warning("tcmalloc preload disabled when using a sanitizer")
395  else:
396  opts.preload.insert(0, os.environ.get("TCMALLOCLIB", "libtcmalloc.so"))
397 
398  # allow preloading of libraries
399  if opts.preload:
400  preload = os.environ.get("LD_PRELOAD", "")
401  if preload:
402  preload = preload.replace(" ", ":").split(":")
403  else:
404  preload = []
405  for libname in set(preload).intersection(opts.preload):
406  logging.warning(
407  "Ignoring preload of library %s because it is "
408  "already in LD_PRELOAD.",
409  libname,
410  )
411  to_load = [libname for libname in opts.preload if libname not in set(preload)]
412  if to_load:
413  preload += to_load
414  preload = ":".join(preload)
415  os.environ["LD_PRELOAD"] = preload
416  logging.info("Restarting with LD_PRELOAD='%s'", preload)
417  # remove the --tcmalloc option from the arguments
418  # FIXME: the --preload arguments will issue a warning but it's tricky to remove them
419  args = [a for a in sys.argv if a != "-T" and not "--tcmalloc".startswith(a)]
420  os.execv(sys.executable, [sys.executable] + args)
421 
422  # Profiler Support ------
423  if opts.profilerName:
424  profilerName = opts.profilerName
425  profilerExecName = ""
426  profilerOutput = opts.profilerOutput or (profilerName + ".output")
427 
428  # To restart the application removing the igprof option and prepending the string
429  args = getArgsWithoutProfilerInfo(sys.argv)
430 
431  igprofPerfOptions = "-d -pp -z -o igprof.pp.gz".split()
432 
433  profilerOptions = ""
434  if profilerName == "igprof":
435  if not opts.profilerOutput:
436  profilerOutput += ".profile.gz"
437  profilerOptions = "-d -z -o %s" % profilerOutput
438  profilerExecName = "igprof"
439 
440  elif profilerName == "igprofPerf":
441  if not opts.profilerOutput:
442  profilerOutput += ".pp.gz"
443  profilerOptions = "-d -pp -z -o %s" % profilerOutput
444  profilerExecName = "igprof"
445 
446  elif profilerName == "igprofMem":
447  if not opts.profilerOutput:
448  profilerOutput += ".mp.gz"
449  profilerOptions = "-d -mp -z -o %s" % profilerOutput
450  profilerExecName = "igprof"
451 
452  elif "valgrind" in profilerName:
453  # extract the tool
454  if not opts.profilerOutput:
455  profilerOutput += ".log"
456  toolname = profilerName.replace("valgrind", "")
457  outoption = "--log-file"
458  if toolname in ("massif", "callgrind", "cachegrind"):
459  outoption = "--%s-out-file" % toolname
460  profilerOptions = "--tool=%s %s=%s" % (toolname, outoption, profilerOutput)
461  profilerExecName = "valgrind"
462 
463  elif profilerName == "jemalloc":
464  opts.preload.insert(0, os.environ.get("JEMALLOCLIB", "libjemalloc.so"))
465  os.environ["MALLOC_CONF"] = "prof:true,prof_leak:true"
466  else:
467  root_logger.warning("Profiler %s not recognized!" % profilerName)
468 
469  # Add potential extra options
470  if opts.profilerExtraOptions != "":
471  profilerExtraOptions = opts.profilerExtraOptions
472  profilerExtraOptions = profilerExtraOptions.replace("__", "--")
473  profilerOptions += " %s" % profilerExtraOptions
474 
475  # now we look for the full path of the profiler: is it really there?
476  if profilerExecName:
477  import distutils.spawn
478 
479  profilerPath = distutils.spawn.find_executable(profilerExecName)
480  if not profilerPath:
481  root_logger.error("Cannot locate profiler %s" % profilerExecName)
482  sys.exit(1)
483 
484  root_logger.info(
485  "------ Profiling options are on ------ \n"
486  " o Profiler: %s\n"
487  " o Options: '%s'.\n"
488  " o Output: %s"
489  % (profilerExecName or profilerName, profilerOptions, profilerOutput)
490  )
491 
492  # allow preloading of libraries
493  # That code need to be acsracted from above
494  to_reload = []
495  if opts.preload:
496  to_reload = setLibraryPreload(opts.preload)
497 
498  if profilerExecName:
499  # We profile python
500  profilerOptions += " python"
501 
502  # now we have all the ingredients to prepare our command
503  arglist = [profilerPath] + profilerOptions.split() + args
504  arglist = [a for a in arglist if a != ""]
505  # print profilerPath
506  # for arg in arglist:
507  # print arg
508  os.execv(profilerPath, arglist)
509  else:
510  arglist = [a for a in sys.argv if not a.startswith("--profiler")]
511  os.execv(sys.executable, [sys.executable] + arglist)
512 
513  # End Profiler Support ------
514 
515  if opts.pickle_output:
516  if opts.output:
517  root_logger.error(
518  "Conflicting options: use only --pickle-output or --output"
519  )
520  sys.exit(1)
521  else:
522  root_logger.warning("--pickle-output is deprecated, use --output instead")
523  opts.output = opts.pickle_output
524 
525  from Gaudi.Main import gaudimain
526 
527  c = gaudimain()
528 
530  """
531  Helper class to be able to process option files or options
532  callables as they come along in the arguments.
533  """
534 
535  def __init__(self, initial_config=None):
536  self.config = {} if initial_config is None else initial_config
537 
538  def __call__(self, arg):
539  from Gaudi.Configuration import importOptions
540  from GaudiConfig2 import CALLABLE_FORMAT, invokeConfig, mergeConfigs
541 
542  if CALLABLE_FORMAT.match(arg):
543  self.config = mergeConfigs(self.config, invokeConfig(arg))
544  else:
545  importOptions(arg)
546 
547  process = ArgProcessor()
548 
549  # Prepare the "configuration script" to parse (like this it is easier than
550  # having a list with files and python commands, with an if statements that
551  # decides to do importOptions or exec)
552  options = ["process({!r})".format(arg) for arg in args]
553  # The option lines are inserted into the list of commands using their
554  # position on the command line
555  optlines = list(opts.options)
556  # this allows to avoid to have to care about corrections of the positions
557  optlines.reverse()
558  for pos, l in optlines:
559  options.insert(pos, l)
560 
561  # prevent the usage of GaudiPython
562  class FakeModule(object):
563  def __init__(self, exception):
564  self.exception = exception
565 
566  def __getattr__(self, *args, **kwargs):
567  raise self.exception
568 
569  sys.modules["GaudiPython"] = FakeModule(
570  RuntimeError("GaudiPython cannot be used in option files")
571  )
572 
573  # when the special env GAUDI_TEMP_OPTS_FILE is set, it overrides any
574  # option(file) on the command line
575  if "GAUDI_TEMP_OPTS_FILE" in os.environ:
576  options = ["process({!r})".format(os.environ["GAUDI_TEMP_OPTS_FILE"])]
577  PrintOff(100)
578 
579  # "execute" the configuration script generated (if any)
580  if options:
581  g = {"process": process}
582  l = {}
583  exec("from Gaudi.Configuration import *", g, l)
584  for o in options:
585  logging.debug(o)
586  exec(o, g, l)
587 
588  import GaudiKernel.Proxy.Configurable
589 
590  if opts.no_conf_user_apply:
591  logging.info("Disabling automatic apply of ConfigurableUser")
592  # pretend that they have been already applied
593  GaudiKernel.Proxy.Configurable._appliedConfigurableUsers_ = True
594 
595  # This need to be done before dumping
596  if opts.old_conf_user_apply:
597  from GaudiKernel.Proxy.Configurable import (
598  applyConfigurableUsers_old as applyConfigurableUsers,
599  )
600  else:
601  from GaudiKernel.Proxy.Configurable import applyConfigurableUsers
603 
604  # Options to be processed after applyConfigurableUsers
605  if opts.post_options:
606  g = {"process": process}
607  l = {}
608  exec("from Gaudi.Configuration import *", g, l)
609  for o in opts.post_options:
610  logging.debug(o)
611  exec(o, g, l)
612 
613  if "GAUDI_TEMP_OPTS_FILE" in os.environ:
614  os.remove(os.environ["GAUDI_TEMP_OPTS_FILE"])
615  opts.use_temp_opts = False
616 
617  # make configurations available to getAllOpts
618  # FIXME the whole machinery has to be inverted, to avoid relying on globals
619  from GaudiConfig2 import Configurable, mergeConfigs
620 
621  Configurable.instances = mergeConfigs(Configurable.instances, process.config)
622 
623  if opts.verbose and not opts.use_temp_opts:
624  c.printconfig(opts.old_opts, opts.all_opts)
625  if opts.output:
626  c.writeconfig(opts.output, opts.all_opts)
627 
628  if opts.use_temp_opts:
629  fd, tmpfile = mkstemp(".opts")
630  os.close(fd)
631  c.writeconfig(tmpfile, opts.all_opts)
632  os.environ["GAUDI_TEMP_OPTS_FILE"] = tmpfile
633  logging.info("Restarting from pre-parsed options")
634  os.execv(sys.executable, [sys.executable] + sys.argv)
635 
636  c.printsequence = opts.printsequence
637  if opts.printsequence:
638  if opts.ncpus:
639  logging.warning("--printsequence not supported with --ncpus: ignored")
640  elif opts.dry_run:
641  logging.warning("--printsequence not supported with --dry-run: ignored")
642 
643  c.application = opts.application
644 
645  # re-enable the GaudiPython module
646  del sys.modules["GaudiPython"]
647 
648  if not opts.dry_run:
649  # Do the real processing
650  retcode = c.run(opts.gdb, opts.ncpus)
651 
652  # Now saving the run information pid, retcode and executable path to
653  # a file is requested
654  if opts.run_info_file:
655  import json
656  import os
657 
658  run_info = {}
659  run_info["pid"] = os.getpid()
660  run_info["retcode"] = retcode
661  if os.path.exists("/proc/self/exe"):
662  # These options can be used only on unix platforms
663  run_info["exe"] = os.readlink("/proc/self/exe")
664 
665  logging.info("Saving run info to: %s" % opts.run_info_file)
666  with open(opts.run_info_file, "w") as f:
667  json.dump(run_info, f)
668 
669  sys.exit(retcode)
gaudirun.FakeModule.__init__
def __init__(self, exception)
Definition: gaudirun.py:563
gaudirun.FakeModule
Definition: gaudirun.py:562
gaudirun.ArgProcessor.__call__
def __call__(self, arg)
Definition: gaudirun.py:538
gaudirun.ArgProcessor
Definition: gaudirun.py:529
gaudirun.FakeModule.exception
exception
Definition: gaudirun.py:564
GaudiConfig2.invokeConfig
def invokeConfig(func, *args, **kwargs)
Definition: __init__.py:70
gaudirun.FakeModule.__getattr__
def __getattr__(self, *args, **kwargs)
Definition: gaudirun.py:566
gaudirun.ArgProcessor.__init__
def __init__(self, initial_config=None)
Definition: gaudirun.py:535
gaudirun.getArgsFromQmt
def getArgsFromQmt(qmtfile)
Definition: gaudirun.py:90
GaudiKernel.ProcessJobOptions
Definition: ProcessJobOptions.py:1
gaudirun.getArgsWithoutProfilerInfo
def getArgsWithoutProfilerInfo(args)
Definition: gaudirun.py:20
GaudiConfig2.mergeConfigs
def mergeConfigs(*configs)
Definition: __init__.py:51
Gaudi.Configuration
Definition: Configuration.py:1
Gaudi.Main
Definition: Main.py:1
Gaudi.Main.gaudimain
Definition: Main.py:326
format
GAUDI_API std::string format(const char *,...)
MsgStream format utility "a la sprintf(...)".
Definition: MsgStream.cpp:119
GaudiKernel.ProcessJobOptions.InstallRootLoggingHandler
def InstallRootLoggingHandler(prefix=None, level=None, stream=None, with_time=False)
Definition: ProcessJobOptions.py:128
GaudiKernel.ProcessJobOptions.importOptions
def importOptions(optsfile)
Definition: ProcessJobOptions.py:541
gaudirun.option_cb
def option_cb(option, opt, value, parser)
Definition: gaudirun.py:195
gaudirun.setLibraryPreload
def setLibraryPreload(newpreload)
Definition: gaudirun.py:49
gaudirun.ArgProcessor.config
config
Definition: gaudirun.py:536
gaudirun.rationalizepath
def rationalizepath(path)
Definition: gaudirun.py:74
GaudiKernel.ProcessJobOptions.PrintOff
def PrintOff(step=1)
Definition: ProcessJobOptions.py:141
GaudiKernel.Configurable.applyConfigurableUsers
def applyConfigurableUsers()
Definition: Configurable.py:1603