DebugClients/Python/AsyncFile.py

branch
jsonrpc
changeset 5132
a094eee9f862
parent 4631
5c1a96925da4
equal deleted inserted replaced
5131:889ed5ff7a68 5132:a094eee9f862
8 debugger. 8 debugger.
9 """ 9 """
10 10
11 import socket 11 import socket
12 12
13 from DebugProtocol import EOT 13 from DebugUtilities import prepareJsonCommand
14 14
15 15
16 def AsyncPendingWrite(file): 16 def AsyncPendingWrite(file):
17 """ 17 """
18 Module function to check for data to be written. 18 Module function to check for data to be written.
42 @param sock the socket object being wrapped 42 @param sock the socket object being wrapped
43 @param mode mode of this file (string) 43 @param mode mode of this file (string)
44 @param name name of this file (string) 44 @param name name of this file (string)
45 """ 45 """
46 # Initialise the attributes. 46 # Initialise the attributes.
47 self.closed = 0 47 self.closed = False
48 self.sock = sock 48 self.sock = sock
49 self.mode = mode 49 self.mode = mode
50 self.name = name 50 self.name = name
51 self.nWriteErrors = 0 51 self.nWriteErrors = 0
52 self.encoding = "utf-8" 52 self.encoding = "utf-8"
72 72
73 @param n the number of bytes to be written (int) 73 @param n the number of bytes to be written (int)
74 """ 74 """
75 if n: 75 if n:
76 try: 76 try:
77 buf = "%s%s" % (self.wpending[:n], EOT) 77 buf = self.wpending[:n]
78 try: 78 try:
79 buf = buf.encode('utf-8') 79 buf = buf.encode('utf-8', 'backslashreplace')
80 except (UnicodeEncodeError, UnicodeDecodeError): 80 except (UnicodeEncodeError, UnicodeDecodeError):
81 pass 81 pass
82 self.sock.sendall(buf) 82 self.sock.sendall(buf)
83 self.wpending = self.wpending[n:] 83 self.wpending = self.wpending[n:]
84 self.nWriteErrors = 0 84 self.nWriteErrors = 0
93 93
94 @return the number of bytes to be written (int) 94 @return the number of bytes to be written (int)
95 """ 95 """
96 return self.wpending.rfind('\n') + 1 96 return self.wpending.rfind('\n') + 1
97 97
98 def close(self, closeit=0): 98 def close(self, closeit=False):
99 """ 99 """
100 Public method to close the file. 100 Public method to close the file.
101 101
102 @param closeit flag to indicate a close ordered by the debugger code 102 @param closeit flag to indicate a close ordered by the debugger code
103 (boolean) 103 (boolean)
104 """ 104 """
105 if closeit and not self.closed: 105 if closeit and not self.closed:
106 self.flush() 106 self.flush()
107 self.sock.close() 107 self.sock.close()
108 self.closed = 1 108 self.closed = True
109 109
110 def flush(self): 110 def flush(self):
111 """ 111 """
112 Public method to write all pending bytes. 112 Public method to write all pending bytes.
113 """ 113 """
117 """ 117 """
118 Public method to indicate whether a tty interface is supported. 118 Public method to indicate whether a tty interface is supported.
119 119
120 @return always false 120 @return always false
121 """ 121 """
122 return 0 122 return False
123 123
124 def fileno(self): 124 def fileno(self):
125 """ 125 """
126 Public method returning the file number. 126 Public method returning the file number.
127 127
130 try: 130 try:
131 return self.sock.fileno() 131 return self.sock.fileno()
132 except socket.error: 132 except socket.error:
133 return -1 133 return -1
134 134
135 def readable(self):
136 """
137 Public method to check, if the stream is readable.
138
139 @return flag indicating a readable stream (boolean)
140 """
141 return self.mode == "r"
142
135 def read_p(self, size=-1): 143 def read_p(self, size=-1):
136 """ 144 """
137 Public method to read bytes from this file. 145 Public method to read bytes from this file.
138 146
139 @param size maximum number of bytes to be read (int) 147 @param size maximum number of bytes to be read (int)
142 self.__checkMode('r') 150 self.__checkMode('r')
143 151
144 if size < 0: 152 if size < 0:
145 size = 20000 153 size = 20000
146 154
147 return self.sock.recv(size).decode('utf8') 155 return self.sock.recv(size).decode('utf8', 'backslashreplace')
148 156
149 def read(self, size=-1): 157 def read(self, size=-1):
150 """ 158 """
151 Public method to read bytes from this file. 159 Public method to read bytes from this file.
152 160
179 # to the debugger relies on the two lines of the debugger command being 187 # to the debugger relies on the two lines of the debugger command being
180 # delivered as two separate events. Therefore we make sure we only 188 # delivered as two separate events. Therefore we make sure we only
181 # read a line at a time. 189 # read a line at a time.
182 line = self.sock.recv(size, socket.MSG_PEEK) 190 line = self.sock.recv(size, socket.MSG_PEEK)
183 191
184 eol = line.find('\n') 192 eol = line.find(b'\n')
185 193
186 if eol >= 0: 194 if eol >= 0:
187 size = eol + 1 195 size = eol + 1
188 else: 196 else:
189 size = len(line) 197 size = len(line)
190 198
191 # Now we know how big the line is, read it for real. 199 # Now we know how big the line is, read it for real.
192 return self.sock.recv(size).decode('utf8') 200 return self.sock.recv(size).decode('utf8', 'backslashreplace')
193 201
194 def readlines(self, sizehint=-1): 202 def readlines(self, sizehint=-1):
195 """ 203 """
196 Public method to read all lines from this file. 204 Public method to read all lines from this file.
197 205
232 line = raw_input() + '\n' 240 line = raw_input() + '\n'
233 if sizehint >= 0: 241 if sizehint >= 0:
234 line = line[:sizehint] 242 line = line[:sizehint]
235 return line 243 return line
236 244
245 def seekable(self):
246 """
247 Public method to check, if the stream is seekable.
248
249 @return flag indicating a seekable stream (boolean)
250 """
251 return False
252
237 def seek(self, offset, whence=0): 253 def seek(self, offset, whence=0):
238 """ 254 """
239 Public method to move the filepointer. 255 Public method to move the filepointer.
240 256
241 @param offset offset to seek for 257 @param offset offset to seek for
262 @exception IOError This method is not supported and always raises an 278 @exception IOError This method is not supported and always raises an
263 IOError. 279 IOError.
264 """ 280 """
265 raise IOError('[Errno 29] Illegal seek') 281 raise IOError('[Errno 29] Illegal seek')
266 282
283 def writable(self):
284 """
285 Public method to check, if a stream is writable.
286
287 @return flag indicating a writable stream (boolean)
288 """
289 return self.mode == "w"
290
267 def write(self, s): 291 def write(self, s):
268 """ 292 """
269 Public method to write a string to the file. 293 Public method to write a string to the file.
270 294
271 @param s bytes to be written (string) 295 @param s bytes to be written (string)
296 """
297 self.__checkMode('w')
298
299 cmd = prepareJsonCommand("ClientOutput", {
300 "text": s,
301 })
302 self.write_p(cmd)
303
304 def write_p(self, s):
305 """
306 Public method to write a string to the file.
307
308 @param s text to be written (string)
272 @exception socket.error raised to indicate too many send attempts 309 @exception socket.error raised to indicate too many send attempts
273 """ 310 """
274 self.__checkMode('w') 311 self.__checkMode('w')
275 tries = 0 312 tries = 0
276 if not self.wpending: 313 if not self.wpending:
277 self.wpending = s 314 self.wpending = s
278 elif type(self.wpending) != type(s) or \ 315 elif len(self.wpending) + len(s) > self.maxbuffersize:
279 len(self.wpending) + len(s) > self.maxbuffersize: 316 # flush wpending if it is too big
280 # flush wpending so that different string types are not
281 # concatenated
282 while self.wpending: 317 while self.wpending:
283 # if we have a persistent error in sending the data, an 318 # if we have a persistent error in sending the data, an
284 # exception will be raised in __nWrite 319 # exception will be raised in __nWrite
285 self.flush() 320 self.flush()
286 tries += 1 321 tries += 1
289 self.wpending = s 324 self.wpending = s
290 else: 325 else:
291 self.wpending += s 326 self.wpending += s
292 self.__nWrite(self.pendingWrite()) 327 self.__nWrite(self.pendingWrite())
293 328
294 def writelines(self, list): 329 def writelines(self, lines):
295 """ 330 """
296 Public method to write a list of strings to the file. 331 Public method to write a list of strings to the file.
297 332
298 @param list the list to be written (list of string) 333 @param lines list of texts to be written (list of string)
299 """ 334 """
300 map(self.write, list) 335 self.write("".join(lines))
301 336
302 # 337 #
303 # eflag: FileType = Python2 338 # eflag: FileType = Python2
304 # eflag: noqa = M601, M702 339 # eflag: noqa = M601, M702

eric ide

mercurial