|
1 | 1 | import errno |
2 | 2 | import logging |
3 | | -import multiprocessing |
4 | 3 | import os |
5 | 4 | import subprocess |
6 | | -import sys |
7 | 5 | import tempfile |
8 | 6 | import textwrap |
9 | 7 | import uuid |
10 | | -from multiprocessing import queues |
11 | 8 | from typing import AnyStr |
12 | 9 |
|
13 | 10 | import pexpect.fdpexpect |
14 | 11 | from pexpect import EOF, TIMEOUT |
15 | 12 | from pexpect.utils import poll_ignore_interrupts, select_ignore_interrupts |
16 | 13 |
|
17 | | -from .utils import Meta, remove_asci_color_code, to_bytes, to_str, utcnow_str |
18 | | - |
19 | | -if sys.platform == 'darwin': |
20 | | - _ctx = multiprocessing.get_context('fork') |
21 | | -else: |
22 | | - _ctx = multiprocessing.get_context() |
23 | | - |
24 | | - |
25 | | -class MessageQueue(queues.Queue): |
26 | | - def __init__(self, *args, **kwargs): |
27 | | - if 'ctx' not in kwargs: |
28 | | - kwargs['ctx'] = _ctx |
29 | | - |
30 | | - super().__init__(*args, **kwargs) |
31 | | - |
32 | | - def put(self, obj, **kwargs): |
33 | | - if not isinstance(obj, str | bytes): |
34 | | - super().put(obj, **kwargs) |
35 | | - return |
36 | | - |
37 | | - if obj == '' or obj == b'': |
38 | | - return |
39 | | - |
40 | | - _b = to_bytes(obj) |
41 | | - try: |
42 | | - super().put(_b, **kwargs) |
43 | | - except: # noqa # queue might be closed |
44 | | - pass |
45 | | - |
46 | | - def write(self, s: AnyStr): |
47 | | - self.put(s) |
48 | | - |
49 | | - def flush(self): |
50 | | - pass |
51 | | - |
52 | | - def isatty(self): |
53 | | - return True |
| 14 | +from pytest_embedded import MP_CTX, MessageQueue |
| 15 | +from pytest_embedded.utils import Meta, remove_asci_color_code, to_bytes, to_str, utcnow_str |
54 | 16 |
|
55 | 17 |
|
56 | 18 | class PexpectProcess(pexpect.fdpexpect.fdspawn): |
@@ -144,18 +106,18 @@ def live_print_call(*args, msg_queue: MessageQueue | None = None, expect_returnc |
144 | 106 | raise subprocess.CalledProcessError(process.returncode, process.args) |
145 | 107 |
|
146 | 108 |
|
147 | | -class _PopenRedirectProcess(_ctx.Process): |
| 109 | +class _PopenRedirectProcess(MP_CTX.Process): |
148 | 110 | def __init__(self, msg_queue: MessageQueue, logfile: str): |
149 | | - self._q = msg_queue |
150 | | - |
151 | | - self.logfile = logfile |
152 | | - |
153 | | - super().__init__(target=self._forward_io, daemon=True) # killed by the main process |
| 111 | + super().__init__(target=self._forward_io, args=(msg_queue, logfile), daemon=True) |
154 | 112 |
|
155 | | - def _forward_io(self) -> None: |
156 | | - with open(self.logfile) as fr: |
| 113 | + @staticmethod |
| 114 | + def _forward_io(msg_queue, logfile) -> None: |
| 115 | + with open(logfile) as fr: |
157 | 116 | while True: |
158 | | - self._q.put(fr.read()) |
| 117 | + try: |
| 118 | + msg_queue.put(fr.read()) # msg_queue may be closed |
| 119 | + except Exception: |
| 120 | + break |
159 | 121 |
|
160 | 122 |
|
161 | 123 | class DuplicateStdoutPopen(subprocess.Popen): |
|
0 commit comments