ATLAS Offline Software
Public Member Functions | Static Public Attributes | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
python.AthConfigFlags.AthConfigFlags Class Reference
Inheritance diagram for python.AthConfigFlags.AthConfigFlags:
Collaboration diagram for python.AthConfigFlags.AthConfigFlags:

Public Member Functions

def __init__ (self)
 
def athHash (self)
 
def __hash__ (self)
 
def __getattr__ (self, name)
 
def __setattr__ (self, name, value)
 
def __delattr__ (self, name)
 
def __getitem__ (self, name)
 
def __setitem__ (self, name, value)
 
def __delitem__ (self, name)
 
def __contains__ (self, name)
 
def __iter__ (self)
 
def asdict (self)
 
def addFlag (self, name, setDef, type=None, help=None)
 
def addFlagsCategory (self, path, generator, prefix=False)
 
def needFlagsCategory (self, name)
 
def loadAllDynamicFlags (self)
 
def hasCategory (self, name)
 
def hasFlag (self, name)
 
def __call__ (self, name)
 
def lock (self)
 
def locked (self)
 
def clone (self)
 
def cloneAndReplace (self, subsetToReplace, replacementSubset, keepOriginal=False)
 
def join (self, other, prefix='')
 
def dump (self, pattern=".*", evaluate=False, formatStr="{:40} : {}", maxLength=None)
 
def initAll (self)
 
def getArgumentParser (self, **kwargs)
 
def parser (self)
 
def args (self)
 
def fillFromString (self, flag_string)
 
def fillFromArgs (self, listOfArgs=None, parser=None, return_unknown=False)
 

Static Public Attributes

 print_context
 

Private Member Functions

def _calculateHash (self)
 
def _renamed_map (self)
 
def _subflag_itr (self)
 
def _loadDynaFlags (self, name)
 
def _set (self, name, value)
 
def _get (self, name)
 
def _tryModify (self)
 

Private Attributes

 _flagdict
 
 _locked
 
 _dynaflags
 
 _loaded
 
 _categoryCache
 
 _hash
 
 _parser
 
 _args
 
 _renames
 

Static Private Attributes

list _hashedFlags = []
 

Detailed Description

Definition at line 230 of file AthConfigFlags.py.

Constructor & Destructor Documentation

◆ __init__()

def python.AthConfigFlags.AthConfigFlags.__init__ (   self)

Definition at line 237 of file AthConfigFlags.py.

237  def __init__(self):
238  self._flagdict=dict()
239  self._locked=False
240  self._dynaflags = dict()
241  self._loaded = set() # dynamic flags that were loaded
242  self._categoryCache = set() # cache for already found categories
243  self._hash = None
244  self._parser = None
245  self._args = None # user args from parser
246  self._renames = {}
247 

Member Function Documentation

◆ __call__()

def python.AthConfigFlags.AthConfigFlags.__call__ (   self,
  name 
)

Definition at line 491 of file AthConfigFlags.py.

491  def __call__(self,name):
492  return self._get(name)
493 

◆ __contains__()

def python.AthConfigFlags.AthConfigFlags.__contains__ (   self,
  name 
)

Definition at line 307 of file AthConfigFlags.py.

307  def __contains__(self, name):
308  return hasattr(self, name)
309 

◆ __delattr__()

def python.AthConfigFlags.AthConfigFlags.__delattr__ (   self,
  name 
)

Definition at line 290 of file AthConfigFlags.py.

290  def __delattr__(self, name):
291  del self[name]
292 

◆ __delitem__()

def python.AthConfigFlags.AthConfigFlags.__delitem__ (   self,
  name 
)

Definition at line 299 of file AthConfigFlags.py.

299  def __delitem__(self, name):
300  self._tryModify()
301  self.loadAllDynamicFlags()
302  for key in list(self._flagdict):
303  if key.startswith(name):
304  del self._flagdict[key]
305  self._categoryCache.clear()
306 

◆ __getattr__()

def python.AthConfigFlags.AthConfigFlags.__getattr__ (   self,
  name 
)

Definition at line 268 of file AthConfigFlags.py.

268  def __getattr__(self, name):
269  # Avoid infinite recursion looking up our own attributes
270  _flagdict = object.__getattribute__(self, "_flagdict")
271 
272  # First try to get an already loaded flag or category
273  if name in _flagdict:
274  return self._get(name)
275 
276  # Check (and load if needed) dynamic flags
277  if self.hasCategory(name):
278  return FlagAddress(self, name)
279 
280  raise AttributeError(f"No such flag: {name}")
281 

◆ __getitem__()

def python.AthConfigFlags.AthConfigFlags.__getitem__ (   self,
  name 
)

Definition at line 293 of file AthConfigFlags.py.

293  def __getitem__(self, name):
294  return getattr(self, name)
295 

◆ __hash__()

def python.AthConfigFlags.AthConfigFlags.__hash__ (   self)

Definition at line 255 of file AthConfigFlags.py.

