black: reformat entire repository with black
This commit is contained in:
@@ -31,21 +31,22 @@
|
||||
termios = None # type: Optional[ModuleType]
|
||||
try:
|
||||
import termios as term_mod
|
||||
|
||||
termios = term_mod
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
# Use this to strip escape sequences
|
||||
_escape = re.compile(r'\x1b[^m]*m|\x1b\[?1034h|\x1b\][0-9]+;[^\x07]*\x07')
|
||||
_escape = re.compile(r"\x1b[^m]*m|\x1b\[?1034h|\x1b\][0-9]+;[^\x07]*\x07")
|
||||
|
||||
# control characters for enabling/disabling echo
|
||||
#
|
||||
# We use control characters to ensure that echo enable/disable are inline
|
||||
# with the other output. We always follow these with a newline to ensure
|
||||
# one per line the following newline is ignored in output.
|
||||
xon, xoff = '\x11\n', '\x13\n'
|
||||
control = re.compile('(\x11\n|\x13\n)')
|
||||
xon, xoff = "\x11\n", "\x13\n"
|
||||
control = re.compile("(\x11\n|\x13\n)")
|
||||
|
||||
|
||||
@contextmanager
|
||||
@@ -59,17 +60,13 @@ def ignore_signal(signum):
|
||||
|
||||
|
||||
def _is_background_tty(stream):
|
||||
"""True if the stream is a tty and calling process is in the background.
|
||||
"""
|
||||
return (
|
||||
stream.isatty() and
|
||||
os.getpgrp() != os.tcgetpgrp(stream.fileno())
|
||||
)
|
||||
"""True if the stream is a tty and calling process is in the background."""
|
||||
return stream.isatty() and os.getpgrp() != os.tcgetpgrp(stream.fileno())
|
||||
|
||||
|
||||
def _strip(line):
|
||||
"""Strip color and control characters from a line."""
|
||||
return _escape.sub('', line)
|
||||
return _escape.sub("", line)
|
||||
|
||||
|
||||
class keyboard_input(object):
|
||||
@@ -147,6 +144,7 @@ class keyboard_input(object):
|
||||
a TTY, ``keyboard_input`` has no effect.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, stream):
|
||||
"""Create a context manager that will enable keyboard input on stream.
|
||||
|
||||
@@ -204,7 +202,7 @@ def check_fg_bg(self):
|
||||
bg = self._is_background()
|
||||
|
||||
# restore sanity if flags are amiss -- see diagram in class docs
|
||||
if not bg and any(flags): # fg, but input not enabled
|
||||
if not bg and any(flags): # fg, but input not enabled
|
||||
self._enable_keyboard_input()
|
||||
elif bg and not all(flags): # bg, but input enabled
|
||||
self._restore_default_terminal_settings()
|
||||
@@ -228,8 +226,7 @@ def __enter__(self):
|
||||
|
||||
# Install a signal handler to disable/enable keyboard input
|
||||
# when the process moves between foreground and background.
|
||||
self.old_handlers[signal.SIGTSTP] = signal.signal(
|
||||
signal.SIGTSTP, self._tstp_handler)
|
||||
self.old_handlers[signal.SIGTSTP] = signal.signal(signal.SIGTSTP, self._tstp_handler)
|
||||
|
||||
# add an atexit handler to ensure the terminal is restored
|
||||
atexit.register(self._restore_default_terminal_settings)
|
||||
@@ -258,6 +255,7 @@ class Unbuffered(object):
|
||||
|
||||
This is implemented by forcing a flush after each write.
|
||||
"""
|
||||
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
|
||||
@@ -302,6 +300,7 @@ class FileWrapper(object):
|
||||
yet), or neither. When unwrapped, it returns an open file (or file-like)
|
||||
object.
|
||||
"""
|
||||
|
||||
def __init__(self, file_like):
|
||||
# This records whether the file-like object returned by "unwrap" is
|
||||
# purely in-memory. In that case a subprocess will need to explicitly
|
||||
@@ -325,9 +324,9 @@ def unwrap(self):
|
||||
if self.open:
|
||||
if self.file_like:
|
||||
if sys.version_info < (3,):
|
||||
self.file = open(self.file_like, 'w')
|
||||
self.file = open(self.file_like, "w")
|
||||
else:
|
||||
self.file = open(self.file_like, 'w', encoding='utf-8') # novm
|
||||
self.file = open(self.file_like, "w", encoding="utf-8") # novm
|
||||
else:
|
||||
self.file = StringIO()
|
||||
return self.file
|
||||
@@ -343,8 +342,9 @@ def close(self):
|
||||
|
||||
class MultiProcessFd(object):
|
||||
"""Return an object which stores a file descriptor and can be passed as an
|
||||
argument to a function run with ``multiprocessing.Process``, such that
|
||||
the file descriptor is available in the subprocess."""
|
||||
argument to a function run with ``multiprocessing.Process``, such that
|
||||
the file descriptor is available in the subprocess."""
|
||||
|
||||
def __init__(self, fd):
|
||||
self._connection = None
|
||||
self._fd = None
|
||||
@@ -434,7 +434,7 @@ def log_output(*args, **kwargs):
|
||||
This method is actually a factory serving a per platform
|
||||
(unix vs windows) log_output class
|
||||
"""
|
||||
if sys.platform == 'win32':
|
||||
if sys.platform == "win32":
|
||||
return winlog(*args, **kwargs)
|
||||
else:
|
||||
return nixlog(*args, **kwargs)
|
||||
@@ -454,8 +454,9 @@ class nixlog(object):
|
||||
work within test frameworks like nose and pytest.
|
||||
"""
|
||||
|
||||
def __init__(self, file_like=None, echo=False, debug=0, buffer=False,
|
||||
env=None, filter_fn=None):
|
||||
def __init__(
|
||||
self, file_like=None, echo=False, debug=0, buffer=False, env=None, filter_fn=None
|
||||
):
|
||||
"""Create a new output log context manager.
|
||||
|
||||
Args:
|
||||
@@ -524,8 +525,7 @@ def __enter__(self):
|
||||
raise RuntimeError("Can't re-enter the same log_output!")
|
||||
|
||||
if self.file_like is None:
|
||||
raise RuntimeError(
|
||||
"file argument must be set by either __init__ or __call__")
|
||||
raise RuntimeError("file argument must be set by either __init__ or __call__")
|
||||
|
||||
# set up a stream for the daemon to write to
|
||||
self.log_file = FileWrapper(self.file_like)
|
||||
@@ -555,9 +555,7 @@ def __enter__(self):
|
||||
input_multiprocess_fd = None
|
||||
try:
|
||||
if sys.stdin.isatty():
|
||||
input_multiprocess_fd = MultiProcessFd(
|
||||
os.dup(sys.stdin.fileno())
|
||||
)
|
||||
input_multiprocess_fd = MultiProcessFd(os.dup(sys.stdin.fileno()))
|
||||
except BaseException:
|
||||
# just don't forward input if this fails
|
||||
pass
|
||||
@@ -566,9 +564,14 @@ def __enter__(self):
|
||||
self.process = multiprocessing.Process(
|
||||
target=_writer_daemon,
|
||||
args=(
|
||||
input_multiprocess_fd, read_multiprocess_fd, write_fd,
|
||||
self.echo, self.log_file, child_pipe, self.filter_fn
|
||||
)
|
||||
input_multiprocess_fd,
|
||||
read_multiprocess_fd,
|
||||
write_fd,
|
||||
self.echo,
|
||||
self.log_file,
|
||||
child_pipe,
|
||||
self.filter_fn,
|
||||
),
|
||||
)
|
||||
self.process.daemon = True # must set before start()
|
||||
self.process.start()
|
||||
@@ -609,7 +612,7 @@ def __enter__(self):
|
||||
self._saved_stderr = sys.stderr
|
||||
|
||||
# create a file object for the pipe; redirect to it.
|
||||
pipe_fd_out = os.fdopen(write_fd, 'w')
|
||||
pipe_fd_out = os.fdopen(write_fd, "w")
|
||||
sys.stdout = pipe_fd_out
|
||||
sys.stderr = pipe_fd_out
|
||||
|
||||
@@ -674,8 +677,7 @@ def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
def force_echo(self):
|
||||
"""Context manager to force local echo, even if echo is off."""
|
||||
if not self._active:
|
||||
raise RuntimeError(
|
||||
"Can't call force_echo() outside log_output region!")
|
||||
raise RuntimeError("Can't call force_echo() outside log_output region!")
|
||||
|
||||
# This uses the xon/xoff to highlight regions to be echoed in the
|
||||
# output. We us these control characters rather than, say, a
|
||||
@@ -691,25 +693,26 @@ def force_echo(self):
|
||||
|
||||
|
||||
class StreamWrapper:
|
||||
""" Wrapper class to handle redirection of io streams """
|
||||
"""Wrapper class to handle redirection of io streams"""
|
||||
|
||||
def __init__(self, sys_attr):
|
||||
self.sys_attr = sys_attr
|
||||
self.saved_stream = None
|
||||
if sys.platform.startswith('win32'):
|
||||
if sys.platform.startswith("win32"):
|
||||
if sys.version_info < (3, 5):
|
||||
libc = ctypes.CDLL(ctypes.util.find_library('c'))
|
||||
libc = ctypes.CDLL(ctypes.util.find_library("c"))
|
||||
else:
|
||||
if hasattr(sys, 'gettotalrefcount'): # debug build
|
||||
libc = ctypes.CDLL('ucrtbased')
|
||||
if hasattr(sys, "gettotalrefcount"): # debug build
|
||||
libc = ctypes.CDLL("ucrtbased")
|
||||
else:
|
||||
libc = ctypes.CDLL('api-ms-win-crt-stdio-l1-1-0')
|
||||
libc = ctypes.CDLL("api-ms-win-crt-stdio-l1-1-0")
|
||||
|
||||
kernel32 = ctypes.WinDLL('kernel32')
|
||||
kernel32 = ctypes.WinDLL("kernel32")
|
||||
|
||||
# https://docs.microsoft.com/en-us/windows/console/getstdhandle
|
||||
if self.sys_attr == 'stdout':
|
||||
if self.sys_attr == "stdout":
|
||||
STD_HANDLE = -11
|
||||
elif self.sys_attr == 'stderr':
|
||||
elif self.sys_attr == "stderr":
|
||||
STD_HANDLE = -12
|
||||
else:
|
||||
raise KeyError(self.sys_attr)
|
||||
@@ -728,7 +731,7 @@ def __init__(self, sys_attr):
|
||||
def redirect_stream(self, to_fd):
|
||||
"""Redirect stdout to the given file descriptor."""
|
||||
# Flush the C-level buffer stream
|
||||
if sys.platform.startswith('win32'):
|
||||
if sys.platform.startswith("win32"):
|
||||
self.libc.fflush(None)
|
||||
else:
|
||||
self.libc.fflush(self.c_stream)
|
||||
@@ -739,13 +742,13 @@ def redirect_stream(self, to_fd):
|
||||
# Make orig_stream_fd point to the same file as to_fd
|
||||
os.dup2(to_fd, self.orig_stream_fd)
|
||||
# Set sys_stream to a new stream that points to the redirected fd
|
||||
new_buffer = open(self.orig_stream_fd, 'wb')
|
||||
new_buffer = open(self.orig_stream_fd, "wb")
|
||||
new_stream = io.TextIOWrapper(new_buffer)
|
||||
setattr(sys, self.sys_attr, new_stream)
|
||||
self.sys_stream = getattr(sys, self.sys_attr)
|
||||
|
||||
def flush(self):
|
||||
if sys.platform.startswith('win32'):
|
||||
if sys.platform.startswith("win32"):
|
||||
self.libc.fflush(None)
|
||||
else:
|
||||
self.libc.fflush(self.c_stream)
|
||||
@@ -768,14 +771,16 @@ class winlog(object):
|
||||
|
||||
Does not support the use of 'v' toggling as nixlog does.
|
||||
"""
|
||||
def __init__(self, file_like=None, echo=False, debug=0, buffer=False,
|
||||
env=None, filter_fn=None):
|
||||
|
||||
def __init__(
|
||||
self, file_like=None, echo=False, debug=0, buffer=False, env=None, filter_fn=None
|
||||
):
|
||||
self.env = env
|
||||
self.debug = debug
|
||||
self.echo = echo
|
||||
self.logfile = file_like
|
||||
self.stdout = StreamWrapper('stdout')
|
||||
self.stderr = StreamWrapper('stderr')
|
||||
self.stdout = StreamWrapper("stdout")
|
||||
self.stderr = StreamWrapper("stderr")
|
||||
self._active = False
|
||||
self._ioflag = False
|
||||
self.old_stdout = sys.stdout
|
||||
@@ -786,8 +791,7 @@ def __enter__(self):
|
||||
raise RuntimeError("Can't re-enter the same log_output!")
|
||||
|
||||
if self.logfile is None:
|
||||
raise RuntimeError(
|
||||
"file argument must be set by __init__ ")
|
||||
raise RuntimeError("file argument must be set by __init__ ")
|
||||
|
||||
# Open both write and reading on logfile
|
||||
if type(self.logfile) == StringIO:
|
||||
@@ -796,8 +800,8 @@ def __enter__(self):
|
||||
sys.stdout = self.logfile
|
||||
sys.stderr = self.logfile
|
||||
else:
|
||||
self.writer = open(self.logfile, mode='wb+')
|
||||
self.reader = open(self.logfile, mode='rb+')
|
||||
self.writer = open(self.logfile, mode="wb+")
|
||||
self.reader = open(self.logfile, mode="rb+")
|
||||
|
||||
# Dup stdout so we can still write to it after redirection
|
||||
self.echo_writer = open(os.dup(sys.stdout.fileno()), "w")
|
||||
@@ -811,7 +815,7 @@ def background_reader(reader, echo_writer, _kill):
|
||||
# if echo: write line to user
|
||||
try:
|
||||
while True:
|
||||
is_killed = _kill.wait(.1)
|
||||
is_killed = _kill.wait(0.1)
|
||||
# Flush buffered build output to file
|
||||
# stdout/err fds refer to log file
|
||||
self.stderr.flush()
|
||||
@@ -819,7 +823,7 @@ def background_reader(reader, echo_writer, _kill):
|
||||
|
||||
line = reader.readline()
|
||||
if self.echo and line:
|
||||
echo_writer.write('{0}'.format(line.decode()))
|
||||
echo_writer.write("{0}".format(line.decode()))
|
||||
echo_writer.flush()
|
||||
|
||||
if is_killed:
|
||||
@@ -829,8 +833,9 @@ def background_reader(reader, echo_writer, _kill):
|
||||
|
||||
self._active = True
|
||||
with replace_environment(self.env):
|
||||
self._thread = Thread(target=background_reader,
|
||||
args=(self.reader, self.echo_writer, self._kill))
|
||||
self._thread = Thread(
|
||||
target=background_reader, args=(self.reader, self.echo_writer, self._kill)
|
||||
)
|
||||
self._thread.start()
|
||||
return self
|
||||
|
||||
@@ -854,13 +859,19 @@ def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
def force_echo(self):
|
||||
"""Context manager to force local echo, even if echo is off."""
|
||||
if not self._active:
|
||||
raise RuntimeError(
|
||||
"Can't call force_echo() outside log_output region!")
|
||||
raise RuntimeError("Can't call force_echo() outside log_output region!")
|
||||
yield
|
||||
|
||||
|
||||
def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo,
|
||||
log_file_wrapper, control_pipe, filter_fn):
|
||||
def _writer_daemon(
|
||||
stdin_multiprocess_fd,
|
||||
read_multiprocess_fd,
|
||||
write_fd,
|
||||
echo,
|
||||
log_file_wrapper,
|
||||
control_pipe,
|
||||
filter_fn,
|
||||
):
|
||||
"""Daemon used by ``log_output`` to write to a log file and to ``stdout``.
|
||||
|
||||
The daemon receives output from the parent process and writes it both
|
||||
@@ -913,16 +924,16 @@ def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo,
|
||||
# write_fd to terminate the reading loop, so we close the file descriptor
|
||||
# here. Forking is the process spawning method everywhere except Mac OS
|
||||
# for Python >= 3.8 and on Windows
|
||||
if sys.version_info < (3, 8) or sys.platform != 'darwin':
|
||||
if sys.version_info < (3, 8) or sys.platform != "darwin":
|
||||
os.close(write_fd)
|
||||
|
||||
# Use line buffering (3rd param = 1) since Python 3 has a bug
|
||||
# that prevents unbuffered text I/O.
|
||||
if sys.version_info < (3,):
|
||||
in_pipe = os.fdopen(read_multiprocess_fd.fd, 'r', 1)
|
||||
in_pipe = os.fdopen(read_multiprocess_fd.fd, "r", 1)
|
||||
else:
|
||||
# Python 3.x before 3.7 does not open with UTF-8 encoding by default
|
||||
in_pipe = os.fdopen(read_multiprocess_fd.fd, 'r', 1, encoding='utf-8')
|
||||
in_pipe = os.fdopen(read_multiprocess_fd.fd, "r", 1, encoding="utf-8")
|
||||
|
||||
if stdin_multiprocess_fd:
|
||||
stdin = os.fdopen(stdin_multiprocess_fd.fd)
|
||||
@@ -931,7 +942,7 @@ def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo,
|
||||
|
||||
# list of streams to select from
|
||||
istreams = [in_pipe, stdin] if stdin else [in_pipe]
|
||||
force_echo = False # parent can force echo for certain output
|
||||
force_echo = False # parent can force echo for certain output
|
||||
|
||||
log_file = log_file_wrapper.unwrap()
|
||||
|
||||
@@ -954,7 +965,7 @@ def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo,
|
||||
# check and the read, so we ignore SIGTTIN here.
|
||||
with ignore_signal(signal.SIGTTIN):
|
||||
try:
|
||||
if stdin.read(1) == 'v':
|
||||
if stdin.read(1) == "v":
|
||||
echo = not echo
|
||||
except IOError as e:
|
||||
# If SIGTTIN is ignored, the system gives EIO
|
||||
@@ -972,14 +983,14 @@ def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo,
|
||||
line = _retry(in_pipe.readline)()
|
||||
except UnicodeDecodeError:
|
||||
# installs like --test=root gpgme produce non-UTF8 logs
|
||||
line = '<line lost: output was not encoded as UTF-8>\n'
|
||||
line = "<line lost: output was not encoded as UTF-8>\n"
|
||||
|
||||
if not line:
|
||||
return
|
||||
line_count += 1
|
||||
|
||||
# find control characters and strip them.
|
||||
clean_line, num_controls = control.subn('', line)
|
||||
clean_line, num_controls = control.subn("", line)
|
||||
|
||||
# Echo to stdout if requested or forced.
|
||||
if echo or force_echo:
|
||||
@@ -1043,6 +1054,7 @@ def _retry(function):
|
||||
relevant for this file.
|
||||
|
||||
"""
|
||||
|
||||
def wrapped(*args, **kwargs):
|
||||
while True:
|
||||
try:
|
||||
@@ -1055,6 +1067,7 @@ def wrapped(*args, **kwargs):
|
||||
if e.args[0] == errno.EINTR:
|
||||
continue
|
||||
raise
|
||||
|
||||
return wrapped
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user