diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:01 +0300 |
commit | 2d37894b1b037cf24231090eda8589bbb44fb6fc (patch) | |
tree | be835aa92c6248212e705f25388ebafcf84bc7a1 /contrib/python/pexpect | |
parent | 718c552901d703c502ccbefdfc3c9028d608b947 (diff) | |
download | ydb-2d37894b1b037cf24231090eda8589bbb44fb6fc.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/pexpect')
-rw-r--r-- | contrib/python/pexpect/pexpect/_async.py | 44 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/expect.py | 34 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/fdpexpect.py | 84 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/popen_spawn.py | 44 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/pty_spawn.py | 128 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/pxssh.py | 208 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/replwrap.py | 20 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/screen.py | 2 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/spawnbase.py | 104 | ||||
-rw-r--r-- | contrib/python/pexpect/pexpect/utils.py | 162 | ||||
-rw-r--r-- | contrib/python/pexpect/ya.make | 20 |
11 files changed, 425 insertions, 425 deletions
diff --git a/contrib/python/pexpect/pexpect/_async.py b/contrib/python/pexpect/pexpect/_async.py index aa2d604d6c..dfbfeef5fb 100644 --- a/contrib/python/pexpect/pexpect/_async.py +++ b/contrib/python/pexpect/pexpect/_async.py @@ -11,16 +11,16 @@ def expect_async(expecter, timeout=None): idx = expecter.existing_data() if idx is not None: return idx - if not expecter.spawn.async_pw_transport: - pw = PatternWaiter() - pw.set_expecter(expecter) - transport, pw = yield from asyncio.get_event_loop()\ - .connect_read_pipe(lambda: pw, expecter.spawn) - expecter.spawn.async_pw_transport = pw, transport - else: - pw, transport = expecter.spawn.async_pw_transport - pw.set_expecter(expecter) - transport.resume_reading() + if not expecter.spawn.async_pw_transport: + pw = PatternWaiter() + pw.set_expecter(expecter) + transport, pw = yield from asyncio.get_event_loop()\ + .connect_read_pipe(lambda: pw, expecter.spawn) + expecter.spawn.async_pw_transport = pw, transport + else: + pw, transport = expecter.spawn.async_pw_transport + pw.set_expecter(expecter) + transport.resume_reading() try: return (yield from asyncio.wait_for(pw.fut, timeout)) except asyncio.TimeoutError as e: @@ -35,7 +35,7 @@ def repl_run_command_async(repl, cmdlines, timeout=-1): yield from repl._expect_prompt(timeout=timeout, async_=True) res.append(repl.child.before) repl.child.sendline(line) - + # Command was fully submitted, now wait for the next prompt prompt_idx = yield from repl._expect_prompt(timeout=timeout, async_=True) if prompt_idx == 1: @@ -46,24 +46,24 @@ def repl_run_command_async(repl, cmdlines, timeout=-1): return u''.join(res + [repl.child.before]) class PatternWaiter(asyncio.Protocol): - transport = None - - def set_expecter(self, expecter): + transport = None + + def set_expecter(self, expecter): self.expecter = expecter self.fut = asyncio.Future() - + def found(self, result): if not self.fut.done(): self.fut.set_result(result) - self.transport.pause_reading() + self.transport.pause_reading() def error(self, exc): if not self.fut.done(): self.fut.set_exception(exc) - self.transport.pause_reading() - - def connection_made(self, transport): - self.transport = transport + self.transport.pause_reading() + + def connection_made(self, transport): + self.transport = transport def data_received(self, data): spawn = self.expecter.spawn @@ -72,11 +72,11 @@ class PatternWaiter(asyncio.Protocol): if self.fut.done(): spawn._before.write(s) - spawn._buffer.write(s) + spawn._buffer.write(s) return try: - index = self.expecter.new_data(s) + index = self.expecter.new_data(s) if index is not None: # Found a match self.found(index) diff --git a/contrib/python/pexpect/pexpect/expect.py b/contrib/python/pexpect/pexpect/expect.py index 4c0bd0fe49..d3409db9d7 100644 --- a/contrib/python/pexpect/pexpect/expect.py +++ b/contrib/python/pexpect/pexpect/expect.py @@ -14,7 +14,7 @@ class Expecter(object): self.lookback = None if hasattr(searcher, 'longest_string'): self.lookback = searcher.longest_string - + def do_search(self, window, freshlen): spawn = self.spawn searcher = self.searcher @@ -22,11 +22,11 @@ class Expecter(object): freshlen = len(window) index = searcher.search(window, freshlen, self.searchwindowsize) if index >= 0: - spawn._buffer = spawn.buffer_type() - spawn._buffer.write(window[searcher.end:]) + spawn._buffer = spawn.buffer_type() + spawn._buffer.write(window[searcher.end:]) spawn.before = spawn._before.getvalue()[ 0:-(len(window) - searcher.start)] - spawn._before = spawn.buffer_type() + spawn._before = spawn.buffer_type() spawn._before.write(window[searcher.end:]) spawn.after = window[searcher.start:searcher.end] spawn.match = searcher.match @@ -38,7 +38,7 @@ class Expecter(object): if spawn._buffer.tell() > maintain: spawn._buffer = spawn.buffer_type() spawn._buffer.write(window[-maintain:]) - + def existing_data(self): # First call from a new call to expect_loop or expect_async. # self.searchwindowsize may have changed. @@ -101,8 +101,8 @@ class Expecter(object): spawn = self.spawn spawn.before = spawn._before.getvalue() - spawn._buffer = spawn.buffer_type() - spawn._before = spawn.buffer_type() + spawn._buffer = spawn.buffer_type() + spawn._before = spawn.buffer_type() spawn.after = EOF index = self.searcher.eof_index if index >= 0: @@ -113,7 +113,7 @@ class Expecter(object): spawn.match = None spawn.match_index = None msg = str(spawn) - msg += '\nsearcher: %s' % self.searcher + msg += '\nsearcher: %s' % self.searcher if err is not None: msg = str(err) + '\n' + msg @@ -135,7 +135,7 @@ class Expecter(object): spawn.match = None spawn.match_index = None msg = str(spawn) - msg += '\nsearcher: %s' % self.searcher + msg += '\nsearcher: %s' % self.searcher if err is not None: msg = str(err) + '\n' + msg @@ -167,8 +167,8 @@ class Expecter(object): return self.timeout() # Still have time left, so read more data incoming = spawn.read_nonblocking(spawn.maxread, timeout) - if self.spawn.delayafterread is not None: - time.sleep(self.spawn.delayafterread) + if self.spawn.delayafterread is not None: + time.sleep(self.spawn.delayafterread) idx = self.new_data(incoming) # Keep reading until exception or return. if idx is not None: @@ -226,7 +226,7 @@ class searcher_string(object): '''This returns a human-readable string that represents the state of the object.''' - ss = [(ns[0], ' %d: %r' % ns) for ns in self._strings] + ss = [(ns[0], ' %d: %r' % ns) for ns in self._strings] ss.append((-1, 'searcher_string:')) if self.eof_index >= 0: ss.append((self.eof_index, ' %d: EOF' % self.eof_index)) @@ -238,7 +238,7 @@ class searcher_string(object): return '\n'.join(ss) def search(self, buffer, freshlen, searchwindowsize=None): - '''This searches 'buffer' for the first occurrence of one of the search + '''This searches 'buffer' for the first occurrence of one of the search strings. 'freshlen' must indicate the number of bytes at the end of 'buffer' which have not been searched before. It helps to avoid searching the same, possibly big, buffer over and over again. @@ -297,7 +297,7 @@ class searcher_re(object): start - index into the buffer, first byte of match end - index into the buffer, first byte after match - match - the re.match object returned by a successful re.search + match - the re.match object returned by a successful re.search ''' @@ -326,7 +326,7 @@ class searcher_re(object): # (n, repr(s.pattern))) for n, s in self._searches] ss = list() for n, s in self._searches: - ss.append((n, ' %d: re.compile(%r)' % (n, s.pattern))) + ss.append((n, ' %d: re.compile(%r)' % (n, s.pattern))) ss.append((-1, 'searcher_re:')) if self.eof_index >= 0: ss.append((self.eof_index, ' %d: EOF' % self.eof_index)) @@ -338,7 +338,7 @@ class searcher_re(object): return '\n'.join(ss) def search(self, buffer, freshlen, searchwindowsize=None): - '''This searches 'buffer' for the first occurrence of one of the regular + '''This searches 'buffer' for the first occurrence of one of the regular expressions. 'freshlen' must indicate the number of bytes at the end of 'buffer' which have not been searched before. @@ -368,4 +368,4 @@ class searcher_re(object): self.start = first_match self.match = the_match self.end = self.match.end() - return best_index + return best_index diff --git a/contrib/python/pexpect/pexpect/fdpexpect.py b/contrib/python/pexpect/pexpect/fdpexpect.py index fbd925f34e..cddd50e100 100644 --- a/contrib/python/pexpect/pexpect/fdpexpect.py +++ b/contrib/python/pexpect/pexpect/fdpexpect.py @@ -1,5 +1,5 @@ '''This is like pexpect, but it will work with any file descriptor that you -pass it. You are responsible for opening and close the file descriptor. +pass it. You are responsible for opening and close the file descriptor. This allows you to use Pexpect with sockets and named pipes (FIFOs). PEXPECT LICENSE @@ -22,8 +22,8 @@ PEXPECT LICENSE ''' from .spawnbase import SpawnBase -from .exceptions import ExceptionPexpect, TIMEOUT -from .utils import select_ignore_interrupts, poll_ignore_interrupts +from .exceptions import ExceptionPexpect, TIMEOUT +from .utils import select_ignore_interrupts, poll_ignore_interrupts import os __all__ = ['fdspawn'] @@ -34,7 +34,7 @@ class fdspawn(SpawnBase): for patterns, or to control a modem or serial device. ''' def __init__ (self, fd, args=None, timeout=30, maxread=2000, searchwindowsize=None, - logfile=None, encoding=None, codec_errors='strict', use_poll=False): + logfile=None, encoding=None, codec_errors='strict', use_poll=False): '''This takes a file descriptor (an int) or an object that support the fileno() method (returning an int). All Python file-like objects support fileno(). ''' @@ -58,7 +58,7 @@ class fdspawn(SpawnBase): self.own_fd = False self.closed = False self.name = '<file descriptor %d>' % fd - self.use_poll = use_poll + self.use_poll = use_poll def close (self): """Close the file descriptor. @@ -89,7 +89,7 @@ class fdspawn(SpawnBase): def terminate (self, force=False): # pragma: no cover '''Deprecated and invalid. Just raises an exception.''' raise ExceptionPexpect('This method is not valid for file descriptors.') - + # These four methods are left around for backwards compatibility, but not # documented as part of fdpexpect. You're encouraged to use os.write # directly. @@ -97,52 +97,52 @@ class fdspawn(SpawnBase): "Write to fd, return number of bytes written" s = self._coerce_send_string(s) self._log(s, 'send') - + b = self._encoder.encode(s, final=False) return os.write(self.child_fd, b) - + def sendline(self, s): "Write to fd with trailing newline, return number of bytes written" s = self._coerce_send_string(s) return self.send(s + self.linesep) - + def write(self, s): "Write to fd, return None" self.send(s) - + def writelines(self, sequence): "Call self.write() for each item in sequence" for s in sequence: self.write(s) - - def read_nonblocking(self, size=1, timeout=-1): - """ - Read from the file descriptor and return the result as a string. - - The read_nonblocking method of :class:`SpawnBase` assumes that a call - to os.read will not block (timeout parameter is ignored). This is not - the case for POSIX file-like objects such as sockets and serial ports. - - Use :func:`select.select`, timeout is implemented conditionally for - POSIX systems. - - :param int size: Read at most *size* bytes. - :param int timeout: Wait timeout seconds for file descriptor to be - ready to read. When -1 (default), use self.timeout. When 0, poll. - :return: String containing the bytes read - """ - if os.name == 'posix': - if timeout == -1: - timeout = self.timeout - rlist = [self.child_fd] - wlist = [] - xlist = [] - if self.use_poll: - rlist = poll_ignore_interrupts(rlist, timeout) - else: - rlist, wlist, xlist = select_ignore_interrupts( - rlist, wlist, xlist, timeout - ) - if self.child_fd not in rlist: - raise TIMEOUT('Timeout exceeded.') - return super(fdspawn, self).read_nonblocking(size) + + def read_nonblocking(self, size=1, timeout=-1): + """ + Read from the file descriptor and return the result as a string. + + The read_nonblocking method of :class:`SpawnBase` assumes that a call + to os.read will not block (timeout parameter is ignored). This is not + the case for POSIX file-like objects such as sockets and serial ports. + + Use :func:`select.select`, timeout is implemented conditionally for + POSIX systems. + + :param int size: Read at most *size* bytes. + :param int timeout: Wait timeout seconds for file descriptor to be + ready to read. When -1 (default), use self.timeout. When 0, poll. + :return: String containing the bytes read + """ + if os.name == 'posix': + if timeout == -1: + timeout = self.timeout + rlist = [self.child_fd] + wlist = [] + xlist = [] + if self.use_poll: + rlist = poll_ignore_interrupts(rlist, timeout) + else: + rlist, wlist, xlist = select_ignore_interrupts( + rlist, wlist, xlist, timeout + ) + if self.child_fd not in rlist: + raise TIMEOUT('Timeout exceeded.') + return super(fdspawn, self).read_nonblocking(size) diff --git a/contrib/python/pexpect/pexpect/popen_spawn.py b/contrib/python/pexpect/pexpect/popen_spawn.py index bb81b5482c..4bb58cfe76 100644 --- a/contrib/python/pexpect/pexpect/popen_spawn.py +++ b/contrib/python/pexpect/pexpect/popen_spawn.py @@ -15,31 +15,31 @@ except ImportError: from .spawnbase import SpawnBase, PY3 from .exceptions import EOF -from .utils import string_types +from .utils import string_types class PopenSpawn(SpawnBase): def __init__(self, cmd, timeout=30, maxread=2000, searchwindowsize=None, - logfile=None, cwd=None, env=None, encoding=None, - codec_errors='strict', preexec_fn=None): + logfile=None, cwd=None, env=None, encoding=None, + codec_errors='strict', preexec_fn=None): super(PopenSpawn, self).__init__(timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize, logfile=logfile, encoding=encoding, codec_errors=codec_errors) - # Note that `SpawnBase` initializes `self.crlf` to `\r\n` - # because the default behaviour for a PTY is to convert - # incoming LF to `\r\n` (see the `onlcr` flag and - # https://stackoverflow.com/a/35887657/5397009). Here we set - # it to `os.linesep` because that is what the spawned - # application outputs by default and `popen` doesn't translate - # anything. - if encoding is None: - self.crlf = os.linesep.encode ("ascii") - else: - self.crlf = self.string_type (os.linesep) - + # Note that `SpawnBase` initializes `self.crlf` to `\r\n` + # because the default behaviour for a PTY is to convert + # incoming LF to `\r\n` (see the `onlcr` flag and + # https://stackoverflow.com/a/35887657/5397009). Here we set + # it to `os.linesep` because that is what the spawned + # application outputs by default and `popen` doesn't translate + # anything. + if encoding is None: + self.crlf = os.linesep.encode ("ascii") + else: + self.crlf = self.string_type (os.linesep) + kwargs = dict(bufsize=0, stdin=subprocess.PIPE, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, - cwd=cwd, preexec_fn=preexec_fn, env=env) + cwd=cwd, preexec_fn=preexec_fn, env=env) if sys.platform == 'win32': startupinfo = subprocess.STARTUPINFO() @@ -47,11 +47,11 @@ class PopenSpawn(SpawnBase): kwargs['startupinfo'] = startupinfo kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP - if isinstance(cmd, string_types) and sys.platform != 'win32': - cmd = shlex.split(cmd, posix=os.name == 'posix') + if isinstance(cmd, string_types) and sys.platform != 'win32': + cmd = shlex.split(cmd, posix=os.name == 'posix') self.proc = subprocess.Popen(cmd, **kwargs) - self.pid = self.proc.pid + self.pid = self.proc.pid self.closed = False self._buf = self.string_type() @@ -131,7 +131,7 @@ class PopenSpawn(SpawnBase): def send(self, s): '''Send data to the subprocess' stdin. - + Returns the number of bytes written. ''' s = self._coerce_send_string(s) @@ -155,7 +155,7 @@ class PopenSpawn(SpawnBase): def wait(self): '''Wait for the subprocess to finish. - + Returns the exit code. ''' status = self.proc.wait() @@ -170,7 +170,7 @@ class PopenSpawn(SpawnBase): def kill(self, sig): '''Sends a Unix signal to the subprocess. - + Use constants from the :mod:`signal` module to specify which signal. ''' if sys.platform == 'win32': diff --git a/contrib/python/pexpect/pexpect/pty_spawn.py b/contrib/python/pexpect/pexpect/pty_spawn.py index c58bca47a8..8e28ca7cd7 100644 --- a/contrib/python/pexpect/pexpect/pty_spawn.py +++ b/contrib/python/pexpect/pexpect/pty_spawn.py @@ -12,9 +12,9 @@ from ptyprocess.ptyprocess import use_native_pty_fork from .exceptions import ExceptionPexpect, EOF, TIMEOUT from .spawnbase import SpawnBase -from .utils import ( - which, split_command_line, select_ignore_interrupts, poll_ignore_interrupts -) +from .utils import ( + which, split_command_line, select_ignore_interrupts, poll_ignore_interrupts +) @contextmanager def _wrap_ptyprocess_err(): @@ -36,8 +36,8 @@ class spawn(SpawnBase): def __init__(self, command, args=[], timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None, ignore_sighup=False, echo=True, preexec_fn=None, - encoding=None, codec_errors='strict', dimensions=None, - use_poll=False): + encoding=None, codec_errors='strict', dimensions=None, + use_poll=False): '''This is the constructor. The command parameter may be a string that includes a command and any arguments to the command. For example:: @@ -109,9 +109,9 @@ class spawn(SpawnBase): child = pexpect.spawn('some_command') child.logfile = sys.stdout - # In Python 3, we'll use the ``encoding`` argument to decode data - # from the subprocess and handle it as unicode: - child = pexpect.spawn('some_command', encoding='utf-8') + # In Python 3, we'll use the ``encoding`` argument to decode data + # from the subprocess and handle it as unicode: + child = pexpect.spawn('some_command', encoding='utf-8') child.logfile = sys.stdout The logfile_read and logfile_send members can be used to separately log @@ -147,7 +147,7 @@ class spawn(SpawnBase): many users that I decided that the default pexpect behavior should be to sleep just before writing to the child application. 1/20th of a second (50 ms) seems to be enough to clear up the problem. You can set - delaybeforesend to None to return to the old behavior. + delaybeforesend to None to return to the old behavior. Note that spawn is clever about finding commands on your path. It uses the same logic that "which" uses to find executables. @@ -157,12 +157,12 @@ class spawn(SpawnBase): in self.exitstatus or self.signalstatus. If the child exited normally then exitstatus will store the exit return code and signalstatus will be None. If the child was terminated abnormally with a signal then - signalstatus will store the signal value and exitstatus will be None:: - - child = pexpect.spawn('some_command') - child.close() - print(child.exitstatus, child.signalstatus) - + signalstatus will store the signal value and exitstatus will be None:: + + child = pexpect.spawn('some_command') + child.close() + print(child.exitstatus, child.signalstatus) + If you need more detail you can also read the self.status member which stores the status returned by os.waitpid. You can interpret this using os.WIFEXITED/os.WEXITSTATUS or os.WIFSIGNALED/os.TERMSIG. @@ -174,7 +174,7 @@ class spawn(SpawnBase): using setecho(False) followed by waitnoecho(). However, for some platforms such as Solaris, this is not possible, and should be disabled immediately on spawn. - + If preexec_fn is given, it will be called in the child process before launching the given command. This is useful to e.g. reset inherited signal handlers. @@ -182,9 +182,9 @@ class spawn(SpawnBase): The dimensions attribute specifies the size of the pseudo-terminal as seen by the subprocess, and is specified as a two-entry tuple (rows, columns). If this is unspecified, the defaults in ptyprocess will apply. - - The use_poll attribute enables using select.poll() over select.select() - for socket handling. This is handy if your system could have > 1024 fds + + The use_poll attribute enables using select.poll() over select.select() + for socket handling. This is handy if your system could have > 1024 fds ''' super(spawn, self).__init__(timeout=timeout, maxread=maxread, searchwindowsize=searchwindowsize, logfile=logfile, encoding=encoding, codec_errors=codec_errors) @@ -203,7 +203,7 @@ class spawn(SpawnBase): self.name = '<pexpect factory incomplete>' else: self._spawn(command, args, preexec_fn, dimensions) - self.use_poll = use_poll + self.use_poll = use_poll def __str__(self): '''This returns a human-readable string that represents the state of @@ -219,8 +219,8 @@ class spawn(SpawnBase): s.append('match: %r' % (self.match,)) s.append('match_index: ' + str(self.match_index)) s.append('exitstatus: ' + str(self.exitstatus)) - if hasattr(self, 'ptyproc'): - s.append('flag_eof: ' + str(self.flag_eof)) + if hasattr(self, 'ptyproc'): + s.append('flag_eof: ' + str(self.flag_eof)) s.append('pid: ' + str(self.pid)) s.append('child_fd: ' + str(self.child_fd)) s.append('closed: ' + str(self.closed)) @@ -271,7 +271,7 @@ class spawn(SpawnBase): self.args.insert(0, command) self.command = command - command_with_path = which(self.command, env=self.env) + command_with_path = which(self.command, env=self.env) if command_with_path is None: raise ExceptionPexpect('The command was not found or was not ' + 'executable: %s.' % self.command) @@ -295,14 +295,14 @@ class spawn(SpawnBase): if dimensions is not None: kwargs['dimensions'] = dimensions - if self.encoding is not None: - # Encode command line using the specified encoding - self.args = [a if isinstance(a, bytes) else a.encode(self.encoding) - for a in self.args] + if self.encoding is not None: + # Encode command line using the specified encoding + self.args = [a if isinstance(a, bytes) else a.encode(self.encoding) + for a in self.args] + + self.ptyproc = self._spawnpty(self.args, env=self.env, + cwd=self.cwd, **kwargs) - self.ptyproc = self._spawnpty(self.args, env=self.env, - cwd=self.cwd, **kwargs) - self.pid = self.ptyproc.pid self.child_fd = self.ptyproc.fd @@ -310,10 +310,10 @@ class spawn(SpawnBase): self.terminated = False self.closed = False - def _spawnpty(self, args, **kwargs): - '''Spawn a pty and return an instance of PtyProcess.''' - return ptyprocess.PtyProcess.spawn(args, **kwargs) - + def _spawnpty(self, args, **kwargs): + '''Spawn a pty and return an instance of PtyProcess.''' + return ptyprocess.PtyProcess.spawn(args, **kwargs) + def close(self, force=True): '''This closes the connection with the child application. Note that calling close() more than once is valid. This emulates standard Python @@ -322,13 +322,13 @@ class spawn(SpawnBase): and SIGINT). ''' self.flush() - with _wrap_ptyprocess_err(): - # PtyProcessError may be raised if it is not possible to terminate - # the child. - self.ptyproc.close(force=force) + with _wrap_ptyprocess_err(): + # PtyProcessError may be raised if it is not possible to terminate + # the child. + self.ptyproc.close(force=force) self.isalive() # Update exit status from ptyproc self.child_fd = -1 - self.closed = True + self.closed = True def isatty(self): '''This returns True if the file descriptor is open and connected to a @@ -540,9 +540,9 @@ class spawn(SpawnBase): This value may be discovered using fpathconf(3):: - >>> from os import fpathconf - >>> print(fpathconf(0, 'PC_MAX_CANON')) - 256 + >>> from os import fpathconf + >>> print(fpathconf(0, 'PC_MAX_CANON')) + 256 On such a system, only 256 bytes may be received per line. Any subsequent bytes received will be discarded. BEL (``'\a'``) is then @@ -553,14 +553,14 @@ class spawn(SpawnBase): Canonical input processing may be disabled altogether by executing a shell, then stty(1), before executing the final program:: - >>> bash = pexpect.spawn('/bin/bash', echo=False) - >>> bash.sendline('stty -icanon') - >>> bash.sendline('base64') - >>> bash.sendline('x' * 5000) + >>> bash = pexpect.spawn('/bin/bash', echo=False) + >>> bash.sendline('stty -icanon') + >>> bash.sendline('base64') + >>> bash.sendline('x' * 5000) ''' - if self.delaybeforesend is not None: - time.sleep(self.delaybeforesend) + if self.delaybeforesend is not None: + time.sleep(self.delaybeforesend) s = self._coerce_send_string(s) self._log(s, 'send') @@ -574,8 +574,8 @@ class spawn(SpawnBase): written. Only a limited number of bytes may be sent for each line in the default terminal mode, see docstring of :meth:`send`. ''' - s = self._coerce_send_string(s) - return self.send(s + self.linesep) + s = self._coerce_send_string(s) + return self.send(s + self.linesep) def _log_control(self, s): """Write control characters to the appropriate log files""" @@ -772,10 +772,10 @@ class spawn(SpawnBase): s = struct.pack("HHHH", 0, 0, 0, 0) a = struct.unpack('hhhh', fcntl.ioctl(sys.stdout.fileno(), termios.TIOCGWINSZ , s)) - if not p.closed: - p.setwinsize(a[0],a[1]) - - # Note this 'p' is global and used in sigwinch_passthrough. + if not p.closed: + p.setwinsize(a[0],a[1]) + + # Note this 'p' is global and used in sigwinch_passthrough. p = pexpect.spawn('/bin/bash') signal.signal(signal.SIGWINCH, sigwinch_passthrough) p.interact() @@ -784,7 +784,7 @@ class spawn(SpawnBase): # Flush the buffer. self.write_to_stdout(self.buffer) self.stdout.flush() - self._buffer = self.buffer_type() + self._buffer = self.buffer_type() mode = tty.tcgetattr(self.STDIN_FILENO) tty.setraw(self.STDIN_FILENO) if escape_character is not None and PY3: @@ -808,20 +808,20 @@ class spawn(SpawnBase): return os.read(fd, 1000) - def __interact_copy( - self, escape_character=None, input_filter=None, output_filter=None - ): + def __interact_copy( + self, escape_character=None, input_filter=None, output_filter=None + ): '''This is used by the interact() method. ''' while self.isalive(): - if self.use_poll: - r = poll_ignore_interrupts([self.child_fd, self.STDIN_FILENO]) - else: - r, w, e = select_ignore_interrupts( - [self.child_fd, self.STDIN_FILENO], [], [] - ) + if self.use_poll: + r = poll_ignore_interrupts([self.child_fd, self.STDIN_FILENO]) + else: + r, w, e = select_ignore_interrupts( + [self.child_fd, self.STDIN_FILENO], [], [] + ) if self.child_fd in r: try: data = self.__interact_read(self.child_fd) diff --git a/contrib/python/pexpect/pexpect/pxssh.py b/contrib/python/pexpect/pexpect/pxssh.py index 03b016ce4f..3d53bd9746 100644 --- a/contrib/python/pexpect/pexpect/pxssh.py +++ b/contrib/python/pexpect/pexpect/pxssh.py @@ -23,8 +23,8 @@ PEXPECT LICENSE from pexpect import ExceptionPexpect, TIMEOUT, EOF, spawn import time import os -import sys -import re +import sys +import re __all__ = ['ExceptionPxssh', 'pxssh'] @@ -33,22 +33,22 @@ class ExceptionPxssh(ExceptionPexpect): '''Raised for pxssh exceptions. ''' -if sys.version_info > (3, 0): - from shlex import quote -else: - _find_unsafe = re.compile(r'[^\w@%+=:,./-]').search - - def quote(s): - """Return a shell-escaped version of the string *s*.""" - if not s: - return "''" - if _find_unsafe(s) is None: - return s - - # use single quotes, and put single quotes into double quotes - # the string $'b is then quoted as '$'"'"'b' - return "'" + s.replace("'", "'\"'\"'") + "'" - +if sys.version_info > (3, 0): + from shlex import quote +else: + _find_unsafe = re.compile(r'[^\w@%+=:,./-]').search + + def quote(s): + """Return a shell-escaped version of the string *s*.""" + if not s: + return "''" + if _find_unsafe(s) is None: + return s + + # use single quotes, and put single quotes into double quotes + # the string $'b is then quoted as '$'"'"'b' + return "'" + s.replace("'", "'\"'\"'") + "'" + class pxssh (spawn): '''This class extends pexpect.spawn to specialize setting up SSH connections. This adds methods for login, logout, and expecting the shell @@ -64,7 +64,7 @@ class pxssh (spawn): Example that runs a few commands on a remote server and prints the result:: - from pexpect import pxssh + from pexpect import pxssh import getpass try: s = pxssh.pxssh() @@ -88,7 +88,7 @@ class pxssh (spawn): Example showing how to specify SSH options:: - from pexpect import pxssh + from pexpect import pxssh s = pxssh.pxssh(options={ "StrictHostKeyChecking": "no", "UserKnownHostsFile": "/dev/null"}) @@ -110,14 +110,14 @@ class pxssh (spawn): password = getpass.getpass('password: ') s.login (hostname, username, password) - `debug_command_string` is only for the test suite to confirm that the string - generated for SSH is correct, using this will not allow you to do - anything other than get a string back from `pxssh.pxssh.login()`. + `debug_command_string` is only for the test suite to confirm that the string + generated for SSH is correct, using this will not allow you to do + anything other than get a string back from `pxssh.pxssh.login()`. ''' def __init__ (self, timeout=30, maxread=2000, searchwindowsize=None, logfile=None, cwd=None, env=None, ignore_sighup=True, echo=True, - options={}, encoding=None, codec_errors='strict', + options={}, encoding=None, codec_errors='strict', debug_command_string=False, use_poll=False): spawn.__init__(self, None, timeout=timeout, maxread=maxread, @@ -137,12 +137,12 @@ class pxssh (spawn): #prompt command different than the regex. # used to match the command-line prompt - self.UNIQUE_PROMPT = r"\[PEXPECT\][\$\#] " + self.UNIQUE_PROMPT = r"\[PEXPECT\][\$\#] " self.PROMPT = self.UNIQUE_PROMPT # used to set shell command-line prompt to UNIQUE_PROMPT. - self.PROMPT_SET_SH = r"PS1='[PEXPECT]\$ '" - self.PROMPT_SET_CSH = r"set prompt='[PEXPECT]\$ '" + self.PROMPT_SET_SH = r"PS1='[PEXPECT]\$ '" + self.PROMPT_SET_CSH = r"set prompt='[PEXPECT]\$ '" self.SSH_OPTS = ("-o'RSAAuthentication=no'" + " -o 'PubkeyAuthentication=no'") # Disabling host key checking, makes you vulnerable to MITM attacks. @@ -155,7 +155,7 @@ class pxssh (spawn): #self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'" self.force_password = False - self.debug_command_string = debug_command_string + self.debug_command_string = debug_command_string # User defined SSH options, eg, # ssh.otions = dict(StrictHostKeyChecking="no",UserKnownHostsFile="/dev/null") @@ -252,13 +252,13 @@ class pxssh (spawn): ### TODO: This is getting messy and I'm pretty sure this isn't perfect. ### TODO: I need to draw a flow chart for this. - ### TODO: Unit tests for SSH tunnels, remote SSH command exec, disabling original prompt sync + ### TODO: Unit tests for SSH tunnels, remote SSH command exec, disabling original prompt sync def login (self, server, username=None, password='', terminal_type='ansi', original_prompt=r"[#$]", login_timeout=10, port=None, auto_prompt_reset=True, ssh_key=None, quiet=True, - sync_multiplier=1, check_local_ip=True, - password_regex=r'(?i)(?:password:)|(?:passphrase for key)', - ssh_tunnels={}, spawn_local_ssh=True, + sync_multiplier=1, check_local_ip=True, + password_regex=r'(?i)(?:password:)|(?:passphrase for key)', + ssh_tunnels={}, spawn_local_ssh=True, sync_original_prompt=True, ssh_config=None, cmd='ssh'): '''This logs the user into the given server. @@ -284,34 +284,34 @@ class pxssh (spawn): not reset then this will disable the :meth:`prompt` method unless you manually set the :attr:`PROMPT` attribute. - Set ``password_regex`` if there is a MOTD message with `password` in it. - Changing this is like playing in traffic, don't (p)expect it to match straight - away. + Set ``password_regex`` if there is a MOTD message with `password` in it. + Changing this is like playing in traffic, don't (p)expect it to match straight + away. - If you require to connect to another SSH server from the your original SSH - connection set ``spawn_local_ssh`` to `False` and this will use your current - session to do so. Setting this option to `False` and not having an active session - will trigger an error. + If you require to connect to another SSH server from the your original SSH + connection set ``spawn_local_ssh`` to `False` and this will use your current + session to do so. Setting this option to `False` and not having an active session + will trigger an error. - Set ``ssh_key`` to a file path to an SSH private key to use that SSH key - for the session authentication. - Set ``ssh_key`` to `True` to force passing the current SSH authentication socket - to the desired ``hostname``. + Set ``ssh_key`` to a file path to an SSH private key to use that SSH key + for the session authentication. + Set ``ssh_key`` to `True` to force passing the current SSH authentication socket + to the desired ``hostname``. - Set ``ssh_config`` to a file path string of an SSH client config file to pass that - file to the client to handle itself. You may set any options you wish in here, however - doing so will require you to post extra information that you may not want to if you - run into issues. + Set ``ssh_config`` to a file path string of an SSH client config file to pass that + file to the client to handle itself. You may set any options you wish in here, however + doing so will require you to post extra information that you may not want to if you + run into issues. Alter the ``cmd`` to change the ssh client used, or to prepend it with network namespaces. For example ```cmd="ip netns exec vlan2 ssh"``` to execute the ssh in network namespace named ```vlan```. ''' - session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT] - session_init_regex_array = [] - session_init_regex_array.extend(session_regex_array) - session_init_regex_array.extend(["(?i)connection closed by remote host", EOF]) + session_regex_array = ["(?i)are you sure you want to continue connecting", original_prompt, password_regex, "(?i)permission denied", "(?i)terminal type", TIMEOUT] + session_init_regex_array = [] + session_init_regex_array.extend(session_regex_array) + session_init_regex_array.extend(["(?i)connection closed by remote host", EOF]) ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()]) if quiet: @@ -320,43 +320,43 @@ class pxssh (spawn): ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'" if self.force_password: ssh_options = ssh_options + ' ' + self.SSH_OPTS - if ssh_config is not None: - if spawn_local_ssh and not os.path.isfile(ssh_config): - raise ExceptionPxssh('SSH config does not exist or is not a file.') + if ssh_config is not None: + if spawn_local_ssh and not os.path.isfile(ssh_config): + raise ExceptionPxssh('SSH config does not exist or is not a file.') ssh_options = ssh_options + ' -F ' + ssh_config if port is not None: ssh_options = ssh_options + ' -p %s'%(str(port)) if ssh_key is not None: - # Allow forwarding our SSH key to the current session - if ssh_key==True: - ssh_options = ssh_options + ' -A' - else: - if spawn_local_ssh and not os.path.isfile(ssh_key): - raise ExceptionPxssh('private ssh key does not exist or is not a file.') - ssh_options = ssh_options + ' -i %s' % (ssh_key) - - # SSH tunnels, make sure you know what you're putting into the lists - # under each heading. Do not expect these to open 100% of the time, - # The port you're requesting might be bound. - # - # The structure should be like this: - # { 'local': ['2424:localhost:22'], # Local SSH tunnels - # 'remote': ['2525:localhost:22'], # Remote SSH tunnels - # 'dynamic': [8888] } # Dynamic/SOCKS tunnels - if ssh_tunnels!={} and isinstance({},type(ssh_tunnels)): - tunnel_types = { - 'local':'L', - 'remote':'R', - 'dynamic':'D' - } - for tunnel_type in tunnel_types: - cmd_type = tunnel_types[tunnel_type] - if tunnel_type in ssh_tunnels: - tunnels = ssh_tunnels[tunnel_type] - for tunnel in tunnels: - if spawn_local_ssh==False: - tunnel = quote(str(tunnel)) - ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(tunnel) + # Allow forwarding our SSH key to the current session + if ssh_key==True: + ssh_options = ssh_options + ' -A' + else: + if spawn_local_ssh and not os.path.isfile(ssh_key): + raise ExceptionPxssh('private ssh key does not exist or is not a file.') + ssh_options = ssh_options + ' -i %s' % (ssh_key) + + # SSH tunnels, make sure you know what you're putting into the lists + # under each heading. Do not expect these to open 100% of the time, + # The port you're requesting might be bound. + # + # The structure should be like this: + # { 'local': ['2424:localhost:22'], # Local SSH tunnels + # 'remote': ['2525:localhost:22'], # Remote SSH tunnels + # 'dynamic': [8888] } # Dynamic/SOCKS tunnels + if ssh_tunnels!={} and isinstance({},type(ssh_tunnels)): + tunnel_types = { + 'local':'L', + 'remote':'R', + 'dynamic':'D' + } + for tunnel_type in tunnel_types: + cmd_type = tunnel_types[tunnel_type] + if tunnel_type in ssh_tunnels: + tunnels = ssh_tunnels[tunnel_type] + for tunnel in tunnels: + if spawn_local_ssh==False: + tunnel = quote(str(tunnel)) + ssh_options = ssh_options + ' -' + cmd_type + ' ' + str(tunnel) if username is not None: ssh_options = ssh_options + ' -l ' + username @@ -393,18 +393,18 @@ class pxssh (spawn): raise TypeError('login() ssh_config has no user entry for %s' % server) cmd += " %s %s" % (ssh_options, server) - if self.debug_command_string: - return(cmd) - - # Are we asking for a local ssh command or to spawn one in another session? - if spawn_local_ssh: - spawn._spawn(self, cmd) - else: - self.sendline(cmd) - + if self.debug_command_string: + return(cmd) + + # Are we asking for a local ssh command or to spawn one in another session? + if spawn_local_ssh: + spawn._spawn(self, cmd) + else: + self.sendline(cmd) + # This does not distinguish between a remote server 'password' prompt # and a local ssh 'passphrase' prompt (for unlocking a private key). - i = self.expect(session_init_regex_array, timeout=login_timeout) + i = self.expect(session_init_regex_array, timeout=login_timeout) # First phase if i==0: @@ -412,16 +412,16 @@ class pxssh (spawn): # This is what you get if SSH does not have the remote host's # public key stored in the 'known_hosts' cache. self.sendline("yes") - i = self.expect(session_regex_array) + i = self.expect(session_regex_array) if i==2: # password or passphrase self.sendline(password) - i = self.expect(session_regex_array) + i = self.expect(session_regex_array) if i==4: self.sendline(terminal_type) - i = self.expect(session_regex_array) - if i==7: - self.close() - raise ExceptionPxssh('Could not establish connection to host') + i = self.expect(session_regex_array) + if i==7: + self.close() + raise ExceptionPxssh('Could not establish connection to host') # Second phase if i==0: @@ -458,10 +458,10 @@ class pxssh (spawn): else: # Unexpected self.close() raise ExceptionPxssh('unexpected login response') - if sync_original_prompt: - if not self.sync_original_prompt(sync_multiplier): - self.close() - raise ExceptionPxssh('could not synchronize with original prompt') + if sync_original_prompt: + if not self.sync_original_prompt(sync_multiplier): + self.close() + raise ExceptionPxssh('could not synchronize with original prompt') # We appear to be in. # set shell prompt to something unique. if auto_prompt_reset: diff --git a/contrib/python/pexpect/pexpect/replwrap.py b/contrib/python/pexpect/pexpect/replwrap.py index f33fd6198a..c930f1e4fe 100644 --- a/contrib/python/pexpect/pexpect/replwrap.py +++ b/contrib/python/pexpect/pexpect/replwrap.py @@ -117,14 +117,14 @@ def bash(command="bash"): bashrc = os.path.join(os.path.dirname(__file__), 'bashrc.sh') child = pexpect.spawn(command, ['--rcfile', bashrc], echo=False, encoding='utf-8') - - # If the user runs 'env', the value of PS1 will be in the output. To avoid - # replwrap seeing that as the next prompt, we'll embed the marker characters - # for invisible characters in the prompt; these show up when inspecting the - # environment variable, but not when bash displays the prompt. - ps1 = PEXPECT_PROMPT[:5] + u'\\[\\]' + PEXPECT_PROMPT[5:] - ps2 = PEXPECT_CONTINUATION_PROMPT[:5] + u'\\[\\]' + PEXPECT_CONTINUATION_PROMPT[5:] - prompt_change = u"PS1='{0}' PS2='{1}' PROMPT_COMMAND=''".format(ps1, ps2) - - return REPLWrapper(child, u'\\$', prompt_change, + + # If the user runs 'env', the value of PS1 will be in the output. To avoid + # replwrap seeing that as the next prompt, we'll embed the marker characters + # for invisible characters in the prompt; these show up when inspecting the + # environment variable, but not when bash displays the prompt. + ps1 = PEXPECT_PROMPT[:5] + u'\\[\\]' + PEXPECT_PROMPT[5:] + ps2 = PEXPECT_CONTINUATION_PROMPT[:5] + u'\\[\\]' + PEXPECT_CONTINUATION_PROMPT[5:] + prompt_change = u"PS1='{0}' PS2='{1}' PROMPT_COMMAND=''".format(ps1, ps2) + + return REPLWrapper(child, u'\\$', prompt_change, extra_init_cmd="export PAGER=cat") diff --git a/contrib/python/pexpect/pexpect/screen.py b/contrib/python/pexpect/pexpect/screen.py index 2626de2fc3..79f95c4e54 100644 --- a/contrib/python/pexpect/pexpect/screen.py +++ b/contrib/python/pexpect/pexpect/screen.py @@ -69,7 +69,7 @@ def constrain (n, min, max): class screen: '''This object maintains the state of a virtual text screen as a - rectangular array. This maintains a virtual cursor position and handles + rectangular array. This maintains a virtual cursor position and handles scrolling as characters are added. This supports most of the methods needed by an ANSI text screen. Row and column indexes are 1-based (not zero-based, like arrays). diff --git a/contrib/python/pexpect/pexpect/spawnbase.py b/contrib/python/pexpect/pexpect/spawnbase.py index 17a182b9fd..59e905764c 100644 --- a/contrib/python/pexpect/pexpect/spawnbase.py +++ b/contrib/python/pexpect/pexpect/spawnbase.py @@ -1,4 +1,4 @@ -from io import StringIO, BytesIO +from io import StringIO, BytesIO import codecs import os import sys @@ -61,7 +61,7 @@ class SpawnBase(object): # Data before searchwindowsize point is preserved, but not searched. self.searchwindowsize = searchwindowsize # Delay used before sending data to child. Time in seconds. - # Set this to None to skip the time.sleep() call completely. + # Set this to None to skip the time.sleep() call completely. self.delaybeforesend = 0.05 # Used by close() to give kernel time to update process status. # Time in seconds. @@ -69,12 +69,12 @@ class SpawnBase(object): # Used by terminate() to give kernel time to update process status. # Time in seconds. self.delayafterterminate = 0.1 - # Delay in seconds to sleep after each call to read_nonblocking(). - # Set this to None to skip the time.sleep() call completely: that - # would restore the behavior from pexpect-2.0 (for performance - # reasons or because you don't want to release Python's global - # interpreter lock). - self.delayafterread = 0.0001 + # Delay in seconds to sleep after each call to read_nonblocking(). + # Set this to None to skip the time.sleep() call completely: that + # would restore the behavior from pexpect-2.0 (for performance + # reasons or because you don't want to release Python's global + # interpreter lock). + self.delayafterread = 0.0001 self.softspace = False self.name = '<' + repr(self) + '>' self.closed = True @@ -86,7 +86,7 @@ class SpawnBase(object): # bytes mode (accepts some unicode for backwards compatibility) self._encoder = self._decoder = _NullCoder() self.string_type = bytes - self.buffer_type = BytesIO + self.buffer_type = BytesIO self.crlf = b'\r\n' if PY3: self.allowed_string_types = (bytes, str) @@ -107,7 +107,7 @@ class SpawnBase(object): self._encoder = codecs.getincrementalencoder(encoding)(codec_errors) self._decoder = codecs.getincrementaldecoder(encoding)(codec_errors) self.string_type = text_type - self.buffer_type = StringIO + self.buffer_type = StringIO self.crlf = u'\r\n' self.allowed_string_types = (text_type, ) if PY3: @@ -116,10 +116,10 @@ class SpawnBase(object): self.linesep = os.linesep.decode('ascii') # This can handle unicode in both Python 2 and 3 self.write_to_stdout = sys.stdout.write - # storage for async transport - self.async_pw_transport = None - # This is the read buffer. See maxread. - self._buffer = self.buffer_type() + # storage for async transport + self.async_pw_transport = None + # This is the read buffer. See maxread. + self._buffer = self.buffer_type() # The buffer may be trimmed for efficiency reasons. This is the # untrimmed buffer, used to create the before attribute. self._before = self.buffer_type() @@ -146,17 +146,17 @@ class SpawnBase(object): return s.encode('utf-8') return s - def _get_buffer(self): - return self._buffer.getvalue() - - def _set_buffer(self, value): - self._buffer = self.buffer_type() - self._buffer.write(value) - - # This property is provided for backwards compatability (self.buffer used - # to be a string/bytes object) - buffer = property(_get_buffer, _set_buffer) - + def _get_buffer(self): + return self._buffer.getvalue() + + def _set_buffer(self, value): + self._buffer = self.buffer_type() + self._buffer.write(value) + + # This property is provided for backwards compatability (self.buffer used + # to be a string/bytes object) + buffer = property(_get_buffer, _set_buffer) + def read_nonblocking(self, size=1, timeout=None): """This reads data from the file descriptor. @@ -240,7 +240,7 @@ class SpawnBase(object): self._pattern_type_err(p) return compiled_pattern_list - def expect(self, pattern, timeout=-1, searchwindowsize=-1, async_=False, **kw): + def expect(self, pattern, timeout=-1, searchwindowsize=-1, async_=False, **kw): '''This seeks through the stream until a pattern is matched. The pattern is overloaded and may take several types. The pattern can be a StringType, EOF, a compiled re, or a list of any of those types. @@ -265,7 +265,7 @@ class SpawnBase(object): # the input is 'foobar' index = p.expect(['foobar', 'foo']) # returns 0('foobar') if all input is available at once, - # but returns 1('foo') if parts of the final 'bar' arrive late + # but returns 1('foo') if parts of the final 'bar' arrive late When a match is found for the given pattern, the class instance attribute *match* becomes an re.MatchObject result. Should an EOF @@ -324,7 +324,7 @@ class SpawnBase(object): If you are trying to optimize for speed then see expect_list(). On Python 3.4, or Python 3.3 with asyncio installed, passing - ``async_=True`` will make this return an :mod:`asyncio` coroutine, + ``async_=True`` will make this return an :mod:`asyncio` coroutine, which you can yield from to get the same result that this method would normally give directly. So, inside a coroutine, you can replace this code:: @@ -332,19 +332,19 @@ class SpawnBase(object): With this non-blocking form:: - index = yield from p.expect(patterns, async_=True) + index = yield from p.expect(patterns, async_=True) ''' - if 'async' in kw: - async_ = kw.pop('async') - if kw: - raise TypeError("Unknown keyword arguments: {}".format(kw)) + if 'async' in kw: + async_ = kw.pop('async') + if kw: + raise TypeError("Unknown keyword arguments: {}".format(kw)) compiled_pattern_list = self.compile_pattern_list(pattern) return self.expect_list(compiled_pattern_list, - timeout, searchwindowsize, async_) + timeout, searchwindowsize, async_) def expect_list(self, pattern_list, timeout=-1, searchwindowsize=-1, - async_=False, **kw): + async_=False, **kw): '''This takes a list of compiled regular expressions and returns the index into the pattern_list that matched the child output. The list may also contain EOF or TIMEOUT(which are not compiled regular @@ -354,25 +354,25 @@ class SpawnBase(object): the expect() method. This is called by expect(). - Like :meth:`expect`, passing ``async_=True`` will make this return an + Like :meth:`expect`, passing ``async_=True`` will make this return an asyncio coroutine. ''' if timeout == -1: timeout = self.timeout - if 'async' in kw: - async_ = kw.pop('async') - if kw: - raise TypeError("Unknown keyword arguments: {}".format(kw)) + if 'async' in kw: + async_ = kw.pop('async') + if kw: + raise TypeError("Unknown keyword arguments: {}".format(kw)) exp = Expecter(self, searcher_re(pattern_list), searchwindowsize) - if async_: - from ._async import expect_async + if async_: + from ._async import expect_async return expect_async(exp, timeout) else: return exp.expect_loop(timeout) def expect_exact(self, pattern_list, timeout=-1, searchwindowsize=-1, - async_=False, **kw): + async_=False, **kw): '''This is similar to expect(), but uses plain string matching instead of compiled regular expressions in 'pattern_list'. The 'pattern_list' @@ -386,15 +386,15 @@ class SpawnBase(object): This method is also useful when you don't want to have to worry about escaping regular expression characters that you want to match. - Like :meth:`expect`, passing ``async_=True`` will make this return an + Like :meth:`expect`, passing ``async_=True`` will make this return an asyncio coroutine. ''' if timeout == -1: timeout = self.timeout - if 'async' in kw: - async_ = kw.pop('async') - if kw: - raise TypeError("Unknown keyword arguments: {}".format(kw)) + if 'async' in kw: + async_ = kw.pop('async') + if kw: + raise TypeError("Unknown keyword arguments: {}".format(kw)) if (isinstance(pattern_list, self.allowed_string_types) or pattern_list in (TIMEOUT, EOF)): @@ -414,8 +414,8 @@ class SpawnBase(object): pattern_list = [prepare_pattern(p) for p in pattern_list] exp = Expecter(self, searcher_string(pattern_list), searchwindowsize) - if async_: - from ._async import expect_async + if async_: + from ._async import expect_async return expect_async(exp, timeout) else: return exp.expect_loop(timeout) @@ -446,7 +446,7 @@ class SpawnBase(object): # I could have done this more directly by not using expect(), but # I deliberately decided to couple read() to expect() so that - # I would catch any bugs early and ensure consistent behavior. + # I would catch any bugs early and ensure consistent behavior. # It's a little less efficient, but there is less for me to # worry about if I have to later modify read() or expect(). # Note, it's OK if size==-1 in the regex. That just means it @@ -518,7 +518,7 @@ class SpawnBase(object): # For 'with spawn(...) as child:' def __enter__(self): return self - + def __exit__(self, etype, evalue, tb): # We rely on subclasses to implement close(). If they don't, it's not # clear what a context manager should do. diff --git a/contrib/python/pexpect/pexpect/utils.py b/contrib/python/pexpect/pexpect/utils.py index 3f4964589b..f774519609 100644 --- a/contrib/python/pexpect/pexpect/utils.py +++ b/contrib/python/pexpect/pexpect/utils.py @@ -1,22 +1,22 @@ import os import sys import stat -import select -import time -import errno - -try: - InterruptedError -except NameError: - # Alias Python2 exception to Python3 - InterruptedError = select.error - -if sys.version_info[0] >= 3: - string_types = (str,) -else: - string_types = (unicode, str) - - +import select +import time +import errno + +try: + InterruptedError +except NameError: + # Alias Python2 exception to Python3 + InterruptedError = select.error + +if sys.version_info[0] >= 3: + string_types = (str,) +else: + string_types = (unicode, str) + + def is_executable_file(path): """Checks that path is an executable regular file, or a symlink towards one. @@ -45,7 +45,7 @@ def is_executable_file(path): return os.access(fpath, os.X_OK) -def which(filename, env=None): +def which(filename, env=None): '''This takes a given filename; tries to find it in the environment path; then checks if it is executable. This returns the full path to the filename if found and executable. Otherwise this returns None.''' @@ -53,10 +53,10 @@ def which(filename, env=None): # Special case where filename contains an explicit path. if os.path.dirname(filename) != '' and is_executable_file(filename): return filename - if env is None: - env = os.environ - p = env.get('PATH') - if not p: + if env is None: + env = os.environ + p = env.get('PATH') + if not p: p = os.defpath pathlist = p.split(os.pathsep) for path in pathlist: @@ -125,63 +125,63 @@ def split_command_line(command_line): if arg != '': arg_list.append(arg) return arg_list - - -def select_ignore_interrupts(iwtd, owtd, ewtd, timeout=None): - - '''This is a wrapper around select.select() that ignores signals. If - select.select raises a select.error exception and errno is an EINTR - error then it is ignored. Mainly this is used to ignore sigwinch - (terminal resize). ''' - - # if select() is interrupted by a signal (errno==EINTR) then - # we loop back and enter the select() again. - if timeout is not None: - end_time = time.time() + timeout - while True: - try: - return select.select(iwtd, owtd, ewtd, timeout) - except InterruptedError: - err = sys.exc_info()[1] - if err.args[0] == errno.EINTR: - # if we loop back we have to subtract the - # amount of time we already waited. - if timeout is not None: - timeout = end_time - time.time() - if timeout < 0: - return([], [], []) - else: - # something else caused the select.error, so - # this actually is an exception. - raise - - -def poll_ignore_interrupts(fds, timeout=None): - '''Simple wrapper around poll to register file descriptors and - ignore signals.''' - - if timeout is not None: - end_time = time.time() + timeout - - poller = select.poll() - for fd in fds: - poller.register(fd, select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR) - - while True: - try: - timeout_ms = None if timeout is None else timeout * 1000 - results = poller.poll(timeout_ms) - return [afd for afd, _ in results] - except InterruptedError: - err = sys.exc_info()[1] - if err.args[0] == errno.EINTR: - # if we loop back we have to subtract the - # amount of time we already waited. - if timeout is not None: - timeout = end_time - time.time() - if timeout < 0: - return [] - else: - # something else caused the select.error, so - # this actually is an exception. - raise + + +def select_ignore_interrupts(iwtd, owtd, ewtd, timeout=None): + + '''This is a wrapper around select.select() that ignores signals. If + select.select raises a select.error exception and errno is an EINTR + error then it is ignored. Mainly this is used to ignore sigwinch + (terminal resize). ''' + + # if select() is interrupted by a signal (errno==EINTR) then + # we loop back and enter the select() again. + if timeout is not None: + end_time = time.time() + timeout + while True: + try: + return select.select(iwtd, owtd, ewtd, timeout) + except InterruptedError: + err = sys.exc_info()[1] + if err.args[0] == errno.EINTR: + # if we loop back we have to subtract the + # amount of time we already waited. + if timeout is not None: + timeout = end_time - time.time() + if timeout < 0: + return([], [], []) + else: + # something else caused the select.error, so + # this actually is an exception. + raise + + +def poll_ignore_interrupts(fds, timeout=None): + '''Simple wrapper around poll to register file descriptors and + ignore signals.''' + + if timeout is not None: + end_time = time.time() + timeout + + poller = select.poll() + for fd in fds: + poller.register(fd, select.POLLIN | select.POLLPRI | select.POLLHUP | select.POLLERR) + + while True: + try: + timeout_ms = None if timeout is None else timeout * 1000 + results = poller.poll(timeout_ms) + return [afd for afd, _ in results] + except InterruptedError: + err = sys.exc_info()[1] + if err.args[0] == errno.EINTR: + # if we loop back we have to subtract the + # amount of time we already waited. + if timeout is not None: + timeout = end_time - time.time() + if timeout < 0: + return [] + else: + # something else caused the select.error, so + # this actually is an exception. + raise diff --git a/contrib/python/pexpect/ya.make b/contrib/python/pexpect/ya.make index 2af4238756..a5bb92fcac 100644 --- a/contrib/python/pexpect/ya.make +++ b/contrib/python/pexpect/ya.make @@ -1,4 +1,4 @@ -PY23_LIBRARY() +PY23_LIBRARY() LICENSE(ISC) @@ -10,8 +10,8 @@ PEERDIR( contrib/python/ptyprocess ) -NO_LINT() - +NO_LINT() + PY_SRCS( TOP_LEVEL pexpect/ANSI.py @@ -30,17 +30,17 @@ PY_SRCS( pexpect/utils.py ) -IF (PYTHON3) - PY_SRCS( - TOP_LEVEL - pexpect/_async.py - ) -ENDIF() +IF (PYTHON3) + PY_SRCS( + TOP_LEVEL + pexpect/_async.py + ) +ENDIF() RESOURCE_FILES( PREFIX contrib/python/pexpect/ .dist-info/METADATA .dist-info/top_level.txt ) - + END() |