ATLAS Offline Software
Loading...
Searching...
No Matches
python.trfUtils Namespace Reference

Classes

class  analytic
 Analytics service class. More...
class  Fit
 Low-level fitting class. More...
class  Job
 Job: a set of pieces of information relevant to a given work function. More...
class  JobGroup
 JobGroup: a set of Job objects and pieces of information relevant to a given set of Job objects. More...
class  math
 some mathematical tools More...
class  memFileToTable
 Extract a table of data from a txt file. More...
class  ParallelJobProcessor
 ParallelJobProcessor: a multiple-process processor of Job objects. More...

Functions

 findFile (pathvar, fname)
 Find a named file along a colon separated PATH type variable.
 getAncestry (listMyOrphans=False)
 List all processes and parents and form a dictionary where the parent key lists all child PIDs.
 listChildren (psTree=None, parent=os.getpid(), listOrphans=False)
 Find all the children of a particular PID (calls itself recursively to descend into each leaf)
 infanticide (childPIDs=None, sleepTime=3, message=True, listOrphans=False)
 Kill all PIDs.
 call (args, bufsize=0, executable=None, stdin=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, message="", logger=msg, loglevel=None, timeout=None, retry=2, timefactor=1.5, sleeptime=10)
 asetupReport ()
 Return a string with a report of the current athena setup.
 releaseIsOlderThan (major, minor=None)
 Test (to the best of our knowledge) if the current release is older than a major, minor version number.
 asetupReleaseIsOlderThan (asetup_string, major, minor=None)
 Test (to the best of our knowledge) if the asetup release is older than a major, minor version number.
 shQuoteStrings (strArray=sys.argv)
 Quote a string array so that it can be echoed back on the command line in a cut 'n' paste safe way.
 lineByLine (filename, strip=True, removeTimestamp=True, substepName=None)
 Generator to return lines and line count from a file.
 prettyXML (element, indent=' ', poolFileCatalogFormat=False)
 XML pretty print an ElementTree.ELement object.
 isodate ()
 Return isoformated 'now' string.
 forceToAlphaNum (string)
 Strip a string down to alpha-numeric characters only.
 cmpMetadata (metadata1, metadata2, guidCheck='valid')
 Compare metadata for files, but taking into account that GUID can vary.
 unpackTarFile (filename, directory=".")
 Unpack a given tarfile.
 unpackDBRelease (tarball, dbversion=None)
 Ensure that the DBRelease tarball has been unpacked.
 setupDBRelease (setup)
 Run a DBRelease setup.
 cvmfsDBReleaseCheck (dbrelease)
 Validate a DBRelease exists on cvmfs and return the path to the setup script.
 pickledDump (argdict)
 Dump a list of arguments to the pickle file given in the 'dumpPickle' argument.
 JSONDump (argdict)
 Dump a list of arguments to the JSON file given in the 'dumpJSON' argument.
 convertToStr (in_string)
 Recursively convert unicode to str, useful when we have just loaded something from json (TODO: make the transforms happy with unicode as well as plain str!)
 cliToKey (option)
 Convert a command line option to the dictionary key that will be used by argparse.
 printHR (the_object)
 print in a human-readable way the items of a given object
 uniqueIdentifier ()
 return a URL-safe, base 64-encoded pseudorandom UUID
 units (quantity=None, unitSingular="unit", unitPlural="units")
 return either singular or plural units as appropriate for a given quantity
 isInteractiveEnv ()
 initialise_processes ()
 initisation procedure for processes of process pool
 ValgrindCommand (defaultOptions=True, extraOptionsList=None, AthenaSerialisedConfigurationFile="athenaConf.pkl", returnFormat="string")
 VTuneCommand (defaultOptions=True, extraOptionsList=None, AthenaCommand=["athena.py", "athenaConf.pkl"], returnFormat="string")
 return VTune command @detail This function returns a VTune command for use with Athena.
 calcCpuTime (start, stop)
 calcWallTime (start, stop)
 bind_port (host, port)
 reportEventsPassedSimFilter (log)
 summarize events passed the ISF_SimEventFilter @detail this function sums up all events passed the ISF_SimEventFilter out of all total events.

Variables

 msg = logging.getLogger(__name__)

Function Documentation

◆ asetupReleaseIsOlderThan()

python.trfUtils.asetupReleaseIsOlderThan ( asetup_string,
major,
minor = None )

Test (to the best of our knowledge) if the asetup release is older than a major, minor version number.

Parameters
asetup_stringasetup string
majorMajor release number
minorMinor release number (if not specified, will not be matched against)
Returns
Boolean if current release is found to be older

Definition at line 303 of file trfUtils.py.

303def asetupReleaseIsOlderThan(asetup_string, major, minor=None):
304 try:
305 relmajor = None
306 relminor = None
307
308 # First split the asetup_string by comma
309 split_string = asetup_string.split(',')
310 # master is always the newest
311 if 'master' in split_string:
312 return False
313
314 # First try major.minor.bugfix
315 reg_exp = re.compile(r'(?P<major>\d+)\.(?P<minor>\d+)\.(?P<other>.*)')
316 for part in split_string:
317 part = part.strip()
318 match = re.match(reg_exp, part)
319 if match:
320 relmajor = int(match.group('major'))
321 relminor = int(match.group('minor'))
322 msg.info('Detected asetup release {0}.{1}(.{2})'.format(relmajor, relminor, match.group('other')))
323 break
324
325 # Then try major.minor
326 if relmajor is None:
327 reg_exp = re.compile(r'(?P<major>\d+)\.(?P<minor>\d+)')
328 for part in split_string:
329 part = part.strip()
330 match = re.match(reg_exp, part)
331 if match:
332 relmajor = int(match.group('major'))
333 relminor = int(match.group('minor'))
334 msg.info('Detected asetup release {0}.{1}'.format(relmajor, relminor))
335 break
336
337 # Bail out
338 if relmajor is None:
339 raise RuntimeError('asetup version could not be parsed')
340
341 # Major beats minor, so test this first
342 if relmajor < major:
343 return True
344 if relmajor > major:
345 return False
346
347 # First case is major equality and don't care about minor
348 if minor is None or relminor >= minor:
349 return False
350 return True
351
352 except Exception as e:
353 msg.warning('Exception thrown when attempting to detect asetup athena version ({0}) from {1}. No release check possible'.format(e, asetup_string))
354 return False
355
356

