remove unnecessary 'print's
[pcucontrol.git] / pcucontrol / transports / pyssh / nbpipe.py
1 """Implements a non-blocking pipe class."""\r
2 \r
3 # Since it uses thread rather than select, it is portable to at least\r
4 # posix and windows environments.\r
5 \r
6 # Author: Rasjid Wilcox, copyright (c) 2002\r
7 # Ideas taken from the Python 2.2 telnetlib.py library.\r
8 #\r
9 # Last modified: 3 August 2002\r
10 # Licence: Python 2.2 Style License.  See license.txt.\r
11 \r
12 # TO DO:\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
17 \r
18 import Queue\r
19 import thread\r
20 import os\r
21 import time\r
22 import types\r
23 \r
24 #INT_TYPE = type(1)\r
25 MIN_TIMEOUT = 0.01\r
26 \r
27 class nbpipe:\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
33             self.fd = readfile\r
34         else:\r
35             self.fd = readfile.fileno()\r
36         self.pipesize = pipesize\r
37         self.blocksize = blocksize\r
38         self.eof = 0\r
39         self._q = Queue.Queue(self.pipesize)\r
40         self.data = ''\r
41         thread.start_new_thread(self._readtoq, ())\r
42     def _readtoq(self):\r
43         finish = 0\r
44         while (1):\r
45             try:\r
46                 item = os.read(self.fd, self.blocksize)\r
47             except (IOError, OSError):\r
48                 finish = 1\r
49             if finish or (item == ''):\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
54                 self.eof = 1\r
55                 thread.exit()\r
56             else:\r
57                 self._q.put(item)\r
58     def has_data(self):\r
59         return self.data\r
60     def eof(self):\r
61         return self.eof\r
62     def read_lazy(self):\r
63         """Process and return data that's already in the queues (lazy).\r
64 \r
65         Return '' if no data available. Don't block.\r
66 \r
67         """\r
68         while not self._q.empty():\r
69             self.data += self._q.get()\r
70         data = self.data\r
71         self.data = ''\r
72         return data\r
73     def read_some(self, until_eof=False):\r
74         """Read at least one byte of cooked data unless EOF is hit.\r
75 \r
76         Return '' if EOF is hit.  Block if no data is immediately\r
77         available.\r
78 \r
79         """\r
80         data = ''\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
84         return data\r
85     def read_until(self, match, timeout=None):\r
86         """Read until a given string is encountered or until timeout.\r
87 \r
88         If no match is found or EOF is hit, return whatever is\r
89         available instead, possibly the empty string.\r
90         """\r
91         if timeout is not None:\r
92             timeout = timeout / MIN_TIMEOUT\r
93         else:\r
94             timeout = 1\r
95         n = len(match)\r
96         data = self.read_lazy()\r
97         i = 0\r
98         while timeout >= 0 and not self.eof:\r
99             i = data.find(match, i)\r
100             if i >= 0:\r
101                 i += n\r
102                 self.data = data[i:]\r
103                 return data[:i]\r
104             time.sleep(MIN_TIMEOUT)\r
105             timeout -= 1\r
106             i = max(0, len(data) - n)\r
107             data += self.read_lazy()\r
108         return data\r
109     def read_all(self):\r
110         """Read until the EOF. May block."""\r
111         return read_some(until_eof=True)\r