Skip to content

Commit 9a111d5

Browse files
committed
[3.12] pythongh-109413: Add more type hints to libregrtest (pythonGH-126352)
(cherry picked from commit bfc1d25) Co-authored-by: sobolevn <mail@sobolevn.me>
1 parent 70f777d commit 9a111d5

13 files changed

Lines changed: 78 additions & 65 deletions

File tree

Lib/test/libregrtest/findtests.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22
import sys
33
import unittest
4+
from collections.abc import Container
45

56
from test import support
67

@@ -34,7 +35,7 @@ def findtestdir(path: StrPath | None = None) -> StrPath:
3435
return path or os.path.dirname(os.path.dirname(__file__)) or os.curdir
3536

3637

37-
def findtests(*, testdir: StrPath | None = None, exclude=(),
38+
def findtests(*, testdir: StrPath | None = None, exclude: Container[str] = (),
3839
split_test_dirs: set[TestName] = SPLITTESTDIRS,
3940
base_mod: str = "") -> TestList:
4041
"""Return a list of all applicable test modules."""
@@ -60,8 +61,9 @@ def findtests(*, testdir: StrPath | None = None, exclude=(),
6061
return sorted(tests)
6162

6263

63-
def split_test_packages(tests, *, testdir: StrPath | None = None, exclude=(),
64-
split_test_dirs=SPLITTESTDIRS):
64+
def split_test_packages(tests, *, testdir: StrPath | None = None,
65+
exclude: Container[str] = (),
66+
split_test_dirs=SPLITTESTDIRS) -> list[TestName]:
6567
testdir = findtestdir(testdir)
6668
splitted = []
6769
for name in tests:
@@ -75,9 +77,9 @@ def split_test_packages(tests, *, testdir: StrPath | None = None, exclude=(),
7577
return splitted
7678

7779

78-
def _list_cases(suite):
80+
def _list_cases(suite: unittest.TestSuite) -> None:
7981
for test in suite:
80-
if isinstance(test, unittest.loader._FailedTest):
82+
if isinstance(test, unittest.loader._FailedTest): # type: ignore[attr-defined]
8183
continue
8284
if isinstance(test, unittest.TestSuite):
8385
_list_cases(test)
@@ -87,7 +89,7 @@ def _list_cases(suite):
8789

8890
def list_cases(tests: TestTuple, *,
8991
match_tests: TestFilter | None = None,
90-
test_dir: StrPath | None = None):
92+
test_dir: StrPath | None = None) -> None:
9193
support.verbose = False
9294
set_match_tests(match_tests)
9395

Lib/test/libregrtest/main.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import sys
66
import sysconfig
77
import time
8+
from typing import NoReturn
89

910
from test.support import os_helper, MS_WINDOWS, flush_std_streams
1011

@@ -152,7 +153,7 @@ def __init__(self, ns: Namespace, _add_python_opts: bool = False):
152153
self.next_single_test: TestName | None = None
153154
self.next_single_filename: StrPath | None = None
154155

155-
def log(self, line=''):
156+
def log(self, line: str = '') -> None:
156157
self.logger.log(line)
157158

158159
def find_tests(self, tests: TestList | None = None) -> tuple[TestTuple, TestList | None]:
@@ -228,11 +229,11 @@ def find_tests(self, tests: TestList | None = None) -> tuple[TestTuple, TestList
228229
return (tuple(selected), tests)
229230

230231
@staticmethod
231-
def list_tests(tests: TestTuple):
232+
def list_tests(tests: TestTuple) -> None:
232233
for name in tests:
233234
print(name)
234235

235-
def _rerun_failed_tests(self, runtests: RunTests):
236+
def _rerun_failed_tests(self, runtests: RunTests) -> RunTests:
236237
# Configure the runner to re-run tests
237238
if self.num_workers == 0:
238239
# Always run tests in fresh processes to have more deterministic
@@ -257,7 +258,7 @@ def _rerun_failed_tests(self, runtests: RunTests):
257258
self._run_tests_mp(runtests, self.num_workers)
258259
return runtests
259260

260-
def rerun_failed_tests(self, runtests: RunTests):
261+
def rerun_failed_tests(self, runtests: RunTests) -> None:
261262
if self.python_cmd:
262263
# Temp patch for https://github.com/python/cpython/issues/94052
263264
self.log(
@@ -326,7 +327,7 @@ def run_bisect(self, runtests: RunTests) -> None:
326327
if not self._run_bisect(runtests, name, progress):
327328
return
328329

329-
def display_result(self, runtests):
330+
def display_result(self, runtests: RunTests) -> None:
330331
# If running the test suite for PGO then no one cares about results.
331332
if runtests.pgo:
332333
return
@@ -353,7 +354,7 @@ def run_test(self, test_name: TestName, runtests: RunTests, tracer):
353354

354355
return result
355356

356-
def run_tests_sequentially(self, runtests):
357+
def run_tests_sequentially(self, runtests: RunTests):
357358
if self.coverage:
358359
import trace
359360
tracer = trace.Trace(trace=False, count=True)
@@ -413,7 +414,7 @@ def run_tests_sequentially(self, runtests):
413414

414415
return tracer
415416

416-
def get_state(self):
417+
def get_state(self) -> str:
417418
state = self.results.get_state(self.fail_env_changed)
418419
if self.first_state:
419420
state = f'{self.first_state} then {state}'
@@ -442,7 +443,7 @@ def finalize_tests(self, tracer):
442443
if self.junit_filename:
443444
self.results.write_junit(self.junit_filename)
444445

445-
def display_summary(self):
446+
def display_summary(self) -> None:
446447
duration = time.perf_counter() - self.logger.start_time
447448
filtered = bool(self.match_tests)
448449

@@ -456,7 +457,7 @@ def display_summary(self):
456457
state = self.get_state()
457458
print(f"Result: {state}")
458459

459-
def create_run_tests(self, tests: TestTuple):
460+
def create_run_tests(self, tests: TestTuple) -> RunTests:
460461
return RunTests(
461462
tests,
462463
fail_fast=self.fail_fast,
@@ -659,9 +660,9 @@ def _execute_python(self, cmd, environ):
659660
f"Command: {cmd_text}")
660661
# continue executing main()
661662

662-
def _add_python_opts(self):
663-
python_opts = []
664-
regrtest_opts = []
663+
def _add_python_opts(self) -> None:
664+
python_opts: list[str] = []
665+
regrtest_opts: list[str] = []
665666

666667
environ, keep_environ = self._add_cross_compile_opts(regrtest_opts)
667668
if self.ci_mode:
@@ -694,7 +695,7 @@ def _init(self):
694695

695696
self.tmp_dir = get_temp_dir(self.tmp_dir)
696697

697-
def main(self, tests: TestList | None = None):
698+
def main(self, tests: TestList | None = None) -> NoReturn:
698699
if self.want_add_python_opts:
699700
self._add_python_opts()
700701

@@ -723,7 +724,7 @@ def main(self, tests: TestList | None = None):
723724
sys.exit(exitcode)
724725

725726

726-
def main(tests=None, _add_python_opts=False, **kwargs):
727+
def main(tests=None, _add_python_opts=False, **kwargs) -> NoReturn:
727728
"""Run the Python suite."""
728729
ns = _parse_args(sys.argv[1:], **kwargs)
729730
Regrtest(ns, _add_python_opts=_add_python_opts).main(tests=tests)

Lib/test/libregrtest/pgo.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
'test_xml_etree_c',
5151
]
5252

53-
def setup_pgo_tests(cmdline_args, pgo_extended: bool):
53+
def setup_pgo_tests(cmdline_args, pgo_extended: bool) -> None:
5454
if not cmdline_args and not pgo_extended:
5555
# run default set of tests for PGO training
5656
cmdline_args[:] = PGO_TESTS[:]

Lib/test/libregrtest/refleak.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def dash_R_cleanup(fs, ps, pic, zdc, abcs):
257257
sys._clear_type_cache()
258258

259259

260-
def warm_caches():
260+
def warm_caches() -> None:
261261
# char cache
262262
s = bytes(range(256))
263263
for i in range(256):

Lib/test/libregrtest/result.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ def __str__(self) -> str:
141141
case State.DID_NOT_RUN:
142142
return f"{self.test_name} ran no tests"
143143
case State.TIMEOUT:
144+
assert self.duration is not None, "self.duration is None"
144145
return f"{self.test_name} timed out ({format_duration(self.duration)})"
145146
case _:
146147
raise ValueError("unknown result state: {state!r}")

Lib/test/libregrtest/results.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def get_state(self, fail_env_changed: bool) -> str:
6868

6969
return ', '.join(state)
7070

71-
def get_exitcode(self, fail_env_changed, fail_rerun):
71+
def get_exitcode(self, fail_env_changed: bool, fail_rerun: bool) -> int:
7272
exitcode = 0
7373
if self.bad:
7474
exitcode = EXITCODE_BAD_TEST
@@ -84,7 +84,7 @@ def get_exitcode(self, fail_env_changed, fail_rerun):
8484
exitcode = EXITCODE_BAD_TEST
8585
return exitcode
8686

87-
def accumulate_result(self, result: TestResult, runtests: RunTests):
87+
def accumulate_result(self, result: TestResult, runtests: RunTests) -> None:
8888
test_name = result.test_name
8989
rerun = runtests.rerun
9090
fail_env_changed = runtests.fail_env_changed
@@ -126,7 +126,7 @@ def accumulate_result(self, result: TestResult, runtests: RunTests):
126126
if xml_data:
127127
self.add_junit(xml_data)
128128

129-
def need_rerun(self):
129+
def need_rerun(self) -> bool:
130130
return bool(self.rerun_results)
131131

132132
def prepare_rerun(self, *, clear: bool = True) -> tuple[TestTuple, FilterDict]:
@@ -149,7 +149,7 @@ def prepare_rerun(self, *, clear: bool = True) -> tuple[TestTuple, FilterDict]:
149149

150150
return (tuple(tests), match_tests_dict)
151151

152-
def add_junit(self, xml_data: list[str]):
152+
def add_junit(self, xml_data: list[str]) -> None:
153153
import xml.etree.ElementTree as ET
154154
for e in xml_data:
155155
try:
@@ -158,7 +158,7 @@ def add_junit(self, xml_data: list[str]):
158158
print(xml_data, file=sys.__stderr__)
159159
raise
160160

161-
def write_junit(self, filename: StrPath):
161+
def write_junit(self, filename: StrPath) -> None:
162162
if not self.testsuite_xml:
163163
# Don't create empty XML file
164164
return
@@ -183,7 +183,7 @@ def write_junit(self, filename: StrPath):
183183
for s in ET.tostringlist(root):
184184
f.write(s)
185185

186-
def display_result(self, tests: TestTuple, quiet: bool, print_slowest: bool):
186+
def display_result(self, tests: TestTuple, quiet: bool, print_slowest: bool) -> None:
187187
if print_slowest:
188188
self.test_times.sort(reverse=True)
189189
print()
@@ -225,7 +225,7 @@ def display_result(self, tests: TestTuple, quiet: bool, print_slowest: bool):
225225
print()
226226
print("Test suite interrupted by signal SIGINT.")
227227

228-
def display_summary(self, first_runtests: RunTests, filtered: bool):
228+
def display_summary(self, first_runtests: RunTests, filtered: bool) -> None:
229229
# Total tests
230230
stats = self.stats
231231
text = f'run={stats.tests_run:,}'

Lib/test/libregrtest/runtests.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
import shlex
66
import subprocess
77
import sys
8-
from typing import Any
8+
from typing import Any, Iterator
99

1010
from test import support
1111

1212
from .utils import (
13-
StrPath, StrJSON, TestTuple, TestFilter, FilterTuple, FilterDict)
13+
StrPath, StrJSON, TestTuple, TestName, TestFilter, FilterTuple, FilterDict)
1414

1515

1616
class JsonFileType:
@@ -41,8 +41,8 @@ def configure_subprocess(self, popen_kwargs: dict) -> None:
4141
popen_kwargs['startupinfo'] = startupinfo
4242

4343
@contextlib.contextmanager
44-
def inherit_subprocess(self):
45-
if self.file_type == JsonFileType.WINDOWS_HANDLE:
44+
def inherit_subprocess(self) -> Iterator[None]:
45+
if sys.platform == 'win32' and self.file_type == JsonFileType.WINDOWS_HANDLE:
4646
os.set_handle_inheritable(self.file, True)
4747
try:
4848
yield
@@ -105,25 +105,25 @@ def copy(self, **override) -> 'RunTests':
105105
state.update(override)
106106
return RunTests(**state)
107107

108-
def create_worker_runtests(self, **override):
108+
def create_worker_runtests(self, **override) -> WorkerRunTests:
109109
state = dataclasses.asdict(self)
110110
state.update(override)
111111
return WorkerRunTests(**state)
112112

113-
def get_match_tests(self, test_name) -> FilterTuple | None:
113+
def get_match_tests(self, test_name: TestName) -> FilterTuple | None:
114114
if self.match_tests_dict is not None:
115115
return self.match_tests_dict.get(test_name, None)
116116
else:
117117
return None
118118

119-
def get_jobs(self):
119+
def get_jobs(self) -> int | None:
120120
# Number of run_single_test() calls needed to run all tests.
121121
# None means that there is not bound limit (--forever option).
122122
if self.forever:
123123
return None
124124
return len(self.tests)
125125

126-
def iter_tests(self):
126+
def iter_tests(self) -> Iterator[TestName]:
127127
if self.forever:
128128
while True:
129129
yield from self.tests

Lib/test/libregrtest/setup.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,18 @@ def setup_test_dir(testdir: str | None) -> None:
2525
sys.path.insert(0, os.path.abspath(testdir))
2626

2727

28-
def setup_process():
28+
def setup_process() -> None:
2929
fix_umask()
3030

31+
assert sys.__stderr__ is not None, "sys.__stderr__ is None"
3132
try:
3233
stderr_fd = sys.__stderr__.fileno()
3334
except (ValueError, AttributeError):
3435
# Catch ValueError to catch io.UnsupportedOperation on TextIOBase
3536
# and ValueError on a closed stream.
3637
#
3738
# Catch AttributeError for stderr being None.
38-
stderr_fd = None
39+
pass
3940
else:
4041
# Display the Python traceback on fatal errors (e.g. segfault)
4142
faulthandler.enable(all_threads=True, file=stderr_fd)
@@ -68,7 +69,7 @@ def setup_process():
6869
for index, path in enumerate(module.__path__):
6970
module.__path__[index] = os.path.abspath(path)
7071
if getattr(module, '__file__', None):
71-
module.__file__ = os.path.abspath(module.__file__)
72+
module.__file__ = os.path.abspath(module.__file__) # type: ignore[type-var]
7273

7374
if hasattr(sys, 'addaudithook'):
7475
# Add an auditing hook for all tests to ensure PySys_Audit is tested
@@ -87,7 +88,7 @@ def _test_audit_hook(name, args):
8788
os.environ.setdefault(UNICODE_GUARD_ENV, FS_NONASCII)
8889

8990

90-
def setup_tests(runtests: RunTests):
91+
def setup_tests(runtests: RunTests) -> None:
9192
support.verbose = runtests.verbose
9293
support.failfast = runtests.fail_fast
9394
support.PGO = runtests.pgo

Lib/test/libregrtest/tsan.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@
2626
]
2727

2828

29-
def setup_tsan_tests(cmdline_args):
29+
def setup_tsan_tests(cmdline_args) -> None:
3030
if not cmdline_args:
3131
cmdline_args[:] = TSAN_TESTS[:]

0 commit comments

Comments
 (0)