◆ asetupReport()

python.trfUtils.asetupReport ( )

Return a string with a report of the current athena setup.

Definition at line 223 of file trfUtils.py.

223def asetupReport():
224 setupMsg = str()
225 eVars = ['AtlasBaseDir', 'AtlasProject', 'AtlasVersion', 'AtlasPatch', 'AtlasPatchVersion', 'CMTCONFIG', 'TestArea']
226 if "AtlasProject" in os.environ:
227 CMake_Platform = "{0}_PLATFORM".format(os.environ["AtlasProject"])
228 if CMake_Platform in os.environ:
229 eVars.remove("CMTCONFIG")
230 eVars.append(CMake_Platform)
231 for eVar in eVars:
232 if eVar in os.environ:
233 setupMsg += '\t%s=%s\n' % (eVar, os.environ[eVar])
234 # Look for patches so that the job can be rerun
235 if 'WorkDir_DIR' in os.environ and os.access(os.environ['WorkDir_DIR'], os.R_OK):
236 pass
237 # lstags is obsolete with git releases.
238 # setupMsg += "\n\tPatch packages are:\n"
239 # try:
240 # cmd = ['lstags']
241 # lstagsOut = Popen(cmd, shell = False, stdout = PIPE, stderr = STDOUT, bufsize = 1).communicate()[0]
242 # setupMsg += "\n".join([ "\t\t{0}".format(pkg) for pkg in lstagsOut.decode().split("\n") ])
243 # except (CalledProcessError, OSError) as e:
244 # setupMsg += 'Execution of lstags failed: {0}'.format(e)
245 else:
246 setupMsg+= "No readable patch area found"
247
248 return setupMsg.rstrip()
249
250

◆ bind_port()

python.trfUtils.bind_port ( host,
port )

Definition at line 1699 of file trfUtils.py.

1699def bind_port(host, port):
1700 ret = 0
1701 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1702 try:
1703 s.bind((host, port))
1704 except socket.error as e:
1705 if e.errno == 98:
1706 print("Port %s is already in use" %port)
1707 else:
1708 # something else raised the socket.error exception
1709 print(e)
1710 ret=1
1711 s.close()
1712 return ret
1713
void print(char *figname, TCanvas *c1)

◆ calcCpuTime()

python.trfUtils.calcCpuTime ( start,
stop )

Definition at line 1684 of file trfUtils.py.

1684def calcCpuTime(start, stop):
1685 cpuTime = None
1686 if start and stop:
1687 cpuTime = reduce(lambda x1, x2: x1+x2, list(map(lambda x1, x2: x2-x1, start[2:4], stop[2:4])))
1688
1689 return cpuTime
1690
1691# calculate wallTime from os.times() times tuple
static void reduce(HepMC::GenEvent *ge, HepMC::GenParticle *gp)
Remove an unwanted particle from the event, collapsing the graph structure consistently.
Definition FixHepMC.cxx:39
STL class.

◆ calcWallTime()

python.trfUtils.calcWallTime ( start,
stop )

Definition at line 1692 of file trfUtils.py.

1692def calcWallTime(start, stop):
1693 wallTime = None
1694 if start and stop:
1695 wallTime = stop[4] - start[4]
1696
1697 return wallTime
1698

◆ call()

python.trfUtils.call ( args,
bufsize = 0,
executable = None,
stdin = None,
preexec_fn = None,
close_fds = False,
shell = False,
cwd = None,
env = None,
universal_newlines = False,
startupinfo = None,
creationflags = 0,
message = "",
logger = msg,
loglevel = None,
timeout = None,
retry = 2,
timefactor = 1.5,
sleeptime = 10 )

Definition at line 155 of file trfUtils.py.

155def call(args, bufsize=0, executable=None, stdin=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, message="", logger=msg, loglevel=None, timeout=None, retry=2, timefactor=1.5, sleeptime=10):
156
157 def logProc(p):
158 line=p.stdout.readline()
159 if line:
160 line="%s%s" % (message, line.rstrip())
161 if logger is None:
162 print(line)
163 else:
164 logger.log(loglevel, line)
165
166 def flushProc(p):
167 line=p.stdout.readline()
168 while line:
169 line="%s%s" % (message, line.strip())
170 if logger is None:
171 print(line)
172 else:
173 logger.log(loglevel, line)
174 line=p.stdout.readline()
175
176 if loglevel is None:
177 loglevel=logging.DEBUG
178
179 if timeout is None or timeout<=0: # no timeout set
180 msg.info('Executing %s...', args)
181 starttime = time.time()
182 p=Popen(args=args, bufsize=bufsize, executable=executable, stdin=stdin, stdout=PIPE, stderr=STDOUT, preexec_fn=preexec_fn, close_fds=close_fds, shell=shell, cwd=cwd, env=env, universal_newlines=universal_newlines, startupinfo=startupinfo, creationflags=creationflags)
183 while p.poll() is None:
184 logProc(p)
185 flushProc(p)
186 if timeout is not None:
187 msg.info('Executed call within %d s.', time.time()-starttime)
188 return p.returncode
189
190 else: #timeout set
191 n=0
192 while n<=retry:
193 msg.info('Try %i out of %i (time limit %ss) to call %s.', n+1, retry+1, timeout, args)
194 starttime = time.time()
195 endtime=starttime+timeout
196 p=Popen(args=args, bufsize=bufsize, executable=executable, stdin=stdin, stdout=PIPE, stderr=STDOUT, preexec_fn=preexec_fn, close_fds=close_fds, shell=shell, cwd=cwd, env=env, universal_newlines=universal_newlines, startupinfo=startupinfo, creationflags=creationflags)
197 while p.poll() is None and time.time()<endtime:
198 logProc(p)
199 if p.poll() is None:
200 msg.warning('Timeout limit of %d s reached. Kill subprocess and its children.', timeout)
201 parent=p.pid
202 pids=[parent]
203 pids.extend(listChildren(parent=parent))
204 infanticide(pids)
205 msg.info('Checking if something is left in buffer.')
206 flushProc(p)
207 if n!=retry:
208 msg.info('Going to sleep for %d s.', sleeptime)
209 time.sleep(sleeptime)
210 n+=1
211 timeout*=timefactor
212 sleeptime*=timefactor
213 else:
214 flushProc(p)
215 msg.info('Executed call within %d s.', time.time()-starttime)
216 return p.returncode
217
218 msg.warning('All %i tries failed!', n)
219 raise Exception
220
221

