def accept_android_license_subprocess(args): logging.info('accept_android_license_subprocess: %s', args) p = subprocess.Popen( args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = nonblocking_io.LineReader(p.stdout) stderr = nonblocking_io.LineReader(p.stderr) current_line = '' while True: select_streams = [] if not stdout.closed: select_streams.append(stdout) if not stderr.closed: select_streams.append(stderr) rset = [] if select_streams: rset, _, _ = select.select(select_streams, [], []) for stream in rset: new_fragment = os.read(stream.fileno(), 4096) if not new_fragment: stream.close() continue current_line = _process_sdk_update_output_fragment( p, current_line + new_fragment) if p.poll() is not None: while not stdout.closed: stdout.read_full_line() while not stderr.closed: stderr.read_full_line() break if p.wait() != 0: raise subprocess.CalledProcessError(p.returncode, args)
def test_no_trailing_line_feed(self): reader, writer = _pipe() reader = nonblocking_io.LineReader(reader) writer.write('abcde\n12345') writer.close() self.assertEqual('abcde\n', reader.read_full_line()) self.assertEqual('12345', reader.read_full_line()) # No \n is contained. self.assertEqual('', reader.read_full_line()) # EOF
def test_read_after_close(self): reader, writer = _pipe() reader = nonblocking_io.LineReader(reader) writer.write('abcde\n12345\nvwxyz') self.assertEqual('abcde\n', reader.read_full_line()) reader.close() # Closed reader must not be readable, even if there are some remaining # data. self.assertRaises(ValueError, reader.read_full_line)
def test_iterator(self): reader, writer = _pipe() reader = nonblocking_io.LineReader(reader) writer.write('abcde\n12345\nvwxyz') read_lines, eof = _read_available_lines(reader) # Currenty, only 'abcde' and '12345' are available, because vwxyz may be # concatenated to next chunk. self.assertListEqual(['abcde\n', '12345\n'], read_lines) self.assertFalse(eof) writer.write('abcde\n12345') read_lines, eof = _read_available_lines(reader) self.assertListEqual(['vwxyzabcde\n'], read_lines) self.assertFalse(eof) writer.close() read_lines, eof = _read_available_lines(reader) self.assertListEqual(['12345'], read_lines) self.assertTrue(eof)
def test_regular_usage(self): reader, writer = _pipe() reader = nonblocking_io.LineReader(reader) # Initially, no data is available. self.assertRaises(io.BlockingIOError, reader.read_full_line) # Test single line. writer.write('abcde\n') self.assertEqual('abcde\n', reader.read_full_line()) # Test double lines. writer.write('abcde\n12345\n') self.assertEqual('abcde\n', reader.read_full_line()) self.assertEqual('12345\n', reader.read_full_line()) # Test a line without trailing linesep. writer.write('abcde\n12345') self.assertEqual('abcde\n', reader.read_full_line()) self.assertRaises(io.BlockingIOError, reader.read_full_line) # Again write the data. The next read_full_line() should concatenate # pending '12345' wrote above, and vwxyz\n. writer.write('vwxyz\n') self.assertEqual('12345vwxyz\n', reader.read_full_line()) writer.close() # Opposite side is closed, so the EOF should be found. self.assertEqual('', reader.read_full_line()) # The reader stream is not yet closed, even after eof. self.assertFalse(reader.closed) reader.close() self.assertTrue(reader.closed) # Calling read_full_line after close() causes ValueError. self.assertRaises(ValueError, reader.read_full_line)
def test_empty(self): reader, writer = _pipe() reader = nonblocking_io.LineReader(reader) writer.close() self.assertEqual('', reader.read_full_line())
def test_fd(self): reader, writer = _pipe() reader_fd = reader.fileno() reader = nonblocking_io.LineReader(reader) # FD must be equal to the original one. self.assertEqual(reader_fd, reader.fileno())
def _maybe_create_line_reader(reader): if reader is None: return None return nonblocking_io.LineReader(reader)