79 lines
2.3 KiB
Python
79 lines
2.3 KiB
Python
|
import os
|
||
|
import subprocess
|
||
|
|
||
|
from pipenv.exceptions import PipenvCmdError
|
||
|
from pipenv.utils.constants import MYPY_RUNNING
|
||
|
from pipenv.vendor import click
|
||
|
|
||
|
if MYPY_RUNNING:
|
||
|
from typing import Tuple # noqa
|
||
|
|
||
|
|
||
|
def run_command(cmd, *args, is_verbose=False, **kwargs):
|
||
|
"""
|
||
|
Take an input command and run it, handling exceptions and error codes and returning
|
||
|
its stdout and stderr.
|
||
|
|
||
|
:param cmd: The list of command and arguments.
|
||
|
:type cmd: list
|
||
|
:returns: A 2-tuple of the output and error from the command
|
||
|
:rtype: Tuple[str, str]
|
||
|
:raises: exceptions.PipenvCmdError
|
||
|
"""
|
||
|
|
||
|
from pipenv.cmdparse import Script
|
||
|
|
||
|
catch_exceptions = kwargs.pop("catch_exceptions", True)
|
||
|
if isinstance(cmd, ((str,), list, tuple)):
|
||
|
cmd = Script.parse(cmd)
|
||
|
if not isinstance(cmd, Script):
|
||
|
raise TypeError("Command input must be a string, list or tuple")
|
||
|
if "env" not in kwargs:
|
||
|
kwargs["env"] = os.environ.copy()
|
||
|
kwargs["env"]["PYTHONIOENCODING"] = "UTF-8"
|
||
|
command = [cmd.command, *cmd.args]
|
||
|
if is_verbose:
|
||
|
click.echo(f"Running command: $ {cmd.cmdify()}")
|
||
|
c = subprocess_run(command, *args, **kwargs)
|
||
|
if is_verbose:
|
||
|
click.echo(
|
||
|
"Command output: {}".format(click.style(c.stdout, fg="cyan")),
|
||
|
err=True,
|
||
|
)
|
||
|
if c.returncode and catch_exceptions:
|
||
|
raise PipenvCmdError(cmd.cmdify(), c.stdout, c.stderr, c.returncode)
|
||
|
return c
|
||
|
|
||
|
|
||
|
def subprocess_run(
|
||
|
args,
|
||
|
*,
|
||
|
block=True,
|
||
|
text=True,
|
||
|
capture_output=True,
|
||
|
encoding="utf-8",
|
||
|
env=None,
|
||
|
**other_kwargs,
|
||
|
):
|
||
|
"""A backward compatible version of subprocess.run().
|
||
|
|
||
|
It outputs text with default encoding, and store all outputs in the returned object instead of
|
||
|
printing onto stdout.
|
||
|
"""
|
||
|
_env = os.environ.copy()
|
||
|
_env["PYTHONIOENCODING"] = encoding
|
||
|
if env:
|
||
|
_env.update(env)
|
||
|
other_kwargs["env"] = _env
|
||
|
if capture_output:
|
||
|
other_kwargs["stdout"] = subprocess.PIPE
|
||
|
other_kwargs["stderr"] = subprocess.PIPE
|
||
|
if block:
|
||
|
return subprocess.run(
|
||
|
args, text=text, encoding=encoding, check=False, **other_kwargs
|
||
|
)
|
||
|
else:
|
||
|
return subprocess.Popen(
|
||
|
args, universal_newlines=text, encoding=encoding, **other_kwargs
|
||
|
)
|