ATLAS Offline Software
Classes | Functions | Variables
python.iconfTool.models.loaders Namespace Reference

Classes

class  ComponentsDiffFileLoader
 
class  ComponentsFileLoader
 

Functions

def __flatten_list (l)
 
def types_in_properties (comp_name, value, dict_to_update)
 
def collect_types (conf)
 
Dict excludeIncludeComps (dic, args, depth, compsToFollow=[])
 
Dict ignoreIrrelevant (dic, args)
 
Dict renameComps (dic, args)
 
Dict ignoreDefaults (allconf, args, known)
 
Dict shortenDefaultComponents (dic, args)
 
list isReference (value, compname, conf, svcCache={})
 
Dict skipProperties (conf, args)
 
Dict loadConfigFile (fname, args)
 
Dict loadDifferencesFile (fname)
 

Variables

 logger
 
 level
 
 mode
 
 componentRenamingDict
 
 baseParser
 
string nargs = "*",
 
list default = [],
 
string help = "Include only components matching (regex) this string",
 
string action = "append",
 
 type = int,
 

Function Documentation

◆ __flatten_list()

def python.iconfTool.models.loaders.__flatten_list (   l)
private

Definition at line 128 of file loaders.py.

128 def __flatten_list(l):
129  return [item for elem in l for item in elem] if l else []
130 
131 

◆ collect_types()

def python.iconfTool.models.loaders.collect_types (   conf)

Definition at line 161 of file loaders.py.

161 def collect_types(conf):
162  name_to_type = {}
163  for (comp_name, comp_settings) in conf.items():
164  types_in_properties(comp_name, comp_settings, name_to_type)
165  return name_to_type
166 
167 

◆ excludeIncludeComps()

Dict python.iconfTool.models.loaders.excludeIncludeComps (   dic,
  args,
  depth,
  compsToFollow = [] 
)

Definition at line 168 of file loaders.py.

168 def excludeIncludeComps(dic, args, depth, compsToFollow=[]) -> Dict:
169  conf = {}
170  if depth == 0:
171  return conf
172  compsToInclude = __flatten_list(args.includeComps)
173  compsToExclude = __flatten_list(args.excludeComps)
174 
175  def eligible(component):
176  exclude = any(re.match(s, component) for s in compsToExclude)
177  if (component in compsToFollow or component.removeprefix("ToolSvc.") in compsToFollow) and not (exclude or component in args.ignore):
178  logger.debug("Considering this component: %s because some other one depends on it", component)
179  return True
180  include = any(re.match(s, component) for s in compsToInclude)
181  if args.includeComps and args.excludeComps:
182  return include and not exclude
183  elif args.includeComps:
184  return include
185  elif args.excludeComps:
186  return not exclude
187 
188  for (comp_name, comp_attributes) in dic.items():
189  if eligible(comp_name):
190  conf[comp_name] = comp_attributes
191  if depth > 0:
192  types = {}
193  types_in_properties(comp_attributes, types, compsToFollow)
194  logger.debug("Following up for types included in here %s whole set of components to follow %s ", types, compsToFollow)
195  compsToFollow += types.keys()
196  logger.debug("Included component %s", comp_name)
197  else:
198  logger.debug("Ignored component %s", comp_name)
199  if depth > 0:
200  conf.update(excludeIncludeComps(dic, args, depth-1, compsToFollow))
201  return conf
202 

◆ ignoreDefaults()

Dict python.iconfTool.models.loaders.ignoreDefaults (   allconf,
  args,
  known 
)

Definition at line 264 of file loaders.py.