◆ cliToKey()

python.trfUtils.cliToKey ( option)

Convert a command line option to the dictionary key that will be used by argparse.

Definition at line 652 of file trfUtils.py.

652def cliToKey(option):
653 return option.lstrip('-').replace('-', '_')
654
655
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310

◆ cmpMetadata()

python.trfUtils.cmpMetadata ( metadata1,
metadata2,
guidCheck = 'valid' )

Compare metadata for files, but taking into account that GUID can vary.

Compare metadata dictionaries, but allowing for differences in the file_guid property as this is generated randomly for file types without an intrinsic GUID

Parameters
metadata1Filel metadata dictionary
metadata2File2 metadata dictionary
giudCheckHow to compare GUIDs. Valid values are:
  • equal GUIDs must be the same
  • valid GUIDs must be valid, but don't have to be the same
  • ignore The file_guid key is ignored
Returns
True if metadata is the same, otherwise False

Definition at line 464 of file trfUtils.py.

464def cmpMetadata(metadata1, metadata2, guidCheck = 'valid'):
465 # First check we have the same files
466 allFiles = set(metadata1) | set(metadata2)
467 if len(allFiles) > len(metadata1) or len(allFiles) > len(metadata2):
468 msg.warning('In metadata comparison file lists are not equal - fails ({0} != {1}'.format(metadata1, metadata2))
469 return False
470 for fname in allFiles:
471 allKeys = set(metadata1[fname]) | set(metadata2[fname])
472 if len(allKeys) > len(metadata1[fname]) or len(allFiles) > len(metadata2[fname]):
473 msg.warning('In metadata comparison key lists are not equal - fails')
474 return False
475 for key in allKeys:
476 if key == 'file_guid':
477 if guidCheck == 'ignore':
478 continue
479 elif guidCheck == 'equal':
480 if metadata1[fname]['file_guid'].upper() == metadata2[fname]['file_guid'].upper():
481 continue
482 else:
483 msg.warning('In metadata comparison strict GUID comparison failed.')
484 return False
485 elif guidCheck == 'valid':
486 try:
487 uuid.UUID(metadata1[fname]['file_guid'])
488 uuid.UUID(metadata2[fname]['file_guid'])
489 continue
490 except ValueError:
491 msg.warning('In metadata comparison found invalid GUID strings.')
492 return False
493 if metadata1[fname][key] != metadata2[fname][key]:
494 msg.warning('In metadata comparison found different key values: {0!s} != {1!s}'.format(metadata1[fname][key], metadata2[fname][key]))
495 return True
496
497
int upper(int c)
STL class.

◆ convertToStr()

python.trfUtils.convertToStr ( in_string)

Recursively convert unicode to str, useful when we have just loaded something from json (TODO: make the transforms happy with unicode as well as plain str!)

Definition at line 636 of file trfUtils.py.

636def convertToStr(in_string):
637 if isinstance(in_string, dict):
638 return dict([(convertToStr(key), convertToStr(value)) for key, value in in_string.items()])
639 elif isinstance(in_string, list):
640 return [convertToStr(element) for element in in_string]
641 # Unicode is always str in Python3, but bytes are not
642 # TODO: remove unicode comparison after Python 3 migration
643 elif in_string.__class__.__name__ == 'unicode':
644 return in_string.encode('utf-8')
645 elif in_string.__class__.__name__ == 'bytes':
646 return in_string.decode('utf-8')
647 else:
648 return in_string
649
650

◆ cvmfsDBReleaseCheck()

python.trfUtils.cvmfsDBReleaseCheck ( dbrelease)

Validate a DBRelease exists on cvmfs and return the path to the setup script.

Parameters
dbreleaseThe DBRelease number (X.Y.Z[.A]) or "current"
Exceptions
trfExceptions.TransformSetupExceptionIf the DBRelease setup is unreadable or the dbrelease parameter is not understood
Returns
Path to setup.py script for this DBRelease

Definition at line 569 of file trfUtils.py.

