ATLAS Offline Software
Classes | Functions | Variables
python.ConfigText Namespace Reference

Classes

class  TextConfig
 
class  TextConfigWarning
 

Functions

def readYaml (yamlPath)
 
def printYaml (d, sort=False, jsonFormat=False)
 
def makeSequence (configPath, *flags=None, algSeq=None, noSystematics=None, dataType=None, geometry=None, autoconfigFromFlags=None, isPhyslite=None, noPhysliteBroken=False)
 
def combineConfigFiles (local, config_path, fragment_key="include")
 
def _load_fragment (pathlib.Path fragment_path)
 
def _find_fragment (fragment_path, config_path)
 
def _merge_dicts (local, fragment)
 

Variables

 logCPAlgTextCfg = logging.getLogger('CPAlgTextCfg')
 

Function Documentation

◆ _find_fragment()

def python.ConfigText._find_fragment (   fragment_path,
  config_path 
)
private

Definition at line 459 of file ConfigText.py.

459 def _find_fragment(fragment_path, config_path):
460  paths_to_check = [
461  fragment_path,
462  config_path / fragment_path,
463  *[x / fragment_path for x in os.environ["DATAPATH"].split(":")]
464  ]
465  for path in paths_to_check:
466  if path.exists():
467  return path
468 
469  raise FileNotFoundError(fragment_path)
470 
471 

◆ _load_fragment()

def python.ConfigText._load_fragment ( pathlib.Path  fragment_path)
private
Load a YAML or JSON fragment

This function is superfluous as of the yaml 1.2 spec (which
has not been implemented in ATLAS Yaml dependencies).
Once https://github.com/yaml/pyyaml/issues/173 is resolved
pyyaml will support yaml 1.2, which is compatable with json. 
Until then yaml and json behave differently in some scientific
notation edge cases.

Definition at line 442 of file ConfigText.py.

442 def _load_fragment(fragment_path: pathlib.Path):
443  """Load a YAML or JSON fragment
444 
445  This function is superfluous as of the yaml 1.2 spec (which
446  has not been implemented in ATLAS Yaml dependencies).
447  Once https://github.com/yaml/pyyaml/issues/173 is resolved
448  pyyaml will support yaml 1.2, which is compatable with json.
449  Until then yaml and json behave differently in some scientific
450  notation edge cases.
451  """
452 
453  with open(fragment_path, 'r') as fragment_file:
454  if fragment_path.suffix.lower() == '.json':
455  return json.load(fragment_file)
456  else:
457  return yaml.safe_load(fragment_file)
458 

◆ _merge_dicts()

def python.ConfigText._merge_dicts (   local,
  fragment 
)
private

Definition at line 472 of file ConfigText.py.

472 def _merge_dicts(local, fragment):
473  # In the list case append the fragment to the local list
474  if isinstance(local, list):
475  local += fragment
476  return
477  # In the dict case, append only missing values to local: the local
478  # values take precedence over the fragment ones.
479  if isinstance(local, dict):
480  for key, value in fragment.items():
481  if key in local:
482  _merge_dicts(local[key], value)
483  else:
484  local[key] = value
485  return

◆ combineConfigFiles()

def python.ConfigText.combineConfigFiles (   local,
  config_path,
  fragment_key = "include" 
)
Recursively combine configuration fragments into `local`.

- Looks for `fragment_key` at any dict node.
- If value is a string/path: merge that fragment.
- If value is a list: merge all fragments in order.
  For conflicts between fragments, the **earlier** file in the list wins. 
  Local keys still override the merged fragments.

Returns True if any merging happened below this node.

Definition at line 373 of file ConfigText.py.

373 def combineConfigFiles(local, config_path, fragment_key="include"):
374  """
375  Recursively combine configuration fragments into `local`.
376 
377  - Looks for `fragment_key` at any dict node.
378  - If value is a string/path: merge that fragment.
379  - If value is a list: merge all fragments in order.
380  For conflicts between fragments, the **earlier** file in the list wins.
381  Local keys still override the merged fragments.
382 
383  Returns True if any merging happened below this node.
384  """
385  combined = False
386 
387  # If this isn't an iterable there's nothing to combine
388  if isinstance(local, dict):
389  to_combine = local.values()
390  elif isinstance(local, list):
391  to_combine = local
392  else:
393  return combined
394 
395  # Recurse first so that nested nodes are resolved
396  for sub in to_combine:
397  combined = combineConfigFiles(sub, config_path, fragment_key=fragment_key) or combined
398 
399  # if there are no fragments to include we're done
400  if fragment_key not in local:
401  return combined
402 
403  # Only dict nodes can have include keys
404  if not isinstance(local, dict):
405  return combined
406 
407  # Normalize to a list of paths
408  value = local[fragment_key]
409  if isinstance(value, (str, pathlib.Path)):
410  warnings.warn(
411  f"{fragment_key} should be followed with a list of files",
412  TextConfigWarning,
413  stacklevel=2,
414  )
415  paths = [value]
416  elif isinstance(value, list):
417  paths = value
418  else:
419  raise TypeError(f"'{fragment_key}' must be a string path or a list of paths, got {type(value).__name__}")
420 
421  # Build an accumulator of all fragments, earlier paths win on conflicts
422  fragments_acc = {}
423  for entry in paths:
424  fragment_path = _find_fragment(pathlib.Path(entry), config_path)
425  fragment = _load_fragment(fragment_path)
426 
427  # Allow recursion inside each fragment, using the fragment's directory as base
428  combineConfigFiles(fragment, fragment_path.parent, fragment_key=fragment_key)
429 
430  # Merge this fragment into the accumulator; earlier entries win
431  _merge_dicts(fragments_acc, fragment)
432 
433  # Remove the key before merging to avoid re-processing it
434  del local[fragment_key]
435 
436  # Merge fragments into local; local values take precedence
437  _merge_dicts(local, fragments_acc)
438 
439  return True
440 
441 

