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 305 of file trfUtils.py.

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

◆ asetupReport()

python.trfUtils.asetupReport ( )

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

Definition at line 225 of file trfUtils.py.

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

◆ bind_port()

python.trfUtils.bind_port ( host,
port )

Definition at line 1710 of file trfUtils.py.

1710def bind_port(host, port):
1711 ret = 0
1712 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
1713 try:
1714 s.bind((host, port))
1715 except socket.error as e:
1716 if e.errno == 98:
1717 print("Port %s is already in use" %port)
1718 else:
1719 # something else raised the socket.error exception
1720 print(e)
1721 ret=1
1722 s.close()
1723 return ret
1724
void print(char *figname, TCanvas *c1)

◆ calcCpuTime()

python.trfUtils.calcCpuTime ( start,
stop )

Definition at line 1695 of file trfUtils.py.

1695def calcCpuTime(start, stop):
1696 cpuTime = None
1697 if start and stop:
1698 cpuTime = reduce(lambda x1, x2: x1+x2, list(map(lambda x1, x2: x2-x1, start[2:4], stop[2:4])))
1699
1700 return cpuTime
1701
1702# 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:40
STL class.

◆ calcWallTime()

python.trfUtils.calcWallTime ( start,
stop )

Definition at line 1703 of file trfUtils.py.

1703def calcWallTime(start, stop):
1704 wallTime = None
1705 if start and stop:
1706 wallTime = stop[4] - start[4]
1707
1708 return wallTime
1709

◆ 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 157 of file trfUtils.py.

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

◆ cliToKey()

python.trfUtils.cliToKey ( option)

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

Definition at line 654 of file trfUtils.py.

654def cliToKey(option):
655 return option.lstrip('-').replace('-', '_')
656
657
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 466 of file trfUtils.py.

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

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

◆ 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 571 of file trfUtils.py.

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

◆ 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 39 of file trfUtils.py.

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

◆ 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 445 of file trfUtils.py.

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

◆ 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 64 of file trfUtils.py.

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

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

◆ initialise_processes()

python.trfUtils.initialise_processes ( )

initisation procedure for processes of process pool

Definition at line 857 of file trfUtils.py.

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

◆ isInteractiveEnv()

python.trfUtils.isInteractiveEnv ( )

Definition at line 705 of file trfUtils.py.

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

◆ isodate()

python.trfUtils.isodate ( )

Return isoformated 'now' string.

Uses datetime.isoformat method, but suppressing microseconds

Definition at line 436 of file trfUtils.py.

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

◆ JSONDump()

python.trfUtils.JSONDump ( argdict)

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

Definition at line 619 of file trfUtils.py.

619def JSONDump(argdict):
620 if 'dumpJSON' not in argdict:
621 return
622
623 from PyJobTransforms.trfArgClasses import argument
624 theArgumentDictionary = {}
625 for k, v in argdict.items():
626 if k == 'dumpJSON':
627 continue
628 if isinstance(v, argument):
629 theArgumentDictionary[k] = getattr(v, "dumpvalue", v.value)
630 else:
631 theArgumentDictionary[k] = v
632 with open(argdict['dumpJSON'], 'w') as JSONFile:
633 import json
634 json.dump(theArgumentDictionary, JSONFile, sort_keys=True, indent=2)
635
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 374 of file trfUtils.py.

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

◆ 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 111 of file trfUtils.py.

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

◆ 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 600 of file trfUtils.py.

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

◆ 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 399 of file trfUtils.py.

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

◆ 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 662 of file trfUtils.py.

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

◆ 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 263 of file trfUtils.py.

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

◆ 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 1728 of file trfUtils.py.

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

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

◆ 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 363 of file trfUtils.py.

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

◆ 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 680 of file trfUtils.py.

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

◆ 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 693 of file trfUtils.py.

697 ):
698 if quantity == 1:
699 return unitSingular
700 else:
701 return unitPlural
702
703
704# @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 522 of file trfUtils.py.

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

◆ unpackTarFile()

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

Unpack a given tarfile.

Parameters
filenameTar file to unpck
directoryDirectory target for the unpacking

Definition at line 503 of file trfUtils.py.

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

◆ ValgrindCommand()

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

Definition at line 1588 of file trfUtils.py.

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

◆ 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 1654 of file trfUtils.py.

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

Variable Documentation

◆ msg

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

Definition at line 33 of file trfUtils.py.