264 def ignoreDefaults(allconf, args, known) -> Dict:
265  conf = {}
266  def drop_defaults(component_name, val_dict):
267  # try picking the name from the dict, if missing use last part of the name, if that fails use the component_name (heuristic)
268  component_name_last_part = component_name.split(".")[-1]
269  component_type = known.get(component_name, known.get(component_name_last_part, component_name_last_part))
270  comp_cls = None
271  try:
272  from AthenaConfiguration.ComponentFactory import CompFactory
273  comp_cls = CompFactory.getComp(component_type)
274  logger.debug("Loaded the configuration class %s/%s for defaults elimination", component_type, component_name)
275  except Exception:
276  logger.debug("Could not find the configuration class %s/%s, no defaults for it can be eliminated", component_type, component_name)
277  return val_dict
278  c = {}
279 
280  for k,v in val_dict.items():
281  if not hasattr(comp_cls,'_descriptors'):
282  logger.debug('No \'_descriptors\' attibute for %s', comp_cls)
283  continue
284  if k not in comp_cls._descriptors: # property not in descriptors (for instance, removed from component now)
285  c[k] = v
286  else:
287  default = str(comp_cls._descriptors[k].default)
288  sv = str(v)
289  if (default == sv or
290  default.replace("StoreGateSvc+", "") == sv.replace("StoreGateSvc+", "") or
291  default.replace("ConditionStore+", "") == sv.replace("ConditionStore+", "")):
292  logger.debug("Dropped default value \'%s\' of property %s in %s because the default is \'%s\'", sv, k, component_name, str(default))
293  elif args.ignoreDefaultNamedComps and isinstance(v, str) and sv.endswith(f"/{default}"):
294  logger.debug("Dropped speculatively value %s of property %s in %s because the default it ends with %s", sv, k, component_name, str(default))
295  else:
296  c[k] = v
297  logger.debug("Keep value %s of property %s in %s because it is different from default %s", str(v), str(k), component_name, str(comp_cls._descriptors[k].default))
298  return c
299 
300  # collect types for all components (we look for A/B or lost of A/B strings)
301  for (comp_name, comp_settings) in allconf.items():
302  remaining = drop_defaults(comp_name, comp_settings)
303  if len(remaining) != 0: # ignore components that have only default settings
304  conf[comp_name] = remaining
305  return conf
306 

◆ ignoreIrrelevant()

Dict python.iconfTool.models.loaders.ignoreIrrelevant (   dic,
  args 
)

Definition at line 203 of file loaders.py.

203 def ignoreIrrelevant(dic, args) -> Dict:
204  def remove_irrelevant(val_dict):
205  return (
206  { key: val for key, val in val_dict.items() if key not in args.ignore }
207  if isinstance(val_dict, dict)
208  else val_dict
209  )
210  conf = {}
211  for (key, value) in dic.items():
212  conf[key] = remove_irrelevant(value)
213  return conf
214 

◆ isReference()

list python.iconfTool.models.loaders.isReference (   value,
  compname,
  conf,
  svcCache = {} 
)
Returns a list of (component,class) if value stores reference to other components
   value - the value to check
   compname - full component name
   conf - complete config dict

Definition at line 337 of file loaders.py.

337 def isReference(value, compname, conf, svcCache={}) -> list:
338  """Returns a list of (component,class) if value stores reference to other components
339  value - the value to check
340  compname - full component name
341  conf - complete config dict
342  """
343 
344  def _getSvcClass(instance):
345  """Find instance in service lists to get class.
346  Keeps a cache of the service classes in the svcCache default value.
347  That's fine, unless we are dealing with more than one conf in the program.
348  In that case, initialise svcCache to {} and specify in the caller."""
349  if not svcCache: # only scan ApplicationMgr once
350  props = conf.get('ApplicationMgr',{"":None})
351  if isinstance(props,dict):
352  for prop,val in props.items():
353  if 'Svc' in prop:
354  try:
355  val = ast.literal_eval(str(val))
356  except Exception:
357  pass
358  if isinstance(val,list):
359  for v in val:
360  if isinstance(v,str):
361  vv = v.split('/')
362  if len(vv) == 2:
363  if svcCache.setdefault(vv[1], vv[0]) != vv[0]:
364  svcCache[vv[1]] = None # fail if same instance, different class
365  return svcCache.get(instance)
366 
367  try:
368  value = ast.literal_eval(str(value))
369  except Exception:
370  pass
371 
372  if isinstance(value, str):
373  ctype_name = value.split('/')
374  cls = ctype_name[0] if len(ctype_name) == 2 else None
375  instance = ctype_name[-1]
376  ref = None
377  if instance:
378  if compname and f"{compname}.{instance}" in conf: # private tool
379  ref = f"{compname}.{instance}"
380  elif f"ToolSvc.{instance}" in conf: # public tool
381  ref = f"ToolSvc.{instance}"
382  elif cls is not None or instance in conf: # service or other component
383  ref = instance
384  if cls is None:
385  cls = _getSvcClass(instance)
386  if ref is not None:
387  return [(ref, cls)]
388 
389  elif isinstance(value, list):
390  refs = [isReference(el, compname, conf) for el in value]
391  if any(refs):
392  flattened = []
393  [flattened.extend(el) for el in refs if el]
394  return flattened
395  return []
396 
397 

◆ loadConfigFile()

