Skip to content

Commit 1265ec5

Browse files
committed
bump libregrtest
Signed-off-by: Ashwin Naren <arihant2math@gmail.com>
1 parent 55b066d commit 1265ec5

27 files changed

+4376
-1558
lines changed

Lib/test/libregrtest/__init__.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +0,0 @@
1-
# We import importlib *ASAP* in order to test #15386
2-
import importlib
3-
4-
from test.libregrtest.cmdline import _parse_args, RESOURCE_NAMES, ALL_RESOURCES
5-
from test.libregrtest.main import main

Lib/test/libregrtest/cmdline.py

Lines changed: 205 additions & 56 deletions
Large diffs are not rendered by default.

Lib/test/libregrtest/filter.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import itertools
2+
import operator
3+
import re
4+
5+
6+
# By default, don't filter tests
7+
_test_matchers = ()
8+
_test_patterns = ()
9+
10+
11+
def match_test(test):
12+
# Function used by support.run_unittest() and regrtest --list-cases
13+
result = False
14+
for matcher, result in reversed(_test_matchers):
15+
if matcher(test.id()):
16+
return result
17+
return not result
18+
19+
20+
def _is_full_match_test(pattern):
21+
# If a pattern contains at least one dot, it's considered
22+
# as a full test identifier.
23+
# Example: 'test.test_os.FileTests.test_access'.
24+
#
25+
# ignore patterns which contain fnmatch patterns: '*', '?', '[...]'
26+
# or '[!...]'. For example, ignore 'test_access*'.
27+
return ('.' in pattern) and (not re.search(r'[?*\[\]]', pattern))
28+
29+
30+
def get_match_tests():
31+
global _test_patterns
32+
return _test_patterns
33+
34+
35+
def set_match_tests(patterns):
36+
global _test_matchers, _test_patterns
37+
38+
if not patterns:
39+
_test_matchers = ()
40+
_test_patterns = ()
41+
else:
42+
itemgetter = operator.itemgetter
43+
patterns = tuple(patterns)
44+
if patterns != _test_patterns:
45+
_test_matchers = [
46+
(_compile_match_function(map(itemgetter(0), it)), result)
47+
for result, it in itertools.groupby(patterns, itemgetter(1))
48+
]
49+
_test_patterns = patterns
50+
51+
52+
def _compile_match_function(patterns):
53+
patterns = list(patterns)
54+
55+
if all(map(_is_full_match_test, patterns)):
56+
# Simple case: all patterns are full test identifier.
57+
# The test.bisect_cmd utility only uses such full test identifiers.
58+
return set(patterns).__contains__
59+
else:
60+
import fnmatch
61+
regex = '|'.join(map(fnmatch.translate, patterns))
62+
# The search *is* case sensitive on purpose:
63+
# don't use flags=re.IGNORECASE
64+
regex_match = re.compile(regex).match
65+
66+
def match_test_regex(test_id, regex_match=regex_match):
67+
if regex_match(test_id):
68+
# The regex matches the whole identifier, for example
69+
# 'test.test_os.FileTests.test_access'.
70+
return True
71+
else:
72+
# Try to match parts of the test identifier.
73+
# For example, split 'test.test_os.FileTests.test_access'
74+
# into: 'test', 'test_os', 'FileTests' and 'test_access'.
75+
return any(map(regex_match, test_id.split(".")))
76+
77+
return match_test_regex

