Browse Source

Update contrib/python/pexpect/py3 to 4.9.0

robot-contrib 1 year ago
parent
commit
425d65a76c

+ 7 - 4
contrib/python/pexpect/py3/.dist-info/METADATA

@@ -1,11 +1,15 @@
 Metadata-Version: 2.1
 Name: pexpect
-Version: 4.8.0
+Version: 4.9.0
 Summary: Pexpect allows easy control of interactive console applications.
 Home-page: https://pexpect.readthedocs.io/
 Author: Noah Spurrier; Thomas Kluyver; Jeff Quast
 Author-email: noah@noah.org, thomas@kluyver.me.uk, contact@jeffquast.com
 License: ISC license
+Project-URL: Bug Tracker, https://github.com/pexpect/pexpect/issues
+Project-URL: Documentation, https://pexpect.readthedocs.io/
+Project-URL: Source Code, https://github.com/pexpect/pexpect
+Project-URL: History, https://pexpect.readthedocs.io/en/stable/history.html
 Platform: UNIX
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
@@ -27,6 +31,7 @@ Classifier: Topic :: System :: Installation/Setup
 Classifier: Topic :: System :: Shells
 Classifier: Topic :: System :: Software Distribution
 Classifier: Topic :: Terminals
+License-File: LICENSE
 Requires-Dist: ptyprocess (>=0.5)
 
 
@@ -36,7 +41,7 @@ Don Libes' Expect. Pexpect allows your script to spawn a child application and
 control it as if a human were typing commands.
 
 Pexpect can be used for automating interactive applications such as ssh, ftp,
-passwd, telnet, etc. It can be used to a automate setup scripts for duplicating
+passwd, telnet, etc. It can be used to automate setup scripts for duplicating
 software package installations on different servers. It can be used for
 automated software testing. Pexpect is in the spirit of Don Libes' Expect, but
 Pexpect is pure Python.
@@ -45,5 +50,3 @@ The main features of Pexpect require the pty module in the Python standard
 library, which is only available on Unix-like systems. Some features—waiting
 for patterns from file descriptors or subprocesses—are also available on
 Windows.
-
-

+ 8 - 2
contrib/python/pexpect/py3/pexpect/__init__.py

