ATLAS Offline Software
Loading...
Searching...
No Matches
python.iconfTool.models.loaders Namespace Reference

Classes

class  ComponentsDiffFileLoader
class  ComponentsFileLoader

Functions

 __flatten_list (l)
 types_in_properties (comp_name, value, dict_to_update)
 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 = logging.getLogger("confTool")
 level
dict componentRenamingDict = {}
 baseParser = argparse.ArgumentParser()
 nargs
 default
 help
 action
 type

Function Documentation

◆ __flatten_list()

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

Definition at line 128 of file loaders.py.

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

◆ collect_types()

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

Definition at line 161 of file loaders.py.

161def 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.

168def 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 263 of file loaders.py.

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

◆ ignoreIrrelevant()

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

Definition at line 203 of file loaders.py.

203def 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 336 of file loaders.py.

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

◆ 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 409 of file loaders.py.

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

◆ 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 598 of file loaders.py.

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

◆ renameComps()

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

Definition at line 215 of file loaders.py.

215def 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 componentRenamingDict.update({
223 old_name: new_name
224 for old_name, new_name in [
225 [e.strip() for e in element.split("=")] for element in compsToRename
226 ]
227 })
228 for f,t in componentRenamingDict.items():
229 logger.info("Renaming from: %s to %s", f, t)
230
231 def rename_comps(comp_name):
232 """Renames component if it is in the dict or, when name fragment is in the dict
233 The later is for cases like: ToolSvc.ToolA.X.Y is renamed to ToolSvc.ToolB.X.Y
234 """
235 logger.debug("Trying renaming on, %s", comp_name)
236 for k,v in componentRenamingDict.items():
237 if k == comp_name:
238# logger.debug("Renamed comp %s to %s", k, v)
239 return v
240
241 old = f".{k}."
242 if old in comp_name:
243 return comp_name.replace(old, f".{v}.")
244
245 old = f"{k}."
246 if comp_name.startswith(old):
247 return comp_name.replace(old, f"{v}.")
248
249
250 old = f".{k}"
251 if comp_name.endswith(old):
252 return comp_name.replace(old, f".{k}")
253 return comp_name
254
255 conf = {}
256 for (key, value) in dic.items():
257 renamed = rename_comps(key)
258 if renamed != key:
259 logger.debug("Renamed comp %s to %s", key, renamed)
260 conf[renamed] = value
261 return conf
262

◆ shortenDefaultComponents()

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

Definition at line 306 of file loaders.py.

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

◆ skipProperties()

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

Definition at line 397 of file loaders.py.

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

◆ types_in_properties()

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.

132def 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

python.iconfTool.models.loaders.action

Definition at line 31 of file loaders.py.

◆ baseParser

python.iconfTool.models.loaders.baseParser = argparse.ArgumentParser()

Definition at line 25 of file loaders.py.

◆ componentRenamingDict

dict python.iconfTool.models.loaders.componentRenamingDict = {}

Definition at line 23 of file loaders.py.

◆ default

python.iconfTool.models.loaders.default

Definition at line 29 of file loaders.py.

◆ help

python.iconfTool.models.loaders.help

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 = logging.getLogger("confTool")

Definition at line 19 of file loaders.py.

◆ nargs

python.iconfTool.models.loaders.nargs

Definition at line 28 of file loaders.py.

◆ type

python.iconfTool.models.loaders.type

Definition at line 118 of file loaders.py.