Skip to content

tox 4: support isatty on stdout/stderr #1773

Closed
@gaborbernat

Description

@gaborbernat

Why? mypy and pytest both use this flag to enable color output support.

Instead of using subprocess.PIPE we could pass in the openpty child handler (which would also allow directly setting the termios information on the stream), but once done that the stdin echo seems to no longer buffer realtime, and is instead only line-buffered. This is bad for interacting with the GDB as you can't see what you're typing. Need to understand why, and fix it (if possible).

Code for LocalSubProcessExecuteInstance.get_stream_file_no:

# on UNIX let's forward it via a pseudo terminal to allow host streams traits to be inherited
try:
    import pty

    main, child = pty.openpty()
except OSError:  # abort if could not open a tty  # pragma: no cover
    pass  # pragma: no cover
else:
    try:
        import termios

        mode = termios.tcgetattr(stream)
        termios.tcsetattr(child, termios.TCSANOW, mode)
    except OSError:  # abort if could inherit traits  # pragma: no cover
        pass  # pragma: no cover
    else:
        if columns != -1 and lines != -1:
            import fcntl
            import struct

            size = struct.pack("HHHH", columns, lines, 0, 0)
            fcntl.ioctl(child, termios.TIOCSWINSZ, size)
        yield child

        # the stream will be written by the subprocess - not by us, so on our end we can close it
        os.close(child)
        yield main  # drain content from main

Code to test with:

import shutil
import sys
import termios
import threading
import time


def _run():
    for i in range(10000):
        time.sleep(1)


thread = threading.Thread(target=_run)
thread.daemon = True
thread.start()

print("----------- START -----------------")
print(f'stdout {sys.stdout.isatty()}')
print(f'stderr {sys.stderr.isatty()}')
print(f'stdin {sys.stdin.isatty()}')

print(shutil.get_terminal_size())
print(termios.tcgetattr(sys.stdin))

print("----------- BREAKPOINT -----------------")
breakpoint()

Of interest links:

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature:newsomething does not exist yet, but shouldtox4

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions