def expect_ftcs_command_finished(zsh: pexpect.spawn) -> typing.Optional[int]:
    """Match a FinalTerm FTCS_COMMAND_FINISHED escape sequence.
    """
    zsh.expect(
        b"\x1b]133;D(?:;(?P<exit_status>[0-9]+))?" + ftcs_extra_arguments_re + b"\x07"
    )
    exit_status = zsh.match.group("exit_status")
    if not exit_status:
        return None
    return int(exit_status)
def assert_bash_exec(
        bash: pexpect.spawn, cmd: str, want_output: bool = False) -> str:

    # Send command
    bash.sendline(cmd)
    bash.expect_exact(cmd)

    # Find prompt, output is before it
    bash.expect_exact("\r\n" + PS1)
    output = bash.before

    # Retrieve exit status
    echo = "echo $?"
    bash.sendline(echo)
    got = bash.expect([
        r"^%s\r\n(\d+)\r\n%s" % (re.escape(echo), re.escape(PS1)),
        PS1,
        pexpect.EOF,
        pexpect.TIMEOUT,
    ])
    status = bash.match.group(1) if got == 0 else "unknown"

    assert status == "0", \
        'Error running "%s": exit status=%s, output="%s"' % \
        (cmd, status, output)
    if output:
        assert want_output, \
            'Unexpected output from "%s": exit status=%s, output="%s"' % \
            (cmd, status, output)
    else:
        assert not want_output, \
            'Expected output from "%s": exit status=%s, output="%s"' % \
            (cmd, status, output)

    return output
Beispiel #3
0
 def spawnAction(self, sp: spawn):
     keys = list(self.keys())
     r = sp.expect(keys)
     yield r
     matched = keys[r]
     print('received {} ({})'.format(matched, r))
     yield from self.get(matched).spawnAction(sp)
def is_bash_type(bash: pexpect.spawn, cmd: str) -> bool:
    typecmd = "type %s &>/dev/null && echo -n 0 || echo -n 1" % cmd
    bash.sendline(typecmd)
    bash.expect_exact(typecmd + "\r\n")
    result = bash.expect_exact(["0", "1"]) == 0
    bash.expect_exact(PS1)
    return result
Beispiel #5
0
    def execute(self, sp: spawn, outputhook=print):
        gen = self.seq.spawnAction(sp)
        try:
            self.last = next(gen)
            while True:
                args = self.log(sp, outputhook)
                self.last = gen.send(args)
        except StopIteration:
            r = sp.expect([EOF, TIMEOUT])
            self.log(sp, outputhook)
            if r:
                self.error(sp.command)
        except (TIMEOUT, EOF) as e:
            self.log(sp, outputhook)
            self.error(sp.command)
            raise e

        return self
def expect_ftcs_command_executed(zsh: pexpect.spawn) -> None:
    """Match a FinalTerm FTCS_COMMAND_EXECUTED escape sequence.
    """
    zsh.expect(b"\x1b]133;C" + ftcs_extra_arguments_re + b"\x07")
def expect_ftcs_command_start(zsh: pexpect.spawn) -> None:
    """Match a FinalTerm FTCS_COMMAND_START escape sequence.
    """
    zsh.expect(b"\x1b]133;B" + ftcs_extra_arguments_re + b"\x07")
def expect_ftcs_prompt(zsh: pexpect.spawn) -> None:
    """Match a FinalTerm FTCS_PROMPT escape sequence.
    """
    zsh.expect(b"\x1b]133;A" + ftcs_extra_arguments_re + b"\x07")
Beispiel #9
0
    def connect(self, connection=None):
        """
        See :meth:`BaseShell.connect` for more information.
        """
        connection = connection or self._default_connection or '0'

        if connection in self._connections and self.is_connected(connection):
            raise AlreadyConnectedError(connection)

        # Inject framework logger to the spawn object
        spawn_args = {
            'logfile': get_logger(
                OrderedDict([
                    ('node_identifier', self._node_identifier),
                    ('shell_name', self._shell_name),
                    ('connection', connection)
                ]),
                category='pexpect'
            ),
        }

        # Create a child process
        spawn_args.update(self._spawn_args)

        spawn = Spawn(
            self._get_connect_command().strip(),
            **spawn_args
        )

        # Add a connection logger
        # Note: self._node and self._name were added to this shell in the
        #       node's call to its _register_shell method.
        spawn._connection_logger = get_logger(
            OrderedDict([
                ('node_identifier', self._node_identifier),
                ('shell_name', self._shell_name),
                ('connection', connection)
            ]),
            category='connection'
        )

        self._connections[connection] = spawn

        try:
            # If connection is via user
            if self._user is not None:
                spawn.expect(
                    [self._user_match], timeout=self._timeout
                )
                spawn.sendline(self._user)

            # If connection is via password
            if self._password is not None:
                spawn.expect(
                    [self._password_match], timeout=self._timeout
                )
                spawn.sendline(self._password)

            # Setup shell before using it
            self._setup_shell(connection)

            # Execute initial command if required
            if self._initial_command is not None:
                spawn.expect(
                    self._prompt, timeout=self._timeout
                )
                spawn.sendline(self._initial_command)

            # Wait for command response to match the prompt
            spawn.expect(
                self._prompt, timeout=self._timeout
            )

        except:
            # Always remove bad connections if it failed
            del self._connections[connection]
            raise

        # Set connection as default connection if required
        if self.default_connection is None:
            self.default_connection = connection