255  def __hash__(self):
256  raise DeprecationWarning("__hash__ method in AthConfigFlags is deprecated. Probably called from function decorator, use AccumulatorCache decorator instead.")
257 

◆ __iter__()

def python.AthConfigFlags.AthConfigFlags.__iter__ (   self)

Definition at line 310 of file AthConfigFlags.py.

310  def __iter__(self):
311  self.loadAllDynamicFlags()
312  rmap = self._renamed_map()
313  used = set()
314  for flag in self._flagdict:
315  for r in rmap[flag]:
316  first = r.split('.',1)[0]
317  if first not in used:
318  yield first
319  used.add(first)
320 

◆ __setattr__()

def python.AthConfigFlags.AthConfigFlags.__setattr__ (   self,
  name,
  value 
)

Definition at line 282 of file AthConfigFlags.py.

282  def __setattr__(self, name, value):
283  if name.startswith("_"):
284  return object.__setattr__(self, name, value)
285 
286  if name in self._flagdict:
287  return self._set(name, value)
288  raise RuntimeError( "No such flag: "+ name+". The name is likely incomplete." )
289 

◆ __setitem__()

def python.AthConfigFlags.AthConfigFlags.__setitem__ (   self,
  name,
  value 
)

Definition at line 296 of file AthConfigFlags.py.

296  def __setitem__(self, name, value):
297  setattr(self, name, value)
298 

◆ _calculateHash()

def python.AthConfigFlags.AthConfigFlags._calculateHash (   self)
private

Definition at line 258 of file AthConfigFlags.py.

258  def _calculateHash(self):
259  # Once we've hashed a flags instance, we need to be sure that
260  # it never goes away. Otherwise, since we base the hash
261  # on just the id of the dictionary, if a flags object is deleted
262  # and a new one created, the hash of the new one could match the
263  # hash of the old, even if contents are different.
264  # See ATLASRECTS-8070.
265  AthConfigFlags._hashedFlags.append (self)
266  return hash( (frozenset({k: v for k, v in self._renames.items() if k != v}), id(self._flagdict)) )
267 

◆ _get()

def python.AthConfigFlags.AthConfigFlags._get (   self,
  name 
)
private

Definition at line 482 of file AthConfigFlags.py.

482  def _get(self,name):
483  try:
484  return self._flagdict[name].get(self)
485  except KeyError:
486  closestMatch = get_close_matches(name,self._flagdict.keys(),1)
487  raise KeyError(f"No flag with name '{name}' found" +
488  (f". Did you mean '{closestMatch[0]}'?" if closestMatch else ""))
489 

◆ _loadDynaFlags()

def python.AthConfigFlags.AthConfigFlags._loadDynaFlags (   self,
  name 
)
private
loads the flags of the form "A.B.C" first attempting the path "A" then "A.B" and then "A.B.C"

Definition at line 403 of file AthConfigFlags.py.

403  def _loadDynaFlags(self, name):
404  """
405  loads the flags of the form "A.B.C" first attempting the path "A" then "A.B" and then "A.B.C"
406  """
407 
408  def __load_impl( flagBaseName ):
409  if flagBaseName in self._loaded:
410  _msg.debug("Flags %s already loaded",flagBaseName )
411  return
412  if flagBaseName in self._dynaflags:
413  _msg.debug("Dynamically loading the flags under %s", flagBaseName )
414  # Retain locked status and hash
415  isLocked = self._locked
416  myHash = self._hash
417  self._locked = False
418  generator, prefix = self._dynaflags[flagBaseName]
419  self.join( generator(), flagBaseName if prefix else "" )
420  self._locked = isLocked
421  self._hash = myHash
422  del self._dynaflags[flagBaseName]
423  self._loaded.add(flagBaseName)
424 
425  pathfrags = name.split('.')
426  for maxf in range(1, len(pathfrags)+1):
427  __load_impl( '.'.join(pathfrags[:maxf]) )
428 

◆ _renamed_map()

def python.AthConfigFlags.AthConfigFlags._renamed_map (   self)
private
mapping from the old names to the new names

This is the inverse of _renamed, which maps new names to old
names

Returns a list of the new names corresponding to the old names
(since cloneAndReplace may or may not disable access to the old name,
it is possible that an old name renames to multiple new names)

Definition at line 331 of file AthConfigFlags.py.

331  def _renamed_map(self):
332  """mapping from the old names to the new names
333 
334  This is the inverse of _renamed, which maps new names to old
335  names
336 
337  Returns a list of the new names corresponding to the old names
338  (since cloneAndReplace may or may not disable access to the old name,
339  it is possible that an old name renames to multiple new names)
340  """
341  revmap = defaultdict(list)
342 
343  for new, old in self._renames.items():
344  if old is not None:
345  revmap[old].append(new)
346 
347  def rename(key):
348  for old, newlist in revmap.items():
349  if key.startswith(old + '.'):
350  stem = key.removeprefix(old)
351  return [ f'{new}{stem}' if new else '' for new in newlist ]
352  return [ key ]
353 
354  return {x:rename(x) for x in self._flagdict.keys()}
355 

