--- a/src/eric7/DebugClients/Python/AsyncFile.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/DebugClients/Python/AsyncFile.py Wed Jul 13 14:55:47 2022 +0200 @@ -18,7 +18,7 @@ def AsyncPendingWrite(file): """ Module function to check for data to be written. - + @param file The file object to be checked @type file @return Flag indicating if there is data waiting @@ -36,15 +36,16 @@ """ Class wrapping a socket object with a file interface. """ + MAX_TRIES = 10 - - BUFSIZE = 2 ** 14 # 16 kBytes - CMD_BUFSIZE = 2 ** 12 # 4 kBytes - + + BUFSIZE = 2**14 # 16 kBytes + CMD_BUFSIZE = 2**12 # 4 kBytes + def __init__(self, sock, mode, name): """ Constructor - + @param sock the socket object being wrapped @type socket @param mode mode of this file @@ -62,28 +63,28 @@ self.errors = None self.newlines = None self.line_buffering = False - + self.writeLock = threading.RLock() self.wpending = [] def __checkMode(self, mode): """ Private method to check the mode. - + This method checks, if an operation is permitted according to the mode of the file. If it is not, an OSError is raised. - + @param mode the mode to be checked @type string @exception OSError raised to indicate a bad file descriptor """ if mode != self.mode: - raise OSError((9, '[Errno 9] Bad file descriptor')) + raise OSError((9, "[Errno 9] Bad file descriptor")) def pendingWrite(self): """ Public method that returns the number of strings waiting to be written. - + @return the number of strings to be written @rtype int """ @@ -92,7 +93,7 @@ def close(self, closeit=False): """ Public method to close the file. - + @param closeit flag to indicate a close ordered by the debugger code @type bool """ @@ -111,23 +112,22 @@ buf = self.wpending.pop(0) except IndexError: break - + try: - with contextlib.suppress(UnicodeEncodeError, - UnicodeDecodeError): - buf = buf.encode('utf-8', 'backslashreplace') + with contextlib.suppress(UnicodeEncodeError, UnicodeDecodeError): + buf = buf.encode("utf-8", "backslashreplace") self.sock.sendall(buf) self.nWriteErrors = 0 except OSError: self.nWriteErrors += 1 if self.nWriteErrors > AsyncFile.MAX_TRIES: - self.wpending = [] # delete all output + self.wpending = [] # delete all output self.writeLock.release() def isatty(self): """ Public method to indicate whether a tty interface is supported. - + @return always false @rtype bool """ @@ -136,7 +136,7 @@ def fileno(self): """ Public method returning the file number. - + @return file number @rtype int """ @@ -148,78 +148,78 @@ def readable(self): """ Public method to check, if the stream is readable. - + @return flag indicating a readable stream @rtype bool """ return self.mode == "r" - + def read_p(self, size=-1): """ Public method to read bytes from this file. - + @param size maximum number of bytes to be read @type int @return the bytes read @rtype str """ - self.__checkMode('r') + self.__checkMode("r") if size < 0: size = AsyncFile.BUFSIZE - return self.sock.recv(size).decode('utf8', 'backslashreplace') + return self.sock.recv(size).decode("utf8", "backslashreplace") def read(self, size=-1): """ Public method to read bytes from this file. - + @param size maximum number of bytes to be read @type int @return the bytes read @rtype str """ - self.__checkMode('r') + self.__checkMode("r") - buf = input() # secok + buf = input() # secok if size >= 0: buf = buf[:size] return buf - + def readCommand(self): """ Public method to read a length prefixed command string. - + @return command string @rtype str """ # The command string is prefixed by a 9 character long length field. length = self.sock.recv(9) length = int(length) - data = b'' + data = b"" while len(data) < length: remaining = length - len(data) newBytes = self.sock.recv(min(remaining, AsyncFile.CMD_BUFSIZE)) data += newBytes - if newBytes[-1] == b'\n': + if newBytes[-1] == b"\n": break - + # step 2: convert the data - return data.decode('utf8', 'backslashreplace') - + return data.decode("utf8", "backslashreplace") + def readline_p(self, size=-1): """ Public method to read a line from this file. - + <b>Note</b>: This method will not block and may return only a part of a line if that is all that is available. - + @param size maximum number of bytes to be read @type int @return one line of text up to size bytes @rtype str """ - self.__checkMode('r') + self.__checkMode("r") if size < 0: size = AsyncFile.BUFSIZE @@ -230,22 +230,22 @@ # read a line at a time. line = self.sock.recv(size, socket.MSG_PEEK) - eol = line.find(b'\n') + eol = line.find(b"\n") size = eol + 1 if eol >= 0 else len(line) # Now we know how big the line is, read it for real. - return self.sock.recv(size).decode('utf8', 'backslashreplace') + return self.sock.recv(size).decode("utf8", "backslashreplace") def readlines(self, sizehint=-1): """ Public method to read all lines from this file. - + @param sizehint hint of the numbers of bytes to be read @type int @return list of lines read @rtype list of str """ - self.__checkMode('r') + self.__checkMode("r") lines = [] room = sizehint @@ -270,32 +270,32 @@ def readline(self, sizehint=-1): """ Public method to read one line from this file. - + @param sizehint hint of the numbers of bytes to be read @type int @return one line read @rtype str """ - self.__checkMode('r') + self.__checkMode("r") - line = input() + '\n' # secok + line = input() + "\n" # secok if sizehint >= 0: line = line[:sizehint] return line - + def seekable(self): """ Public method to check, if the stream is seekable. - + @return flag indicating a seekable stream @rtype bool """ return False - + def seek(self, offset, whence=0): """ Public method to move the filepointer. - + @param offset offset to move the filepointer to @type int @param whence position the offset relates to @@ -303,67 +303,70 @@ @exception OSError This method is not supported and always raises an OSError. """ - raise OSError((29, '[Errno 29] Illegal seek')) + raise OSError((29, "[Errno 29] Illegal seek")) def tell(self): """ Public method to get the filepointer position. - + @exception OSError This method is not supported and always raises an OSError. """ - raise OSError((29, '[Errno 29] Illegal seek')) + raise OSError((29, "[Errno 29] Illegal seek")) def truncate(self, size=-1): """ Public method to truncate the file. - + @param size size to truncate to @type int @exception OSError This method is not supported and always raises an OSError. """ - raise OSError((29, '[Errno 29] Illegal seek')) + raise OSError((29, "[Errno 29] Illegal seek")) def writable(self): """ Public method to check, if a stream is writable. - + @return flag indicating a writable stream @rtype bool """ return self.mode == "w" - + def write(self, s): """ Public method to write a string to the file. - + @param s text to be written @type str, bytes or bytearray """ - self.__checkMode('w') - + self.__checkMode("w") + self.writeLock.acquire() if isinstance(s, (bytes, bytearray)): # convert to string to send it s = repr(s) - - cmd = prepareJsonCommand("ClientOutput", { - "text": s, - "debuggerId": "", - }) + + cmd = prepareJsonCommand( + "ClientOutput", + { + "text": s, + "debuggerId": "", + }, + ) self.wpending.append(cmd) self.flush() self.writeLock.release() - + def write_p(self, s): """ Public method to write a json-rpc 2.0 coded string to the file. - + @param s text to be written @type str """ - self.__checkMode('w') + self.__checkMode("w") self.wpending.append(s) self.flush() @@ -371,7 +374,7 @@ def writelines(self, lines): """ Public method to write a list of strings to the file. - + @param lines list of texts to be written @type list of str """