Lib/test/libregrtest/findtests.py

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import os
2+
import sys
3+
import unittest
4+
from collections.abc import Container
5+
6+
from test import support
7+
8+
from .filter import match_test, set_match_tests
9+
from .utils import (
10+
StrPath, TestName, TestTuple, TestList, TestFilter,
11+
abs_module_name, count, printlist)
12+
13+
14+
# If these test directories are encountered recurse into them and treat each
15+
# "test_*.py" file or each sub-directory as a separate test module. This can
16+
# increase parallelism.
17+
#
18+
# Beware this can't generally be done for any directory with sub-tests as the
19+
# __init__.py may do things which alter what tests are to be run.
20+
SPLITTESTDIRS: set[TestName] = {
21+
"test_asyncio",
22+
"test_concurrent_futures",
23+
"test_doctests",
24+
"test_future_stmt",
25+
"test_gdb",
26+
"test_inspect",
27+
"test_pydoc",
28+
"test_multiprocessing_fork",
29+
"test_multiprocessing_forkserver",
30+
"test_multiprocessing_spawn",
31+
}
32+
33+
34+
def findtestdir(path: StrPath | None = None) -> StrPath:
35+
return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir
36+
37+
38+
def findtests(*, testdir: StrPath | None = None, exclude: Container[str] = (),
39+
split_test_dirs: set[TestName] = SPLITTESTDIRS,
40+
base_mod: str = "") -> TestList:
41+
"""Return a list of all applicable test modules."""
42+
testdir = findtestdir(testdir)
43+
tests = []
44+
for name in os.listdir(testdir):
45+
mod, ext = os.path.splitext(name)
46+
if (not mod.startswith("test_")) or (mod in exclude):
47+
continue
48+
if base_mod:
49+
fullname = f"{base_mod}.{mod}"
50+
else:
51+
fullname = mod
52+
if fullname in split_test_dirs:
53+
subdir = os.path.join(testdir, mod)
54+
if not base_mod:
55+
fullname = f"test.{mod}"
56+
tests.extend(findtests(testdir=subdir, exclude=exclude,
57+
split_test_dirs=split_test_dirs,
58+
base_mod=fullname))
59+
elif ext in (".py", ""):
60+
tests.append(fullname)
61+
return sorted(tests)
62+
63+
64+
def split_test_packages(tests, *, testdir: StrPath | None = None,
65+
exclude: Container[str] = (),
66+
split_test_dirs=SPLITTESTDIRS) -> list[TestName]:
67+
testdir = findtestdir(testdir)
68+
splitted = []
69+
for name in tests:
70+
if name in split_test_dirs:
71+
subdir = os.path.join(testdir, name)
72+
splitted.extend(findtests(testdir=subdir, exclude=exclude,
73+
split_test_dirs=split_test_dirs,
74+
base_mod=name))
75+
else:
76+
splitted.append(name)
77+
return splitted
78+
79+
80+
def _list_cases(suite: unittest.TestSuite) -> None:
81+
for test in suite:
82+
if isinstance(test, unittest.loader._FailedTest): # type: ignore[attr-defined]
83+
continue
84+
if isinstance(test, unittest.TestSuite):
85+
_list_cases(test)
86+
elif isinstance(test, unittest.TestCase):
87+
if match_test(test):
88+
print(test.id())
89+
90+
def list_cases(tests: TestTuple, *,
91+
match_tests: TestFilter | None = None,
92+
test_dir: StrPath | None = None) -> None:
93+
support.verbose = False
94+
set_match_tests(match_tests)
95+
96+
skipped = []
97+
for test_name in tests:
98+
module_name = abs_module_name(test_name, test_dir)
99+
try:
100+
suite = unittest.defaultTestLoader.loadTestsFromName(module_name)
101+
_list_cases(suite)
102+
except unittest.SkipTest:
103+
skipped.append(test_name)
104+
105+
if skipped:
106+
sys.stdout.flush()
107+
stderr = sys.stderr
108+
print(file=stderr)
109+
print(count(len(skipped), "test"), "skipped:", file=stderr)
110+
printlist(skipped, file=stderr)

Lib/test/libregrtest/logger.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import os
2+
import time
3+
4+
from test.support import MS_WINDOWS
5+
from .results import TestResults
6+
from .runtests import RunTests
7+
from .utils import print_warning
8+
9+
if MS_WINDOWS:
10+
from .win_utils import WindowsLoadTracker
11+
12+
13+
class Logger:
14+
def __init__(self, results: TestResults, quiet: bool, pgo: bool):
15+
self.start_time = time.perf_counter()
16+
self.test_count_text = ''
17+
self.test_count_width = 3
18+
self.win_load_tracker: WindowsLoadTracker | None = None
19+
self._results: TestResults = results
20+
self._quiet: bool = quiet
21+
self._pgo: bool = pgo
22+
23+
def log(self, line: str = '') -> None:
24+
empty = not line
25+
26+
# add the system load prefix: "load avg: 1.80 "
27+
load_avg = self.get_load_avg()
28+
if load_avg is not None:
29+
line = f"load avg: {load_avg:.2f} {line}"
30+
31+
# add the timestamp prefix: "0:01:05 "
32+
log_time = time.perf_counter() - self.start_time
33+
34+
mins, secs = divmod(int(log_time), 60)
35+
hours, mins = divmod(mins, 60)
36+
formatted_log_time = "%d:%02d:%02d" % (hours, mins, secs)
37+
38+
line = f"{formatted_log_time} {line}"
39+
if empty:
40+
line = line[:-1]
41+
42+
print(line, flush=True)
43+
44+
def get_load_avg(self) -> float | None:
45+
if hasattr(os, 'getloadavg'):
46+
try:
47+
return os.getloadavg()[0]
48+
except OSError:
49+
pass
50+
if self.win_load_tracker is not None:
51+
return self.win_load_tracker.getloadavg()
52+
return None
53+
54+
def display_progress(self, test_index: int, text: str) -> None:
55+
if self._quiet:
56+
return
57+
results = self._results
58+
59+
# "[ 51/405/1] test_tcl passed"
60+
line = f"{test_index:{self.test_count_width}}{self.test_count_text}"
61+
fails = len(results.bad) + len(results.env_changed)
62+
if fails and not self._pgo:
63+
line = f"{line}/{fails}"
64+
self.log(f"[{line}] {text}")
65+
66+
def set_tests(self, runtests: RunTests) -> None:
67+
if runtests.forever:
68+
self.test_count_text = ''
69+
self.test_count_width = 3
70+
else:
71+
self.test_count_text = '/{}'.format(len(runtests.tests))
72+
self.test_count_width = len(self.test_count_text) - 1
73+
74+
def start_load_tracker(self) -> None:
75+
if not MS_WINDOWS:
76+
return
77+
78+
try:
79+
self.win_load_tracker = WindowsLoadTracker()
80+
except PermissionError as error:
81+
# Standard accounts may not have access to the performance
82+
# counters.
83+
print_warning(f'Failed to create WindowsLoadTracker: {error}')
84+
85+
def stop_load_tracker(self) -> None:
86+
if self.win_load_tracker is None:
87+
return
88+
self.win_load_tracker.close()
89+
self.win_load_tracker = None

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy