Ejemplo n.º 1
0
    def test_write(self):
        timing = []
        stdout = Stdout(timing)

        stdout.write(b'foo')
        stdout.write(b'barbaz')

        assert_equal(b'foobarbaz', stdout.data)
        assert_equal([[2, 3], [7, 6]], timing)
Ejemplo n.º 2
0
    def test_write(self):
        stdout = Stdout()

        stdout.write(b'foo')
        stdout.write(b'barbaz')
        stdout.write('żó'.encode('utf-8') + bytes([0xc5]))
        stdout.write(bytes([0x82]) + 'ć'.encode('utf-8'))

        assert_equal([[2, 'foo'], [7, 'barbaz'], [3, 'żó'], [4, 'łć']], stdout.frames)
Ejemplo n.º 3
0
    def test_close(self):
        stdout = Stdout()

        stdout.write(b'foo')
        stdout.write(b'barbaz')
        stdout.close()

        assert_equal(12, stdout.duration)
Ejemplo n.º 4
0
    def test_write(self):
        timing = []
        stdout = Stdout(timing)

        stdout.write(b'foo')
        stdout.write(b'barbaz')

        assert_equal(b'foobarbaz', stdout.data)
        assert_equal([[2, 3], [7, 6]], timing)
Ejemplo n.º 5
0
    def test_close(self):
        stdout = Stdout()

        stdout.close()

        assert_raises(ValueError, stdout.write, 'qux')
Ejemplo n.º 6
0
    def record_command(self, command, output=None):
        command = shlex.split(command)
        output = output if output is not None else Stdout()
        master_fd = None

        def _set_pty_size():
            '''
            Sets the window size of the child pty based on the window size
            of our own controlling terminal.
            '''

            # Get the terminal size of the real terminal, set it on the pseudoterminal.
            if os.isatty(pty.STDOUT_FILENO):
                buf = array.array('h', [0, 0, 0, 0])
                fcntl.ioctl(pty.STDOUT_FILENO, termios.TIOCGWINSZ, buf, True)
                fcntl.ioctl(master_fd, termios.TIOCSWINSZ, buf)
            else:
                buf = array.array('h', [24, 80, 0, 0])
                fcntl.ioctl(master_fd, termios.TIOCSWINSZ, buf)

        def _signal_winch(signal, frame):
            '''Signal handler for SIGWINCH - window size has changed.'''

            _set_pty_size()

        def _write_stdout(data):
            '''Writes to stdout as if the child process had written the data.'''

            os.write(pty.STDOUT_FILENO, data)

        def _handle_master_read(data):
            '''Handles new data on child process stdout.'''

            _write_stdout(data)
            output.write(data)

        def _write_master(data):
            '''Writes to the child process from its controlling terminal.'''

            while data:
                n = os.write(master_fd, data)
                data = data[n:]

        def _handle_stdin_read(data):
            '''Handles new data on child process stdin.'''

            _write_master(data)

        def _copy():
            '''Main select loop.

            Passes control to _master_read() or _stdin_read()
            when new data arrives.
            '''

            while 1:
                try:
                    rfds, wfds, xfds = select.select(
                        [master_fd, pty.STDIN_FILENO], [], [])
                except select.error as e:
                    if e[0] == 4:  # Interrupted system call.
                        continue

                if master_fd in rfds:
                    data = os.read(master_fd, 1024)

                    if len(data) == 0:
                        break

                    _handle_master_read(data)

                if pty.STDIN_FILENO in rfds:
                    data = os.read(pty.STDIN_FILENO, 1024)
                    _handle_stdin_read(data)

        pid, master_fd = pty.fork()

        if pid == pty.CHILD:
            os.execlp(command[0], *command)

        old_handler = signal.signal(signal.SIGWINCH, _signal_winch)

        try:
            mode = tty.tcgetattr(pty.STDIN_FILENO)
            tty.setraw(pty.STDIN_FILENO)
            restore = 1
        except tty.error:  # This is the same as termios.error
            restore = 0

        _set_pty_size()

        try:
            _copy()
        except (IOError, OSError):
            if restore:
                tty.tcsetattr(pty.STDIN_FILENO, tty.TCSAFLUSH, mode)

        os.close(master_fd)
        signal.signal(signal.SIGWINCH, old_handler)

        return output
Ejemplo n.º 7
0
    def test_close(self):
        stdout = Stdout()

        stdout.close()

        assert_raises(ValueError, stdout.write, 'qux')