DebugClients/Python/AsyncFile.py

changeset 5258
cfca063afa07
parent 5179
5f56410e7624
child 5287
971f24c89e6b
equal deleted inserted replaced
5256:4720cbf7ab52 5258:cfca063afa07
21 21
22 def AsyncPendingWrite(file): 22 def AsyncPendingWrite(file):
23 """ 23 """
24 Module function to check for data to be written. 24 Module function to check for data to be written.
25 25
26 @param file The file object to be checked (file) 26 @param file The file object to be checked
27 @return Flag indicating if there is data wating (int) 27 @type file
28 @return Flag indicating if there is data waiting
29 @rtype int
28 """ 30 """
29 try: 31 try:
30 pending = file.pendingWrite() 32 pending = file.pendingWrite()
31 except Exception: 33 except Exception:
32 pending = 0 34 pending = 0
37 class AsyncFile(object): 39 class AsyncFile(object):
38 """ 40 """
39 Class wrapping a socket object with a file interface. 41 Class wrapping a socket object with a file interface.
40 """ 42 """
41 maxtries = 10 43 maxtries = 10
42 maxbuffersize = 1024 * 1024 * 4
43 44
44 def __init__(self, sock, mode, name): 45 def __init__(self, sock, mode, name):
45 """ 46 """
46 Constructor 47 Constructor
47 48
48 @param sock the socket object being wrapped 49 @param sock the socket object being wrapped
49 @param mode mode of this file (string) 50 @type socket
50 @param name name of this file (string) 51 @param mode mode of this file
52 @type str
53 @param name name of this file
54 @type str
51 """ 55 """
52 # Initialise the attributes. 56 # Initialise the attributes.
53 self.closed = False 57 self.closed = False
54 self.sock = sock 58 self.sock = sock
55 self.mode = mode 59 self.mode = mode
56 self.name = name 60 self.name = name
57 self.nWriteErrors = 0 61 self.nWriteErrors = 0
58 self.encoding = "utf-8" 62 self.encoding = "utf-8"
59 63
60 self.wpending = unicode('') 64 self.wpending = []
61 65
62 def __checkMode(self, mode): 66 def __checkMode(self, mode):
63 """ 67 """
64 Private method to check the mode. 68 Private method to check the mode.
65 69
66 This method checks, if an operation is permitted according to 70 This method checks, if an operation is permitted according to
67 the mode of the file. If it is not, an IOError is raised. 71 the mode of the file. If it is not, an IOError is raised.
68 72
69 @param mode the mode to be checked (string) 73 @param mode the mode to be checked
74 @type string
70 @exception IOError raised to indicate a bad file descriptor 75 @exception IOError raised to indicate a bad file descriptor
71 """ 76 """
72 if mode != self.mode: 77 if mode != self.mode:
73 raise IOError((9, '[Errno 9] Bad file descriptor')) 78 raise IOError((9, '[Errno 9] Bad file descriptor'))
74 79
75 def __nWrite(self, n): 80 def pendingWrite(self):
76 """ 81 """
77 Private method to write a specific number of pending bytes. 82 Public method that returns the number of strings waiting to be written.
78 83
79 @param n the number of bytes to be written (int) 84 @return the number of strings to be written
80 """ 85 @rtype int
81 if n: 86 """
87 return len(self.wpending)
88
89 def close(self, closeit=False):
90 """
91 Public method to close the file.
92
93 @param closeit flag to indicate a close ordered by the debugger code
94 @type bool
95 """
96 if closeit and not self.closed:
97 self.flush()
98 self.sock.close()
99 self.closed = True
100
101 def flush(self):
102 """
103 Public method to write all pending entries.
104 """
105 while self.wpending:
106 buf = self.wpending.pop(0)
82 try: 107 try:
83 buf = self.wpending[:n]
84 try: 108 try:
85 buf = buf.encode('utf-8', 'backslashreplace') 109 buf = buf.encode('utf-8', 'backslashreplace')
86 except (UnicodeEncodeError, UnicodeDecodeError): 110 except (UnicodeEncodeError, UnicodeDecodeError):
87 pass 111 pass
88 self.sock.sendall(buf) 112 self.sock.sendall(buf)
89 self.wpending = self.wpending[n:]
90 self.nWriteErrors = 0 113 self.nWriteErrors = 0
91 except socket.error: 114 except socket.error:
92 self.nWriteErrors += 1 115 self.nWriteErrors += 1
93 if self.nWriteErrors > self.maxtries: 116 if self.nWriteErrors > self.maxtries:
94 self.wpending = unicode('') # delete all output 117 self.wpending = [] # delete all output
95
96 def pendingWrite(self):
97 """
98 Public method that returns the number of bytes waiting to be written.
99
100 @return the number of bytes to be written (int)
101 """
102 return self.wpending.rfind('\n') + 1
103
104 def close(self, closeit=False):
105 """
106 Public method to close the file.
107
108 @param closeit flag to indicate a close ordered by the debugger code
109 (boolean)
110 """
111 if closeit and not self.closed:
112 self.flush()
113 self.sock.close()
114 self.closed = True
115
116 def flush(self):
117 """
118 Public method to write all pending bytes.
119 """
120 self.__nWrite(len(self.wpending))
121 118
122 def isatty(self): 119 def isatty(self):
123 """ 120 """
124 Public method to indicate whether a tty interface is supported. 121 Public method to indicate whether a tty interface is supported.
125 122
126 @return always false 123 @return always false
124 @rtype bool
127 """ 125 """
128 return False 126 return False
129 127
130 def fileno(self): 128 def fileno(self):
131 """ 129 """
132 Public method returning the file number. 130 Public method returning the file number.
133 131
134 @return file number (int) 132 @return file number
133 @rtype int
135 """ 134 """
136 try: 135 try:
137 return self.sock.fileno() 136 return self.sock.fileno()
138 except socket.error: 137 except socket.error:
139 return -1 138 return -1
140 139
141 def readable(self): 140 def readable(self):
142 """ 141 """
143 Public method to check, if the stream is readable. 142 Public method to check, if the stream is readable.
144 143
145 @return flag indicating a readable stream (boolean) 144 @return flag indicating a readable stream
145 @rtype bool
146 """ 146 """
147 return self.mode == "r" 147 return self.mode == "r"
148 148
149 def read_p(self, size=-1): 149 def read_p(self, size=-1):
150 """ 150 """
151 Public method to read bytes from this file. 151 Public method to read bytes from this file.
152 152
153 @param size maximum number of bytes to be read (int) 153 @param size maximum number of bytes to be read
154 @return the bytes read (any) 154 @type int
155 @return the bytes read
156 @rtype str
155 """ 157 """
156 self.__checkMode('r') 158 self.__checkMode('r')
157 159
158 if size < 0: 160 if size < 0:
159 size = 20000 161 size = 20000
162 164
163 def read(self, size=-1): 165 def read(self, size=-1):
164 """ 166 """
165 Public method to read bytes from this file. 167 Public method to read bytes from this file.
166 168
167 @param size maximum number of bytes to be read (int) 169 @param size maximum number of bytes to be read
168 @return the bytes read (any) 170 @type int
171 @return the bytes read
172 @rtype str
169 """ 173 """
170 self.__checkMode('r') 174 self.__checkMode('r')
171 175
172 buf = raw_input() 176 buf = raw_input()
173 if size >= 0: 177 if size >= 0:
179 Public method to read a line from this file. 183 Public method to read a line from this file.
180 184
181 <b>Note</b>: This method will not block and may return 185 <b>Note</b>: This method will not block and may return
182 only a part of a line if that is all that is available. 186 only a part of a line if that is all that is available.
183 187
184 @param size maximum number of bytes to be read (int) 188 @param size maximum number of bytes to be read
185 @return one line of text up to size bytes (string) 189 @type int
190 @return one line of text up to size bytes
191 @rtype str
186 """ 192 """
187 self.__checkMode('r') 193 self.__checkMode('r')
188 194
189 if size < 0: 195 if size < 0:
190 size = 20000 196 size = 20000
207 213
208 def readlines(self, sizehint=-1): 214 def readlines(self, sizehint=-1):
209 """ 215 """
210 Public method to read all lines from this file. 216 Public method to read all lines from this file.
211 217
212 @param sizehint hint of the numbers of bytes to be read (int) 218 @param sizehint hint of the numbers of bytes to be read
213 @return list of lines read (list of strings) 219 @type int
220 @return list of lines read
221 @rtype list of str
214 """ 222 """
215 self.__checkMode('r') 223 self.__checkMode('r')
216 224
217 lines = [] 225 lines = []
218 room = sizehint 226 room = sizehint
236 244
237 def readline(self, sizehint=-1): 245 def readline(self, sizehint=-1):
238 """ 246 """
239 Public method to read one line from this file. 247 Public method to read one line from this file.
240 248
241 @param sizehint hint of the numbers of bytes to be read (int) 249 @param sizehint hint of the numbers of bytes to be read
242 @return one line read (string) 250 @type int
251 @return one line read
252 @rtype str
243 """ 253 """
244 self.__checkMode('r') 254 self.__checkMode('r')
245 255
246 line = raw_input() + '\n' 256 line = raw_input() + '\n'
247 if sizehint >= 0: 257 if sizehint >= 0:
250 260
251 def seekable(self): 261 def seekable(self):
252 """ 262 """
253 Public method to check, if the stream is seekable. 263 Public method to check, if the stream is seekable.
254 264
255 @return flag indicating a seekable stream (boolean) 265 @return flag indicating a seekable stream
266 @rtype bool
256 """ 267 """
257 return False 268 return False
258 269
259 def seek(self, offset, whence=0): 270 def seek(self, offset, whence=0):
260 """ 271 """
261 Public method to move the filepointer. 272 Public method to move the filepointer.
262 273
263 @param offset offset to move the filepointer to (integer) 274 @param offset offset to move the filepointer to
275 @type int
264 @param whence position the offset relates to 276 @param whence position the offset relates to
277 @type int
265 @exception IOError This method is not supported and always raises an 278 @exception IOError This method is not supported and always raises an
266 IOError. 279 IOError.
267 """ 280 """
268 raise IOError((29, '[Errno 29] Illegal seek')) 281 raise IOError((29, '[Errno 29] Illegal seek'))
269 282
278 291
279 def truncate(self, size=-1): 292 def truncate(self, size=-1):
280 """ 293 """
281 Public method to truncate the file. 294 Public method to truncate the file.
282 295
283 @param size size to truncate to (integer) 296 @param size size to truncate to
297 @type int
284 @exception IOError This method is not supported and always raises an 298 @exception IOError This method is not supported and always raises an
285 IOError. 299 IOError.
286 """ 300 """
287 raise IOError((29, '[Errno 29] Illegal seek')) 301 raise IOError((29, '[Errno 29] Illegal seek'))
288 302
289 def writable(self): 303 def writable(self):
290 """ 304 """
291 Public method to check, if a stream is writable. 305 Public method to check, if a stream is writable.
292 306
293 @return flag indicating a writable stream (boolean) 307 @return flag indicating a writable stream
308 @rtype bool
294 """ 309 """
295 return self.mode == "w" 310 return self.mode == "w"
296 311
297 def write(self, s): 312 def write(self, s):
298 """ 313 """
299 Public method to write a string to the file. 314 Public method to write a string to the file.
300 315
301 @param s text to be written (string) 316 @param s text to be written
317 @type str
302 """ 318 """
303 self.__checkMode('w') 319 self.__checkMode('w')
304 320
305 cmd = prepareJsonCommand("ClientOutput", { 321 cmd = prepareJsonCommand("ClientOutput", {
306 "text": s, 322 "text": s,
307 }) 323 })
308 self.write_p(cmd) 324 self.wpending.append(cmd)
325 self.flush()
309 326
310 def write_p(self, s): 327 def write_p(self, s):
311 """ 328 """
312 Public method to write a string to the file. 329 Public method to write a json-rpc 2.0 coded string to the file.
313 330
314 @param s text to be written (string) 331 @param s text to be written
315 @exception socket.error raised to indicate too many send attempts 332 @type str
316 """ 333 """
317 self.__checkMode('w') 334 self.__checkMode('w')
318 tries = 0 335
319 if not self.wpending: 336 self.wpending.append(s)
320 self.wpending = s 337 self.flush()
321 elif len(self.wpending) + len(s) > self.maxbuffersize:
322 # flush wpending if it is too big
323 while self.wpending:
324 # if we have a persistent error in sending the data, an
325 # exception will be raised in __nWrite
326 self.flush()
327 tries += 1
328 if tries > self.maxtries:
329 raise socket.error("Too many attempts to send data")
330 self.wpending = s
331 else:
332 self.wpending += s
333 self.__nWrite(self.pendingWrite())
334 338
335 def writelines(self, lines): 339 def writelines(self, lines):
336 """ 340 """
337 Public method to write a list of strings to the file. 341 Public method to write a list of strings to the file.
338 342
339 @param lines list of texts to be written (list of string) 343 @param lines list of texts to be written
344 @type list of str
340 """ 345 """
341 self.write("".join(lines)) 346 self.write("".join(lines))
342 347
343 # 348 #
344 # eflag: noqa = M702 349 # eflag: noqa = M702

eric ide

mercurial