Beispiel #10
0
 def spawnAction(self, sp: spawn):
     print("sendline {}".format(self))
     yield sp.sendline(self)
Beispiel #11
0
def wait_for_pexpect_process(process: pexpect.spawn) -> int:
    process.expect_exact(pexpect.EOF)
    return process.wait()
def send_and_expect_byte_by_byte(zsh: pexpect.spawn, input: bytes) -> bytes:
    for byte in input:
        current_input = bytes([byte])
        zsh.send(current_input)
        zsh.expect(string_ignoring_escape_sequences_re(current_input))
Beispiel #13
0
def assert_complete(
        bash: pexpect.spawn, cmd: str, **kwargs) -> CompletionResult:
    skipif = kwargs.get("skipif")
    if skipif:
        try:
            assert_bash_exec(bash, skipif)
        except AssertionError:
            pass
        else:
            pytest.skip(skipif)
            return CompletionResult("", [])
    cwd = kwargs.get("cwd")
    if cwd:
        assert_bash_exec(bash, "cd '%s'" % cwd)
    env_prefix = "_BASHCOMP_TEST_"
    env = kwargs.get("env", {})
    if env:
        # Back up environment and apply new one
        assert_bash_exec(bash, " ".join(
            '%s%s="$%s"' % (env_prefix, k, k) for k in env.keys()
        ))
        assert_bash_exec(bash, "export %s" % " ".join(
            "%s=%s" % (k, v) for k, v in env.items()
        ))
    bash.send(cmd + "\t")
    bash.expect_exact(cmd)
    bash.send(MAGIC_MARK)
    got = bash.expect([
        r"\r\n" + re.escape(PS1 + cmd),  # 0: multiple lines, result in .before
        r"^" + MAGIC_MARK,               # 1: no completion
        r"^[^\r]+",                      # 2: on same line, result in .after
        pexpect.EOF,
        pexpect.TIMEOUT,
    ])
    if got == 0:
        line = bash.before
        if line.endswith(MAGIC_MARK):
            line = bash.before[:-len(MAGIC_MARK)]
        result = CompletionResult(
            line,
            sorted(x for x in re.split(r" {2,}|\r\n", line) if x),
        )
    elif got == 2:
        line = bash.after
        if line.endswith(MAGIC_MARK):
            line = bash.after[:-len(MAGIC_MARK)]
        result = CompletionResult(
            line,
            [shlex.split(cmd + line)[-1]],
        )
    else:
        # TODO: warn about EOF/TIMEOUT?
        result = CompletionResult("", [])
    bash.sendintr()
    bash.expect_exact(PS1)
    if env:
        # Restore environment, and clean up backup
        # TODO: Test with declare -p if a var was set, backup only if yes, and
        #       similarly restore only backed up vars. Should remove some need
        #       for ignore_env.
        assert_bash_exec(bash, "export %s" % " ".join(
            '%s="$%s%s"' % (k, env_prefix, k) for k in env.keys()
        ))
        assert_bash_exec(bash, "unset -v %s" % " ".join(
            "%s%s" % (env_prefix, k) for k in env.keys()
        ))
    if cwd:
        assert_bash_exec(bash, "cd - >/dev/null")
    return result