Dict python.iconfTool.models.loaders.loadConfigFile (   fname,
  args 
)
loads config file into a dictionary, supports several modifications of the input switched on via additional arguments
Supports reading: Pickled file with the CA or properties & JSON

Definition at line 410 of file loaders.py.

410 def loadConfigFile(fname, args) -> Dict:
411  """loads config file into a dictionary, supports several modifications of the input switched on via additional arguments
412  Supports reading: Pickled file with the CA or properties & JSON
413  """
414  if args.debug:
415  print("Debugging info from reading ", fname, " in ", logger.handlers[0].baseFilename)
416  logger.setLevel(logging.DEBUG)
417 
418  conf = {}
419  if fname.endswith(".pkl"):
420  with open(fname, "rb") as input_file:
421  # determine if there is a old or new configuration pickled
422  cfg = pickle.load(input_file)
423  logger.info("... Read %s from %s", cfg.__class__.__name__, fname)
424  from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
425  if isinstance(cfg, ComponentAccumulator): # new configuration
426  props = cfg.gatherProps()
427  # to make json compatible with old configuration
428  jos_props = props[2]
429  to_json = {}
430  for comp, name, value in jos_props:
431  to_json.setdefault(comp, {})[name] = value
432  to_json[comp][name] = value
433  conf.update(to_json)
434  conf['ApplicationMgr'] = props[0]
435  conf['MessageSvc'] = props[1]
436 
437  elif isinstance(
438  cfg, (collections.defaultdict, dict)
439  ): # old configuration
440  conf.update(cfg)
441  conf.update(pickle.load(input_file)) # special services
442  # FIXME: there's a third pickle object with python components
443  elif isinstance(cfg, (collections.Sequence)):
444  for c in cfg:
445  conf.update(c)
446  logger.info("... Read %d items from python pickle file: %s", len(conf), fname)
447 
448  elif fname.endswith(".json"):
449 
450  def __keepPlainStrings(element):
451  if isinstance(element, str):
452  return str(element)
453  if isinstance(element, list):
454  return [__keepPlainStrings(x) for x in element]
455  if isinstance(element, dict):
456  return {
457  __keepPlainStrings(key): __keepPlainStrings(value)
458  for key, value in element.items()
459  }
460  return element
461 
462  with open(fname, "r") as input_file:
463  cfg = json.load(input_file, object_hook=__keepPlainStrings)
464  for c in cfg:
465  conf.update(cfg)
466 
467  # For compatibility with HLTJobOptions json, which produces structure:
468  # {
469  # "filetype": "joboptions",
470  # "properties": { the thing we are interested in}
471  # }
472  if 'properties' in conf:
473  conf = conf['properties']
474 
475  logger.info("... Read %d items from json file: %s", len(conf), fname)
476 
477  else:
478  sys.exit("File format not supported.")
479 
480  if conf is None:
481  sys.exit("Unable to load %s file" % fname)
482 
483  if args.includeComps or args.excludeComps or args.includeClasses or args.excludeClasses:
484  logger.info(f"include/exclude comps like {args.includeComps}/{args.excludeComps}")
485  conf = excludeIncludeComps(conf, args, args.follow)
486 
487  if args.ignoreIrrelevant:
488  conf = ignoreIrrelevant(conf, args)
489 
490  if args.renameComps or args.renameCompsFile:
491  conf = renameComps(conf, args)
492 
493  if args.ignoreDefaults:
494  known_types = collect_types(conf)
495  conf = ignoreDefaults(conf, args, known_types)
496 
497  if args.shortenDefaultComponents:
498  conf = shortenDefaultComponents(conf, args)
499 
500  if args.skipProperties:
501  conf = skipProperties(conf, args)
502  return conf
503 

◆ loadDifferencesFile()

Dict python.iconfTool.models.loaders.loadDifferencesFile (   fname)
Read differences file
Format:
full_component_name.property oldvalue=newvalue
example:
AlgX.ToolA.SubToolB.SettingZ 45=46
It is possible to specify missing values, e.g:
AlgX.ToolA.SubToolB.SettingZ 45=    means that now the old value should be ignored
AlgX.ToolA.SubToolB.SettingZ =46    means that now the new value should be ignored
AlgX.ToolA.SubToolB.SettingZ =      means that any change of the value should be ignored 

Definition at line 599 of file loaders.py.

