| 18 | from .utils import string_types |
| 19 | |
| 20 | class PopenSpawn(SpawnBase): |
| 21 | def __init__(self, cmd, timeout=30, maxread=2000, searchwindowsize=None, |
| 22 | logfile=None, cwd=None, env=None, encoding=None, |
| 23 | codec_errors='strict', preexec_fn=None): |
| 24 | super(PopenSpawn, self).__init__(timeout=timeout, maxread=maxread, |
| 25 | searchwindowsize=searchwindowsize, logfile=logfile, |
| 26 | encoding=encoding, codec_errors=codec_errors) |
| 27 | |
| 28 | # Note that `SpawnBase` initializes `self.crlf` to `\r\n` |
| 29 | # because the default behaviour for a PTY is to convert |
| 30 | # incoming LF to `\r\n` (see the `onlcr` flag and |
| 31 | # https://stackoverflow.com/a/35887657/5397009). Here we set |
| 32 | # it to `os.linesep` because that is what the spawned |
| 33 | # application outputs by default and `popen` doesn't translate |
| 34 | # anything. |
| 35 | if encoding is None: |
| 36 | self.crlf = os.linesep.encode ("ascii") |
| 37 | else: |
| 38 | self.crlf = self.string_type (os.linesep) |
| 39 | |
| 40 | kwargs = dict(bufsize=0, stdin=subprocess.PIPE, |
| 41 | stderr=subprocess.STDOUT, stdout=subprocess.PIPE, |
| 42 | cwd=cwd, preexec_fn=preexec_fn, env=env) |
| 43 | |
| 44 | if sys.platform == 'win32': |
| 45 | startupinfo = subprocess.STARTUPINFO() |
| 46 | startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW |
| 47 | kwargs['startupinfo'] = startupinfo |
| 48 | kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP |
| 49 | |
| 50 | if isinstance(cmd, string_types) and sys.platform != 'win32': |
| 51 | cmd = shlex.split(cmd, posix=os.name == 'posix') |
| 52 | |
| 53 | self.proc = subprocess.Popen(cmd, **kwargs) |
| 54 | self.pid = self.proc.pid |
| 55 | self.closed = False |
| 56 | self._buf = self.string_type() |
| 57 | |
| 58 | self._read_queue = Queue() |
| 59 | self._read_thread = threading.Thread(target=self._read_incoming) |
| 60 | self._read_thread.daemon = True |
| 61 | self._read_thread.start() |
| 62 | |
| 63 | _read_reached_eof = False |
| 64 | |
| 65 | def read_nonblocking(self, size, timeout): |
| 66 | buf = self._buf |
| 67 | if self._read_reached_eof: |
| 68 | # We have already finished reading. Use up any buffered data, |
| 69 | # then raise EOF |
| 70 | if buf: |
| 71 | self._buf = buf[size:] |
| 72 | return buf[:size] |
| 73 | else: |
| 74 | self.flag_eof = True |
| 75 | raise EOF('End Of File (EOF).') |
| 76 | |
| 77 | if timeout == -1: |
no outgoing calls
searching dependent graphs…