◆ makeSequence()

def python.ConfigText.makeSequence (   configPath,
flags = None,
  algSeq = None,
  noSystematics = None,
  dataType = None,
  geometry = None,
  autoconfigFromFlags = None,
  isPhyslite = None,
  noPhysliteBroken = False 
)
 

Definition at line 321 of file ConfigText.py.

321 def makeSequence(configPath, *, flags=None, algSeq=None, noSystematics=None, dataType=None, geometry=None, autoconfigFromFlags=None, isPhyslite=None, noPhysliteBroken=False):
322  """
323  """
324 
325  # Historically we have used the identifier
326  # `autoconfigFromFlags`, but in the rest of the code base
327  # `flags` is used. So for now we allow either, and can hopefully
328  # at some point remove the former (21 Aug 25).
329  if autoconfigFromFlags is not None:
330  if flags is not None:
331  raise ValueError("Cannot pass both flags and autoconfigFromFlags arguments")
332  flags = autoconfigFromFlags
333  warnings.warn ('Using autoconfigFromFlags parameter is deprecated, use flags instead', category=deprecationWarningCategory, stacklevel=2)
334  elif flags is None:
335  warnings.warn ('it is deprecated to configure meta-data for analysis configuration manually, please read the configuration flags via the meta-data reader', category=deprecationWarningCategory, stacklevel=2)
336 
337  from AnalysisAlgorithmsConfig.ConfigAccumulator import ConfigAccumulator
338 
339  config = TextConfig(configPath)
340 
341  logCPAlgTextCfg.info("Configuration file read in:")
342  config.printConfig()
343 
344  logCPAlgTextCfg.info("Default algorithms:")
345  config.printAlgs(printOpts=True)
346 
347  logCPAlgTextCfg.info("Configuring algorithms based on YAML file:")
348  configSeq = config.configure()
349 
350  # defaults are added to config as algs are configured
351  logCPAlgTextCfg.info("Configuration used:")
352  config.printConfig()
353 
354  # compile
355  configAccumulator = ConfigAccumulator(algSeq=algSeq, dataType=dataType, isPhyslite=isPhyslite, geometry=geometry, autoconfigFromFlags=autoconfigFromFlags, flags=flags, noSystematics=noSystematics)
356  configSeq.fullConfigure(configAccumulator)
357 
358  # blocks can be reordered during configSeq.fullConfigure
359  logCPAlgTextCfg.info("ConfigBlocks and their configuration:")
360  configSeq.printOptions()
361 
362  from AnaAlgorithm.DualUseConfig import isAthena, useComponentAccumulator
363  if isAthena and useComponentAccumulator:
364  return configAccumulator.CA
365  else:
366  return None
367 
368 
369 # Combine configuration files
370 #
371 # See the README for more info on how this works
372 #

◆ printYaml()

def python.ConfigText.printYaml (   d,
  sort = False,
  jsonFormat = False 
)
Prints a dictionary as YAML

Definition at line 30 of file ConfigText.py.

30 def printYaml(d, sort=False, jsonFormat=False):
31  """Prints a dictionary as YAML"""
32  print(yaml.dump(d, default_flow_style=jsonFormat, sort_keys=sort))
33 

◆ readYaml()

def python.ConfigText.readYaml (   yamlPath)
Loads YAML file into a dictionary

Definition at line 21 of file ConfigText.py.

21 def readYaml(yamlPath):
22  """Loads YAML file into a dictionary"""
23  if not os.path.isfile(yamlPath):
24  raise ValueError(f"{yamlPath} is not a file.")
25  with open(yamlPath, 'r') as f:
26  textConfig = yaml.safe_load(f)
27  return textConfig
28 
29 

Variable Documentation

◆ logCPAlgTextCfg

python.ConfigText.logCPAlgTextCfg = logging.getLogger('CPAlgTextCfg')

Definition at line 18 of file ConfigText.py.

python.ConfigText.combineConfigFiles
def combineConfigFiles(local, config_path, fragment_key="include")
Definition: ConfigText.py:373
python.ConfigText.readYaml
def readYaml(yamlPath)
Definition: ConfigText.py:21
python.ConfigText._find_fragment
def _find_fragment(fragment_path, config_path)
Definition: ConfigText.py:459
python.ConfigText.printYaml
def printYaml(d, sort=False, jsonFormat=False)
Definition: ConfigText.py:30
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:26
Trk::open
@ open
Definition: BinningType.h:40
python.ConfigText.makeSequence
def makeSequence(configPath, *flags=None, algSeq=None, noSystematics=None, dataType=None, geometry=None, autoconfigFromFlags=None, isPhyslite=None, noPhysliteBroken=False)
Definition: ConfigText.py:321
python.ConfigText._load_fragment
def _load_fragment(pathlib.Path fragment_path)
Definition: ConfigText.py:442
python.ConfigText._merge_dicts
def _merge_dicts(local, fragment)
Definition: ConfigText.py:472
Trk::split
@ split
Definition: LayerMaterialProperties.h:38