569def cvmfsDBReleaseCheck(dbrelease):
570 dbsetup = None
571 dbdMatch = re.match(r'([\d\.]+|current)$', dbrelease)
572 msg.debug('Attempting to setup DBRelease {0} from cvmfs'.format(dbrelease))
573 if dbdMatch:
574 if 'VO_ATLAS_SW_DIR' in os.environ:
575 msg.debug('Found site defined path to ATLAS software: {0}'.format(os.environ['VO_ATLAS_SW_DIR']))
576 dbsetup = path.join(os.environ['VO_ATLAS_SW_DIR'], 'database', 'DBRelease', dbrelease, 'setup.py')
577 if os.access(dbsetup, os.R_OK):
578 return dbsetup
579 msg.warning('Site defined path to ATLAS software seems invalid (failed to access {0}). Will also try standard cvmfs path.'.format(dbsetup))
580 else:
581 msg.debug('Using standard CVMFS path to ATLAS software')
582
583 dbsetup = path.join('/cvmfs/atlas.cern.ch/repo/sw/database/DBRelease', dbrelease, 'setup.py')
584 if not os.access(dbsetup, os.R_OK):
585 raise trfExceptions.TransformSetupException(trfExit.nameToCode('TRF_DBRELEASE_PROBLEM'),
586 'CVMFS DBRelease setup file {0} was not readable'.format(dbsetup))
587 msg.debug('Using cvmfs based dbrelease: {0}'.format(path.dirname(dbsetup)))
588 else:
589 raise trfExceptions.TransformSetupException(trfExit.nameToCode('TRF_DBRELEASE_PROBLEM'),
590 'Unable to interpret DBRelease "{0}" as either a tarball or a CVMFS release directory'.format(dbrelease))
591 return dbsetup
592
593

◆ findFile()

python.trfUtils.findFile ( pathvar,
fname )

Find a named file along a colon separated PATH type variable.

Note will also work for finding directories

Returns
Full path to file or None is file is not found

Definition at line 37 of file trfUtils.py.

37def findFile(pathvar, fname):
38 # First see if the file already includes a path.
39 msg.debug('Finding full path for {fileName} in path {path}'.format(
40 fileName = fname,
41 path = pathvar
42 ))
43 if fname.startswith('/'):
44 return(fname)
45
46 # Split the path.
47 pathElements = pathvar.split(':')
48 for pathElement in pathElements:
49 if path.exists(path.join(pathElement, fname)):
50 return(path.join(pathElement, fname))
51
52 return(None)
53
54

◆ forceToAlphaNum()

python.trfUtils.forceToAlphaNum ( string)

Strip a string down to alpha-numeric characters only.

Note
This is used to force executor names and substep aliases to a form that the substep argument parser will recognise. None is still allowed as this is the default for "unset" in some cases.

Definition at line 443 of file trfUtils.py.

443def forceToAlphaNum(string):
444 if string is None or string.isalnum():
445 return string
446 newstring = ''
447 for piece in string:
448 if piece.isalnum():
449 newstring += piece
450 msg.warning("String {0} was stripped to alphanumeric characters only: {1}".format(string, newstring))
451 return newstring
452
453

◆ getAncestry()

python.trfUtils.getAncestry ( listMyOrphans = False)

List all processes and parents and form a dictionary where the parent key lists all child PIDs.

Parameters
listMyOrphansIf this is True, then processes which share the same pgid as this process and have parent PID=1 (i.e., init) get added to this process's children, which allows these orphans to be added to the kill list. N.B. this means that orphans have two entries - as child of init and a child of this process

Definition at line 62 of file trfUtils.py.

62def getAncestry(listMyOrphans = False):
63 psCmd = ['ps', 'ax', '-o', 'pid,ppid,pgid,args', '-m']
64
65 try:
66 msg.debug('Executing %s', psCmd)
67 p = Popen(psCmd, stdout=PIPE, stderr=PIPE)
68 stdout = p.communicate()[0]
69 psPID = p.pid
70 except OSError as e:
71 msg.error('Failed to execute "ps" to get process ancestry: %s', repr(e))
72 raise
73
74 childDict = {}
75 myPgid = os.getpgrp()
76 myPid = os.getpid()
77 for line in stdout.decode().split('\n'):
78 try:
79 (pid, ppid, pgid, cmd) = line.split(None, 3)
80 pid = int(pid)
81 ppid = int(ppid)
82 pgid = int(pgid)
83 # Ignore the ps process
84 if pid == psPID:
85 continue
86 if ppid in childDict:
87 childDict[ppid].append(pid)
88 else:
89 childDict[ppid] = [pid]
90 if listMyOrphans and ppid == 1 and pgid == myPgid:
91 msg.info("Adding PID {0} to list of my children as it seems to be orphaned: {1}".format(pid, cmd))
92 if myPid in childDict:
93 childDict[myPid].append(pid)
94 else:
95 childDict[myPid] = [pid]
96
97 except ValueError:
98 # Not a nice line
99 pass
100 return childDict
101
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:177

◆ infanticide()

python.trfUtils.infanticide ( childPIDs = None,
sleepTime = 3,
message = True,
listOrphans = False )

Kill all PIDs.

Note
Even if this function is used, subprocess objects need to join() with the child to prevent it becoming a zombie
Parameters
childPIDsExplicit list of PIDs to kill; if absent then listChildren() is called
sleepTimeTime between SIGTERM and SIGKILL
messageBoolean if messages should be printed
listOrphansParameter value to pass to getAncestry(), if necessary (beware, killing orphans is dangerous, you may kill "upstream" processes; Caveat Emptor)

Definition at line 132 of file trfUtils.py.

132def infanticide(childPIDs = None, sleepTime = 3, message = True, listOrphans = False):
133 if childPIDs is None:
134 childPIDs = listChildren(listOrphans = listOrphans)
135
136 if len(childPIDs) > 0 and message:
137 msg.info('Killing these child processes: {0}...'.format(childPIDs))
138
139 for pid in childPIDs:
140 try:
141 os.kill(pid, signal.SIGTERM)
142 except OSError:
143 pass
144
145 time.sleep(sleepTime)
146
147 for pid in childPIDs:
148 try:
149 os.kill(pid, signal.SIGKILL)
150 except OSError:
151 # OSError happens when the process no longer exists - harmless
152 pass
153
154

◆ initialise_processes()

