A simple class that represents a mypy build worker.
| 265 | |
| 266 | |
| 267 | class WorkerClient: |
| 268 | """A simple class that represents a mypy build worker.""" |
| 269 | |
| 270 | conn: IPCClient |
| 271 | |
| 272 | def __init__(self, status_file: str, options_data: str, env: Mapping[str, str]) -> None: |
| 273 | self.status_file = status_file |
| 274 | if os.path.isfile(status_file): |
| 275 | os.unlink(status_file) |
| 276 | |
| 277 | command = [ |
| 278 | sys.executable, |
| 279 | "-m", |
| 280 | "mypy.build_worker", |
| 281 | f"--status-file={status_file}", |
| 282 | f"--options-data={options_data}", |
| 283 | ] |
| 284 | # Return early without waiting, caller must call connect() before using the client. |
| 285 | self.proc = subprocess.Popen(command, env=env) |
| 286 | self.connected = False |
| 287 | |
| 288 | def connect(self) -> None: |
| 289 | end_time = time.time() + WORKER_START_TIMEOUT |
| 290 | last_exception: Exception | None = None |
| 291 | while time.time() < end_time: |
| 292 | try: |
| 293 | data = read_status(self.status_file) |
| 294 | except BadStatus as exc: |
| 295 | last_exception = exc |
| 296 | time.sleep(WORKER_START_INTERVAL) |
| 297 | continue |
| 298 | try: |
| 299 | pid, connection_name = data["pid"], data["connection_name"] |
| 300 | assert isinstance(pid, int), f"Bad PID: {pid}" |
| 301 | assert isinstance(connection_name, str), f"Bad connection name: {connection_name}" |
| 302 | if sys.platform != "win32": |
| 303 | # Windows uses "wrapper processes" to run Python, so we cannot |
| 304 | # verify PIDs reliably. |
| 305 | assert pid == self.proc.pid, f"PID mismatch: {pid} vs {self.proc.pid}" |
| 306 | self.conn = IPCClient(connection_name, WORKER_CONNECTION_TIMEOUT) |
| 307 | self.connected = True |
| 308 | return |
| 309 | except Exception as exc: |
| 310 | last_exception = exc |
| 311 | break |
| 312 | print(f"Failed to establish connection with worker: {last_exception}") |
| 313 | |
| 314 | def close(self) -> None: |
| 315 | if self.connected: |
| 316 | self.conn.close() |
| 317 | # Technically we don't need to wait, but otherwise we will get ResourceWarnings. |
| 318 | try: |
| 319 | self.proc.wait(timeout=WORKER_SHUTDOWN_TIMEOUT) |
| 320 | except subprocess.TimeoutExpired: |
| 321 | pass |
| 322 | if os.path.isfile(self.status_file): |
| 323 | os.unlink(self.status_file) |
| 324 |
no outgoing calls
no test coverage detected
searching dependent graphs…