Exemple #1
0
def test_run_with_check_raise() -> None:
    """Asure compatibility with subprocess.run when using check (return 1)."""
    with pytest.raises(subprocess.CalledProcessError) as ours:
        run("false", check=True)
    with pytest.raises(subprocess.CalledProcessError) as original:
        subprocess.run("false", check=True, universal_newlines=True)
    assert ours.value.returncode == original.value.returncode
    assert ours.value.cmd == original.value.cmd
    assert ours.value.output == original.value.output
    assert ours.value.stdout == original.value.stdout
    assert ours.value.stderr == original.value.stderr
Exemple #2
0
def run_command(cmd, env=None, debug=False, echo=False) -> CompletedProcess:
    """
    Execute the given command and returns None.

    :param cmd: :
        - a string or list of strings (similar to subprocess.run)
        - a BakedCommand object (
    :param debug: An optional bool to toggle debug output.
    :return: ``sh`` object
    """
    args = []
    stdout = None
    stderr = None
    if cmd.__class__.__name__ == "Command":
        raise RuntimeError(
            "Molecule 3.2.0 dropped use of sh library, update plugin code to use new API. "
            "See https://github.com/ansible-community/molecule/issues/2678")
    elif cmd.__class__.__name__ == "BakedCommand":
        env = cmd.env if not env else cmd.env.copy().update(env)
        args = cmd.cmd
        stdout = cmd.stdout
        stderr = cmd.stderr
    else:
        args = cmd

    if debug:
        print_environment_vars(env)

    return run(args, env=env, stdout=stdout, stderr=stderr, echo=echo or debug)
Exemple #3
0
def test_run_shell_undefined() -> None:
    """Validate run call with multiple shell commands works."""
    cmd = "echo a && echo b && false || exit 4"
    # "python --version"
    result = run(cmd, echo=True, env={})
    assert result.returncode == 4
    assert result.stdout == "a\nb\n"
def run_command(
    cmd: Union[str, List[str]],
    env: Optional[Dict[str, str]] = None,
    debug: bool = False,
    echo: bool = False,
    quiet: bool = False,
    check: bool = False,
    cwd: Union[Optional[str], Optional[Path]] = None,
) -> CompletedProcess:
    """Run a command

    Parameters
    ----------
    cmd: Union[str, List[str]]
        A string or list of strings that will be passed to subprocess.run()
    env: Optional[Dict[str, str]]
        A dict of environment variables and their respective values (defaults to None)
    debug: bool
        Whether to run in debug mode, which prints environment variables and command output (defaults to False)
    echo: bool
        Whether to print the command before running it (defaults to False)
    quiet: bool
        Whether to print the output of command while running it (defaults to False)
    check: bool
        Whether to check the return code of the command, which implies raising CallecProcessError (defaults to False)
    cwd: Union[Optional[str], Optional[Path]]
        In which directory to run the command (defaults to None, which means current working directory)

    Raises
    ------
    CalledProcessError
        If check is True and the commands return code is not 0

    Returns
    -------
    CompletedProcess
        The result of the command
    """

    if debug:
        _print_env(env)

    result = run(
        cmd,
        env=env,
        stdout=PIPE,
        stderr=STDOUT,
        echo=echo or debug,
        quiet=quiet,
        cwd=cwd,
    )
    if result.returncode != 0 and check:
        raise CalledProcessError(
            returncode=result.returncode,
            cmd=result.args,
            output=result.stdout,
            stderr=result.stderr,
        )
    return result
Exemple #5
0
def test_run_with_check_pass() -> None:
    """Asure compatibility with subprocess.run when using check (return 0)."""
    ours = run("true", check=True)
    original = subprocess.run("true", check=True, universal_newlines=True)
    assert ours.returncode == original.returncode
    assert ours.args == original.args
    assert ours.stdout == original.stdout
    assert ours.stderr == original.stderr
Exemple #6
0
def run_command(cmd,
                env=None,
                debug=False,
                echo=False,
                quiet=False,
                check=False,
                cwd=None) -> CompletedProcess:
    """
    Execute the given command and returns None.

    :param cmd: :
        - a string or list of strings (similar to subprocess.run)
        - a BakedCommand object (
    :param debug: An optional bool to toggle debug output.
    """
    args = []
    stdout = None
    stderr = None
    if cmd.__class__.__name__ == "Command":
        raise RuntimeError(
            "Molecule 3.2.0 dropped use of sh library, update plugin code to use new API. "
            "See https://github.com/ansible-community/molecule/issues/2678")
    elif cmd.__class__.__name__ == "BakedCommand":
        if cmd.env and env:
            env = dict(cmd.env, **env)
        else:
            env = cmd.env or env
        args = cmd.cmd
        stdout = cmd.stdout
        stderr = cmd.stderr
    else:
        args = cmd

    if debug:
        print_environment_vars(env)

    result = run(
        args,
        env=env,
        stdout=stdout,
        stderr=stderr,
        echo=echo or debug,
        quiet=quiet,
        cwd=cwd,
    )
    if result.returncode != 0 and check:
        raise CalledProcessError(
            returncode=result.returncode,
            cmd=result.args,
            output=result.stdout,
            stderr=result.stderr,
        )
    return result
