[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

`#=======================================================================

`