def test_isatty_from_env(self): self.assertEqual( NailgunProtocol.isatty_from_env({ 'NAILGUN_TTY_0': '1', 'NAILGUN_TTY_1': '0', 'NAILGUN_TTY_2': '1' }), (True, False, True))
def test_isatty_from_env(self): self.assertEqual( NailgunProtocol.isatty_from_env( {"NAILGUN_TTY_0": "1", "NAILGUN_TTY_1": "0", "NAILGUN_TTY_2": "1"} ), (True, False, True), )
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env( self._env) # Launch a thread to read stdin data from the socket (the only messages expected from the client # for the remainder of the protocol), and threads to copy from stdout/stderr pipes onto the # socket. with NailgunStreamWriter.open_multi( sock, (ChunkType.STDOUT, ChunkType.STDERR), None, (stdout_isatty, stderr_isatty) ) as ((stdout_fd, stderr_fd), writer),\ NailgunStreamStdinReader.open(sock, stdin_isatty) as stdin_fd,\ stdio_as(stdout_fd=stdout_fd, stderr_fd=stderr_fd, stdin_fd=stdin_fd): # N.B. This will be passed to and called by the `DaemonExiter` prior to sending an # exit chunk, to avoid any socket shutdown vs write races. stdout, stderr = sys.stdout, sys.stderr def finalizer(): try: stdout.flush() stderr.flush() finally: time.sleep( .001 ) # HACK: Sleep 1ms in the main thread to free the GIL. writer.stop() writer.join() stdout.close() stderr.close() yield finalizer
def test_isatty_from_env_mixed(self): self.assertEquals( NailgunProtocol.isatty_from_env({ 'NAILGUN_TTY_0': '0', 'NAILGUN_TTY_1': '1' }), (False, True, False) )
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(self._env) if all((stdin_isatty, stdout_isatty, stderr_isatty)): with self._tty_stdio() as finalizer: yield finalizer else: with self._pipe_stdio(sock, stdin_isatty, stdout_isatty, stderr_isatty) as finalizer: yield finalizer
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(self._env) if all((stdin_isatty, stdout_isatty, stderr_isatty)): with self._tty_stdio() as finalizer: yield finalizer else: with self._pipe_stdio(sock, stdin_isatty, stdout_isatty, stderr_isatty) as finalizer: yield finalizer
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env( self._env) # If all stdio is a tty, there's only one logical I/O device (the tty device). This happens to # be addressable as a file in OSX and Linux, so we take advantage of that and directly open the # character device for output redirection - eliminating the need to directly marshall any # interactive stdio back/forth across the socket and permitting full, correct tty control with # no middle-man. if all((stdin_isatty, stdout_isatty, stderr_isatty)): stdin_ttyname, stdout_ttyname, stderr_ttyname = NailgunProtocol.ttynames_from_env( self._env) assert stdin_ttyname == stdout_ttyname == stderr_ttyname, ( 'expected all stdio ttys to be the same, but instead got: {}\n' 'please file a bug at http://github.com/pantsbuild/pants'. format([stdin_ttyname, stdout_ttyname, stderr_ttyname])) with open(stdin_ttyname, 'rb+wb', 0) as tty: tty_fileno = tty.fileno() with stdio_as(stdin_fd=tty_fileno, stdout_fd=tty_fileno, stderr_fd=tty_fileno): def finalizer(): termios.tcdrain(tty_fileno) yield finalizer else: stdio_writers = ((ChunkType.STDOUT, stdout_isatty), (ChunkType.STDERR, stderr_isatty)) types, ttys = zip(*(stdio_writers)) with NailgunStreamStdinReader.open(sock, stdin_isatty) as stdin_fd,\ NailgunStreamWriter.open_multi(sock, types, ttys) as ((stdout_fd, stderr_fd), writer),\ stdio_as(stdout_fd=stdout_fd, stderr_fd=stderr_fd, stdin_fd=stdin_fd): # N.B. This will be passed to and called by the `DaemonExiter` prior to sending an # exit chunk, to avoid any socket shutdown vs write races. stdout, stderr = sys.stdout, sys.stderr def finalizer(): try: stdout.flush() stderr.flush() finally: time.sleep( .001 ) # HACK: Sleep 1ms in the main thread to free the GIL. writer.stop() writer.join() stdout.close() stderr.close() yield finalizer
def nailgunned_stdio(cls, sock, env, handle_stdin=True): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env( env) is_tty_capable = all((stdin_isatty, stdout_isatty, stderr_isatty)) if is_tty_capable: with cls._tty_stdio(env) as finalizer: yield finalizer else: with cls._pipe_stdio(sock, stdin_isatty, stdout_isatty, stderr_isatty, handle_stdin) as finalizer: yield finalizer
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env( self._env) # Launch a thread to read stdin data from the socket (the only messages expected from the client # for the remainder of the protocol), and threads to copy from stdout/stderr pipes onto the # socket. with NailgunStreamStdinReader.open(sock, isatty=stdin_isatty) as stdin,\ NailgunStreamWriter.open(sock, ChunkType.STDOUT, None, isatty=stdout_isatty) as stdout,\ NailgunStreamWriter.open(sock, ChunkType.STDERR, None, isatty=stderr_isatty) as stderr: with stdio_as(stdout=stdout, stderr=stderr, stdin=stdin): yield
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. _, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(self._env) # TODO(kwlzn): Implement remote input reading and fix the non-fork()-safe sys.stdin reference # in NailgunClient to enable support for interactive goals like `repl` etc. # Construct StreamWriters for stdout, stderr. streams = ( NailgunStreamWriter(sock, ChunkType.STDOUT, isatty=stdout_isatty), NailgunStreamWriter(sock, ChunkType.STDERR, isatty=stderr_isatty) ) # Launch the stdin StreamReader and redirect stdio. with stdio_as(*streams): yield
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. _, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(self._env) # TODO(kwlzn): Implement remote input reading and fix the non-fork()-safe sys.stdin reference # in NailgunClient to enable support for interactive goals like `repl` etc. # Construct StreamWriters for stdout, stderr. streams = ( NailgunStreamWriter(sock, ChunkType.STDOUT, isatty=stdout_isatty), NailgunStreamWriter(sock, ChunkType.STDERR, isatty=stderr_isatty) ) # Launch the stdin StreamReader and redirect stdio. with stdio_as(*streams): yield
def nailgunned_stdio(cls, sock, env, handle_stdin=True): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. stdin_isatty, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(env) is_tty_capable = all((stdin_isatty, stdout_isatty, stderr_isatty)) if is_tty_capable: with cls._tty_stdio(env) as finalizer: yield finalizer else: with cls._pipe_stdio( sock, stdin_isatty, stdout_isatty, stderr_isatty, handle_stdin ) as finalizer: yield finalizer
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. _, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env(self._env) # Construct a StreamReader for stdin. stdin_reader = NailgunStreamReader(sys.stdin, sock) # Construct StreamWriters for stdout, stderr. streams = ( NailgunStreamWriter(sock, ChunkType.STDOUT, isatty=stdout_isatty), NailgunStreamWriter(sock, ChunkType.STDERR, isatty=stderr_isatty), stdin_reader ) # Launch the stdin StreamReader and redirect stdio. with stdin_reader.running(), stdio_as(*streams): yield
def _nailgunned_stdio(self, sock): """Redirects stdio to the connected socket speaking the nailgun protocol.""" # Determine output tty capabilities from the environment. _, stdout_isatty, stderr_isatty = NailgunProtocol.isatty_from_env( self._env) # Construct a StreamReader for stdin. stdin_reader = NailgunStreamReader(sys.stdin, sock) # Construct StreamWriters for stdout, stderr. streams = (NailgunStreamWriter(sock, ChunkType.STDOUT, isatty=stdout_isatty), NailgunStreamWriter(sock, ChunkType.STDERR, isatty=stderr_isatty), stdin_reader) # Launch the stdin StreamReader and redirect stdio. with stdin_reader.running(), stdio_as(*streams): yield
def test_isatty_from_empty_env(self): self.assertEquals(NailgunProtocol.isatty_from_env({}), (False, False, False))