The Gaudi Framework  master (37c0b60a)
preprocessors.py
Go to the documentation of this file.
1 
11 import re
12 
13 
15  """Base class for a callable that takes a file and returns a modified
16  version of it."""
17 
18  def __processLine__(self, line):
19  return line
20 
21  def __processFile__(self, lines):
22  output = []
23  for l in lines:
24  l = self.__processLine__(l)
25  if l:
26  output.append(l)
27  return output
28 
29  def __call__(self, input):
30  if not isinstance(input, str):
31  lines = input
32  mergeback = False
33  else:
34  lines = input.splitlines()
35  mergeback = True
36  output = self.__processFile__(lines)
37  if mergeback:
38  output = "\n".join(output)
39  return output
40 
41  def __add__(self, rhs):
42  return FilePreprocessorSequence([self, rhs])
43 
44 
46  def __init__(self, members=[]):
47  self.members = members
48 
49  def __add__(self, rhs):
50  return FilePreprocessorSequence(self.members + [rhs])
51 
52  def __call__(self, input):
53  output = input
54  for pp in self.members:
55  output = pp(output)
56  return output
57 
58 
60  def __init__(self, strings=[], regexps=[]):
61  import re
62 
63  self.strings = strings
64  self.regexps = list(map(re.compile, regexps))
65 
66  def __processLine__(self, line):
67  for s in self.strings:
68  if line.find(s) >= 0:
69  return None
70  for r in self.regexps:
71  if r.search(line):
72  return None
73  return line
74 
75 
77  def __init__(self, start, end):
78  self.start = start
79  self.end = end
80  self._skipping = False
81 
82  def __processLine__(self, line):
83  if self.start in line:
84  self._skipping = True
85  return None
86  elif self.end in line:
87  self._skipping = False
88  elif self._skipping:
89  return None
90  return line
91 
92 
94  def __init__(self, orig, repl="", when=None):
95  if when:
96  when = re.compile(when)
97  self._operations = [(when, re.compile(orig), repl)]
98 
99  def __add__(self, rhs):
100  if isinstance(rhs, RegexpReplacer):
101  res = RegexpReplacer("", "", None)
102  res._operations = self._operations + rhs._operations
103  else:
104  res = FilePreprocessor.__add__(self, rhs)
105  return res
106 
107  def __processLine__(self, line):
108  for w, o, r in self._operations:
109  if w is None or w.search(line):
110  line = o.sub(r, line)
111  return line
112 
113 
114 # Common preprocessors
115 maskPointers = RegexpReplacer("0x[0-9a-fA-F]{4,16}", "0x########")
116 normalizeDate = RegexpReplacer(
117  "[0-2]?[0-9]:[0-5][0-9]:[0-5][0-9] [0-9]{4}[-/][01][0-9][-/][0-3][0-9][ A-Z]*",
118  "00:00:00 1970-01-01",
119 )
120 normalizeEOL = FilePreprocessor()
121 normalizeEOL.__processLine__ = lambda line: str(line).rstrip() + "\n"
122 
123 skipEmptyLines = FilePreprocessor()
124 # FIXME: that's ugly
125 skipEmptyLines.__processLine__ = lambda line: (line.strip() and line) or None
126 
127 # Special preprocessor sorting the list of strings (whitespace separated)
128 # that follow a signature on a single line
129 
130 
132  def __init__(self, signature):
133  self.signature = signature
134  self.siglen = len(signature)
135 
136  def __processLine__(self, line):
137  pos = line.find(self.signature)
138  if pos >= 0:
139  line = line[: (pos + self.siglen)]
140  lst = line[(pos + self.siglen) :].split()
141  lst.sort()
142  line += " ".join(lst)
143  return line
144 
145 
147  """
148  Sort group of lines matching a regular expression
149  """
150 
151  def __init__(self, exp):
152  self.exp = exp if hasattr(exp, "match") else re.compile(exp)
153 
154  def __processFile__(self, lines):
155  match = self.exp.match
156  output = []
157  group = []
158  for l in lines:
159  if match(l):
160  group.append(l)
161  else:
162  if group:
163  group.sort()
164  output.extend(group)
165  group = []
166  output.append(l)
167  return output
168 
169 
170 # Preprocessors for GaudiTestSuite
171 normalizeTestSuite = maskPointers + normalizeDate
172 for w, o, r in [
173  ("TIMER", r"\s+[+-]?[0-9]+[0-9.e+-]*", " 0"), # Normalize time output
174  ("release all pending", r"^.*/([^/]*:.*)", r"\1"),
175  ("^#.*file", r"file '.*[/\\]([^/\\]*)$", r"file '\1"),
176  (
177  "^JobOptionsSvc.*options successfully read in from",
178  r"read in from .*[/\\]([^/\\]*)$",
179  r"file \1",
180  ), # normalize path to options
181  # Normalize UUID, except those ending with all 0s (i.e. the class IDs)
182  (
183  None,
184  r"[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}(?!-0{12})-[0-9A-Fa-f]{12}",
185  "00000000-0000-0000-0000-000000000000",
186  ),
187  # Absorb a change in ServiceLocatorHelper
188  (
189  "ServiceLocatorHelper::",
190  "ServiceLocatorHelper::(create|locate)Service",
191  "ServiceLocatorHelper::service",
192  ),
193  # Remove the leading 0 in Windows' exponential format
194  (None, r"e([-+])0([0-9][0-9])", r"e\1\2"),
195  # Output line changed in Gaudi v24
196  (None, r"Service reference count check:", r"Looping over all active services..."),
197  # Ignore count of declared properties (anyway they are all printed)
198  (
199  None,
200  r"^(.*(DEBUG|SUCCESS) List of ALL properties of .*#properties = )\d+",
201  r"\1NN",
202  ),
203  ("ApplicationMgr", r"(declareMultiSvcType|addMultiSvc): ", ""),
204  (r"Property \['Name': Value\]", r"( = '[^']+':)'(.*)'", r"\1\2"),
205  ("TimelineSvc", "to file 'TimelineFile':", "to file "),
206  ("DataObjectHandleBase", r'DataObjectHandleBase\‍("([^"]*)"\‍)', r"'\1'"),
207 ]:
208  normalizeTestSuite += RegexpReplacer(o, r, w)
209 
210 lineSkipper = LineSkipper(
211  [
212  "//GP:",
213  "JobOptionsSvc INFO # ",
214  "JobOptionsSvc WARNING # ",
215  "Time User",
216  "Welcome to",
217  "This machine has a speed",
218  "running on",
219  "ToolSvc.Sequenc... INFO",
220  "DataListenerSvc INFO XML written to file:",
221  "[INFO]",
222  "[WARNING]",
223  "DEBUG No writable file catalog found which contains FID:",
224  "DEBUG Service base class initialized successfully",
225  # changed between v20 and v21
226  "DEBUG Incident timing:",
227  # introduced with patch #3487
228  # changed the level of the message from INFO to
229  # DEBUG
230  "INFO 'CnvServices':[",
231  # message removed because could be printed in constructor
232  "DEBUG 'CnvServices':[",
233  # The signal handler complains about SIGXCPU not
234  # defined on some platforms
235  "SIGXCPU",
236  # Message removed with redesing of JobOptionsSvc
237  "ServiceLocatorHelper::service: found service JobOptionsSvc",
238  # Ignore warnings for properties case mismatch
239  "mismatching case for property name:",
240  # Message demoted to DEBUG in gaudi/Gaudi!992
241  "Histograms saving not required.",
242  # Message added in gaudi/Gaudi!577
243  "Properties are dumped into",
244  # Messages changed in gaudi/Gaudi!1426
245  "WARNING no ROOT output file name",
246  "INFO Writing ROOT histograms to:",
247  "INFO Completed update of ROOT histograms in:",
248  # absorb changes in data dependencies reports (https://gitlab.cern.ch/gaudi/Gaudi/-/merge_requests/1348)
249  "Data Deps for ",
250  "data dependencies:",
251  ],
252  regexps=[
253  r"^JobOptionsSvc INFO *$",
254  r"^# ", # Ignore python comments
255  # skip the message reporting the version of the root file
256  r"(Always|SUCCESS)\s*(Root f|[^ ]* F)ile version:",
257  r"File '.*.xml' does not exist",
258  r"INFO Refer to dataset .* by its file ID:",
259  r"INFO Referring to dataset .* by its file ID:",
260  r"INFO Disconnect from dataset",
261  r"INFO Disconnected from dataset",
262  r"INFO Disconnected data IO:",
263  r"IncidentSvc\s*(DEBUG (Adding|Removing)|VERBOSE Calling)",
264  # Ignore StatusCodeSvc related messages
265  r".*StatusCodeSvc.*",
266  r".*StatusCodeCheck.*",
267  r"Num\s*\|\s*Function\s*\|\s*Source Library",
268  r"^[-+]*\s*$",
269  # Hide the fake error message coming from POOL/ROOT (ROOT 5.21)
270  r"ERROR Failed to modify file: .* Errno=2 No such file or directory",
271  # Hide unchecked StatusCodes from dictionaries
272  r"^ +[0-9]+ \|.*ROOT",
273  r"^ +[0-9]+ \|.*\|.*Dict",
274  # Hide EventLoopMgr total timing report
275  r"EventLoopMgr.*---> Loop Finished",
276  r"HiveSlimEventLo.*---> Loop Finished",
277  # Remove ROOT TTree summary table, which changes from one version to the
278  # other
279  r"^\*.*\*$",
280  # Remove Histos Summaries
281  r"SUCCESS\s*Booked \d+ Histogram\‍(s\‍)",
282  r"^ \|",
283  r"^ ID=",
284  # Ignore added/removed properties
285  r"Property(.*)'Audit(Algorithm|Tool|Service)s':",
286  r"Property(.*)'Audit(Begin|End)Run':",
287  # these were missing in tools
288  r"Property(.*)'AuditRe(start|initialize)':",
289  r"Property(.*)'Blocking':",
290  # removed with gaudi/Gaudi!273
291  r"Property(.*)'ErrorCount(er)?':",
292  # added with gaudi/Gaudi!306
293  r"Property(.*)'Sequential':",
294  # added with gaudi/Gaudi!314
295  r"Property(.*)'FilterCircularDependencies':",
296  # removed with gaudi/Gaudi!316
297  r"Property(.*)'IsClonable':",
298  # ignore uninteresting/obsolete messages
299  r"Property update for OutputLevel : new value =",
300  r"EventLoopMgr\s*DEBUG Creating OutputStream",
301  ],
302 )
303 
304 normalizeTestSuite = (
305  lineSkipper
306  + normalizeTestSuite
307  + skipEmptyLines
308  + normalizeEOL
309  + LineSorter("Services to release : ")
310  + SortGroupOfLines(r"^\S+\s+(DEBUG|SUCCESS) Property \[\'Name\':")
311 )
GaudiTesting.preprocessors.RegexpReplacer.__init__
def __init__(self, orig, repl="", when=None)
Definition: preprocessors.py:94
GaudiTesting.preprocessors.FilePreprocessorSequence.__add__
def __add__(self, rhs)
Definition: preprocessors.py:49
GaudiTesting.preprocessors.BlockSkipper.start
start
Definition: preprocessors.py:78
GaudiTesting.preprocessors.RegexpReplacer._operations
_operations
Definition: preprocessors.py:97
GaudiTesting.preprocessors.LineSorter
Definition: preprocessors.py:131
GaudiTesting.preprocessors.FilePreprocessorSequence
Definition: preprocessors.py:45
GaudiTesting.preprocessors.LineSorter.__processLine__
def __processLine__(self, line)
Definition: preprocessors.py:136
GaudiTesting.preprocessors.RegexpReplacer
Definition: preprocessors.py:93
GaudiTesting.preprocessors.LineSkipper.__init__
def __init__(self, strings=[], regexps=[])
Definition: preprocessors.py:60
GaudiTesting.preprocessors.SortGroupOfLines.__processFile__
def __processFile__(self, lines)
Definition: preprocessors.py:154
GaudiTesting.preprocessors.RegexpReplacer.__processLine__
def __processLine__(self, line)
Definition: preprocessors.py:107
GaudiTesting.preprocessors.LineSorter.__init__
def __init__(self, signature)
Definition: preprocessors.py:132
Containers::map
struct GAUDI_API map
Parametrisation class for map-like implementation.
Definition: KeyedObjectManager.h:35
GaudiTesting.preprocessors.BlockSkipper._skipping
_skipping
Definition: preprocessors.py:80
GaudiTesting.preprocessors.LineSorter.siglen
siglen
Definition: preprocessors.py:134
GaudiTesting.preprocessors.LineSkipper.__processLine__
def __processLine__(self, line)
Definition: preprocessors.py:66
GaudiTesting.preprocessors.FilePreprocessor.__processLine__
def __processLine__(self, line)
Definition: preprocessors.py:18
GaudiTesting.preprocessors.SortGroupOfLines.exp
exp
Definition: preprocessors.py:152
GaudiTesting.preprocessors.FilePreprocessorSequence.__init__
def __init__(self, members=[])
Definition: preprocessors.py:46
GaudiTesting.preprocessors.LineSkipper.regexps
regexps
Definition: preprocessors.py:64
GaudiTesting.preprocessors.BlockSkipper.end
end
Definition: preprocessors.py:79
GaudiTesting.preprocessors.LineSkipper.strings
strings
Definition: preprocessors.py:63
GaudiTesting.preprocessors.FilePreprocessor
Definition: preprocessors.py:14
GaudiTesting.preprocessors.LineSkipper
Definition: preprocessors.py:59
GaudiTesting.preprocessors.BlockSkipper.__processLine__
def __processLine__(self, line)
Definition: preprocessors.py:82
GaudiTesting.preprocessors.FilePreprocessor.__processFile__
def __processFile__(self, lines)
Definition: preprocessors.py:21
GaudiTesting.preprocessors.BlockSkipper
Definition: preprocessors.py:76
GaudiTesting.preprocessors.FilePreprocessor.__add__
def __add__(self, rhs)
Definition: preprocessors.py:41
GaudiTesting.preprocessors.SortGroupOfLines.__init__
def __init__(self, exp)
Definition: preprocessors.py:151
GaudiTesting.preprocessors.FilePreprocessor.__call__
def __call__(self, input)
Definition: preprocessors.py:29
GaudiTesting.preprocessors.BlockSkipper.__init__
def __init__(self, start, end)
Definition: preprocessors.py:77
GaudiTesting.preprocessors.FilePreprocessorSequence.members
members
Definition: preprocessors.py:47
compareOutputFiles.pp
pp
Definition: compareOutputFiles.py:507
GaudiTesting.preprocessors.RegexpReplacer.__add__
def __add__(self, rhs)
Definition: preprocessors.py:99
GaudiTesting.preprocessors.LineSorter.signature
signature
Definition: preprocessors.py:133
GaudiTesting.preprocessors.SortGroupOfLines
Definition: preprocessors.py:146
GaudiTesting.preprocessors.FilePreprocessorSequence.__call__
def __call__(self, input)
Definition: preprocessors.py:52