ATLAS Offline Software
Loading...
Searching...
No Matches
python.AthConfigFlags.AthConfigFlags Class Reference
Inheritance diagram for python.AthConfigFlags.AthConfigFlags:
Collaboration diagram for python.AthConfigFlags.AthConfigFlags:

Public Types

typedef HLT::TypeInformation::for_each_type_c< typenameEDMLIST::map, my_functor, my_result<>, my_arg< HLT::TypeInformation::get_cont, CONTAINER > >::type result

Public Member Functions

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

Protected Member Functions

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

Protected Attributes

 _flagdict = dict()
bool _locked = False
 _dynaflags = dict()
 _loaded = set()
 _categoryCache = set()
 _hash = None
 _parser = None
 _args = None
dict _renames = {}

Static Protected Attributes

list _hashedFlags = []

Detailed Description

Definition at line 231 of file AthConfigFlags.py.

Member Typedef Documentation

◆ result

Definition at line 90 of file EDM_MasterSearch.h.

Constructor & Destructor Documentation

◆ __init__()

python.AthConfigFlags.AthConfigFlags.__init__ ( self)

Definition at line 238 of file AthConfigFlags.py.

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

Member Function Documentation

◆ __call__()

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

Definition at line 492 of file AthConfigFlags.py.

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

◆ __contains__()

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

Definition at line 308 of file AthConfigFlags.py.

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

◆ __delattr__()

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

Definition at line 291 of file AthConfigFlags.py.

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

◆ __delitem__()

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

Definition at line 300 of file AthConfigFlags.py.

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

◆ __getattr__()

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

Definition at line 269 of file AthConfigFlags.py.

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

◆ __getitem__()

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

Definition at line 294 of file AthConfigFlags.py.

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

◆ __hash__()

python.AthConfigFlags.AthConfigFlags.__hash__ ( self)

Definition at line 256 of file AthConfigFlags.py.

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

◆ __iter__()

python.AthConfigFlags.AthConfigFlags.__iter__ ( self)

Definition at line 311 of file AthConfigFlags.py.

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

◆ __setattr__()

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

Definition at line 283 of file AthConfigFlags.py.

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

◆ __setitem__()

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

Definition at line 297 of file AthConfigFlags.py.

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

◆ _calculateHash()

python.AthConfigFlags.AthConfigFlags._calculateHash ( self)
protected

Definition at line 259 of file AthConfigFlags.py.

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

◆ _get()

python.AthConfigFlags.AthConfigFlags._get ( self,
name )
protected

Definition at line 483 of file AthConfigFlags.py.

483 def _get(self,name):
484 try:
485 return self._flagdict[name].get(self)
486 except KeyError:
487 closestMatch = get_close_matches(name,self._flagdict.keys(),1)
488 raise KeyError(f"No flag with name '{name}' found" +
489 (f". Did you mean '{closestMatch[0]}'?" if closestMatch else ""))
490
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition hcg.cxx:130

◆ _loadDynaFlags()

python.AthConfigFlags.AthConfigFlags._loadDynaFlags ( self,
name )
protected
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 404 of file AthConfigFlags.py.

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

◆ _renamed_map()

python.AthConfigFlags.AthConfigFlags._renamed_map ( self)
protected
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 332 of file AthConfigFlags.py.

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

◆ _set()

python.AthConfigFlags.AthConfigFlags._set ( self,
name,
value )
protected

Definition at line 474 of file AthConfigFlags.py.

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

◆ _subflag_itr()

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

This is used by the asdict() function.

Definition at line 357 of file AthConfigFlags.py.

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

◆ _tryModify()

python.AthConfigFlags.AthConfigFlags._tryModify ( self)
protected

Definition at line 505 of file AthConfigFlags.py.

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

◆ addFlag()

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

Definition at line 378 of file AthConfigFlags.py.

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

◆ addFlagsCategory()

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 385 of file AthConfigFlags.py.

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

◆ args()

python.AthConfigFlags.AthConfigFlags.args ( self)

Definition at line 655 of file AthConfigFlags.py.

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

◆ asdict()

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 322 of file AthConfigFlags.py.

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

◆ athHash()

python.AthConfigFlags.AthConfigFlags.athHash ( self)

Definition at line 249 of file AthConfigFlags.py.

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

◆ clone()

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

Definition at line 512 of file AthConfigFlags.py.

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

◆ cloneAndReplace()

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 521 of file AthConfigFlags.py.

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

◆ dump()

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

Definition at line 593 of file AthConfigFlags.py.

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

◆ fillFromArgs()

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 700 of file AthConfigFlags.py.

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

◆ fillFromString()

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

Definition at line 659 of file AthConfigFlags.py.

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

◆ getArgumentParser()

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

Definition at line 640 of file AthConfigFlags.py.

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

◆ hasCategory()

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

Definition at line 437 of file AthConfigFlags.py.

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

◆ hasFlag()

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

Definition at line 462 of file AthConfigFlags.py.

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

◆ initAll()

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

Definition at line 631 of file AthConfigFlags.py.

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

◆ join()

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 572 of file AthConfigFlags.py.

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

◆ loadAllDynamicFlags()

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

Definition at line 430 of file AthConfigFlags.py.

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

◆ lock()

python.AthConfigFlags.AthConfigFlags.lock ( self)

Definition at line 495 of file AthConfigFlags.py.

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

◆ locked()

python.AthConfigFlags.AthConfigFlags.locked ( self)

Definition at line 502 of file AthConfigFlags.py.

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

◆ needFlagsCategory()

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

Definition at line 400 of file AthConfigFlags.py.

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

◆ parser()

python.AthConfigFlags.AthConfigFlags.parser ( self)

Definition at line 651 of file AthConfigFlags.py.

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

Member Data Documentation

◆ _args

python.AthConfigFlags.AthConfigFlags._args = None
protected

Definition at line 246 of file AthConfigFlags.py.

◆ _categoryCache

python.AthConfigFlags.AthConfigFlags._categoryCache = set()
protected

Definition at line 243 of file AthConfigFlags.py.

◆ _dynaflags

python.AthConfigFlags.AthConfigFlags._dynaflags = dict()
protected

Definition at line 241 of file AthConfigFlags.py.

◆ _flagdict

python.AthConfigFlags.AthConfigFlags._flagdict = dict()
protected

Definition at line 239 of file AthConfigFlags.py.

◆ _hash

python.AthConfigFlags.AthConfigFlags._hash = None
protected

Definition at line 244 of file AthConfigFlags.py.

◆ _hashedFlags

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

Definition at line 236 of file AthConfigFlags.py.

◆ _loaded

python.AthConfigFlags.AthConfigFlags._loaded = set()
protected

Definition at line 242 of file AthConfigFlags.py.

◆ _locked

bool python.AthConfigFlags.AthConfigFlags._locked = False
protected

Definition at line 240 of file AthConfigFlags.py.

◆ _parser

python.AthConfigFlags.AthConfigFlags._parser = None
protected

Definition at line 245 of file AthConfigFlags.py.

◆ _renames

python.AthConfigFlags.AthConfigFlags._renames = {}
protected

Definition at line 247 of file AthConfigFlags.py.


The documentation for this class was generated from the following file: