Skip to content

Commit

Permalink
client: spawn: refactor: change stdin to string
Browse files Browse the repository at this point in the history
  • Loading branch information
doronz88 committed Feb 21, 2022
1 parent 398bb99 commit b927e02
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 13 deletions.
20 changes: 11 additions & 9 deletions src/rpcclient/rpcclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
except ImportError:
logging.warning('termios not available on your system. some functionality may not work as expected')

io_or_str = typing.TypeVar('io_or_str', typing.IO, str)

SpawnResult = namedtuple('SpawnResult', 'error pid stdout')

INVALID_PID = 0xffffffff
Expand Down Expand Up @@ -200,16 +202,16 @@ def get_dummy_block(self) -> Symbol:
self._sock.sendall(message)
return self.symbol(dummy_block_t.parse(self._recvall(8)))

def spawn(self, argv: typing.List[str] = None, envp: typing.List[str] = None, stdin=sys.stdin, stdout=sys.stdout,
tty=False, background=False) -> SpawnResult:
def spawn(self, argv: typing.List[str] = None, envp: typing.List[str] = None, stdin: io_or_str = sys.stdin,
stdout=sys.stdout, raw_tty=False, background=False) -> SpawnResult:
"""
spawn a new process and forward its stdin, stdout & stderr
:param argv: argv of the process to be executed
:param envp: envp of the process to be executed
:param stdin: either a file object to read from or a string
:param stdin: either a file object to read from OR a string
:param stdout: a file object to write both stdout and stderr to
:param tty: should enable raw tty mode
:param raw_tty: should enable raw tty mode
:param background: should execute process in background
:return: a SpawnResult. error is None if background is requested
"""
Expand All @@ -235,19 +237,19 @@ def spawn(self, argv: typing.List[str] = None, envp: typing.List[str] = None, st

self._sock.setblocking(False)

if tty:
if raw_tty:
self._prepare_terminal()
try:
error = self._execution_loop(stdin, stdout)
except Exception: # noqa: E722
# this is important to really catch every exception here, even exceptions not inheriting from Exception
# so the controlling terminal will remain working with its previous settings
if tty:
if raw_tty:
self._restore_terminal()
self.reconnect()
raise

if tty:
if raw_tty:
self._restore_terminal()
self.reconnect()

Expand Down Expand Up @@ -402,7 +404,7 @@ def _recvall(self, size: int) -> bytes:
buf += chunk
return buf

def _execution_loop(self, stdin=sys.stdin, stdout=sys.stdout):
def _execution_loop(self, stdin: io_or_str = sys.stdin, stdout=sys.stdout):
"""
if stdin is a file object, we need to select between the fds and give higher priority to stdin.
otherwise, we can simply write all stdin contents directly to the process
Expand All @@ -412,7 +414,7 @@ def _execution_loop(self, stdin=sys.stdin, stdout=sys.stdout):
fds.append(stdin)
else:
# assume it's just raw bytes
self._sock.sendall(stdin)
self._sock.sendall(stdin.encode())
fds.append(self._sock)

while True:
Expand Down
2 changes: 1 addition & 1 deletion src/rpcclient/tests/test_processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ def test_list_sanity(client):

def test_get_process_by_listening_port(client):
# there should only be one process listening on this port and that's us
assert client.processes.get_process_by_listening_port(DEFAULT_PORT).pid == client.symbols.getpid()
assert client.processes.get_process_by_listening_port(DEFAULT_PORT).pid == client.pid
6 changes: 3 additions & 3 deletions src/rpcclient/tests/test_spawn.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
])
def test_spawn_sanity(client, argv, expected_stdout, errorcode):
stdout = StringIO()
assert errorcode == client.spawn(argv, stdout=stdout, stdin=b'').error
assert errorcode == client.spawn(argv, stdout=stdout, stdin='').error

stdout.seek(0)
assert expected_stdout == stdout.read().strip()
Expand All @@ -18,14 +18,14 @@ def test_spawn_sanity(client, argv, expected_stdout, errorcode):
def test_spawn_bad_value_stress(client):
for i in range(100):
stdout = StringIO()
assert 256 == client.spawn(['/bin/ls', 'INVALID_PATH'], stdout=stdout, stdin=b'').error
assert 256 == client.spawn(['/bin/ls', 'INVALID_PATH'], stdout=stdout, stdin='').error

stdout.seek(0)
assert 'ls: INVALID_PATH: No such file or directory' == stdout.read().strip()


def test_spawn_background(client):
spawn_result = client.spawn(['/bin/sleep', '5'], stdout=StringIO(), stdin=b'', background=True)
spawn_result = client.spawn(['/bin/sleep', '5'], stdout=StringIO(), stdin='', background=True)

# when running in background, no error is returned
assert spawn_result.error is None
Expand Down

0 comments on commit b927e02

Please sign in to comment.