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