From 0157f74a31adc1bd999ea5e5bc3a9c34af90b98c Mon Sep 17 00:00:00 2001 From: Prasanna Kumar Kalever Date: Thu, 2 Apr 2020 16:03:57 +0530 Subject: [PATCH] Fix StringIO/BytesIO stuck issue We all know the way python3 handles strings is a bit different. $ python2 Python 2.7.16 (default, Apr 30 2019, 15:54:43) [GCC 9.0.1 20190312 (Red Hat 9.0.1-0.10)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import io >>> s=io.BytesIO() >>> s.write('hello') 5L >>> s.getvalue() 'hello' >>> s=io.StringIO() >>> s.write('hello') Traceback (most recent call last): File "", line 1, in TypeError: unicode argument expected, got 'str' >>> s.write(u'hello') 5L >>> s.getvalue() u'hello' >>> $ python3 Python 3.6.8 (default, Dec 5 2019, 15:45:45) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import io >>> s=io.BytesIO() >>> s.write('hello') Traceback (most recent call last): File "", line 1, in TypeError: a bytes-like object is required, not 'str' >>> s.write(b'hello') 5 >>> s.getvalue() b'hello' >>> s=io.StringIO() >>> s.write('hello') 5 >>> s.getvalue() 'hello' >>> The way Python2 and Python3 handles String and Bytes IO is different. * In Python2 BytesIO() accepts text format syntax, and StringIO() expects unicodes * While in Python3 StringIO() accepts text format syntax, and BytesIO() expects bytes like objects I think the compatibility of using both the IO streams with python2 and python3 is compromised. Hence this patch, uses BytesIO() and StringIO() based on python version. Signed-off-by: Prasanna Kumar Kalever --- daemon/targetclid | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/daemon/targetclid b/daemon/targetclid index d4c6562..5df6ca2 100755 --- a/daemon/targetclid +++ b/daemon/targetclid @@ -32,9 +32,13 @@ import struct import fcntl import signal import errno -import io +if sys.version_info < (3, 0): + from io import BytesIO as StringIO +else: + from io import StringIO + err = sys.stderr class TargetCLI: @@ -154,24 +158,23 @@ class TargetCLI: connection.close() still_listen = False else: - self.con._stdout = self.con._stderr = f = io.BytesIO() + self.con._stdout = self.con._stderr = f = StringIO() try: # extract multiple commands delimited with '%' list_data = data.decode().split('%') for cmd in list_data: self.shell.run_cmdline(cmd) except Exception as e: - print(str(e), file=f) # push error to stream + print(str(e).encode(), file=f) # push error to stream # Restore self.con._stdout = self.con_stdout_ self.con._stderr = self.con_stderr_ - - output = f.getvalue() + output = f.getvalue().encode() var = struct.pack('i', len(output)) connection.sendall(var) # length of string if len(output): - connection.sendall(output.encode()) # actual string + connection.sendall(output) # actual string f.close() -- 2.21.0