#!/usr/bin/env python import os import select import six import empty import dbg def no_buffering(f): if six.PY2: return os.fdopen(f.fileno(), 'r', 0) return os.fdopen(f.fileno(), 'rb', buffering=0) readable = lambda f, tmout=0: select.select([f], [], [], tmout)[0] == [f] def read1(f, tmout=0): if readable(f, tmout): return f.read(1) # EOF is b'' or '' return None # timeout def reader_new(f, tmout=0, to_str=True, no_buf=False): # return '' is EOF # return None is timeout if no_buf: f = no_buffering(f) e = empty.new() readable_ = lambda : readable(f, tmout) e.readable = readable_ e.type = None def read1_(): b = read1(f, tmout) if b == None: return None # timeout if e.type == None or e.type != type(b): e.type = type(b) if to_str and e.type == bytes: return b.decode() # EOF is '' return b # EOF is '' or b'' e.read1 = read1_ def read(): lst = [] r1 = None while True: r1 = read1_() if not r1: # None is timeout , '' or b'' is EOF break lst.append(r1) if not lst: if r1 == None: # timeout return None r0 = '' if e.type in (str, None) else b'' return r0 r0 = '' if type(lst[0]) == str else b'' return r0.join(lst) def read_to(k): # to_str=True only buf = '' while True: r1 = read1_() if not r1: # None is timeout , '' is EOF return buf if buf else r1 buf += r1 if buf.endswith(k): break return buf e.buf = '' def pop_buf(): (r, e.buf) = (e.buf, '') return r def readline(): # to_str=True only while True: c = read1_() if c == None: # timeout break if c == '': # EOF return pop_buf() e.buf += c if c in ('\n', '\r'): return pop_buf() # '\n', '\r' contained return None # timeout e.lines = [] def pop_lines(): (r, e.lines) = (e.lines, []) return r def readlines(): # to_str=True only # delim is "\n" line # return list of str # return [] is EOF # return None is timeout while True: s = readline() if s == None: # timeout break if s == '': # EOF return pop_lines() e.lines.append(s) if s == '\n': # delim return pop_lines() # delim contained return None # timeout return empty.to_attr( e, locals() ) if __name__ == "__main__": import cmd_ut import yaml cmd = 'ls ; echo "" ; ls ; echo ""' proc = cmd_ut.proc_new(cmd, stdout=cmd_ut.PIPE) f = proc.get_stdout() rdr = reader_new(f) while True: lst = rdr.readlines() if lst == []: break if lst: for s in lst: dbg.out(s, '') # EOF