107 Public method to write all pending entries. |
109 Public method to write all pending entries. |
108 """ |
110 """ |
109 self.writeLock.acquire() |
111 self.writeLock.acquire() |
110 while self.wpending: |
112 while self.wpending: |
111 try: |
113 try: |
112 buf = self.wpending.pop(0) |
114 data = self.wpending.pop(0) |
113 except IndexError: |
115 except IndexError: |
114 break |
116 break |
115 |
117 |
116 try: |
118 try: |
117 with contextlib.suppress(UnicodeEncodeError, UnicodeDecodeError): |
119 with contextlib.suppress(UnicodeEncodeError, UnicodeDecodeError): |
118 buf = buf.encode("utf-8", "backslashreplace") |
120 data = data.encode("utf-8", "backslashreplace") |
119 self.sock.sendall(buf) |
121 header = struct.pack(b"!II", len(data), zlib.adler32(data) & 0xFFFFFFFF) |
|
122 self.sock.sendall(header) |
|
123 self.sock.sendall(data) |
120 self.nWriteErrors = 0 |
124 self.nWriteErrors = 0 |
121 except OSError: |
125 except OSError: |
122 self.nWriteErrors += 1 |
126 self.nWriteErrors += 1 |
123 if self.nWriteErrors > AsyncFile.MAX_TRIES: |
127 if self.nWriteErrors > AsyncFile.MAX_TRIES: |
124 self.wpending = [] # delete all output |
128 self.wpending = [] # delete all output |
186 buf = buf[:size] |
190 buf = buf[:size] |
187 return buf |
191 return buf |
188 |
192 |
189 def readCommand(self): |
193 def readCommand(self): |
190 """ |
194 """ |
191 Public method to read a length prefixed command string. |
195 Public method to read a command string prefixed by a command header. |
192 |
196 |
193 @return command string |
197 @return command string |
194 @rtype str |
198 @rtype str |
195 """ |
199 """ |
196 # The command string is prefixed by a 9 character long length field. |
200 header = self.sock.recv(struct.calcsize(b"!II")) |
197 length = self.sock.recv(9) |
201 if header: |
198 length = int(length) |
202 length, datahash = struct.unpack(b"!II", header) |
199 data = b"" |
203 |
200 while len(data) < length: |
204 length = int(length) |
201 remaining = length - len(data) |
205 data = bytearray() |
202 newBytes = self.sock.recv(min(remaining, AsyncFile.CMD_BUFSIZE)) |
206 while len(data) < length: |
203 data += newBytes |
207 newData = self.sock.recv(length - len(data)) |
204 if newBytes[-1] == b"\n": |
208 data += newData |
205 break |
209 if not newData: |
206 |
210 break |
207 # step 2: convert the data |
211 |
208 return data.decode("utf8", "backslashreplace") |
212 if data and zlib.adler32(data) & 0xFFFFFFFF == datahash: |
|
213 return data.decode("utf8", "backslashreplace") |
|
214 |
|
215 return "" |
209 |
216 |
210 def readline_p(self, size=-1): |
217 def readline_p(self, size=-1): |
211 """ |
218 """ |
212 Public method to read a line from this file. |
219 Public method to read a line from this file. |
213 |
220 |
346 self.writeLock.acquire() |
353 self.writeLock.acquire() |
347 if isinstance(s, (bytes, bytearray)): |
354 if isinstance(s, (bytes, bytearray)): |
348 # convert to string to send it |
355 # convert to string to send it |
349 s = repr(s) |
356 s = repr(s) |
350 |
357 |
351 cmd = prepareJsonCommand( |
358 jsonCommand = prepareJsonCommand( |
352 "ClientOutput", |
359 "ClientOutput", |
353 { |
360 { |
354 "text": s, |
361 "text": s, |
355 "debuggerId": "", |
362 "debuggerId": "", |
356 }, |
363 }, |
357 ) |
364 ) |
358 self.wpending.append(cmd) |
365 self.wpending.append(jsonCommand) |
359 self.flush() |
366 self.flush() |
360 self.writeLock.release() |
367 self.writeLock.release() |
361 |
368 |
362 def write_p(self, s): |
369 def write_p(self, s): |
363 """ |
370 """ |