python.trfUtils.initialise_processes ( )

initisation procedure for processes of process pool

Definition at line 855 of file trfUtils.py.

855def initialise_processes():
856 # Multiprocessing uses signals to communicate with subprocesses, so the
857 # following two lines prevent the transforms signal handlers from
858 # interfering:
859 from PyJobTransforms.trfSignal import resetTrfSignalHandlers
860 resetTrfSignalHandlers()
861 signal.signal(signal.SIGINT, signal.SIG_IGN)
862
863
Signal handling utilities for ATLAS job transforms.

◆ isInteractiveEnv()

python.trfUtils.isInteractiveEnv ( )

Definition at line 703 of file trfUtils.py.

703def isInteractiveEnv():
704 isInteractiveEnv = False
705 # PS1 is for sh, bash; prompt is for tcsh and zsh
706 if 'PS1' in os.environ or 'prompt' in os.environ:
707 isInteractiveEnv = True
708 elif os.isatty(sys.stdout.fileno()) or os.isatty(sys.stdin.fileno()):
709 isInteractiveEnv = True
710
711 return isInteractiveEnv
712
713

◆ isodate()

python.trfUtils.isodate ( )

Return isoformated 'now' string.

Uses datetime.isoformat method, but suppressing microseconds

Definition at line 434 of file trfUtils.py.

434def isodate():
435 return datetime.now().replace(microsecond=0).isoformat()
436
437

◆ JSONDump()

python.trfUtils.JSONDump ( argdict)

Dump a list of arguments to the JSON file given in the 'dumpJSON' argument.

Definition at line 617 of file trfUtils.py.

617def JSONDump(argdict):
618 if 'dumpJSON' not in argdict:
619 return
620
621 from PyJobTransforms.trfArgClasses import argument
622 theArgumentDictionary = {}
623 for k, v in argdict.items():
624 if k == 'dumpJSON':
625 continue
626 if isinstance(v, argument):
627 theArgumentDictionary[k] = getattr(v, "dumpvalue", v.value)
628 else:
629 theArgumentDictionary[k] = v
630 with open(argdict['dumpJSON'], 'w') as JSONFile:
631 import json
632 json.dump(theArgumentDictionary, JSONFile, sort_keys=True, indent=2)
633
Transform argument class definitions.

◆ lineByLine()

python.trfUtils.lineByLine ( filename,
strip = True,
removeTimestamp = True,
substepName = None )

Generator to return lines and line count from a file.

Parameters
filenameFilename to open and deliver lines from
stripIf lines get stripped before being returned (default True)
removeTimestampRemoves timestamp from left.(default True) Since strings are removed only from left, this option requires explicit removal of substepName.
substepNameRemoves substepName from left, if it's value is provided. (default None)
Note
This is useful so that multiple parts of code can co-operatively take lines from the file

Definition at line 372 of file trfUtils.py.

372def lineByLine(filename, strip=True, removeTimestamp=True, substepName=None):
373 linecounter = 0
374 encargs = {'encoding' : 'utf8'}
375 f = open(filename, 'r', **encargs)
376 for line in f:
377 linecounter += 1
378 if substepName and isinstance(substepName, str): # Remove substepName only if caller provides that string.
379 line = line.lstrip(substepName)
380 if removeTimestamp:
381 line = line.lstrip('0123456789:-, ') # Remove timestamps in both serial and MP mode.
382 if strip:
383 line = line.strip()
384 yield line, linecounter
385 f.close()
386
387

◆ listChildren()

python.trfUtils.listChildren ( psTree = None,
parent = os.getpid(),
listOrphans = False )

Find all the children of a particular PID (calls itself recursively to descend into each leaf)

Note
The list of child PIDs is reversed, so the grandchildren are listed before the children, etc. so signaling left to right is correct
Parameters
psTreeThe process tree returned by trfUtils.listChildren(); if None then trfUtils.listChildren() is called internally.
parentThe parent process for which to return all the child PIDs
listOrphansParameter value to pass to getAncestry() if necessary
Returns
children List of child PIDs
Take a psTree dictionary and list all children

Definition at line 109 of file trfUtils.py.

109def listChildren(psTree = None, parent = os.getpid(), listOrphans = False): # noqa: B008 (PID is constant)
110 '''Take a psTree dictionary and list all children'''
111 if psTree is None:
112 psTree = getAncestry(listMyOrphans = listOrphans)
113
114 msg.debug("List children of %d (%s)", parent, psTree.get(parent, []))
115 children = []
116 if parent in psTree:
117 children.extend(psTree[parent])
118 for child in psTree[parent]:
119 children.extend(listChildren(psTree, child))
120 children.reverse()
121 return children
122
123

◆ pickledDump()

python.trfUtils.pickledDump ( argdict)

Dump a list of arguments to the pickle file given in the 'dumpPickle' argument.

Note
This is a copy of the JSONDump function, but should in fact be deprecated soon so no point in merging the common parts! TODO: Deprecate me!

Definition at line 598 of file trfUtils.py.

598def pickledDump(argdict):
599 if 'dumpPickle' not in argdict:
600 return
601
602 from PyJobTransforms.trfArgClasses import argument
603 theArgumentDictionary = {}
604 for k, v in argdict.items():
605 if k == 'dumpPickle':
606 continue
607 if isinstance(v, argument):
608 theArgumentDictionary[k] = getattr(v, "dumpvalue", v.value)
609 else:
610 theArgumentDictionary[k] = v
611 with open(argdict['dumpPickle'], 'wb') as pickleFile:
612 import pickle as pickle
613 pickle.dump(theArgumentDictionary, pickleFile)
614
615

◆ prettyXML()

python.trfUtils.prettyXML ( element,
indent = ' ',
poolFileCatalogFormat = False )

XML pretty print an ElementTree.ELement object.

