]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-109413: regrtest: add WorkerRunTests class (#112588)
authorVictor Stinner <vstinner@python.org>
Fri, 1 Dec 2023 13:46:50 +0000 (14:46 +0100)
committerGitHub <noreply@github.com>
Fri, 1 Dec 2023 13:46:50 +0000 (13:46 +0000)
Lib/test/libregrtest/main.py
Lib/test/libregrtest/run_workers.py
Lib/test/libregrtest/runtests.py
Lib/test/libregrtest/worker.py

index 55fc3a820d345121f16b4b172bbf4c3e5c2d72e7..16f6974ae324653f484c7be7137b7eaac97cbffa 100644 (file)
@@ -423,7 +423,6 @@ class Regrtest:
             python_cmd=self.python_cmd,
             randomize=self.randomize,
             random_seed=self.random_seed,
-            json_file=None,
         )
 
     def _run_tests(self, selected: TestTuple, tests: TestList | None) -> int:
index 35aaf90ffc42992d4575a1ac001ef135ca80e4e9..18a0342f0611cf0e285bc80bc59a7b8df7ad5344 100644 (file)
@@ -18,7 +18,7 @@ from test.support import os_helper, MS_WINDOWS
 from .logger import Logger
 from .result import TestResult, State
 from .results import TestResults
-from .runtests import RunTests, JsonFile, JsonFileType
+from .runtests import RunTests, WorkerRunTests, JsonFile, JsonFileType
 from .single import PROGRESS_MIN_TIME
 from .utils import (
     StrPath, TestName,
@@ -162,7 +162,7 @@ class WorkerThread(threading.Thread):
         self._stopped = True
         self._kill()
 
-    def _run_process(self, runtests: RunTests, output_fd: int,
+    def _run_process(self, runtests: WorkerRunTests, output_fd: int,
                      tmp_dir: StrPath | None = None) -> int | None:
         popen = create_worker_process(runtests, output_fd, tmp_dir)
         self._popen = popen
@@ -252,9 +252,7 @@ class WorkerThread(threading.Thread):
                 json_file = JsonFile(json_fd, JsonFileType.UNIX_FD)
         return (json_file, json_tmpfile)
 
-    def create_worker_runtests(self, test_name: TestName, json_file: JsonFile) -> RunTests:
-        """Create the worker RunTests."""
-
+    def create_worker_runtests(self, test_name: TestName, json_file: JsonFile) -> WorkerRunTests:
         tests = (test_name,)
         if self.runtests.rerun:
             match_tests = self.runtests.get_match_tests(test_name)
@@ -267,12 +265,12 @@ class WorkerThread(threading.Thread):
         if self.runtests.output_on_failure:
             kwargs['verbose'] = True
             kwargs['output_on_failure'] = False
-        return self.runtests.copy(
+        return self.runtests.create_worker_runtests(
             tests=tests,
             json_file=json_file,
             **kwargs)
 
-    def run_tmp_files(self, worker_runtests: RunTests,
+    def run_tmp_files(self, worker_runtests: WorkerRunTests,
                       stdout_fd: int) -> tuple[int | None, list[StrPath]]:
         # gh-93353: Check for leaked temporary files in the parent process,
         # since the deletion of temporary files can happen late during
index b765ba5b41d236d01a7128f958605b6711eb1c8c..edd72276320e4198cfe538702c793555441f2511 100644 (file)
@@ -93,13 +93,17 @@ class RunTests:
     python_cmd: tuple[str, ...] | None
     randomize: bool
     random_seed: int | str
-    json_file: JsonFile | None
 
-    def copy(self, **override):
+    def copy(self, **override) -> 'RunTests':
         state = dataclasses.asdict(self)
         state.update(override)
         return RunTests(**state)
 
+    def create_worker_runtests(self, **override):
+        state = dataclasses.asdict(self)
+        state.update(override)
+        return WorkerRunTests(**state)
+
     def get_match_tests(self, test_name) -> FilterTuple | None:
         if self.match_tests_dict is not None:
             return self.match_tests_dict.get(test_name, None)
@@ -120,13 +124,6 @@ class RunTests:
         else:
             yield from self.tests
 
-    def as_json(self) -> StrJSON:
-        return json.dumps(self, cls=_EncodeRunTests)
-
-    @staticmethod
-    def from_json(worker_json: StrJSON) -> 'RunTests':
-        return json.loads(worker_json, object_hook=_decode_runtests)
-
     def json_file_use_stdout(self) -> bool:
         # Use STDOUT in two cases:
         #
@@ -141,9 +138,21 @@ class RunTests:
         )
 
 
+@dataclasses.dataclass(slots=True, frozen=True)
+class WorkerRunTests(RunTests):
+    json_file: JsonFile
+
+    def as_json(self) -> StrJSON:
+        return json.dumps(self, cls=_EncodeRunTests)
+
+    @staticmethod
+    def from_json(worker_json: StrJSON) -> 'WorkerRunTests':
+        return json.loads(worker_json, object_hook=_decode_runtests)
+
+
 class _EncodeRunTests(json.JSONEncoder):
     def default(self, o: Any) -> dict[str, Any]:
-        if isinstance(o, RunTests):
+        if isinstance(o, WorkerRunTests):
             result = dataclasses.asdict(o)
             result["__runtests__"] = True
             return result
@@ -158,6 +167,6 @@ def _decode_runtests(data: dict[str, Any]) -> RunTests | dict[str, Any]:
             data['hunt_refleak'] = HuntRefleak(**data['hunt_refleak'])
         if data['json_file']:
             data['json_file'] = JsonFile(**data['json_file'])
-        return RunTests(**data)
+        return WorkerRunTests(**data)
     else:
         return data
index b3bb0b7f34a060dd98f805c013db2e00c1a32a35..7a6d33d4499943e0353e12dd6643afff18a6846a 100644 (file)
@@ -7,7 +7,7 @@ from test import support
 from test.support import os_helper, Py_DEBUG
 
 from .setup import setup_process, setup_test_dir
-from .runtests import RunTests, JsonFile, JsonFileType
+from .runtests import WorkerRunTests, JsonFile, JsonFileType
 from .single import run_single_test
 from .utils import (
     StrPath, StrJSON, TestFilter,
@@ -17,7 +17,7 @@ from .utils import (
 USE_PROCESS_GROUP = (hasattr(os, "setsid") and hasattr(os, "killpg"))
 
 
-def create_worker_process(runtests: RunTests, output_fd: int,
+def create_worker_process(runtests: WorkerRunTests, output_fd: int,
                           tmp_dir: StrPath | None = None) -> subprocess.Popen:
     python_cmd = runtests.python_cmd
     worker_json = runtests.as_json()
@@ -73,7 +73,7 @@ def create_worker_process(runtests: RunTests, output_fd: int,
 
 
 def worker_process(worker_json: StrJSON) -> NoReturn:
-    runtests = RunTests.from_json(worker_json)
+    runtests = WorkerRunTests.from_json(worker_json)
     test_name = runtests.tests[0]
     match_tests: TestFilter = runtests.match_tests
     json_file: JsonFile = runtests.json_file