Skip to content

Commit 85401af

Browse files
committed
[roottest] Precompile regexes in custom_diff.py.
Instead of specifying regexes lazily inside the line filter loop, precompile them by instantiating a filter class. In this way, adding a new filter or replacement can be done by adding a single line, and the regexes run a tiny bit faster.
1 parent 88f5555 commit 85401af

File tree

1 file changed

+62
-49
lines changed

1 file changed

+62
-49
lines changed

roottest/scripts/custom_diff.py

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -13,55 +13,67 @@
1313
import sys
1414
import time
1515

16+
1617
#---------------------------------------------------------------------------------------------------------------------------
1718
#---Filter and substitutions------------------------------------------------------------------------------------------------
19+
class LineFilter:
20+
"""A line filter to suppress lines in the diff.
21+
self.skip_regexes contains patterns to skip entirely.
22+
self.substitutions contains patterns to replace with the given strings.
23+
These patterns only need to be compiled once for all the incoming lines.
24+
"""
1825

19-
def filter(lines, ignoreWhiteSpace = False):
20-
outlines = []
21-
for line in lines:
22-
if sys.platform == 'win32':
23-
if 'Creating library ' in line:
24-
continue
25-
if '_ACLiC_dict' in line:
26-
continue
27-
if 'Warning in <TInterpreter::ReadRootmapFile>:' in line:
28-
continue
29-
if 'Warning in <TClassTable::Add>:' in line:
30-
continue
31-
if 'Error: Removing ' in line:
26+
def __init__(self):
27+
# Skip these lines
28+
self.skip_regexes = [re.compile(pattern) for pattern in [
29+
r'^Processing ', # Interpreted macros
30+
r'^Info in <\w+::ACLiC>: creating shared library', # Compiled macros
31+
r'^In file included from input_line', # Wrapper input line
32+
r'^[:space:]*$', # Lines which are empty apart from spaces
33+
]]
34+
35+
# Replace these patterns in all lines
36+
self.substitutions = [
37+
(re.compile(r'[ ]@0x[a-fA-F0-9]+'), ''), # Remove pointers from output
38+
(re.compile(r'std::__[0-9]+::'), 'std::'), # Canonicalise standard namespaces
39+
(re.compile(r'^(\S*/|)([^:/]+)[-:0-9]*(?=: error:)'), r'\2'), # Trim file paths and line numbers from lines with ": error:"
40+
(re.compile(r'(input_line_|ROOT_prompt_)[0-9]+'), r'\1--'), # Canonicalise input_line_123, ROOT_prompt_345
41+
]
42+
43+
def filter(self, lines, ignoreWhiteSpace = False):
44+
outlines = []
45+
for line in lines:
46+
if sys.platform == 'win32':
47+
if 'Creating library ' in line:
48+
continue
49+
if '_ACLiC_dict' in line:
50+
continue
51+
if 'Warning in <TInterpreter::ReadRootmapFile>:' in line:
52+
continue
53+
if 'Warning in <TClassTable::Add>:' in line:
54+
continue
55+
if 'Error: Removing ' in line:
56+
continue
57+
if ' -nologo -TP -c -nologo -I' in line:
58+
continue
59+
if 'rootcling -v1 -f ' in line:
60+
continue
61+
if 'No precompiled header available' in line:
62+
continue
63+
64+
#---Skip all lines matching predefined expressions---------------------------
65+
if any(pattern.match(line) is not None for pattern in self.skip_regexes):
3266
continue
33-
if ' -nologo -TP -c -nologo -I' in line:
34-
continue
35-
if 'rootcling -v1 -f ' in line:
36-
continue
37-
if 'No precompiled header available' in line:
38-
continue
39-
#if line in ['\n', '\r\n']:
40-
# continue
41-
#---Processing line from interpreter (root.exe)------------------------------
42-
if re.match(r'^Processing ', line):
43-
continue
44-
#---ACLiC info---------------------------------------------------------------
45-
if re.match(r'^Info in <\w+::ACLiC>: creating shared library', line):
46-
continue
47-
#---Compilation error--------------------------------------------------------
48-
elif re.search(r': error:', line):
49-
nline = re.sub(r'\S+/', '', line)
50-
nline = re.sub(r'(:|_)[0-9]+(?=:)', ':--', nline)
51-
#---Wrapper input line-------------------------------------------------------
52-
elif re.match(r'^In file included from input_line', line):
53-
continue
54-
else:
55-
nline = line
56-
#---Remove Addresses in cling/cint-------------------------------------------
57-
nline = re.sub(r'[ ]@0x[a-fA-F0-9]+', '', nline)
58-
#---Remove versioning in std-------------------------------------------------
59-
nline = re.sub(r'std::__[0-9]::', 'std::', nline)
60-
#---Remove white spaces------------------------------------------------------
61-
if (ignoreWhiteSpace):
62-
nline = re.sub(r'[ ]', '', nline)
63-
outlines.append(nline)
64-
return outlines
67+
68+
#---Apply predefined replacements--------------------------------------------
69+
for pattern, replacement in self.substitutions:
70+
line = pattern.sub(replacement, line)
71+
72+
#---Remove white spaces------------------------------------------------------
73+
if (ignoreWhiteSpace):
74+
line = re.sub(r'[ ]', '', line)
75+
outlines.append(line)
76+
return outlines
6577

6678
#-----------------------------------------------------------------------------------------------------------------------------
6779
def main():
@@ -92,17 +104,18 @@ def main():
92104
fromlines = open(fromfile, 'r' if sys.version_info >= (3, 4) else 'U').readlines()
93105
tolines = open(tofile, 'r' if sys.version_info >= (3, 4) else 'U').readlines()
94106

95-
nows_fromlines = filter(fromlines, True)
96-
nows_tolines = filter(tolines, True)
107+
lineFilter = LineFilter()
108+
nows_fromlines = lineFilter.filter(fromlines, True)
109+
nows_tolines = lineFilter.filter(tolines, True)
97110

98111
check = difflib.context_diff(nows_fromlines, nows_tolines)
99112
try:
100113
_ = next(check)
101114
except StopIteration:
102115
sys.exit(0)
103116

104-
fromlines = filter(fromlines, False)
105-
tolines = filter(tolines, False)
117+
fromlines = lineFilter.filter(fromlines, False)
118+
tolines = lineFilter.filter(tolines, False)
106119

107120
if options.u:
108121
diff = difflib.unified_diff(fromlines, tolines, fromfile, tofile, fromdate, todate, n=n)

0 commit comments

Comments
 (0)