Parameters
elementElementTree.ELement object to print
indentIndent parameter for minidom toprettyxml method
poolFileCatalogFormatWhether to reformat the XML as a classic POOLFILECATALOG document
Returns
String with the pretty printed XML version
Note
This is rather a convoluted way to get the correct DOCTYPE set and there's probably a better way to do it, but as this is a deprecated way of delivering metadata upstream it's not worth improving at this stage.

Definition at line 397 of file trfUtils.py.

397def prettyXML(element, indent = ' ', poolFileCatalogFormat = False):
398 # Use minidom for pretty printing
399 # See http://broadcast.oreilly.com/2010/03/pymotw-creating-xml-documents.html
400 xmlstring = ElementTree.tostring(element, 'utf-8')
401 try:
402 metadataDoc = minidom.parseString(xmlstring)
403 except ExpatError:
404 # Getting weird \x00 NULLs on the end of some GUIDs, which minidom.parsestring does not like (is this APR?)
405 msg.warning('Error parsing ElementTree string - will try removing hex literals ({0!r})'.format(xmlstring))
406 xmlstring = xmlstring.replace('\x00', '')
407 metadataDoc = minidom.parseString(xmlstring)
408
409
410 if poolFileCatalogFormat is False:
411 return metadataDoc.toprettyxml(indent=indent, encoding='UTF-8')
412
413 # Now create a new document with the correct doctype for classic POOLFILECATALOG
414 # See http://stackoverflow.com/questions/2337285/set-a-dtd-using-minidom-in-python
415 imp = minidom.DOMImplementation()
416 doctype = imp.createDocumentType(qualifiedName='POOLFILECATALOG', publicId='', systemId='InMemory')
417 doc = imp.createDocument(None, 'POOLFILECATALOG', doctype)
418
419 # Cut and paste the parsed document into the new one
420 # See http://stackoverflow.com/questions/1980380/how-to-render-a-doctype-with-pythons-xml-dom-minidom
421 refel = doc.documentElement
422 for child in metadataDoc.childNodes:
423 if child.nodeType==child.ELEMENT_NODE:
424 doc.replaceChild(doc.importNode(child, True), doc.documentElement)
425 refel= None
426 elif child.nodeType!=child.DOCUMENT_TYPE_NODE:
427 doc.insertBefore(doc.importNode(child, True), refel)
428
429 return doc.toprettyxml(indent=indent, encoding='UTF-8')
430
431

◆ printHR()

python.trfUtils.printHR ( the_object)

print in a human-readable way the items of a given object

This function prints in a human-readable way the items of a given object.

Parameters
objectto print

Definition at line 660 of file trfUtils.py.

660def printHR(the_object):
661 # dictionary
662 if isinstance(the_object, dict):
663 for key, value in sorted(the_object.items()):
664 print(u'{key}: {value}'.format(key = key, value = value))
665 # list or tuple
666 elif isinstance(the_object, (list, tuple)):
667 for element in the_object:
668 print(element)
669 # other
670 else:
671 print(the_object)
672
673

◆ releaseIsOlderThan()

python.trfUtils.releaseIsOlderThan ( major,
minor = None )

Test (to the best of our knowledge) if the current release is older than a major, minor version number.

There's no unambiguous reference to the release that encompasses all of the development builds (dev, devval, migs), but almost everything can be determined from AtlasVersion and AtlasBaseDir. If neither of those contain version information then we assume a development build that is new by definition (so we return False)

Parameters
majorMajor release number
minorMinor release number (if not specified, will not be matched against)
Returns
Boolean if current release is found to be older

Definition at line 261 of file trfUtils.py.

261def releaseIsOlderThan(major, minor=None):
262 if 'AtlasVersion' not in os.environ or 'AtlasBaseDir' not in os.environ:
263 msg.warning("Could not find 'AtlasVersion' and 'AtlasBaseDir' in the environment - no release match possible")
264 return False
265 try:
266 # First try AtlasVersion, which is clean
267 relRegExp = re.compile(r'(?P<major>\d+)\.(?P<minor>\d+)\.(?P<other>.*)')
268 relMatch = re.match(relRegExp, os.environ['AtlasVersion'])
269 if not relMatch:
270 # Now try the final part of AtlasBaseDir
271 leafDir = path.basename(os.environ['AtlasBaseDir'])
272 relMatch = re.match(relRegExp, leafDir)
273 if not relMatch:
274 msg.info('No identifiable numbered release found from AtlasVersion or AtlasBaseDir - assuming dev/devval/mig')
275 return False
276
277 relmajor = int(relMatch.group('major'))
278 relminor = int(relMatch.group('minor'))
279 msg.info('Detected release major {0}, minor {1} (.{2}) from environment'.format(relmajor, relminor, relMatch.group('other')))
280
281 # Major beats minor, so test this first
282 if relmajor < major:
283 return True
284 if relmajor > major:
285 return False
286
287 # First case is major equality and don't care about minor
288 if minor is None or relminor >= minor:
289 return False
290 return True
291
292 except Exception as e:
293 msg.warning('Exception thrown when attempting to detect athena version ({0}). No release check possible'.format(e))
294 return False
295
296

◆ reportEventsPassedSimFilter()

python.trfUtils.reportEventsPassedSimFilter ( log)

summarize events passed the ISF_SimEventFilter @detail this function sums up all events passed the ISF_SimEventFilter out of all total events.

All this inforamation is extracted from log.ReSim

Definition at line 1717 of file trfUtils.py.

