-#! /usr/bin/env python
+#! /usr/bin/env python3
"""Run a subprocess and communicate with it via stdin, stdout, and stderr.
the subprocess stderr stream."""
pid = 0
- cmd = ''
+ cmd = b''
expire_noisily = 1 # Announce subproc destruction?
pipefiles = []
readbuf = 0 # fork will assign to be a readbuf obj
else: ### PARENT ### noqa: E262
# Connect to the child's file descriptors, using our customized
# fdopen:
- self.toChild = os.fdopen(pWc, 'w')
+ self.toChild = os.fdopen(pWc, 'wb')
self.toChild_fdlist = [pWc]
self.readbuf = ReadBuf(pRc)
self.errbuf = ReadBuf(pRe)
# XXX Can write-buffer full be handled better??
raise IOError("write to %s blocked" % self) # ===>
- def writeline(self, line=''):
+ def writeline(self, line=b''):
"""Write STRING, with added newline termination, to subprocess."""
- self.write(line + '\n')
+ self.write(line + b'\n')
### Get output from subprocess ### noqa: E266
"""Read N chars, or all pending if no N specified."""
if n is None:
return self.readPendingChars()
- got = ''
+ got = b''
while n:
got0 = self.readPendingChars(n)
got = got + got0
raise ValueError
self.fd = fd
self.eof = 0 # May be set with stuff still in .buf
- self.buf = ''
+ self.buf = b''
self.chunkSize = maxChunkSize # Biggest read chunk, default 1024.
def fileno(self):
return self.buf[0] # ===>
if self.eof:
- return '' # ===>
+ return b'' # ===>
sel = select.select([self.fd], [], [self.fd], 0)
if sel[2]:
self.buf = os.read(self.fd, self.chunkSize) # ===>
return self.buf[0] # Assume select don't lie.
else:
- return '' # ===>
+ return b'' # ===>
def readPendingChar(self):
"""Consume first character of unconsumed output from file, or empty
return got # ===>
if self.eof:
- return '' # ===>
+ return b'' # ===>
sel = select.select([self.fd], [], [self.fd], 0)
if sel[2]:
if sel[0]:
return os.read(self.fd, 1) # ===>
else:
- return '' # ===>
+ return b'' # ===>
def readPendingChars(self, max=None):
"""Consume uncomsumed output from FILE, or empty string if nothing
pending."""
- got = ""
+ got = b""
if self.buf:
- if (max > 0) and (len(self.buf) > max):
+ if max and (len(self.buf) > max):
got = self.buf[0:max]
self.buf = self.buf[max:]
else:
- got, self.buf = self.buf, ''
+ got, self.buf = self.buf, b''
return got
if self.eof:
- return ''
+ return b''
sel = select.select([self.fd], [], [self.fd], 0)
if sel[2]:
got = got + os.read(self.fd, self.chunkSize)
if max == 0:
self.buf = got
- return ''
+ return b''
elif max is None:
return got
elif len(got) > max:
else:
return got
else:
- return ''
+ return b''
def readPendingLine(self, block=0):
"""Return pending output from FILE, up to first newline (inclusive).
any newline."""
if self.buf:
- to = self.buf.find('\n')
+ to = self.buf.find(b'\n')
if to != -1:
got, self.buf = self.buf[:to+1], self.buf[to+1:]
return got # ===>
- got, self.buf = self.buf, ''
+ got, self.buf = self.buf, b''
else:
if self.eof:
- return '' # ===>
- got = ''
+ return b'' # ===>
+ got = b''
# Herein, 'got' contains the (former) contents of the buffer, and it
# doesn't include a newline.
if sel[0]:
got = got + os.read(self.fd, self.chunkSize)
- to = got.find('\n')
+ to = got.find(b'\n')
if to != -1:
got, self.buf = got[:to+1], got[to+1:]
return got # ===>
if not block:
return got # ===>
if self.eof:
- self.buf = '' # this is how an ordinary file acts...
+ self.buf = b'' # this is how an ordinary file acts...
return got
# otherwise - no newline, blocking requested, no eof - loop. # ==^
def write_record(self, s):
"Write so self.read knows exactly how much to read."
f = self.__dict__['file']
- f.write("%s\n%s" % (len(s), s))
+ f.write(b"%d\n%s" % (len(s), s))
if hasattr(f, 'flush'):
f.flush()
return f.read(_l)
else:
# EOF.
- return ''
+ return b''
def __getattr__(self, attr):
"""Implement characteristic file object attributes."""
self.clear()
- self.proc.writeline('query ' + q)
+ self.proc.writeline(b'query ' + q)
got = []
it = {}
while 1:
raise ValueError("ph failed match: '%s'" % response) # ===>
for line in response:
# convert to a dict:
- line = line.split(':')
- it[line.strip([0])] = (''.join(line[1:])).strip()
+ line = line.split(b':')
+ it[line.strip([0])] = (b''.join(line[1:])).strip()
def getreply(self):
"""Consume next response from ph, returning list of lines or string
nextChar = self.proc.waitForPendingChar(60)
if not nextChar:
raise SubprocessError('ph subprocess not responding') # ===>
- elif nextChar == '-':
+ elif nextChar == b'-':
# dashed line - discard it, and continue reading:
self.proc.readline()
return self.getreply() # ===>
- elif nextChar == 'p':
+ elif nextChar == b'p':
# 'ph> ' prompt - don't think we should hit this, but what the hay:
return '' # ===>
- elif nextChar in '0123456789':
+ elif nextChar in b'0123456789':
# Error notice - we're currently assuming single line errors:
return self.proc.readline()[:-1] # ===>
- elif nextChar in ' \t':
+ elif nextChar in b' \t':
# Get content, up to next dashed line:
got = []
- while nextChar != '-' and nextChar != '':
+ while nextChar != b'-' and nextChar != b'':
got.append(self.proc.readline()[:-1])
nextChar = self.proc.peekPendingChar()
return got
pause = .5
maxIter = 10 # 5 seconds to clear
iterations = 0
- got = ''
- self.proc.write('')
+ got = b''
+ self.proc.write(b'')
while iterations < maxIter:
got = got + self.proc.readPendingChars()
# Strip out all but the last incomplete line:
- got = got.split('\n')[-1]
- if got == 'ph> ':
+ got = got.split(b'\n')[-1]
+ if got == b'ph> ':
return # Ok. ===>
time.sleep(pause)
raise SubprocessError('ph not responding within %s secs' %
p = Subprocess('cat', 1) # set to expire noisily...
print(p)
print('\tWrite, then read, two newline-teriminated lines, using readline:')
- p.write('first full line written\n')
- p.write('second.\n')
+ p.write(b'first full line written\n')
+ p.write(b'second.\n')
print(repr(p.readline()))
print(repr(p.readline()))
print('\tThree lines, last sans newline, read using combination:')
- p.write('first\n')
- p.write('second\n')
- p.write('third, (no cr)')
+ p.write(b'first\n')
+ p.write(b'second\n')
+ p.write(b'third, (no cr)')
print('\tFirst line via readline:')
print(repr(p.readline()))
print('\tRest via readPendingChars:')
print('\t** Stop seems to have failed!')
else:
print('\tWriting line while subprocess is paused...')
- p.write('written while subprocess paused\n')
+ p.write(b'written while subprocess paused\n')
print('\tNonblocking read of paused subprocess (should be empty):')
print(p.readPendingChars())
print('\tContinuing subprocess (verbose):')