◆ _set()

def python.AthConfigFlags.AthConfigFlags._set (   self,
  name,
  value 
)
private

Definition at line 473 of file AthConfigFlags.py.

473  def _set(self,name,value):
474  self._tryModify()
475  try:
476  self._flagdict[name].set(value)
477  except KeyError:
478  closestMatch = get_close_matches(name,self._flagdict.keys(),1)
479  raise KeyError(f"No flag with name '{name}' found" +
480  (f". Did you mean '{closestMatch[0]}'?" if closestMatch else ""))
481 

◆ _subflag_itr()

def python.AthConfigFlags.AthConfigFlags._subflag_itr (   self)
private
Subflag iterator for all flags

This is used by the asdict() function.

Definition at line 356 of file AthConfigFlags.py.

356  def _subflag_itr(self):
357  """Subflag iterator for all flags
358 
359  This is used by the asdict() function.
360  """
361  self.loadAllDynamicFlags()
362 
363  for old, newlist in self._renamed_map().items():
364  for new in newlist:
365  # Lots of modules are missing in analysis releases. I
366  # tried to prevent imports using the _addFlagsCategory
367  # function which checks if some module exists, but this
368  # turned in to quite a rabbit hole. Catching and ignoring
369  # the missing module exception seems to work, even if it's
370  # not pretty.
371  try:
372  yield new, getattr(self, old)
373  except ModuleNotFoundError as err:
374  _msg.debug(f'missing module: {err}')
375  pass
376 

◆ _tryModify()

def python.AthConfigFlags.AthConfigFlags._tryModify (   self)
private

Definition at line 504 of file AthConfigFlags.py.

504  def _tryModify(self):
505  if self._locked:
506  raise RuntimeError("Attempt to modify locked flag container")
507  else:
508  # if unlocked then invalidate hash
509  self._hash = None
510 

◆ addFlag()

def python.AthConfigFlags.AthConfigFlags.addFlag (   self,
  name,
  setDef,
  type = None,
  help = None 
)

Definition at line 377 of file AthConfigFlags.py.

377  def addFlag(self, name, setDef, type=None, help=None):
378  self._tryModify()
379  if name in self._flagdict:
380  raise KeyError("Duplicated flag name: {}".format( name ))
381  self._flagdict[name]=CfgFlag(setDef, type, help)
382  return
383 

◆ addFlagsCategory()

def python.AthConfigFlags.AthConfigFlags.addFlagsCategory (   self,
  path,
  generator,
  prefix = False 
)
The path is the beginning of the flag name (e.g. "X" for flags generated with name "X.*").
The generator is a function that returns a flags container, the flags have to start with the same path.
When the prefix is True the flags created by the generator are prefixed by "path".

Supported calls are then:
 addFlagsCategory("A", g) - where g is function creating flags  is f.addFlag("A.x", someValue)
 addFlagsCategory("A", g, True) - when flags are defined in g like this: f.addFalg("x", somevalue),
The latter option allows to share one generator among flags that are later loaded in different paths.

Definition at line 384 of file AthConfigFlags.py.

384  def addFlagsCategory(self, path, generator, prefix=False):
385  """
386  The path is the beginning of the flag name (e.g. "X" for flags generated with name "X.*").
387  The generator is a function that returns a flags container, the flags have to start with the same path.
388  When the prefix is True the flags created by the generator are prefixed by "path".
389 
390  Supported calls are then:
391  addFlagsCategory("A", g) - where g is function creating flags is f.addFlag("A.x", someValue)
392  addFlagsCategory("A", g, True) - when flags are defined in g like this: f.addFalg("x", somevalue),
393  The latter option allows to share one generator among flags that are later loaded in different paths.
394  """
395  self._tryModify()
396  _msg.debug("Adding flag category %s", path)
397  self._dynaflags[path] = (generator, prefix)
398 

◆ args()

def python.AthConfigFlags.AthConfigFlags.args (   self)

Definition at line 654 of file AthConfigFlags.py.

654  def args(self):
655  return self._args
656 
657 

◆ asdict()

def python.AthConfigFlags.AthConfigFlags.asdict (   self)
Convert to a python dictionary

This is identical to the `asdict` in FlagAddress, but for all
the flags.

Definition at line 321 of file AthConfigFlags.py.

321  def asdict(self):
322  """Convert to a python dictionary
323 
324  This is identical to the `asdict` in FlagAddress, but for all
325  the flags.
326 
327  """
328  return _asdict(self._subflag_itr())
329 
330 

◆ athHash()

def python.AthConfigFlags.AthConfigFlags.athHash (   self)

Definition at line 248 of file AthConfigFlags.py.

248  def athHash(self):
249  if self._locked is False:
250  raise RuntimeError("Cannot calculate hash of unlocked flag container")
251  elif self._hash is None:
252  self._hash = self._calculateHash()
253  return self._hash
254 

◆ clone()