599 def loadDifferencesFile(fname) -> Dict:
600  """
601  Read differences file
602  Format:
603  full_component_name.property oldvalue=newvalue
604  example:
605  AlgX.ToolA.SubToolB.SettingZ 45=46
606  It is possible to specify missing values, e.g:
607  AlgX.ToolA.SubToolB.SettingZ 45= means that now the old value should be ignored
608  AlgX.ToolA.SubToolB.SettingZ =46 means that now the new value should be ignored
609  AlgX.ToolA.SubToolB.SettingZ = means that any change of the value should be ignored
610 
611  """
612  from collections import defaultdict
613  differences = defaultdict(dict)
614  count=0
615  with open(fname, "r") as f:
616  for line in f:
617  if line[0] == "#" or line == "\n":
618  continue
619  line = line.strip()
620  compAndProp, values = line.split(" ")
621  comp, prop = compAndProp.rsplit(".", 1)
622  o,n = values.split("=")
623  oldval,newval = o if o else None, n if n else None
624 
625  differences[comp][prop] = (oldval,newval)
626  count+=1
627  logger.info("... Read %d known differences from file: %s", count, fname)
628  logger.info("..... %s", str(differences))
629 
630  return differences
631 

◆ renameComps()

Dict python.iconfTool.models.loaders.renameComps (   dic,
  args 
)

Definition at line 215 of file loaders.py.

215 def renameComps(dic, args) -> Dict:
216  compsToRename = __flatten_list(args.renameComps)
217  if args.renameCompsFile:
218  with open( args.renameCompsFile, "r") as refile:
219  for line in refile:
220  if not (line.startswith("#") or line.isspace() ):
221  compsToRename.append( line.rstrip('\n') )
222  global componentRenamingDict
223  componentRenamingDict.update({
224  old_name: new_name
225  for old_name, new_name in [
226  [e.strip() for e in element.split("=")] for element in compsToRename
227  ]
228  })
229  for f,t in componentRenamingDict.items():
230  logger.info("Renaming from: %s to %s", f, t)
231 
232  def rename_comps(comp_name):
233  """Renames component if it is in the dict or, when name fragment is in the dict
234  The later is for cases like: ToolSvc.ToolA.X.Y is renamed to ToolSvc.ToolB.X.Y
235  """
236  logger.debug("Trying renaming on, %s", comp_name)
237  for k,v in componentRenamingDict.items():
238  if k == comp_name:
239 # logger.debug("Renamed comp %s to %s", k, v)
240  return v
241 
242  old = f".{k}."
243  if old in comp_name:
244  return comp_name.replace(old, f".{v}.")
245 
246  old = f"{k}."
247  if comp_name.startswith(old):
248  return comp_name.replace(old, f"{v}.")
249 
250 
251  old = f".{k}"
252  if comp_name.endswith(old):
253  return comp_name.replace(old, f".{k}")
254  return comp_name
255 
256  conf = {}
257  for (key, value) in dic.items():
258  renamed = rename_comps(key)
259  if renamed != key:
260  logger.debug("Renamed comp %s to %s", key, renamed)
261  conf[renamed] = value
262  return conf
263 

◆ shortenDefaultComponents()

Dict python.iconfTool.models.loaders.shortenDefaultComponents (   dic,
  args 
)

Definition at line 307 of file loaders.py.

307 def shortenDefaultComponents(dic, args) -> Dict:
308  conf = {}
309  def shorten(val):
310  value = val
311  # the value can possibly be a serialized object (like a list)
312  try:
313  value = ast.literal_eval(str(value))
314  except Exception:
315  pass
316 
317  if isinstance(value, str):
318  svalue = value.split("/")
319  if len(svalue) == 2 and svalue[0] == svalue[1]:
320  logger.debug("Shortened %s", svalue)
321  return svalue[0]
322  if isinstance(value, list):
323  return [shorten(el) for el in value]
324  if isinstance(value, dict):
325  return shorten_defaults(value)
326 
327  return value
328 
329  def shorten_defaults(val_dict):
330  if isinstance(val_dict, dict):
331  return { key: shorten(val) for key,val in val_dict.items() }
332 
333  for (key, value) in dic.items():
334  conf[key] = shorten_defaults(value)
335  return conf
336 

◆ skipProperties()

Dict python.iconfTool.models.loaders.skipProperties (   conf,
  args 
)

Definition at line 398 of file loaders.py.

398 def skipProperties(conf, args) -> Dict:
399  updated = {}
400  for (name, properties) in conf.items():
401  updated[name] = {}
402  if not isinstance(properties, dict): # keep it
403  updated[name] = properties
404  else:
405  for property_name, value in properties.items():
406  if isReference( value, name, conf) or property_name == 'Members': # later for sequences structure
407  updated[name][property_name] = value
408  return updated
409 

