1 """Implements a non-blocking pipe class."""
\r
3 # Since it uses thread rather than select, it is portable to at least
\r
4 # posix and windows environments.
\r
6 # Author: Rasjid Wilcox, copyright (c) 2002
\r
7 # Ideas taken from the Python 2.2 telnetlib.py library.
\r
9 # Last modified: 3 August 2002
\r
10 # Licence: Python 2.2 Style License. See license.txt.
\r
13 # * Handle excpetions better, particularly Keyboard Interupts.
\r
14 # * Possibly do a threadless version for posix environments
\r
15 # where we can use select (is probably more efficient).
\r
16 # * A test function.
\r
28 def __init__(self, readfile, pipesize=0, blocksize=1024):
\r
29 """Initialise a non-blocking pipe object, given a real file or file-descriptor.
\r
30 pipesize = the size (in blocks) of the queue used to buffer the blocks read
\r
31 blocksize = the maximum block size for a raw read."""
\r
32 if type(readfile) == types.IntType:
\r
35 self.fd = readfile.fileno()
\r
36 self.pipesize = pipesize
\r
37 self.blocksize = blocksize
\r
39 self._q = Queue.Queue(self.pipesize)
\r
41 thread.start_new_thread(self._readtoq, ())
\r
46 item = os.read(self.fd, self.blocksize)
\r
47 except (IOError, OSError):
\r
49 if (item == '') or finish:
\r
50 # Wait until everything has been read from the queue before
\r
51 # setting eof = 1 and exiting.
\r
52 while not self._q.empty():
\r
53 time.sleep(MIN_TIMEOUT)
\r
62 def read_lazy(self):
\r
63 """Process and return data that's already in the queues (lazy).
\r
65 Return '' if no data available. Don't block.
\r
68 while not self._q.empty():
\r
69 self.data += self._q.get()
\r
73 def read_some(self, until_eof=False):
\r
74 """Read at least one byte of cooked data unless EOF is hit.
\r
76 Return '' if EOF is hit. Block if no data is immediately
\r
81 while (until_eof or not data) and not self.eof:
\r
82 data += self.read_lazy()
\r
83 time.sleep(MIN_TIMEOUT)
\r
85 def read_until(self, match, timeout=None):
\r
86 """Read until a given string is encountered or until timeout.
\r
88 If no match is found or EOF is hit, return whatever is
\r
89 available instead, possibly the empty string.
\r
91 if timeout is not None:
\r
92 timeout = timeout / MIN_TIMEOUT
\r
96 data = self.read_lazy()
\r
98 while timeout >= 0 and not self.eof:
\r
99 i = data.find(match, i)
\r
102 self.data = data[i:]
\r
104 time.sleep(MIN_TIMEOUT)
\r
106 i = max(0, len(data) - n)
\r
107 data += self.read_lazy()
\r
109 def read_all(self):
\r
110 """Read until the EOF. May block."""
\r
111 return read_some(until_eof=True)
\r