Beispiel #14
0
def assert_complete(bash: pexpect.spawn, cmd: str,
                    **kwargs) -> CompletionResult:
    skipif = kwargs.get("skipif")
    if skipif:
        try:
            assert_bash_exec(bash, skipif)
        except AssertionError:
            pass
        else:
            pytest.skip(skipif)
            return CompletionResult("", [])
    cwd = kwargs.get("cwd")
    if cwd:
        assert_bash_exec(bash, "cd '%s'" % cwd)
    env_prefix = "_BASHCOMP_TEST_"
    env = kwargs.get("env", {})
    if env:
        # Back up environment and apply new one
        assert_bash_exec(
            bash,
            " ".join('%s%s="$%s"' % (env_prefix, k, k) for k in env.keys()))
        assert_bash_exec(
            bash,
            "export %s" % " ".join("%s=%s" % (k, v) for k, v in env.items()))
    bash.send(cmd + "\t")
    bash.expect_exact(cmd)
    bash.send(MAGIC_MARK)
    got = bash.expect([
        # 0: multiple lines, result in .before
        r"\r\n" + re.escape(PS1 + cmd) + ".*" + MAGIC_MARK,
        # 1: no completion
        r"^" + MAGIC_MARK,
        # 2: on same line, result in .match
        r"^([^\r]+)%s$" % MAGIC_MARK,
        pexpect.EOF,
        pexpect.TIMEOUT,
    ])
    if got == 0:
        output = bash.before
        if output.endswith(MAGIC_MARK):
            output = bash.before[:-len(MAGIC_MARK)]
        result = CompletionResult(output)
    elif got == 2:
        output = bash.match.group(1)
        result = CompletionResult(output, [shlex.split(cmd + output)[-1]])
    else:
        # TODO: warn about EOF/TIMEOUT?
        result = CompletionResult("", [])
    bash.sendintr()
    bash.expect_exact(PS1)
    if env:
        # Restore environment, and clean up backup
        # TODO: Test with declare -p if a var was set, backup only if yes, and
        #       similarly restore only backed up vars. Should remove some need
        #       for ignore_env.
        assert_bash_exec(
            bash, "export %s" % " ".join('%s="$%s%s"' % (k, env_prefix, k)
                                         for k in env.keys()))
        assert_bash_exec(
            bash, "unset -v %s" % " ".join("%s%s" % (env_prefix, k)
                                           for k in env.keys()))
    if cwd:
        assert_bash_exec(bash, "cd - >/dev/null")
    return result
Beispiel #15
0
 def spawnAction(self, sp: spawn):
     print("expecting {}".format(self))
     yield sp.expect(self)
def expect_iterm_current_dir(zsh: pexpect.spawn) -> bytes:
    """Match a iTerm CurrentDir escape sequence.
    """
    zsh.expect(b"\x1b](?:1337|50);CurrentDir=(?P<iterm_current_dir_path>.*?)\x07")
    return zsh.match.group("iterm_current_dir_path")
Beispiel #17
0
 def spawnAction(self, sp: spawn):
     print("sending {}".format(self))
     yield sp.send(self)
Beispiel #18
0
    def connect(self, connection=None):
        """
        See :meth:`BaseShell.connect` for more information.
        """
        connection = connection or self._default_connection or '0'

        if connection in self._connections and self.is_connected(connection):
            raise AlreadyConnectedError(connection)

        # Create a child process
        spawn = Spawn(
            self._get_connect_command().strip(),
            **self._spawn_args
        )
        self._connections[connection] = spawn

        try:
            # If connection is via user
            if self._user is not None:
                spawn.expect(
                    [self._user_match], timeout=self._timeout
                )
                spawn.sendline(self._user)

            # If connection is via password
            if self._password is not None:
                spawn.expect(
                    [self._password_match], timeout=self._timeout
                )
                spawn.sendline(self._password)

            # Setup shell before using it
            self._setup_shell(connection)

            # Execute initial command if required
            if self._initial_command is not None:
                spawn.expect(
                    self._prompt, timeout=self._timeout
                )
                spawn.sendline(self._initial_command)

            # Wait for command response to match the prompt
            spawn.expect(
                self._prompt, timeout=self._timeout
            )

        except:
            # Always remove bad connections if it failed
            del self._connections[connection]
            raise

        # Set connection as default connection if required
        if self.default_connection is None:
            self.default_connection = connection
Beispiel #19
0
    def connect(self, connection=None):
        """
        See :meth:`BaseShell.connect` for more information.
        """
        connection = connection or self._default_connection or '0'

        if connection in self._connections and self.is_connected(connection):
            raise AlreadyConnectedError(connection)

        # Create a child process
        spawn = Spawn(self._get_connect_command().strip(), **self._spawn_args)
        self._connections[connection] = spawn

        try:
            # If connection is via user
            if self._user is not None:
                spawn.expect([self._user_match], timeout=self._timeout)
                spawn.sendline(self._user)

            # If connection is via password
            if self._password is not None:
                spawn.expect([self._password_match], timeout=self._timeout)
                spawn.sendline(self._password)

            # Setup shell before using it
            self._setup_shell(connection)

            # Execute initial command if required
            if self._initial_command is not None:
                spawn.expect(self._prompt, timeout=self._timeout)
                spawn.sendline(self._initial_command)

            # Wait for command response to match the prompt
            spawn.expect(self._prompt, timeout=self._timeout)

        except:
            # Always remove bad connections if it failed
            del self._connections[connection]
            raise

        # Set connection as default connection if required
        if self.default_connection is None:
            self.default_connection = connection