diff options
author | Steven Silvester <steven.silvester@ieee.org> | 2014-11-23 17:51:21 -0800 |
---|---|---|
committer | Thomas Kluyver <takowl@gmail.com> | 2015-09-12 11:49:09 +0100 |
commit | 157d2f4d9418aacd95f6c426279b52de318f7666 (patch) | |
tree | bfb6e05c315272eaf322899fb49b611ecd152284 /pexpect | |
parent | eee85ecfeda167dd07e3abeaffcf8c51a6b0d5a8 (diff) | |
download | pexpect-git-157d2f4d9418aacd95f6c426279b52de318f7666.tar.gz |
Start implementing a Pexpect spawn class based on Popen
Initial implementation copied from https://gist.github.com/blink1073/9a0ea82efc84cb9216d0
Diffstat (limited to 'pexpect')
-rw-r--r-- | pexpect/popen_spawn.py | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/pexpect/popen_spawn.py b/pexpect/popen_spawn.py new file mode 100644 index 0000000..b3b02bd --- /dev/null +++ b/pexpect/popen_spawn.py @@ -0,0 +1,83 @@ +"""Spawn interface using subprocess.Popen +""" +import os +import threading +import subprocess +import sys + +try: + from queue import Queue # Python 3 +except ImportError: + from Queue import Queue # Python 2 + +from .spawnbase import SpawnBase + +class PopenSpawn(SpawnBase): + def __init__(self, cmd, timeout=30, maxread=2000, searchwindowsize=None, + logfile=None, **kwargs): + super(PopenSpawn, self).__init__(timeout=timeout, maxread=maxread, + searchwindowsize=searchwindowsize, logfile=logfile) + + kwargs.update(dict(bufsize=0, stdin=subprocess.PIPE, + stderr=subprocess.STDOUT, + stdout=subprocess.PIPE)) + + if sys.platform == 'win32': + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + kwargs['startupinfo'] = startupinfo + kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP + + self.proc = subprocess.Popen(cmd, **kwargs) + self._buf = '' + + self._read_queue = Queue() + self._read_thread = threading.Thread(target=self._read_incoming) + self._read_thread.setDaemon(True) + self._read_thread.start() + + def read_nonblocking(self, n): + orig = len(self._buf) + while 1: + try: + self._buf += self._read_queue.get_nowait() + except Queue.Empty: + return + else: + if len(self._buf) - orig >= n: + return + + def _read_incoming(self): + """Run in a thread to move output from a pipe to a queue.""" + while 1: + buf = os.read(self.proc.stdout.fileno(), 1024) + self._read_queue.put(buf) + + def readline(self): + while not '\n' in self._buf: + self.read_nonblocking(1024) + ind = self._buf.index('\n') + ret, self._buf = self._buf[:ind], self._buf[ind:] + return ret + + def write(self, s): + '''This is similar to send() except that there is no return value. + ''' + self.send(s) + + def writelines(self, sequence): + '''This calls write() for each element in the sequence. + + The sequence can be any iterable object producing strings, typically a + list of strings. This does not add line separators. There is no return + value. + ''' + for s in sequence: + self.send(s) + + def send(self, s): + self._log(s, 'send') + return self.proc.stdin.write(s) + + def sendline(self, line): + return self.send(line + '\n') |