def python.AthConfigFlags.AthConfigFlags.clone (   self)
Return an unlocked copy of self (dynamic flags are not loaded)

Definition at line 511 of file AthConfigFlags.py.

511  def clone(self):
512  """Return an unlocked copy of self (dynamic flags are not loaded)"""
513  cln = AthConfigFlags()
514  cln._flagdict = deepcopy(self._flagdict)
515  cln._dynaflags = copy(self._dynaflags)
516  cln._renames = deepcopy(self._renames)
517  return cln
518 
519 

◆ cloneAndReplace()

def python.AthConfigFlags.AthConfigFlags.cloneAndReplace (   self,
  subsetToReplace,
  replacementSubset,
  keepOriginal = False 
)
This is to replace subsets of configuration flags like

Example:
newflags = flags.cloneAndReplace('Muon', 'Trigger.Offline.Muon')

Definition at line 520 of file AthConfigFlags.py.

520  def cloneAndReplace(self,subsetToReplace,replacementSubset, keepOriginal=False):
521  """
522  This is to replace subsets of configuration flags like
523 
524  Example:
525  newflags = flags.cloneAndReplace('Muon', 'Trigger.Offline.Muon')
526  """
527 
528  _msg.debug("cloning flags and replacing %s by %s", subsetToReplace, replacementSubset)
529 
530  self._loadDynaFlags( subsetToReplace )
531  self._loadDynaFlags( replacementSubset )
532 
533  subsetToReplace = subsetToReplace.strip(".")
534  replacementSubset = replacementSubset.strip(".")
535 
536  #Sanity check: Don't replace a by a
537  if (subsetToReplace == replacementSubset):
538  raise RuntimeError(f'Can not replace flags {subsetToReplace} with themselves')
539 
540  # protect against subsequent remaps within remaps: clone = flags.cloneAndReplace('Y', 'X').cloneAndReplace('X.b', 'X.a')
541  for alias,src in self._renames.items():
542  if src is None: continue
543  if src+"." in subsetToReplace:
544  raise RuntimeError(f'Can not replace flags {subsetToReplace} by {replacementSubset} because of already present replacement of {alias} by {src}')
545 
546 
547  newFlags = copy(self) # shallow copy
548  newFlags._renames = deepcopy(self._renames) #maintains renames
549 
550  if replacementSubset in newFlags._renames: #and newFlags._renames[replacementSubset]:
551  newFlags._renames[subsetToReplace] = newFlags._renames[replacementSubset]
552  else:
553  newFlags._renames[subsetToReplace] = replacementSubset
554 
555  if not keepOriginal:
556  if replacementSubset not in newFlags._renames or newFlags._renames[replacementSubset] == replacementSubset:
557  newFlags._renames[replacementSubset] = None # block access to original flags
558  else:
559  del newFlags._renames[replacementSubset]
560  #If replacementSubset was a "pure renaming" of another set of flags,
561  #the original set of flags gets propagated down to its potential further renamings:
562  #no need to worry about maintaining the intermediate steps in the renaming.
563  else:
564  if replacementSubset not in newFlags._renames:
565  newFlags._renames[replacementSubset] = replacementSubset
566  #For _renamed_map to know that these flags still work.
567  newFlags._hash = None
568  return newFlags
569 
570 

◆ dump()

def python.AthConfigFlags.AthConfigFlags.dump (   self,
  pattern = ".*",
  evaluate = False,
  formatStr = "{:40} : {}",
  maxLength = None 
)

Definition at line 592 of file AthConfigFlags.py.

592  def dump(self, pattern=".*", evaluate=False, formatStr="{:40} : {}", maxLength=None): import re
593  compiled = re.compile(pattern)
594  def truncate(s): return s[:maxLength] + ("..." if maxLength and len(s)>maxLength else "")
595  reverse_renames = {value: key for key, value in self._renames.items() if value is not None} # new name to old
596  for name in sorted(self._flagdict):
597  renamed = name
598  if any([name.startswith(r) for r in reverse_renames.keys() if r is not None]):
599  for oldprefix, newprefix in reverse_renames.items():
600  if name.startswith(oldprefix):
601  renamed = name.replace(oldprefix, newprefix)
602  break
603  if compiled.match(renamed):
604  if evaluate:
605  try:
606  rep = repr(self._flagdict[name] )
607  val = repr(self._flagdict[name].get(self))
608  if val != rep:
609  print(formatStr.format(renamed,truncate("{} {}".format( val, rep )) ))
610  else:
611  print(formatStr.format(renamed, truncate("{}".format(val)) ) )
612  except Exception as e:
613  print(formatStr.format(renamed, truncate("Exception: {}".format( e )) ))
614  else:
615  print(formatStr.format( renamed, truncate("{}".format(repr(self._flagdict[name] ) )) ))
616 
617  if len(self._dynaflags) != 0 and any([compiled.match(x) for x in self._dynaflags.keys()]):
618  print("Flag categories that can be loaded dynamically")
619  print("{:25} : {:>30} : {}".format( "Category","Generator name", "Defined in" ) )
620  for name,gen_and_prefix in sorted(self._dynaflags.items()):
621  if compiled.match(name):
622  print("{:25} : {:>30} : {}".format( name, gen_and_prefix[0].__name__, '/'.join(gen_and_prefix[0].__code__.co_filename.split('/')[-2:]) ) )
623  if len(self._renames):
624  print("Flag categories that are redirected by the cloneAndReplace")
625  for alias,src in self._renames.items():
626  print("{:30} points to {:>30} ".format( alias, src if src else "nothing") )
627 
628 
629 

