Skip to content

Commit 17e4a45

Browse files
authored
Add Windows CI for parallel checking (python#20803)
I am only running a subset of tests, just to make things faster.
1 parent 608134f commit 17e4a45

File tree

4 files changed

+33
-12
lines changed

4 files changed

+33
-12
lines changed

.github/workflows/test.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ jobs:
112112
toxenv: py
113113
tox_extra_args: "-n 4 --mypy-num-workers=4 mypy/test/testcheck.py"
114114
test_mypyc: true
115+
- name: Parallel tests with py314-windows-64, interpreted
116+
python: '3.14'
117+
os: windows-latest
118+
toxenv: py
119+
tox_extra_args: "-n 2 --mypy-num-workers=2 mypy/test/testcheck.py -k 'incremental or modules or classes'"
115120

116121
- name: Type check our own code (py310-ubuntu)
117122
python: '3.10'

mypy/build.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,16 @@
100100
)
101101
from mypy.graph_utils import prepare_sccs, strongly_connected_components, topsort
102102
from mypy.indirection import TypeIndirectionVisitor
103-
from mypy.ipc import BadStatus, IPCClient, IPCMessage, read_status, ready_to_read, receive, send
103+
from mypy.ipc import (
104+
BadStatus,
105+
IPCClient,
106+
IPCException,
107+
IPCMessage,
108+
read_status,
109+
ready_to_read,
110+
receive,
111+
send,
112+
)
104113
from mypy.messages import MessageBuilder
105114
from mypy.nodes import (
106115
ClassDef,
@@ -280,9 +289,8 @@ def connect(self) -> None:
280289
assert isinstance(pid, int), f"Bad PID: {pid}"
281290
assert isinstance(connection_name, str), f"Bad connection name: {connection_name}"
282291
if sys.platform != "win32":
283-
# TODO(emmatyping): for some reason this does not work on Windows. Probably
284-
# because we don't fork? We should check this
285-
# Double-check this status file is created by us.
292+
# Windows uses "wrapper processes" to run Python, so we cannot
293+
# verify PIDs reliably.
286294
assert pid == self.proc.pid, f"PID mismatch: {pid} vs {self.proc.pid}"
287295
self.conn = IPCClient(connection_name, WORKER_CONNECTION_TIMEOUT)
288296
return
@@ -402,7 +410,7 @@ def default_flush_errors(
402410
for worker in workers:
403411
try:
404412
send(worker.conn, SccRequestMessage(scc_id=None))
405-
except OSError:
413+
except (OSError, IPCException):
406414
pass
407415
for worker in workers:
408416
worker.close()

mypy/build_worker/worker.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
from mypy.defaults import RECURSION_LIMIT, WORKER_CONNECTION_TIMEOUT
4242
from mypy.errors import CompileError, Errors, report_internal_error
4343
from mypy.fscache import FileSystemCache
44-
from mypy.ipc import IPCServer, receive, send
44+
from mypy.ipc import IPCException, IPCServer, receive, send
4545
from mypy.modulefinder import BuildSource, BuildSourceSet, compute_search_paths
4646
from mypy.options import Options
4747
from mypy.util import read_py_file
@@ -82,9 +82,13 @@ def main(argv: list[str]) -> None:
8282
status_file = args.status_file
8383
server = IPCServer(CONNECTION_NAME, WORKER_CONNECTION_TIMEOUT)
8484

85-
with open(status_file, "w") as f:
86-
json.dump({"pid": os.getpid(), "connection_name": server.connection_name}, f)
87-
f.write("\n")
85+
try:
86+
with open(status_file, "w") as f:
87+
json.dump({"pid": os.getpid(), "connection_name": server.connection_name}, f)
88+
f.write("\n")
89+
except Exception as exc:
90+
print(f"Error writing status file {status_file}:", exc)
91+
raise
8892

8993
fscache = FileSystemCache()
9094
cached_read = fscache.read
@@ -94,7 +98,7 @@ def main(argv: list[str]) -> None:
9498
try:
9599
with server:
96100
serve(server, ctx)
97-
except OSError as exc:
101+
except (OSError, IPCException) as exc:
98102
if options.verbosity >= 1:
99103
print("Error communicating with coordinator:", exc)
100104
except Exception as exc:

mypy/ipc.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
HEADER_SIZE = 4
4242

4343

44+
# TODO: we should make sure consistent exceptions are raised on different platforms.
45+
# Currently we raise either IPCException or OSError for equivalent conditions.
4446
class IPCException(Exception):
4547
"""Exception for IPC issues."""
4648

@@ -354,7 +356,7 @@ def read_status(status_file: str) -> dict[str, object]:
354356
try:
355357
data = json.load(f)
356358
except Exception as e:
357-
raise BadStatus("Malformed status file (not JSON)") from e
359+
raise BadStatus(f"Malformed status file: {str(e)}") from e
358360
if not isinstance(data, dict):
359361
raise BadStatus(f"Invalid status file (not a dict): {data}")
360362
return data
@@ -380,7 +382,9 @@ def ready_to_read(conns: list[IPCClient], timeout: float | None = None) -> list[
380382
try:
381383
ov, err = _winapi.ReadFile(conn.connection, 1, overlapped=True)
382384
except OSError:
383-
# Broken/closed pipe
385+
# Broken/closed pipe. Mimic Linux behavior here, caller will get
386+
# the exception when trying to read from this socket.
387+
ready.append(i)
384388
continue
385389
if err == _winapi.ERROR_IO_PENDING:
386390
events.append(ov.event)

0 commit comments

Comments
 (0)