◆ types_in_properties()

def python.iconfTool.models.loaders.types_in_properties (   comp_name,
  value,
  dict_to_update 
)
Updates the dictionary with (potentially) component name -> component type

Definition at line 132 of file loaders.py.

132 def types_in_properties(comp_name, value, dict_to_update):
133  """Updates the dictionary with (potentially) component name -> component type"""
134  parsable = False
135  try:
136  s = ast.literal_eval(str(value))
137  parsable = True
138  if isinstance(s, list):
139  for el in s:
140  types_in_properties(comp_name, el, dict_to_update)
141  except Exception:
142  pass
143  # Exclude non-strings, or strings that look like paths rather than type/name pairs
144  if isinstance(value,str):
145  slash_startend = value.startswith("/") or value.endswith("/")
146  json_dict = value.startswith("{") and value.endswith("}")
147  if value.count("/")==1 and not parsable and not slash_startend and not json_dict:
148  comp = value.split("/")
149  if len(comp) == 2:
150  # Record with and without parent
151  dict_to_update[f'{comp_name}.{comp[1]}'] = comp[0]
152  dict_to_update[f'{comp[1]}'] = comp[0]
153  logger.debug("Parsing %s, found type of %s.%s to be %s", value, comp_name, comp[1], comp[0])
154  else:
155  logger.debug("What is typeless comp? %s", value)
156  if isinstance(value, dict):
157  for v in value.values():
158  types_in_properties(comp_name, v, dict_to_update)
159 
160 

Variable Documentation

◆ action

string python.iconfTool.models.loaders.action = "append",

Definition at line 31 of file loaders.py.

◆ baseParser

python.iconfTool.models.loaders.baseParser

Definition at line 25 of file loaders.py.

◆ componentRenamingDict

python.iconfTool.models.loaders.componentRenamingDict

Definition at line 23 of file loaders.py.

◆ default

int python.iconfTool.models.loaders.default = [],

Definition at line 29 of file loaders.py.

◆ help

string python.iconfTool.models.loaders.help = "Include only components matching (regex) this string",

Definition at line 30 of file loaders.py.

◆ level

python.iconfTool.models.loaders.level

Definition at line 20 of file loaders.py.

◆ logger

python.iconfTool.models.loaders.logger

Definition at line 19 of file loaders.py.

◆ mode

python.iconfTool.models.loaders.mode

Definition at line 21 of file loaders.py.

◆ nargs

string python.iconfTool.models.loaders.nargs = "*",

Definition at line 28 of file loaders.py.

◆ type

python.iconfTool.models.loaders.type = int,

Definition at line 118 of file loaders.py.

python.iconfTool.models.loaders.ignoreDefaults
Dict ignoreDefaults(allconf, args, known)
Definition: loaders.py:264
python.iconfTool.models.loaders.collect_types
def collect_types(conf)
Definition: loaders.py:161
python.iconfTool.models.loaders.shortenDefaultComponents
Dict shortenDefaultComponents(dic, args)
Definition: loaders.py:307
python.iconfTool.models.loaders.__flatten_list
def __flatten_list(l)
Definition: loaders.py:128
python.iconfTool.models.loaders.types_in_properties
def types_in_properties(comp_name, value, dict_to_update)
Definition: loaders.py:132
python.iconfTool.models.loaders.skipProperties
Dict skipProperties(conf, args)
Definition: loaders.py:398
python.iconfTool.models.loaders.renameComps
Dict renameComps(dic, args)
Definition: loaders.py:215
python.iconfTool.models.loaders.isReference
list isReference(value, compname, conf, svcCache={})
Definition: loaders.py:337
python.iconfTool.models.loaders.excludeIncludeComps
Dict excludeIncludeComps(dic, args, depth, compsToFollow=[])
Definition: loaders.py:168
python.iconfTool.models.loaders.ignoreIrrelevant
Dict ignoreIrrelevant(dic, args)
Definition: loaders.py:203
Trk::open
@ open
Definition: BinningType.h:40
python.iconfTool.models.loaders.loadDifferencesFile
Dict loadDifferencesFile(fname)
Definition: loaders.py:599
str
Definition: BTagTrackIpAccessor.cxx:11
dbg::print
void print(std::FILE *stream, std::format_string< Args... > fmt, Args &&... args)
Definition: SGImplSvc.cxx:70
python.iconfTool.models.loaders.loadConfigFile
Dict loadConfigFile(fname, args)
Definition: loaders.py:410