◆ fillFromArgs()

def python.AthConfigFlags.AthConfigFlags.fillFromArgs (   self,
  listOfArgs = None,
  parser = None,
  return_unknown = False 
)
Used to set flags from command-line parameters, like flags.fillFromArgs(sys.argv[1:])

if return_unknown=False, returns: args 
       otherwise returns: args, uknown_args
     where unknown_args is the list of arguments that did not correspond to one of the flags 

Definition at line 699 of file AthConfigFlags.py.

699  def fillFromArgs(self, listOfArgs=None, parser=None, return_unknown=False):
700  """
701  Used to set flags from command-line parameters, like flags.fillFromArgs(sys.argv[1:])
702 
703  if return_unknown=False, returns: args
704  otherwise returns: args, uknown_args
705  where unknown_args is the list of arguments that did not correspond to one of the flags
706  """
707  import sys
708 
709  self._tryModify()
710 
711  if parser is None:
712  parser = self.parser()
713  self._parser = parser # set our parser to given one
714  argList = listOfArgs if listOfArgs is not None else sys.argv[1:]
715  do_help = False
716  # We will now do a pre-parse of the command line arguments to propagate these to the flags
717  # the reason for this is so that we can use the help messaging to display the values of all
718  # flags as they would be *after* any parsing takes place. This is nice to see e.g. the value
719  # that any derived flag (functional flag) will take after, say, the filesInput are set
720  import argparse
721  unrequiredActions = []
722  if "-h" in argList or "--help" in argList:
723  do_help = True
724  if "-h" in argList: argList.remove("-h")
725  if "--help" in argList: argList.remove("--help")
726  # need to unrequire any required arguments in order to do a "pre parse"
727  for a in parser._actions:
728  if a.required:
729  unrequiredActions.append(a)
730  a.required = False
731  (args,leftover)=parser.parse_known_args(argList)
732  for a in unrequiredActions: a.required=True
733 
734  # remove the leftovers from the argList ... for later use in the do_help
735  argList = [a for a in argList if a not in leftover]
736 
737  # First, handle athena.py-like arguments (if available in parser):
738  def arg_set(dest):
739  """Check if dest is available in parser and has been set"""
740  return vars(args).get(dest, None) is not None
741 
742  if arg_set('debug'):
743  self.Exec.DebugStage=args.debug
744 
745  if arg_set('evtMax'):
746  self.Exec.MaxEvents=args.evtMax
747 
748  if arg_set('interactive'):
749  self.Exec.Interactive=args.interactive
750 
751  if arg_set('skipEvents'):
752  self.Exec.SkipEvents=args.skipEvents
753 
754  if arg_set('filesInput'):
755  self.Input.Files = [] # remove generic
756  for f in args.filesInput.split(","):
757  found = glob.glob(f)
758  # if not found, add string directly
759  self.Input.Files += found if found else [f]
760 
761  if "-l" in argList or "--loglevel" in argList: # different check b.c. has a default value so will always be in args
762  from AthenaCommon import Constants
763  self.Exec.OutputLevel = getattr(Constants, args.loglevel)
764 
765  if arg_set('config_only') and args.config_only is not False:
766  from os import environ
767  environ["PICKLECAFILE"] = "" if args.config_only is True else args.config_only
768 
769  if arg_set('threads'):
770  self.Concurrency.NumThreads = args.threads
771  #Work-around a possible inconsistency of NumThreads and NumConcurrentEvents that may
772  #occur when these values are set by the transforms and overwritten by --athenaopts ..
773  #See also ATEAM-907
774  if args.concurrent_events is None and self.Concurrency.NumConcurrentEvents==0:
775  self.Concurrency.NumConcurrentEvents = args.threads
776 
777  if arg_set('concurrent_events'):
778  self.Concurrency.NumConcurrentEvents = args.concurrent_events
779 
780  if arg_set('nprocs'):
781  self.Concurrency.NumProcs = args.nprocs
782 
783  if arg_set('perfmon'):
784  from PerfMonComps.PerfMonConfigHelpers import setPerfmonFlagsFromRunArgs
785  setPerfmonFlagsFromRunArgs(self, args)
786 
787  if arg_set('mtes'):
788  self.Exec.MTEventService = args.mtes
789 
790  if arg_set('mtes_channel'):
791  self.Exec.MTEventServiceChannel = args.mtes_channel
792 
793  if arg_set('profile_python'):
794  from AthenaCommon.Debugging import dumpPythonProfile
795  import atexit, cProfile, functools
796  cProfile._athena_python_profiler = cProfile.Profile()
797  cProfile._athena_python_profiler.enable()
798 
799  # Save stats to file at exit
800  atexit.register(functools.partial(dumpPythonProfile, args.profile_python))
801 
802  if arg_set('mpi'):
803  self.Exec.MPI = args.mpi
804 
805  # All remaining arguments are assumed to be key=value pairs to set arbitrary flags:
806  unknown_args = []
807  for arg in leftover:
808  if arg=='--':
809  argList += ["---"]
810  continue # allows for multi-value arguments to be terminated by a " -- "
811  if do_help and '=' not in arg:
812  argList += arg.split(".") # put arg back back for help (but split by sub-categories)
813  continue
814  try:
815  self.fillFromString(arg)
816  except KeyError as e:
817  if return_unknown:
818  unknown_args += [arg]
819  else:
820  raise e
821 
822  if do_help:
823  if parser.epilog is None: parser.epilog=""
824  parser.epilog += " Note: Specify additional flags in form <flagName>=<value>."
825  subparsers = {"":[parser,parser.add_subparsers(help=argparse.SUPPRESS)]} # first is category's parser, second is subparsers (effectively the category's subcategories)
826  # silence logging while evaluating flags
827  logging.root.setLevel(logging.ERROR)
828  def getParser(category): # get parser for a given category
829  if category not in subparsers.keys():
830  cat1,cat2 = category.rsplit(".",1) if "." in category else ("",category)
831  p,subp = getParser(cat1)
832  if subp.help==argparse.SUPPRESS:
833  subp.help = "Flag subcategories:"
834  newp = subp.add_parser(cat2,help="{} flags".format(category),
835  formatter_class = argparse.ArgumentDefaultsHelpFormatter,usage=argparse.SUPPRESS)
836  newp._positionals.title = "flags"
837  subparsers[category] = [newp,newp.add_subparsers(help=argparse.SUPPRESS)]
838  return subparsers[category]
839  self.loadAllDynamicFlags()
840  for name in sorted(self._flagdict):
841  category,flagName = name.rsplit(".",1) if "." in name else ("",name)
842  flag = self._flagdict[name]
843  try:
844  val = repr(flag.get(self))
845  except Exception:
846  val = None
847  if flag._help != argparse.SUPPRESS:
848  helptext = ""
849  if flag._help is not None:
850  helptext = f": {flag._help}"
851  if flag._type is not None:
852  helptext += f' [type: {flag._type.__name__}]'
853  if val is not None and helptext == "":
854  helptext = ": " # ensures default values are displayed even if there's no help text
855  getParser(category)[0].add_argument(name, nargs='?', default=val, help=helptext)
856 
857  parser._positionals.title = 'flags and positional arguments'
858  parser.parse_known_args(argList + ["--help"])
859 
860  self._args = args
861 
862  if return_unknown:
863  return args,unknown_args
864  else:
865  return args
866 
867 
868 

