The Gaudi Framework  master (b9786168)
Loading...
Searching...
No Matches
preprocessors.py
Go to the documentation of this file.
11import 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
115maskPointers = RegexpReplacer("0x[0-9a-fA-F]{4,16}", "0x########")
116normalizeDate = 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)
120normalizeEOL = FilePreprocessor()
121normalizeEOL.__processLine__ = lambda line: str(line).rstrip() + "\n"
122
123skipEmptyLines = FilePreprocessor()
124# FIXME: that's ugly
125skipEmptyLines.__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
171normalizeTestSuite = maskPointers + normalizeDate
172for 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
210lineSkipper = 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
304normalizeTestSuite = (
305 lineSkipper
306 + normalizeTestSuite
307 + skipEmptyLines
308 + normalizeEOL
309 + LineSorter("Services to release : ")
310 + SortGroupOfLines(r"^\S+\s+(DEBUG|SUCCESS) Property \[\'Name\':")
311)
__init__(self, strings=[], regexps=[])
__init__(self, orig, repl="", when=None)