Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2948d9c

Browse files
committed
Add JsonFile and JsonFileType classes
1 parent 7f54b9c commit 2948d9c

File tree

3 files changed

+61
-36
lines changed

3 files changed

+61
-36
lines changed

Lib/test/libregrtest/run_workers.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from .logger import Logger
1818
from .result import TestResult, State
1919
from .results import TestResults
20-
from .runtests import RunTests
20+
from .runtests import RunTests, JsonFile, JsonFileType
2121
from .single import PROGRESS_MIN_TIME
2222
from .utils import (
2323
StrPath, StrJSON, TestName, MS_WINDOWS, TMP_PREFIX,
@@ -240,11 +240,15 @@ def _runtest(self, test_name: TestName) -> MultiprocessResult:
240240
with (stdout_file, json_tmpfile):
241241
stdout_fd = stdout_file.fileno()
242242
if json_file_use_filename:
243-
json_file = json_tmpfile.name
243+
json_file = JsonFile(json_tmpfile.name, JsonFileType.FILENAME)
244244
else:
245-
json_file = json_tmpfile.fileno()
245+
json_fd = json_tmpfile.fileno()
246246
if MS_WINDOWS:
247-
json_file = msvcrt.get_osfhandle(json_file)
247+
json_handle = msvcrt.get_osfhandle(json_fd)
248+
json_file = JsonFile(json_handle, JsonFileType.WINDOWS_HANDLE)
249+
else:
250+
json_file = JsonFile(json_fd, JsonFileType.UNIX_FD)
251+
248252

249253
kwargs = {}
250254
if match_tests:

Lib/test/libregrtest/runtests.py

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import contextlib
12
import dataclasses
23
import json
34
from typing import Any
@@ -8,8 +9,50 @@
89
StrPath, StrJSON, TestTuple, FilterTuple, FilterDict)
910

1011

11-
# See RunTests.json_file_use_filename()
12-
JsonFileType = int | StrPath
12+
class JsonFileType:
13+
UNIX_FD = "UNIX_FD"
14+
WINDOWS_HANDLE = "WINDOWS_HANDLE"
15+
FILENAME = "FILENAME"
16+
17+
18+
@dataclasses.dataclass(slots=True, frozen=True)
19+
class JsonFile:
20+
# See RunTests.json_file_use_filename()
21+
file: int | StrPath
22+
file_type: str
23+
24+
def configure_subprocess(self, popen_kwargs: dict) -> None:
25+
match self.file_type:
26+
case JsonFileType.UNIX_FD:
27+
# Unix file descriptor
28+
popen_kwargs['pass_fds'] = [self.file]
29+
case JsonFileType.WINDOWS_HANDLE:
30+
# Windows handle
31+
startupinfo = subprocess.STARTUPINFO()
32+
startupinfo.lpAttributeList = {"handle_list": [self.file]}
33+
popen_kwargs['startupinfo'] = startupinfo
34+
case JsonFileType.FILENAME:
35+
# Filename: nothing to do to
36+
pass
37+
38+
@contextlib.contextmanager
39+
def inherit_subprocess(self):
40+
if self.file_type == JsonFileType.WINDOWS_HANDLE:
41+
os.set_handle_inheritable(self.file, True)
42+
try:
43+
yield
44+
finally:
45+
os.set_handle_inheritable(self.file, False)
46+
else:
47+
yield
48+
49+
def open(self, mode, *, encoding):
50+
file = self.file
51+
if self.file_type == JsonFileType.WINDOWS_HANDLE:
52+
import msvcrt
53+
# Create a file descriptor from the handle
54+
file = msvcrt.open_osfhandle(file, os.O_WRONLY)
55+
return open(file, mode, encoding=encoding)
1356

1457

1558
@dataclasses.dataclass(slots=True, frozen=True)
@@ -44,7 +87,7 @@ class RunTests:
4487
python_cmd: tuple[str] | None
4588
randomize: bool
4689
random_seed: int | None
47-
json_file: JsonFileType | None
90+
json_file: JsonFile | None
4891

4992
def copy(self, **override):
5093
state = dataclasses.asdict(self)
@@ -105,6 +148,8 @@ def _decode_runtests(data: dict[str, Any]) -> RunTests | dict[str, Any]:
105148
data.pop('__runtests__')
106149
if data['hunt_refleak']:
107150
data['hunt_refleak'] = HuntRefleak(**data['hunt_refleak'])
151+
if data['json_file']:
152+
data['json_file'] = JsonFile(**data['json_file'])
108153
return RunTests(**data)
109154
else:
110155
return data

Lib/test/libregrtest/worker.py

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from test.support import os_helper
88

99
from .setup import setup_process, setup_test_dir
10-
from .runtests import RunTests, JsonFileType
10+
from .runtests import RunTests, JsonFile
1111
from .single import run_single_test
1212
from .utils import (
1313
StrPath, StrJSON, FilterTuple, MS_WINDOWS,
@@ -57,28 +57,10 @@ def create_worker_process(runtests: RunTests, output_fd: int,
5757

5858
# Pass json_file to the worker process
5959
json_file = runtests.json_file
60-
if isinstance(json_file, str):
61-
# Filename: nothing to do to
62-
pass
63-
elif MS_WINDOWS:
64-
# Windows handle
65-
startupinfo = subprocess.STARTUPINFO()
66-
startupinfo.lpAttributeList = {"handle_list": [json_file]}
67-
kwargs['startupinfo'] = startupinfo
68-
else:
69-
# Unix file descriptor
70-
kwargs['pass_fds'] = [json_file]
71-
72-
if USE_PROCESS_GROUP:
73-
kwargs['start_new_session'] = True
60+
json_file.configure_subprocess(kwargs)
7461

75-
if MS_WINDOWS:
76-
os.set_handle_inheritable(json_file, True)
77-
try:
62+
with json_file.inherit_subprocess():
7863
return subprocess.Popen(cmd, **kwargs)
79-
finally:
80-
if MS_WINDOWS:
81-
os.set_handle_inheritable(json_file, False)
8264

8365

8466
def worker_process(worker_json: StrJSON) -> NoReturn:
@@ -89,13 +71,7 @@ def worker_process(worker_json: StrJSON) -> NoReturn:
8971
# - Unix: file descriptor (int)
9072
# - Windows: handle (int)
9173
# - Emscripten/WASI or if --python is used: filename (str)
92-
json_file: JsonFileType = runtests.json_file
93-
94-
if MS_WINDOWS:
95-
import msvcrt
96-
# Create a file descriptor from the handle
97-
json_file = msvcrt.open_osfhandle(json_file, os.O_WRONLY)
98-
74+
json_file: JsonFile = runtests.json_file
9975

10076
setup_test_dir(runtests.test_dir)
10177
setup_process()
@@ -109,7 +85,7 @@ def worker_process(worker_json: StrJSON) -> NoReturn:
10985

11086
result = run_single_test(test_name, runtests)
11187

112-
with open(json_file, 'w', encoding='utf-8') as json_fp:
88+
with json_file.open('w', encoding='utf-8') as json_fp:
11389
result.write_json_into(json_fp)
11490

11591
sys.exit(0)

0 commit comments

Comments
 (0)