From 4b01d7f222970700768e779db280bb77f7d62bc6 Mon Sep 17 00:00:00 2001 From: Samuel FORESTIER Date: Sat, 17 Aug 2024 14:10:25 +0200 Subject: [PATCH] update ptyprocess version to v0.7.0 --- all/ptyprocess/__init__.py | 2 +- all/ptyprocess/_fork_pty.py | 5 +++-- all/ptyprocess/ptyprocess.py | 41 ++++++++++++++++++++++++------------ all/ptyprocess/util.py | 6 +++++- 4 files changed, 36 insertions(+), 18 deletions(-) mode change 100755 => 100644 all/ptyprocess/__init__.py mode change 100755 => 100644 all/ptyprocess/_fork_pty.py mode change 100755 => 100644 all/ptyprocess/ptyprocess.py mode change 100755 => 100644 all/ptyprocess/util.py diff --git a/all/ptyprocess/__init__.py b/all/ptyprocess/__init__.py old mode 100755 new mode 100644 index fff62f3..3a6268e --- a/all/ptyprocess/__init__.py +++ b/all/ptyprocess/__init__.py @@ -1,4 +1,4 @@ """Run a subprocess in a pseudo terminal""" from .ptyprocess import PtyProcess, PtyProcessUnicode, PtyProcessError -__version__ = '0.5.2' +__version__ = '0.7.0' diff --git a/all/ptyprocess/_fork_pty.py b/all/ptyprocess/_fork_pty.py old mode 100755 new mode 100644 index d00eb65..a8d05fe --- a/all/ptyprocess/_fork_pty.py +++ b/all/ptyprocess/_fork_pty.py @@ -4,6 +4,7 @@ import errno from pty import (STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CHILD) +from .util import PtyProcessError def fork_pty(): '''This implements a substitute for the forkpty system call. This @@ -63,7 +64,7 @@ def pty_make_controlling_tty(tty_fd): try: fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY) os.close(fd) - raise ExceptionPexpect("OSError of errno.ENXIO should be raised.") + raise PtyProcessError("OSError of errno.ENXIO should be raised.") except OSError as err: if err.errno != errno.ENXIO: raise @@ -74,4 +75,4 @@ def pty_make_controlling_tty(tty_fd): # Verify we now have a controlling tty. fd = os.open("/dev/tty", os.O_WRONLY) - os.close(fd) \ No newline at end of file + os.close(fd) diff --git a/all/ptyprocess/ptyprocess.py b/all/ptyprocess/ptyprocess.py old mode 100755 new mode 100644 index c992974..c557b76 --- a/all/ptyprocess/ptyprocess.py +++ b/all/ptyprocess/ptyprocess.py @@ -21,7 +21,7 @@ # Constants from pty import (STDIN_FILENO, CHILD) -from .util import which +from .util import which, PtyProcessError _platform = sys.platform.lower() @@ -62,11 +62,18 @@ def _make_eof_intr(): # inherit EOF and INTR definitions from controlling process. try: from termios import VEOF, VINTR - try: - fd = sys.__stdin__.fileno() - except ValueError: - # ValueError: I/O operation on closed file - fd = sys.__stdout__.fileno() + fd = None + for name in 'stdin', 'stdout': + stream = getattr(sys, '__%s__' % name, None) + if stream is None or not hasattr(stream, 'fileno'): + continue + try: + fd = stream.fileno() + except ValueError: + continue + if fd is None: + # no fd, raise ValueError to fallback on CEOF, CINTR + raise ValueError("No stream has a fileno") intr = ord(termios.tcgetattr(fd)[6][VINTR]) eof = ord(termios.tcgetattr(fd)[6][VEOF]) except (ImportError, OSError, IOError, ValueError, termios.error): @@ -83,14 +90,11 @@ def _make_eof_intr(): _INTR = _byte(intr) _EOF = _byte(eof) -class PtyProcessError(Exception): - """Generic error class for this package.""" - # setecho and setwinsize are pulled out here because on some platforms, we need # to do this from the child before we exec() def _setecho(fd, state): - errmsg = 'setecho() may not be called on this platform' + errmsg = 'setecho() may not be called on this platform (it may still be possible to enable/disable echo when spawning the child process)' try: attr = termios.tcgetattr(fd) @@ -176,7 +180,7 @@ def __init__(self, pid, fd): @classmethod def spawn( cls, argv, cwd=None, env=None, echo=True, preexec_fn=None, - dimensions=(24, 80)): + dimensions=(24, 80), pass_fds=()): '''Start the given command in a child process in a pseudo terminal. This does all the fork/exec type of stuff for a pty, and returns an @@ -188,6 +192,10 @@ def spawn( Dimensions of the psuedoterminal used for the subprocess can be specified as a tuple (rows, cols), or the default (24, 80) will be used. + + By default, all file descriptors except 0, 1 and 2 are closed. This + behavior can be overridden with pass_fds, a list of file descriptors to + keep open between the parent and the child. ''' # Note that it is difficult for this method to fail. # You cannot detect if the child process cannot start. @@ -253,9 +261,14 @@ def spawn( # Do not allow child to inherit open file descriptors from parent, # with the exception of the exec_err_pipe_write of the pipe - max_fd = resource.getrlimit(resource.RLIMIT_NOFILE)[0] - os.closerange(3, exec_err_pipe_write) - os.closerange(exec_err_pipe_write+1, max_fd) + # and pass_fds. + # Impose ceiling on max_fd: AIX bugfix for users with unlimited + # nofiles where resource.RLIMIT_NOFILE is 2^63-1 and os.closerange() + # occasionally raises out of range error + max_fd = min(1048576, resource.getrlimit(resource.RLIMIT_NOFILE)[0]) + spass_fds = sorted(set(pass_fds) | {exec_err_pipe_write}) + for pair in zip([2] + spass_fds, spass_fds + [max_fd]): + os.closerange(pair[0]+1, pair[1]) if cwd is not None: os.chdir(cwd) diff --git a/all/ptyprocess/util.py b/all/ptyprocess/util.py old mode 100755 new mode 100644 index d7fb7b2..aadbd62 --- a/all/ptyprocess/util.py +++ b/all/ptyprocess/util.py @@ -64,4 +64,8 @@ def _access_check(fn, mode): name = os.path.join(dir, thefile) if _access_check(name, mode): return name - return None \ No newline at end of file + return None + + +class PtyProcessError(Exception): + """Generic error class for this package."""