1717def reportEventsPassedSimFilter(log):
1718
1719 # Currently the pattern which contains the information for passed events is for example like:
1720 # ISF_SimEventFilter INFO accepted 1 out of 10 events for filter ISF_SimEventFilter (SimEventFilter)
1721 # In case the filter name truncated by ... due to long timestamps, the pattern could still match
1722 # e.g. ISF_SimEventFi... or ISF_SimEventFil...
1723 regExp = re.compile(r'ISF_SimEventFi[lter|...]+\s.*INFO.*accepted\s*(?P<events>[0-9]*)\s*out of\s*(?P<total>[0-9]*).*')
1724 try:
1725 myGen = lineByLine(log)
1726 except IOError as e:
1727 msg.warning('Failed to open transform logfile {0}: {1:s}'.format(log, e))
1728
1729 resimevents = None
1730 passed_events = 0
1731 total_events = 0
1732 for line, lineCounter in myGen:
1733 m = regExp.match(line)
1734 if m:
1735 passed_events += int(m.group('events'))
1736 total_events += int(m.group('total'))
1737 resimevents = passed_events
1738
1739 if resimevents is not None:
1740 msg.info("Summary of events passed the ISF_SimEventFilter: {0} events of total {1}".format(passed_events, total_events) )
1741 else:
1742 msg.warning("Returning null value for the resimevents. No line matched with the regExp for extracting events passed the ISF_SimEventFilter")
1743
1744 return resimevents

◆ setupDBRelease()

python.trfUtils.setupDBRelease ( setup)

Run a DBRelease setup.

Parameters
setupDMRelease setup script location (absolute or relative path)
Returns
: None

Definition at line 543 of file trfUtils.py.

543def setupDBRelease(setup):
544 try:
545 dbdir=path.abspath(path.dirname(setup))
546 msg.debug('Will add {0} to sys.path to load DBRelease setup module'.format(dbdir))
547 # N.B. We cannot use __import__ because the X.Y.Z directory name is illegal for a python module path
548 opath = sys.path
549 sys.path.insert(0, dbdir)
550 from setup import Setup
551 # Instansiate the Setup module, which activates the customisation
552 Setup(dbdir)
553 sys.path = opath
554 msg.debug('DBRelease setup module was initialised successfully')
555 except ImportError as e:
556 errMsg = 'Import error while trying to load DB Setup module: {0}'.format(e)
557 msg.error(errMsg)
558 raise trfExceptions.TransformSetupException(trfExit.nameToCode('TRF_DBRELEASE_PROBLEM'), errMsg)
559 except Exception as e:
560 errMsg = 'Unexpected error while trying to load DB Setup module: {0}'.format(e)
561 msg.error(errMsg)
562 raise trfExceptions.TransformSetupException(trfExit.nameToCode('TRF_DBRELEASE_PROBLEM'), errMsg)
563
564

◆ shQuoteStrings()

python.trfUtils.shQuoteStrings ( strArray = sys.argv)

Quote a string array so that it can be echoed back on the command line in a cut 'n' paste safe way.

Parameters
strArrayArray of strings to quote

Technique is to first quote any pre-existing single quotes, then single quote all of the array elements so that the shell sees them as a single argument

Definition at line 361 of file trfUtils.py.

361def shQuoteStrings(strArray = sys.argv):
362 return [ "'" + qstring.replace("'", "\\'") + "'" for qstring in strArray ]
363
364

◆ uniqueIdentifier()

python.trfUtils.uniqueIdentifier ( )

return a URL-safe, base 64-encoded pseudorandom UUID

This function returns a URL-safe, base 64-encoded pseudorandom Universally Unique IDentifier (UUID).

Returns
string of URL-safe, base 64-encoded pseudorandom UUID

Definition at line 678 of file trfUtils.py.

678def uniqueIdentifier():
679 return str(base64.urlsafe_b64encode(uuid.uuid4().bytes).strip("="))
680
681

◆ units()

python.trfUtils.units ( quantity = None,
unitSingular = "unit",
unitPlural = "units" )

return either singular or plural units as appropriate for a given quantity

This function returns either singular or plural units as appropriate for a given quantity. So, a quantity of 1 would cause the return of singular units and a quantity of 2 would cause the return of plural units.

Parameters
quantitythe numerical quantity
unitSingularthe string for singular units
unitSingularthe string for plural units
Returns
string of singular or plural units

Definition at line 691 of file trfUtils.py.

695 ):
696 if quantity == 1:
697 return unitSingular
698 else:
699 return unitPlural
700
701
702# @brief returns if the current job is running in interactive environment.

◆ unpackDBRelease()

python.trfUtils.unpackDBRelease ( tarball,
dbversion = None )

Ensure that the DBRelease tarball has been unpacked.

Extract the dbversion number and look for an unpacked directory. If found then this release is already setup. If not then try to unpack the tarball.

Parameters
tarballThe tarball file
dbversionThe version number (if not given the look at the tarball name to get it)
Exceptions
trfExceptions.TransformSetupExceptionIf the DBRelease tarball is unreadable or the version is not understood
Returns
Two element tuple: (True if release was unpacked or False if release was already unpacked, dbsetup path)

Definition at line 520 of file trfUtils.py.

520def unpackDBRelease(tarball, dbversion=None):
521 if dbversion is None:
522 dbdMatch = re.match(r'DBRelease-([\d\.]+)\.tar\.gz', path.basename(tarball))
523 if dbdMatch is None:
524 raise trfExceptions.TransformSetupException(trfExit.nameToCode('TRF_DBRELEASE_PROBLEM'),
525 'Could not find a valid version in the DBRelease tarball: {0}'.format(tarball))
526 dbversion = dbdMatch.group(1)
527 dbsetup = path.abspath(path.join("DBRelease", dbversion, "setup.py"))
528 if os.access(dbsetup, os.R_OK):
529 msg.debug('DBRelease {0} is already unpacked, found {1}'.format(tarball, dbsetup))
530 return False, dbsetup
531 else:
532 msg.debug('Will attempt to unpack DBRelease {0}'.format(tarball))
533 unpackTarFile(tarball)
534 msg.info('DBRelease {0} was unpacked'.format(tarball))
535 if not os.access(dbsetup, os.R_OK):
536 raise trfExceptions.TransformSetupException(trfExit.nameToCode('TRF_DBRELEASE_PROBLEM'),
537 'DBRelease setup file {0} was not readable, even after unpacking {1}'.format(dbsetup, tarball))
538 return True, dbsetup
539

