예제 #1
0
def test_printable_command_with_string(cmd):
    """
    Correctly transform a string into a runnable shell command.

    Arguments:
        cmd: The command as a string.
    """
    assert printable_command(cmd) == cmd
예제 #2
0
def test_printable_command_with_list(cmd, expected) -> None:
    """
    Correctly transform a list of arguments into a runnable shell command.

    Arguments:
        cmd: The command as a list of arguments.
        expected: The expected result after transformation.
    """
    assert printable_command(cmd) == expected
예제 #3
0
def test_printable_command_with_callable(cmd, args, kwargs, expected):
    """
    Correctly transform a callable into a runnable shell command.

    Arguments:
        cmd: The command as a string.
        args: Arguments passed to `printable_command`.
        kwargs: Keyword arguments passed to `printable_command`.
        expected: The expected result after transformation.
    """
    assert printable_command(cmd, args, kwargs) == expected
예제 #4
0
def run_subprocess(
    cmd: CmdType,
    capture: Capture = Capture.BOTH,
    shell: bool = False,
    stdin: Optional[str] = None,
) -> Tuple[int, str]:
    """
    Run a command in a subprocess.

    Arguments:
        cmd: The command to run.
        capture: The output to capture.
        shell: Whether to run the command in a shell.
        stdin: String to use as standard input.

    Returns:
        The exit code and the command raw output.
    """
    if capture == Capture.NONE:
        stdout_opt = None
        stderr_opt = None
    else:
        stdout_opt = subprocess.PIPE

        if capture == Capture.BOTH:
            stderr_opt = subprocess.STDOUT
        else:
            stderr_opt = subprocess.PIPE

    if shell and not isinstance(cmd, str):
        cmd = printable_command(cmd)

    process = subprocess.run(  # noqa: S603,W1510 (we trust the input, and don't want to "check")
        cmd,
        input=stdin,
        stdout=stdout_opt,
        stderr=stderr_opt,
        shell=shell,  # noqa: S602 (shell=True)
        universal_newlines=True,
        encoding="utf8",
    )

    if capture == Capture.NONE:
        output = ""
    elif capture == Capture.STDERR:
        output = process.stderr
    else:
        output = process.stdout

    return process.returncode, output
예제 #5
0
def run(  # noqa: WPS231 (high complexity)
    cmd: CmdFuncType,
    args=None,
    kwargs=None,
    number: int = 1,
    capture: Optional[Union[str, bool, Capture]] = None,
    title: Optional[str] = None,
    fmt: Optional[str] = None,
    pty: bool = False,
    progress: bool = True,
    nofail: bool = False,
    quiet: bool = False,
    silent: bool = False,
    stdin: Optional[str] = None,
) -> RunResult:
    """
    Run a command in a subprocess or a Python function, and print its output if it fails.

    Arguments:
        cmd: The command to run.
        args: Arguments to pass to the callable.
        kwargs: Keyword arguments to pass to the callable.
        number: The command number.
        capture: The output to capture.
        title: The command title.
        fmt: The output format.
        pty: Whether to run in a PTY.
        progress: Whether to show progress.
        nofail: Whether to always succeed.
        quiet: Whether to not print the command output.
        silent: Don't print anything.
        stdin: String to use as standard input.

    Returns:
        The command exit code, or 0 if `nofail` is True.
    """
    format_name: str = fmt or os.environ.get("FAILPRINT_FORMAT", DEFAULT_FORMAT)  # type: ignore
    format_name = accept_custom_format(format_name)
    format_obj = formats.get(format_name, formats[DEFAULT_FORMAT])

    env = Environment(autoescape=False)  # noqa: S701 (no HTML: no need to escape)
    env.filters["indent"] = textwrap.indent

    command = printable_command(cmd, args, kwargs)

    if not silent and progress and format_obj.progress_template:
        progress_template = env.from_string(format_obj.progress_template)
        ansiprint(progress_template.render({"title": title, "command": command}), end="\r")

    capture = cast_capture(capture)

    if callable(cmd):
        code, output = run_function(cmd, args, kwargs, capture, stdin)
    else:
        code, output = run_command(cmd, capture, format_obj.accept_ansi, pty, stdin)

    if not silent:
        template = env.from_string(format_obj.template)
        ansiprint(
            template.render(
                {
                    "title": title,
                    "command": command,
                    "code": code,
                    "success": code == 0,
                    "failure": code != 0,
                    "number": number,
                    "output": output,
                    "nofail": nofail,
                    "quiet": quiet,
                    "silent": silent,
                },
            ),
        )

    return RunResult(0 if nofail else code, output)