Exemple #7
0
def test_run_string() -> None:
    """Valida run() called with a single string command."""
    cmd = "echo 111 && >&2 echo 222"
    old_result = subprocess.run(
        cmd,
        shell=True,
        universal_newlines=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )
    result = run(cmd)
    assert result.returncode == old_result.returncode
    assert result.stdout == old_result.stdout
    assert result.stderr == old_result.stderr
Exemple #8
0
def test_rich_console_ex() -> None:
    """Validate that ConsoleEx can capture output from print() calls."""
    console = Console(record=True, redirect=True)
    console.print("alpha")
    print("beta")
    sys.stdout.write("gamma\n")
    sys.stderr.write("delta\n")
    # While not supposed to happen we want to be sure that this will not raise
    # an exception. Some libraries may still sometimes send bytes to the
    # streams, notable example being click.
    # sys.stdout.write(b"epsilon\n")  # type: ignore
    proc = run("echo 123")
    assert proc.stdout == "123\n"
    text = console.export_text()
    assert text == "alpha\nbeta\ngamma\ndelta\n123\n"
Exemple #9
0
def test_rich_console_ex_ansi() -> None:
    """Validate that ANSI sent to sys.stdout does not become garbage in record."""
    print()
    console = Console(force_terminal=True, record=True, redirect=True)
    console.print("[green]this from Console.print()[/green]", style="red")
    proc = run(r'echo -e "\033[31mred\033[0m"')
    assert proc.returncode == 0
    assert "red" in proc.stdout

    # validate that what rich recorded is the same as what the subprocess produced
    text = console.export_text(clear=False)
    assert "red" in text

    # validate that html export also contains at least the "red" text
    html = console.export_html(clear=False)
    assert '<span class="r3">red</span>' in html
Exemple #10
0
def test_run_echo(capsys: CaptureFixture[str]) -> None:
    """Validate run call with echo dumps command."""
    cmd = ["python3", "--version"]
    old_result = subprocess.run(
        cmd,
        # shell=True,
        universal_newlines=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )
    result = run(cmd, echo=True)
    assert result.returncode == old_result.returncode
    assert result.stdout == old_result.stdout
    assert result.stderr == old_result.stderr
    out, err = capsys.readouterr()
    assert out.startswith("COMMAND:")
    assert err == ""
Exemple #11
0
def test_run_list() -> None:
    """Validate run call with a command made of list of strings."""
    # NOTICE: subprocess.run() does fail to capture any output when cmd is
    # a list and you specific shell=True. Still, when not mentioning shell,
    # it does work.
    cmd = ["python3", "--version"]
    old_result = subprocess.run(
        cmd,
        # shell=True,
        universal_newlines=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        check=False,
    )
    result = run(cmd)
    assert result.returncode == old_result.returncode
    assert result.stdout == old_result.stdout
    assert result.stderr == old_result.stderr
Exemple #12
0
def main():
    """
    Execute input command and send output to telegram bot.
    """
    config = get_config()

    # parsing the arguments
    parser = argparse.ArgumentParser()
    parser.add_argument('command', type=str, help='command to be executed')
    input = parser.parse_args()

    start_time = time.time()
    print(f'executing command {input.command}')
    try:
        output = subprocess_tee.run(input.command, shell=True)
        output = output.stdout
        duration = time.time() - start_time
        message = f'Job {input.command} at {config["other"]["loc_name"]} just finished. ' \
                  f'It took {duration} seconds or {duration // 60} minutes. \n '

        # Telegram limits the message length to 4096 characters
        if len(output) > 4095 and config.getboolean('other', 'ppb'):
            import tempfile
            import os

            with tempfile.TemporaryDirectory() as tmpdirname:
                file_path = Path(tmpdirname) / 'tempfile.txt'
                with open(file_path, mode='w') as f:
                    f.write(output)
                ppb_output = str(
                    subprocess.check_output(f'ppb {file_path}',
                                            shell=True).rstrip())
            for substr in ppb_output.split():
                if substr.startswith('http'):
                    break
            message += f'The output can be seen here: {substr}.'
        else:
            message += f'The output is: \n\n {output[:3500]}'
    except:
        e = sys.exc_info()[0]
        duration = time.time() - start_time
        message = f'your job got killed with: \n {e} \n It lived for {duration} seconds. Sorry for your loss.'

    send_msg(message)
Exemple #13
0
def test_run_with_env(env: Dict[str, str]) -> None:
    """Validate that passing custom env to run() works."""
    env["FOO"] = "BAR"
    result = run("echo $FOO", env=env, echo=True)
    assert result.stdout == "BAR\n"
Exemple #14
0
def test_run_cwd() -> None:
    """Validate that run accepts cwd and respects it."""
    cmd = "pwd"
    result = run(cmd, echo=True, cwd="/")
    assert result.returncode == 0
    assert result.stdout == "/\n"