[3.6] bpo-31324: Optimize support._match_test() (#4523) · python/cpython@70b2f87 (original) (raw)
`@@ -281,7 +281,6 @@ def get_attribute(obj, name):
`
281
281
`# small sizes, to make sure they work.)
`
282
282
`real_max_memuse = 0
`
283
283
`failfast = False
`
284
``
`-
match_tests = None
`
285
284
``
286
285
`# _original_stdout is meant to hold stdout at the time regrtest began.
`
287
286
`# This may be "the real" stdout, or IDLE's emulation of stdout, or whatever.
`
`@@ -1897,21 +1896,67 @@ def _run_suite(suite):
`
1897
1896
`raise TestFailed(err)
`
1898
1897
``
1899
1898
``
1900
``
`-
def _match_test(test):
`
1901
``
`-
global match_tests
`
``
1899
`+
By default, don't filter tests
`
``
1900
`+
_match_test_func = None
`
``
1901
`+
_match_test_patterns = None
`
1902
1902
``
1903
``
`-
if match_tests is None:
`
``
1903
+
``
1904
`+
def match_test(test):
`
``
1905
`+
Function used by support.run_unittest() and regrtest --list-cases
`
``
1906
`+
if _match_test_func is None:
`
1904
1907
`return True
`
1905
``
`-
test_id = test.id()
`
``
1908
`+
else:
`
``
1909
`+
return _match_test_func(test.id())
`
1906
1910
``
1907
``
`-
for match_test in match_tests:
`
1908
``
`-
if fnmatch.fnmatchcase(test_id, match_test):
`
1909
``
`-
return True
`
1910
1911
``
1911
``
`-
for name in test_id.split("."):
`
1912
``
`-
if fnmatch.fnmatchcase(name, match_test):
`
``
1912
`+
def _is_full_match_test(pattern):
`
``
1913
`+
If a pattern contains at least one dot, it's considered
`
``
1914
`+
as a full test identifier.
`
``
1915
`+
Example: 'test.test_os.FileTests.test_access'.
`
``
1916
`+
`
``
1917
`+
Reject patterns which contain fnmatch patterns: '*', '?', '[...]'
`
``
1918
`+
or '[!...]'. For example, reject 'test_access*'.
`
``
1919
`+
return ('.' in pattern) and (not re.search(r'[?*[]]', pattern))
`
``
1920
+
``
1921
+
``
1922
`+
def set_match_tests(patterns):
`
``
1923
`+
global _match_test_func, _match_test_patterns
`
``
1924
+
``
1925
`+
if patterns == _match_test_patterns:
`
``
1926
`+
No change: no need to recompile patterns.
`
``
1927
`+
return
`
``
1928
+
``
1929
`+
if not patterns:
`
``
1930
`+
func = None
`
``
1931
`+
set_match_tests(None) behaves as set_match_tests(())
`
``
1932
`+
patterns = ()
`
``
1933
`+
elif all(map(_is_full_match_test, patterns)):
`
``
1934
`+
Simple case: all patterns are full test identifier.
`
``
1935
`+
The test.bisect utility only uses such full test identifiers.
`
``
1936
`+
func = set(patterns).contains
`
``
1937
`+
else:
`
``
1938
`+
regex = '|'.join(map(fnmatch.translate, patterns))
`
``
1939
`+
The search is case sensitive on purpose:
`
``
1940
`+
don't use flags=re.IGNORECASE
`
``
1941
`+
regex_match = re.compile(regex).match
`
``
1942
+
``
1943
`+
def match_test_regex(test_id):
`
``
1944
`+
if regex_match(test_id):
`
``
1945
`+
The regex matchs the whole identifier like
`
``
1946
`+
'test.test_os.FileTests.test_access'
`
1913
1947
`return True
`
1914
``
`-
return False
`
``
1948
`+
else:
`
``
1949
`+
Try to match parts of the test identifier.
`
``
1950
`+
For example, split 'test.test_os.FileTests.test_access'
`
``
1951
`+
into: 'test', 'test_os', 'FileTests' and 'test_access'.
`
``
1952
`+
return any(map(regex_match, test_id.split(".")))
`
``
1953
+
``
1954
`+
func = match_test_regex
`
``
1955
+
``
1956
`+
Create a copy since patterns can be mutable and so modified later
`
``
1957
`+
_match_test_patterns = tuple(patterns)
`
``
1958
`+
_match_test_func = func
`
``
1959
+
1915
1960
``
1916
1961
``
1917
1962
`def run_unittest(*classes):
`
`@@ -1928,7 +1973,7 @@ def run_unittest(*classes):
`
1928
1973
`suite.addTest(cls)
`
1929
1974
`else:
`
1930
1975
`suite.addTest(unittest.makeSuite(cls))
`
1931
``
`-
_filter_suite(suite, _match_test)
`
``
1976
`+
_filter_suite(suite, match_test)
`
1932
1977
`_run_suite(suite)
`
1933
1978
``
1934
1979
`#=======================================================================
`