◆ unpackTarFile()

python.trfUtils.unpackTarFile ( filename,
directory = "." )

Unpack a given tarfile.

Parameters
filenameTar file to unpck
directoryDirectory target for the unpacking

Definition at line 501 of file trfUtils.py.

501def unpackTarFile(filename, directory="."):
502 try:
503 tar = tarfile.open(filename)
504 tar.extractall(path=directory)
505 tar.close()
506 except Exception as e:
507 errMsg = 'Error encountered while unpacking {0} to {1}: {2}'.format(filename, directory, e)
508 msg.error(errMsg)
509 raise trfExceptions.TransformSetupException(trfExit.nameToCode('TRF_SETUP'), errMsg)
510
511

◆ ValgrindCommand()

python.trfUtils.ValgrindCommand ( defaultOptions = True,
extraOptionsList = None,
AthenaSerialisedConfigurationFile = "athenaConf.pkl",
returnFormat = "string" )

Definition at line 1577 of file trfUtils.py.

1582 ):
1583
1584 # Access Valgrind suppressions files by finding the paths from
1585 # environment variables. Append the files to the Valgrind suppressions
1586 # options.
1587 suppressionFilesAndCorrespondingPathEnvironmentVariables = {
1588 "etc/valgrind-root.supp": "ROOTSYS",
1589 "Gaudi.supp": "DATAPATH",
1590 "oracleDB.supp": "DATAPATH",
1591 "valgrindRTT.supp": "DATAPATH",
1592 "root.supp": "DATAPATH"
1593 }
1594 optionsList = ["valgrind"]
1595 # If default options are not suppressed, use them.
1596 if defaultOptions:
1597 optionsList.append("--num-callers=30")
1598 optionsList.append("--tool=memcheck")
1599 optionsList.append("--leak-check=full")
1600 optionsList.append("--smc-check=all")
1601 # If extra options are specified, append them to the existing options.
1602 if extraOptionsList:
1603 for option in extraOptionsList:
1604 optionsList.append(option)
1605 # Add suppression files and athena commands
1606 for suppressionFile, pathEnvironmentVariable in suppressionFilesAndCorrespondingPathEnvironmentVariables.items():
1607 suppFile = findFile(os.environ[pathEnvironmentVariable], suppressionFile)
1608 if suppFile:
1609 optionsList.append("--suppressions=" + suppFile)
1610 else:
1611 msg.warning("Bad path to suppression file: {sfile}, {path} not defined".format(
1612 sfile = suppressionFile, path = pathEnvironmentVariable)
1613 )
1614 optionsList.append("$(which python)")
1615 optionsList.append("$(which athena.py)")
1616 optionsList.append(AthenaSerialisedConfigurationFile)
1617 # Return the command in the requested format, string (by default) or list.
1618 if returnFormat is None or returnFormat == "string":
1619 return(" ".join(optionsList))
1620 elif returnFormat == "list":
1621 return(optionsList)
1622 else:
1623 print(
1624 "error: invalid Valgrind command format request (requested " +
1625 "format: {format}; valid formats: string, list)".format(
1626 format = returnFormat
1627 ))
1628 raise(Exception)
1629

◆ VTuneCommand()

python.trfUtils.VTuneCommand ( defaultOptions = True,
extraOptionsList = None,
AthenaCommand = ["athena.py", "athenaConf.pkl"],
returnFormat = "string" )

return VTune command @detail This function returns a VTune command for use with Athena.

The command is returned as a string (by default) or a list, as requested using the argument returnFormat. The function will return a default VTune command specification, unless the user suppress them through an option. To append additional options to the command specification the argument extraOptionsList is used. This causes the list of extra specified command options to be appended to the command specification, which will contain the default options unless these are suppressed. The Athena serialised configuration file is specified using the argument AthenaSerialisedConfigurationFile.

Returns
command as string

Definition at line 1643 of file trfUtils.py.

1648 ):
1649
1650 # Access VTune suppressions files by finding the paths from
1651 # environment variables. Append the files to the VTune suppressions
1652 # options.
1653 # setsid prevents vtune killing the entire job / terminal session when it finishes
1654 optionsList = ["setsid", "vtune"]
1655 # If default options are not suppressed, use them.
1656 if defaultOptions:
1657 optionsList.append("-run-pass-thru=--no-altstack")
1658 optionsList.append("-mrte-mode=native")
1659 # If extra options are specified, append them to the existing options.
1660 isCollectSpecified=False
1661 if extraOptionsList:
1662 for option in extraOptionsList:
1663 optionsList.append(option)
1664 if option.startswith("-collect="):
1665 isCollectSpecified=True
1666 if not isCollectSpecified:
1667 optionsList.append("-collect=hotspots")
1668 optionsList.append("--")
1669 optionsList.extend(AthenaCommand)
1670 # Return the command in the requested format, string (by default) or list.
1671 if returnFormat is None or returnFormat == "string":
1672 return(" ".join(optionsList))
1673 elif returnFormat == "list":
1674 return(optionsList)
1675 else:
1676 print(
1677 "error: invalid VTune command format request (requested " +
1678 "format: {format}; valid formats: string, list)".format(
1679 format = returnFormat
1680 ))
1681 raise(Exception)
1682
1683# calculate cpuTime from os.times() times tuple

Variable Documentation

◆ msg

python.trfUtils.msg = logging.getLogger(__name__)

Definition at line 31 of file trfUtils.py.