◆ fillFromString()

def python.AthConfigFlags.AthConfigFlags.fillFromString (   self,
  flag_string 
)
Fill the flags from a string of type key=value

Definition at line 658 of file AthConfigFlags.py.

658  def fillFromString(self, flag_string):
659  """Fill the flags from a string of type key=value"""
660  import ast
661 
662  try:
663  key, value = flag_string.split("=")
664  except ValueError:
665  raise ValueError(f"Cannot interpret argument {flag_string}, expected a key=value format")
666 
667  key = key.strip()
668  value = value.strip()
669 
670  # also allow key+=value to append
671  oper = "="
672  if (key[-1]=="+"):
673  oper = "+="
674  key = key[:-1]
675 
676  if key not in self._flagdict:
677  self._loadDynaFlags( '.'.join(key.split('.')[:-1]) ) # for a flag A.B.C dynamic flags from category A.B
678  if key not in self._flagdict:
679  raise KeyError(f"{key} is not a known configuration flag")
680 
681  flag_type = self._flagdict[key]._type
682  if flag_type is None:
683  # Regular flag
684  try:
685  ast.literal_eval(value)
686  except Exception: # Can't determine type, assume we got an un-quoted string
687  value=f"\"{value}\""
688 
689  elif isinstance(flag_type, EnumMeta):
690  # Flag is an enum, so we need to import the module containing the enum
691  ENUM = importlib.import_module(flag_type.__module__) # noqa: F841 (used in exec)
692  value=f"ENUM.{value}"
693 
694  # Set the value (this also does the type checking if needed)
695  exec(f"self.{key}{oper}{value}")
696 
697 

◆ getArgumentParser()

def python.AthConfigFlags.AthConfigFlags.getArgumentParser (   self,
**  kwargs 
)
Scripts calling AthConfigFlags.fillFromArgs can extend this parser, and pass their version to fillFromArgs

Definition at line 639 of file AthConfigFlags.py.

