def _process_output_no_watchers( # pylint: disable=too-many-arguments session: Session, channel: Channel, encoding: str, stdout_stream: StringIO, stderr_stream: StringIO, timeout: NullableTiming, timeout_read_data_chunk: NullableTiming) -> bool: eof_result = stdout_size = stderr_size = LIBSSH2_ERROR_EAGAIN if timeout: end_time = perf_counter() + timeout else: end_time = float_info.max while eof_result == LIBSSH2_ERROR_EAGAIN or stdout_size == LIBSSH2_ERROR_EAGAIN or stdout_size > 0 or \ stderr_size == LIBSSH2_ERROR_EAGAIN or stderr_size > 0: # pylint: disable=consider-using-in if perf_counter() > end_time: return False with session.lock: if stdout_size == LIBSSH2_ERROR_EAGAIN and stderr_size == LIBSSH2_ERROR_EAGAIN: # pylint: disable=consider-using-in session.simple_select(timeout=timeout_read_data_chunk) eof_result = channel.wait_eof() stdout_size, stdout_chunk = channel.read() stderr_size, stderr_chunk = channel.read_stderr() if stdout_chunk and stdout_stream is not None: stdout_stream.write(stdout_chunk.decode(encoding)) if stderr_chunk and stderr_stream is not None: stderr_stream.write(stderr_chunk.decode(encoding)) return True
def _read_output( # pylint: disable=too-many-arguments,too-many-branches self, session: Session, channel: Channel, timeout: NullableTiming, timeout_read_data: NullableTiming, stdout_stream: Queue, stderr_stream: Queue): """Reads data from ssh session, split it into lines and forward lines into stderr ad stdout pipes It is required for it to be fast, that is why there is code duplications and non-pythonic code """ # pylint: disable=too-many-locals stdout_remainder = stderr_remainder = b'' if timeout is None: end_time = float_info.max else: end_time = perf_counter() + timeout eof_result = stdout_size = stderr_size = 1 while eof_result == LIBSSH2_ERROR_EAGAIN or stdout_size == LIBSSH2_ERROR_EAGAIN or \ stdout_size > 0 or stderr_size == LIBSSH2_ERROR_EAGAIN or stderr_size > 0: # pylint: disable=consider-using-in if not self._can_run.is_set(): break if perf_counter() > end_time: self.timeout_reached = True break with session.lock: if stdout_size == LIBSSH2_ERROR_EAGAIN and stderr_size == LIBSSH2_ERROR_EAGAIN: # pylint: disable=consider-using-in session.simple_select(timeout=timeout_read_data) stdout_size, stdout_chunk = channel.read() stderr_size, stderr_chunk = channel.read_stderr() eof_result = channel.eof() if stdout_chunk and stdout_stream is not None: data_splitted = stdout_chunk.split(LINESEP) if len(data_splitted) == 1: stdout_remainder = stdout_remainder + data_splitted.pop() else: if stdout_remainder: stdout_stream.put(stdout_remainder + data_splitted.pop(0)) stdout_remainder = data_splitted.pop() for chunk in data_splitted: stdout_stream.put(chunk) if stderr_chunk and stderr_stream is not None: data_splitted = stderr_chunk.split(LINESEP) if len(data_splitted) == 1: stderr_remainder = stderr_remainder + data_splitted.pop() else: if stderr_remainder: stderr_stream.put(stderr_remainder + data_splitted.pop(0)) stderr_remainder = data_splitted.pop() for chunk in data_splitted: stderr_stream.put(chunk) if stdout_remainder: stdout_stream.put(stdout_remainder) if stderr_remainder: stderr_stream.put(stderr_remainder)
def drop_channel(self, channel: Channel): if channel in self.channels: self.channels.remove(channel) try: channel.close() except: # pylint: disable=bare-except pass try: channel.wait_closed() except: # pylint: disable=bare-except pass del channel
def _complete_run(self, channel: Channel, exception: Exception, # pylint: disable=too-many-arguments timeout_reached: NullableTiming, timeout: NullableTiming, result: Result, warn, # pylint: disable=redefined-outer-name stdout: StringIO, stderr: StringIO) -> Result: """Complete executing command and return result, no matter what had happened. """ exit_status = None result.stdout = stdout.getvalue() result.stderr = stderr.getvalue() if channel is not None: try: self.session.eagain(channel.close, timeout=self.timings.channel_close_timeout) except Exception as exc: # pylint: disable=broad-except print(f'Failed to close channel due to the following error: {exc}') try: self.session.eagain(channel.wait_closed, timeout=self.timings.channel_close_timeout) except Exception as exc: # pylint: disable=broad-except print(f'Failed to close channel due to the following error: {exc}') exit_status = channel.get_exit_status() self.session.drop_channel(channel) result.exited = exit_status if exception: raise exception if timeout_reached: raise CommandTimedOut(result, timeout) if not warn: if exit_status != 0: raise UnexpectedExit(result) return result
from ssh2.session import Session from ssh2.channel import Channel s = Session() c = Channel(s)
def _apply_env(channel: Channel, env: Dict[str, str]): if env: for var, val in env.items(): channel.setenv(str(var), str(val))