@@ -1,6 +1,6 @@
 '''Pexpect is a Python module for spawning child applications and controlling
 them automatically. Pexpect can be used for automating interactive applications
-such as ssh, ftp, passwd, telnet, etc. It can be used to a automate setup
+such as ssh, ftp, passwd, telnet, etc. It can be used to automate setup
 scripts for duplicating software package installations on different servers. It
 can be used for automated software testing. Pexpect is in the spirit of Don
 Libes' Expect, but Pexpect is pure Python. Other Expect-like modules for Python
@@ -29,6 +29,12 @@ For example::
     child.expect('Password:')
     child.sendline(mypassword)
 
+Context manager can be used for the spawn() function::
+
+    with pexpect.spawn('scp foo user@example.com:.') as child:
+        child.expect('Password:')
+        child.sendline(mypassword)
+
 This works even for commands that ask for passwords or other input outside of
 the normal stdio streams. For example, ssh reads input directly from the TTY
 device which bypasses stdin.
@@ -75,7 +81,7 @@ if sys.platform != 'win32':
     from .pty_spawn import spawn, spawnu
     from .run import run, runu
 
-__version__ = '4.8.0'
+__version__ = '4.9.0'
 __revision__ = ''
 __all__ = ['ExceptionPexpect', 'EOF', 'TIMEOUT', 'spawn', 'spawnu', 'run', 'runu',
            'which', 'split_command_line', '__version__', '__revision__']

+ 28 - 101
contrib/python/pexpect/py3/pexpect/_async.py

@@ -1,101 +1,28 @@
-import asyncio
-import errno
-import signal
-
-from pexpect import EOF
-
-async def expect_async(expecter, timeout=None):
-    # First process data that was previously read - if it maches, we don't need
-    # async stuff.
-    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 = await 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 (await asyncio.wait_for(pw.fut, timeout))
-    except asyncio.TimeoutError as e:
-        transport.pause_reading()
-        return expecter.timeout(e)
-
-async def repl_run_command_async(repl, cmdlines, timeout=-1):
-    res = []
-    repl.child.sendline(cmdlines[0])
-    for line in cmdlines[1:]:
-        await 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 = await repl._expect_prompt(timeout=timeout, async_=True)
-    if prompt_idx == 1:
-        # We got the continuation prompt - command was incomplete
-        repl.child.kill(signal.SIGINT)
-        await repl._expect_prompt(timeout=1, async_=True)
-        raise ValueError("Continuation prompt found - input was incomplete:")
-    return u''.join(res + [repl.child.before])
-
-class PatternWaiter(asyncio.Protocol):
-    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()
-
-    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
-
-    def data_received(self, data):
-        spawn = self.expecter.spawn
-        s = spawn._decoder.decode(data)
-        spawn._log(s, 'read')
-
-        if self.fut.done():
-            spawn._before.write(s)
-            spawn._buffer.write(s)
-            return
-
-        try:
-            index = self.expecter.new_data(s)
-            if index is not None:
-                # Found a match
-                self.found(index)
-        except Exception as e:
-            self.expecter.errored()
-            self.error(e)
-
-    def eof_received(self):
-        # N.B. If this gets called, async will close the pipe (the spawn object)
-        # for us
-        try:
-            self.expecter.spawn.flag_eof = True
-            index = self.expecter.eof()
-        except EOF as e:
-            self.error(e)
-        else:
-            self.found(index)
-
-    def connection_lost(self, exc):
-        if isinstance(exc, OSError) and exc.errno == errno.EIO:
-            # We may get here without eof_received being called, e.g on Linux
-            self.eof_received()
-        elif exc is not None:
-            self.error(exc)
+"""Facade that provides coroutines implementation pertinent to running Py version.
+
+Python 3.5 introduced the async def/await syntax keyword.
+With later versions coroutines and methods to get the running asyncio loop are
+being deprecated, not supported anymore.
+
+For Python versions later than 3.6, coroutines and objects that are defined via
+``async def``/``await`` keywords are imported.
+
+Here the code is just imported, to provide the same interface to older code.
+"""
+# pylint: disable=unused-import
+# flake8: noqa: F401
+from sys import version_info as py_version_info
+
+# this assumes async def/await are more stable
+if py_version_info >= (3, 6):
+    from pexpect._async_w_await import (
+        PatternWaiter,
+        expect_async,
+        repl_run_command_async,
+    )
+else:
+    from pexpect._async_pre_await import (
+        PatternWaiter,
+        expect_async,
+        repl_run_command_async,
+    )

+ 111 - 0
contrib/python/pexpect/py3/pexpect/_async_pre_await.py

@@ -0,0 +1,111 @@
+"""Implementation of coroutines without using ``async def``/``await`` keywords.
+
+``@asyncio.coroutine`` and ``yield from`` are  used here instead.
+"""
+import asyncio
+import errno
+import signal
+
+from pexpect import EOF
+
+
+@asyncio.coroutine
+def expect_async(expecter, timeout=None):
+    # First process data that was previously read - if it maches, we don't need
+    # async stuff.
+    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()
+    try:
+        return (yield from asyncio.wait_for(pw.fut, timeout))
+    except asyncio.TimeoutError as e:
+        transport.pause_reading()
+        return expecter.timeout(e)
+
+
+@asyncio.coroutine
+def repl_run_command_async(repl, cmdlines, timeout=-1):
+    res = []
+    repl.child.sendline(cmdlines[0])
+    for line in cmdlines[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:
+        # We got the continuation prompt - command was incomplete
+        repl.child.kill(signal.SIGINT)
+        yield from repl._expect_prompt(timeout=1, async_=True)
+        raise ValueError("Continuation prompt found - input was incomplete:")
+    return "".join(res + [repl.child.before])
+
+
+class PatternWaiter(asyncio.Protocol):
+    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()
+
+    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
+
+    def data_received(self, data):
+        spawn = self.expecter.spawn
+        s = spawn._decoder.decode(data)
+        spawn._log(s, "read")
+
+        if self.fut.done():
+            spawn._before.write(s)
+            spawn._buffer.write(s)
+            return
+
+        try:
+            index = self.expecter.new_data(s)
+            if index is not None:
+                # Found a match
+                self.found(index)
+        except Exception as e:
+            self.expecter.errored()
+            self.error(e)
+
+    def eof_received(self):
+        # N.B. If this gets called, async will close the pipe (the spawn object)
+        # for us
+        try:
+            self.expecter.spawn.flag_eof = True
+            index = self.expecter.eof()
+        except EOF as e:
+            self.error(e)
+        else:
+            self.found(index)
+
+    def connection_lost(self, exc):
+        if isinstance(exc, OSError) and exc.errno == errno.EIO:
+            # We may get here without eof_received being called, e.g on Linux
+            self.eof_received()
+        elif exc is not None:
+            self.error(exc)

+ 118 - 0
contrib/python/pexpect/py3/pexpect/_async_w_await.py

@@ -0,0 +1,118 @@
+"""Implementation of coroutines using ``async def``/``await`` keywords.
+
+These keywords replaced ``@asyncio.coroutine`` and ``yield from`` from
+Python 3.5 onwards.
+"""
+import asyncio
+import errno
+import signal
+from sys import version_info as py_version_info
+
+from pexpect import EOF
+
+if py_version_info >= (3, 7):
+    # get_running_loop, new in 3.7, is preferred to get_event_loop
+    _loop_getter = asyncio.get_running_loop
+else:
+    # Deprecation warning since 3.10
+    _loop_getter = asyncio.get_event_loop
+
+
+async def expect_async(expecter, timeout=None):
+    # First process data that was previously read - if it maches, we don't need
+    # async stuff.
+    idx = expecter.existing_data()
+    if idx is not None:
+        return idx
+    if not expecter.spawn.async_pw_transport:
+        pattern_waiter = PatternWaiter()
+        pattern_waiter.set_expecter(expecter)
+        transport, pattern_waiter = await _loop_getter().connect_read_pipe(
+            lambda: pattern_waiter, expecter.spawn
+        )
+        expecter.spawn.async_pw_transport = pattern_waiter, transport
+    else:
+        pattern_waiter, transport = expecter.spawn.async_pw_transport
+        pattern_waiter.set_expecter(expecter)
+        transport.resume_reading()
+    try:
+        return await asyncio.wait_for(pattern_waiter.fut, timeout)
+    except asyncio.TimeoutError as exc:
+        transport.pause_reading()
+        return expecter.timeout(exc)
+
+
+async def repl_run_command_async(repl, cmdlines, timeout=-1):
+    res = []
+    repl.child.sendline(cmdlines[0])
+    for line in cmdlines[1:]:
+        await 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 = await repl._expect_prompt(timeout=timeout, async_=True)
+    if prompt_idx == 1:
+        # We got the continuation prompt - command was incomplete
+        repl.child.kill(signal.SIGINT)
+        await repl._expect_prompt(timeout=1, async_=True)
+        raise ValueError("Continuation prompt found - input was incomplete:")
+    return "".join(res + [repl.child.before])
+
+
+class PatternWaiter(asyncio.Protocol):
+    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()
+
+    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
+
+    def data_received(self, data):
+        spawn = self.expecter.spawn
+        s = spawn._decoder.decode(data)
+        spawn._log(s, "read")
+
+        if self.fut.done():
+            spawn._before.write(s)
+            spawn._buffer.write(s)
+            return
+
+        try:
+            index = self.expecter.new_data(s)
+            if index is not None:
+                # Found a match
+                self.found(index)
+        except Exception as exc:
+            self.expecter.errored()
+            self.error(exc)
+
+    def eof_received(self):
+        # N.B. If this gets called, async will close the pipe (the spawn object)
+        # for us
+        try:
+            self.expecter.spawn.flag_eof = True
+            index = self.expecter.eof()
+        except EOF as exc:
+            self.error(exc)
+        else:
+            self.found(index)
+
+    def connection_lost(self, exc):
+        if isinstance(exc, OSError) and exc.errno == errno.EIO:
+            # We may get here without eof_received being called, e.g on Linux
+            self.eof_received()
+        elif exc is not None:
+            self.error(exc)

+ 2 - 0
contrib/python/pexpect/py3/pexpect/bashrc.sh

@@ -14,3 +14,5 @@ PS1="$"
 
 # Unset PROMPT_COMMAND, so that it can't change PS1 to something unexpected.
 unset PROMPT_COMMAND
+
+bind 'set enable-bracketed-paste off'

+ 5 - 1
contrib/python/pexpect/py3/pexpect/fdpexpect.py

@@ -1,7 +1,11 @@
-'''This is like pexpect, but it will work with any file descriptor that you
+'''This is like :mod:`pexpect`, but it will work with any file descriptor that you
 pass it. You are responsible for opening and close the file descriptor.
 This allows you to use Pexpect with sockets and named pipes (FIFOs).
 
+.. note::
+    socket.fileno() does not give a readable file descriptor on windows.
+    Use :mod:`pexpect.socket_pexpect` for cross-platform socket support
+
 PEXPECT LICENSE
 
     This license is approved by the OSI and FSF as GPL-compatible.

+ 1 - 1
contrib/python/pexpect/py3/pexpect/popen_spawn.py

@@ -57,7 +57,7 @@ class PopenSpawn(SpawnBase):
 
         self._read_queue = Queue()
         self._read_thread = threading.Thread(target=self._read_incoming)
-        self._read_thread.setDaemon(True)
+        self._read_thread.daemon = True
         self._read_thread.start()
 
     _read_reached_eof = False

+ 8 - 5
contrib/python/pexpect/py3/pexpect/pxssh.py

@@ -143,8 +143,8 @@ class pxssh (spawn):
         # 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.SSH_OPTS = ("-o'RSAAuthentication=no'"
-                + " -o 'PubkeyAuthentication=no'")
+        self.PROMPT_SET_ZSH = "prompt restore;\nPS1='[PEXPECT]%(!.#.$) '"
+        self.SSH_OPTS = (" -o 'PubkeyAuthentication=no'")
 # Disabling host key checking, makes you vulnerable to MITM attacks.
 #                + " -o 'StrictHostKeyChecking=no'"
 #                + " -o 'UserKnownHostsFile /dev/null' ")
@@ -152,7 +152,7 @@ class pxssh (spawn):
         # displaying a GUI password dialog. I have not figured out how to
         # disable only SSH_ASKPASS without also disabling X11 forwarding.
         # Unsetting SSH_ASKPASS on the remote side doesn't disable it! Annoying!
-        #self.SSH_OPTS = "-x -o'RSAAuthentication=no' -o 'PubkeyAuthentication=no'"
+        #self.SSH_OPTS = "-x -o 'PubkeyAuthentication=no'"
         self.force_password = False
 
         self.debug_command_string = debug_command_string
@@ -530,8 +530,11 @@ class pxssh (spawn):
         if i == 0: # csh-style
             self.sendline(self.PROMPT_SET_CSH)
             i = self.expect([TIMEOUT, self.PROMPT], timeout=10)
-            if i == 0:
-                return False
+            if i == 0: # zsh-style
+                self.sendline(self.PROMPT_SET_ZSH)
+                i = self.expect([TIMEOUT, self.PROMPT], timeout=10)
+                if i == 0:
+                    return False
         return True
 
 # vi:ts=4:sw=4:expandtab:ft=python:

+ 14 - 8
contrib/python/pexpect/py3/pexpect/replwrap.py

@@ -108,23 +108,29 @@ class REPLWrapper(object):
                              + command)
         return u''.join(res + [self.child.before])
 
-def python(command="python"):
+def python(command=sys.executable):
     """Start a Python shell and return a :class:`REPLWrapper` object."""
     return REPLWrapper(command, u">>> ", u"import sys; sys.ps1={0!r}; sys.ps2={1!r}")
 
-def bash(command="bash"):
-    """Start a bash shell and return a :class:`REPLWrapper` object."""
-    bashrc = os.path.join(os.path.dirname(__file__), 'bashrc.sh')
-    child = pexpect.spawn(command, ['--rcfile', bashrc], echo=False,
-                          encoding='utf-8')
+def _repl_sh(command, args, non_printable_insert):
+    child = pexpect.spawn(command, args, 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:]
+    ps1 = PEXPECT_PROMPT[:5] + non_printable_insert + PEXPECT_PROMPT[5:]
+    ps2 = PEXPECT_CONTINUATION_PROMPT[:5] + non_printable_insert + 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")
+
+def bash(command="bash"):
+    """Start a bash shell and return a :class:`REPLWrapper` object."""
+    bashrc = os.path.join(os.path.dirname(__file__), 'bashrc.sh')
+    return _repl_sh(command, ['--rcfile', bashrc], non_printable_insert='\\[\\]')
+
+def zsh(command="zsh", args=("--no-rcs", "-V", "+Z")):
+    """Start a zsh shell and return a :class:`REPLWrapper` object."""
+    return _repl_sh(command, list(args), non_printable_insert='%(!..)')

Some files were not shown because too many files changed in this diff