639  def getArgumentParser(self, **kwargs):
640  """
641  Scripts calling AthConfigFlags.fillFromArgs can extend this parser, and pass their version to fillFromArgs
642  """
643  import argparse
644  from AthenaCommon.AthOptionsParser import getArgumentParser
645  parser = getArgumentParser(**kwargs)
646  parser.add_argument("---",dest="terminator",action='store_true', help=argparse.SUPPRESS) # special hidden option required to convert option terminator -- for --help calls
647 
648  return parser
649 

◆ hasCategory()

def python.AthConfigFlags.AthConfigFlags.hasCategory (   self,
  name 
)
Check if category exists (loads dynamic flags if needed)

Definition at line 436 of file AthConfigFlags.py.

436  def hasCategory(self, name):
437  """Check if category exists (loads dynamic flags if needed)"""
438  # We cache successfully found categories
439  if name in self._categoryCache:
440  return True
441 
442  if (re_name := self._renames.get(name)) is not None and re_name != name:
443  return self.hasCategory(re_name)
444 
445  # Load dynamic flags if needed
446  self._loadDynaFlags(name)
447 
448  # If not found do search through all keys.
449  # TODO: could be improved by using a trie for _flagdict
450  for f in self._flagdict.keys():
451  if f.startswith(name+'.'):
452  self._categoryCache.add(name)
453  return True
454  for c in self._dynaflags.keys():
455  if c.startswith(name):
456  self._categoryCache.add(name)
457  return True
458 
459  return False
460 

◆ hasFlag()

def python.AthConfigFlags.AthConfigFlags.hasFlag (   self,
  name 
)
Check if flag exists (loads dynamic flags if needed)

Definition at line 461 of file AthConfigFlags.py.

461  def hasFlag(self, name):
462  """Check if flag exists (loads dynamic flags if needed)"""
463  # Use attrgetter to check if attribute exists. As opposed to getattr,
464  # this also supports nested attributes, which is required to trigger loading
465  # of dynamics flags.
466  try:
467  attrgetter(name)(self)
468  # Now check if flag was found (taking into account renames)
469  return any(name in x for x in self._renamed_map().values())
470  except AttributeError:
471  return False
472 

◆ initAll()

def python.AthConfigFlags.AthConfigFlags.initAll (   self)
Mostly a self-test method

Definition at line 630 of file AthConfigFlags.py.

630  def initAll(self):
631  """
632  Mostly a self-test method
633  """
634  for n,f in list(self._flagdict.items()):
635  f.get(self)
636  return
637 
638 

◆ join()

def python.AthConfigFlags.AthConfigFlags.join (   self,
  other,
  prefix = '' 
)
Merges two flag containers
When the prefix is passed each flag from the "other" is prefixed by "prefix."

Definition at line 571 of file AthConfigFlags.py.

571  def join(self, other, prefix=''):
572  """
573  Merges two flag containers
574  When the prefix is passed each flag from the "other" is prefixed by "prefix."
575  """
576  self._tryModify()
577 
578  for (name,flag) in other._flagdict.items():
579  fullName = prefix+"."+name if prefix != "" else name
580  if fullName in self._flagdict:
581  raise KeyError("Duplicated flag name: {}".format( fullName ) )
582  self._flagdict[fullName]=flag
583 
584  for (name,loader) in other._dynaflags.items():
585  fullName = prefix+"."+name if prefix != "" else name
586  if fullName in self._dynaflags:
587  raise KeyError("Duplicated dynamic flags name: {}".format( fullName ) )
588  _msg.debug("Joining dynamic flags with %s", fullName)
589  self._dynaflags[fullName] = loader
590  return
591 

◆ loadAllDynamicFlags()

def python.AthConfigFlags.AthConfigFlags.loadAllDynamicFlags (   self)
Force load all the dynamic flags 

Definition at line 429 of file AthConfigFlags.py.

429  def loadAllDynamicFlags(self):
430  """Force load all the dynamic flags """
431  while len(self._dynaflags) != 0:
432  # Need to convert to a list since _loadDynaFlags may change the dict.
433  for prefix in list(self._dynaflags.keys()):
434  self._loadDynaFlags( prefix )
435 

◆ lock()

def python.AthConfigFlags.AthConfigFlags.lock (   self)

Definition at line 494 of file AthConfigFlags.py.

494  def lock(self):
495  if not self._locked:
496  # before locking, parse args if a parser was defined
497  if self._args is None and self._parser is not None: self.fillFromArgs()
498  self._locked = True
499  return
500 

◆ locked()

def python.AthConfigFlags.AthConfigFlags.locked (   self)

Definition at line 501 of file AthConfigFlags.py.

501  def locked(self):
502  return self._locked
503 

◆ needFlagsCategory()

def python.AthConfigFlags.AthConfigFlags.needFlagsCategory (   self,
  name 
)
public interface for _loadDynaFlags 

Definition at line 399 of file AthConfigFlags.py.

399  def needFlagsCategory(self, name):
400  """ public interface for _loadDynaFlags """
401  self._loadDynaFlags( name )
402 

◆ parser()

def python.AthConfigFlags.AthConfigFlags.parser (   self)

Definition at line 650 of file AthConfigFlags.py.

650  def parser(self):
651  if self._parser is None: self._parser = self.getArgumentParser()
652  return self._parser
653 

Member Data Documentation

◆ _args

python.AthConfigFlags.AthConfigFlags._args
private

Definition at line 245 of file AthConfigFlags.py.

◆ _categoryCache

python.AthConfigFlags.AthConfigFlags._categoryCache
private

Definition at line 242 of file AthConfigFlags.py.

◆ _dynaflags

python.AthConfigFlags.AthConfigFlags._dynaflags
private

Definition at line 240 of file AthConfigFlags.py.

◆ _flagdict

python.AthConfigFlags.AthConfigFlags._flagdict
private

Definition at line 238 of file AthConfigFlags.py.

◆ _hash

python.AthConfigFlags.AthConfigFlags._hash
private

Definition at line 243 of file AthConfigFlags.py.

◆ _hashedFlags

list python.AthConfigFlags.AthConfigFlags._hashedFlags = []
staticprivate

Definition at line 235 of file AthConfigFlags.py.

◆ _loaded

python.AthConfigFlags.AthConfigFlags._loaded
private

Definition at line 241 of file AthConfigFlags.py.

◆ _locked

python.AthConfigFlags.AthConfigFlags._locked
private

Definition at line 239 of file AthConfigFlags.py.

◆ _parser

python.AthConfigFlags.AthConfigFlags._parser
private

Definition at line 244 of file AthConfigFlags.py.

◆ _renames

python.AthConfigFlags.AthConfigFlags._renames
private

Definition at line 246 of file AthConfigFlags.py.

◆ print_context

python.AthConfigFlags.AthConfigFlags.print_context
static

Definition at line 490 of file AthConfigFlags.py.


The documentation for this class was generated from the following file:
DerivationFramework::TriggerMatchingUtils::sorted
std::vector< typename R::value_type > sorted(const R &r, PROJ proj={})
Helper function to create a sorted vector from an unsorted range.
python.AthOptionsParser.getArgumentParser
def getArgumentParser(legacy_args=False, **kwargs)
Definition: AthOptionsParser.py:140
vtune_athena.format
format
Definition: vtune_athena.py:14
python.CaloAddPedShiftConfig.args
args
Definition: CaloAddPedShiftConfig.py:47
python.Bindings.__iter__
__iter__
Definition: Control/AthenaPython/python/Bindings.py:794
python.processes.powheg.ZZj_MiNNLO.ZZj_MiNNLO.__init__
def __init__(self, base_directory, **kwargs)
Constructor: all process options are set here.
Definition: ZZj_MiNNLO.py:18
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.Utilities.clone
clone
Definition: Utilities.py:134
python.Bindings.values
values
Definition: Control/AthenaPython/python/Bindings.py:808
run_Egamma1_LArStrip_Fex.dump
dump
Definition: run_Egamma1_LArStrip_Fex.py:87
python.CaloAddPedShiftConfig.parser
parser
Definition: CaloAddPedShiftConfig.py:41
python.AthConfigFlags._asdict
def _asdict(iterator)
Definition: AthConfigFlags.py:107
LArG4FSStartPointFilter.exec
exec
Definition: LArG4FSStartPointFilter.py:103
python.PerfMonConfigHelpers.setPerfmonFlagsFromRunArgs
def setPerfmonFlagsFromRunArgs(flags, runArgs)
Definition: PerfMonConfigHelpers.py:3
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:194
PyAthena::repr
std::string repr(PyObject *o)
returns the string representation of a python object equivalent of calling repr(o) in python
Definition: PyAthenaUtils.cxx:106
add
bool add(const std::string &hname, TKey *tobj)
Definition: fastadd.cxx:55
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:26
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
python.plotting.G4DebuggerUtils.rename
def rename(label)
Definition: G4DebuggerUtils.py:11
mc.generator
generator
Configure Herwig7 These are the commands corresponding to what would go into the regular Herwig infil...
Definition: mc.MGH7_FxFx_H71-DEFAULT_test.py:18
VKalVrtAthena::varHolder_detail::clear
void clear(T &var)
Definition: NtupleVars.h:48
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
python.Bindings.__setitem__
__setitem__
Definition: Control/AthenaPython/python/Bindings.py:774
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:801
python.PyAthenaComps.__setattr__
__setattr__
Definition: PyAthenaComps.py:39
calibdata.copy
bool copy
Definition: calibdata.py:26
python.Bindings.__getitem__
__getitem__
Definition: Control/AthenaPython/python/Bindings.py:782
python.Bindings.__contains__
__contains__
Definition: Control/AthenaPython/python/Bindings.py:768
LArG4ShowerLibProcessing.truncate
truncate
Definition: LArG4ShowerLibProcessing.py:38