(
    cmd,  # type: List[str]
    show_stdout=False,  # type: bool
    cwd=None,  # type: Optional[str]
    on_returncode='raise',  # type: str
    extra_ok_returncodes=None,  # type: Optional[Iterable[int]]
    command_desc=None,  # type: Optional[str]
    extra_environ=None,  # type: Optional[Mapping[str, Any]]
    unset_environ=None,  # type: Optional[Iterable[str]]
    spinner=None  # type: Optional[SpinnerInterface]
)
return ''.join(all_output)
Args:
      show_stdout: if true, use INFO to log the subprocess's stderr and
        stdout streams.  Otherwise, use DEBUG.  Defaults to False.
      extra_ok_returncodes: an iterable of integer return codes that are
        acceptable, in addition to 0. Defaults to None, which means [].
      unset_environ: an iterable of environment variable names to unset
        prior to calling subprocess.Popen().
Args:
      show_stdout: if true, use INFO to log the subprocess's stderr and
        stdout streams.  Otherwise, use DEBUG.  Defaults to False.
      extra_ok_returncodes: an iterable of integer return codes that are
        acceptable, in addition to 0. Defaults to None, which means [].
      unset_environ: an iterable of environment variable names to unset
        prior to calling subprocess.Popen().
Args : show_stdout : if true use INFO to log the subprocess s stderr and stdout streams . Otherwise use DEBUG . Defaults to False . extra_ok_returncodes : an iterable of integer return codes that are acceptable in addition to 0 . Defaults to None which means [] . unset_environ : an iterable of environment variable names to unset prior to calling subprocess . Popen () .
def call_subprocess(
    cmd,  # type: List[str]
    show_stdout=False,  # type: bool
    cwd=None,  # type: Optional[str]
    on_returncode='raise',  # type: str
    extra_ok_returncodes=None,  # type: Optional[Iterable[int]]
    command_desc=None,  # type: Optional[str]
    extra_environ=None,  # type: Optional[Mapping[str, Any]]
    unset_environ=None,  # type: Optional[Iterable[str]]
    spinner=None  # type: Optional[SpinnerInterface]
):
    # type: (...) -> Text
    """
    Args:
      show_stdout: if true, use INFO to log the subprocess's stderr and
        stdout streams.  Otherwise, use DEBUG.  Defaults to False.
      extra_ok_returncodes: an iterable of integer return codes that are
        acceptable, in addition to 0. Defaults to None, which means [].
      unset_environ: an iterable of environment variable names to unset
        prior to calling subprocess.Popen().
    """
    if extra_ok_returncodes is None:
        extra_ok_returncodes = []
    if unset_environ is None:
        unset_environ = []
    # Most places in pip use show_stdout=False. What this means is--
    #
    # - We connect the child's output (combined stderr and stdout) to a
    #   single pipe, which we read.
    # - We log this output to stderr at DEBUG level as it is received.
    # - If DEBUG logging isn't enabled (e.g. if --verbose logging wasn't
    #   requested), then we show a spinner so the user can still see the
    #   subprocess is in progress.
    # - If the subprocess exits with an error, we log the output to stderr
    #   at ERROR level if it hasn't already been displayed to the console
    #   (e.g. if --verbose logging wasn't enabled).  This way we don't log
    #   the output to the console twice.
    #
    # If show_stdout=True, then the above is still done, but with DEBUG
    # replaced by INFO.
    if show_stdout:
        # Then log the subprocess output at INFO level.
        log_subprocess = subprocess_logger.info
        used_level = std_logging.INFO
    else:
        # Then log the subprocess output using DEBUG.  This also ensures
        # it will be logged to the log file (aka user_log), if enabled.
        log_subprocess = subprocess_logger.debug
        used_level = std_logging.DEBUG

    # Whether the subprocess will be visible in the console.
    showing_subprocess = subprocess_logger.getEffectiveLevel() <= used_level

    # Only use the spinner if we're not showing the subprocess output
    # and we have a spinner.
    use_spinner = not showing_subprocess and spinner is not None

    if command_desc is None:
        command_desc = format_command_args(cmd)

    log_subprocess("Running command %s", command_desc)
    env = os.environ.copy()
    if extra_environ:
        env.update(extra_environ)
    for name in unset_environ:
        env.pop(name, None)
    try:
        proc = subprocess.Popen(
            cmd, stderr=subprocess.STDOUT, stdin=subprocess.PIPE,
            stdout=subprocess.PIPE, cwd=cwd, env=env,
        )
        proc.stdin.close()
    except Exception as exc:
        subprocess_logger.critical(
            "Error %s while executing command %s", exc, command_desc,
        )
        raise
    all_output = []
    while True:
        # The "line" value is a unicode string in Python 2.
        line = console_to_str(proc.stdout.readline())
        if not line:
            break
        line = line.rstrip()
        all_output.append(line + '\n')

        # Show the line immediately.
        log_subprocess(line)
        # Update the spinner.
        if use_spinner:
            spinner.spin()
    try:
        proc.wait()
    finally:
        if proc.stdout:
            proc.stdout.close()
    proc_had_error = (
        proc.returncode and proc.returncode not in extra_ok_returncodes
    )
    if use_spinner:
        if proc_had_error:
            spinner.finish("error")
        else:
            spinner.finish("done")
    if proc_had_error:
        if on_returncode == 'raise':
            if not showing_subprocess:
                # Then the subprocess streams haven't been logged to the
                # console yet.
                msg = make_subprocess_output_error(
                    cmd_args=cmd,
                    cwd=cwd,
                    lines=all_output,
                    exit_status=proc.returncode,
                )
                subprocess_logger.error(msg)
            exc_msg = (
                'Command errored out with exit status {}: {} '
                'Check the logs for full command output.'
            ).format(proc.returncode, command_desc)
            raise InstallationError(exc_msg)
        elif on_returncode == 'warn':
            subprocess_logger.warning(
                'Command "%s" had error code %s in %s',
                command_desc, proc.returncode, cwd,
            )
        elif on_returncode == 'ignore':
            pass
        else:
            raise ValueError('Invalid value: on_returncode=%s' %
                             repr(on_returncode))
    return ''.join(all_output)
def call_subprocess ( cmd , # type: List[str] show_stdout = False , # type: bool cwd = None , # type: Optional[str] on_returncode = 'raise' , # type: str extra_ok_returncodes = None , # type: Optional[Iterable[int]] command_desc = None , # type: Optional[str] extra_environ = None , # type: Optional[Mapping[str, Any]] unset_environ = None , # type: Optional[Iterable[str]] spinner = None # type: Optional[SpinnerInterface] ) : # type: (...) -> Text if extra_ok_returncodes is None : extra_ok_returncodes = [ ] if unset_environ is None : unset_environ = [ ] # Most places in pip use show_stdout=False. What this means is-- # # - We connect the child's output (combined stderr and stdout) to a #   single pipe, which we read. # - We log this output to stderr at DEBUG level as it is received. # - If DEBUG logging isn't enabled (e.g. if --verbose logging wasn't #   requested), then we show a spinner so the user can still see the #   subprocess is in progress. # - If the subprocess exits with an error, we log the output to stderr #   at ERROR level if it hasn't already been displayed to the console #   (e.g. if --verbose logging wasn't enabled).  This way we don't log #   the output to the console twice. # # If show_stdout=True, then the above is still done, but with DEBUG # replaced by INFO. if show_stdout : # Then log the subprocess output at INFO level. log_subprocess = subprocess_logger . info used_level = std_logging . INFO else : # Then log the subprocess output using DEBUG.  This also ensures # it will be logged to the log file (aka user_log), if enabled. log_subprocess = subprocess_logger . debug used_level = std_logging . DEBUG # Whether the subprocess will be visible in the console. showing_subprocess = subprocess_logger . getEffectiveLevel ( ) <= used_level # Only use the spinner if we're not showing the subprocess output # and we have a spinner. use_spinner = not showing_subprocess and spinner is not None if command_desc is None : command_desc = format_command_args ( cmd ) log_subprocess ( "Running command %s" , command_desc ) env = os . environ . copy ( ) if extra_environ : env . update ( extra_environ ) for name in unset_environ : env . pop ( name , None ) try : proc = subprocess . Popen ( cmd , stderr = subprocess . STDOUT , stdin = subprocess . PIPE , stdout = subprocess . PIPE , cwd = cwd , env = env , ) proc . stdin . close ( ) except Exception as exc : subprocess_logger . critical ( "Error %s while executing command %s" , exc , command_desc , ) raise all_output = [ ] while True : # The "line" value is a unicode string in Python 2. line = console_to_str ( proc . stdout . readline ( ) ) if not line : break line = line . rstrip ( ) all_output . append ( line + '\n' ) # Show the line immediately. log_subprocess ( line ) # Update the spinner. if use_spinner : spinner . spin ( ) try : proc . wait ( ) finally : if proc . stdout : proc . stdout . close ( ) proc_had_error = ( proc . returncode and proc . returncode not in extra_ok_returncodes ) if use_spinner : if proc_had_error : spinner . finish ( "error" ) else : spinner . finish ( "done" ) if proc_had_error : if on_returncode == 'raise' : if not showing_subprocess : # Then the subprocess streams haven't been logged to the # console yet. msg = make_subprocess_output_error ( cmd_args = cmd , cwd = cwd , lines = all_output , exit_status = proc . returncode , ) subprocess_logger . error ( msg ) exc_msg = ( 'Command errored out with exit status {}: {} ' 'Check the logs for full command output.' ) . format ( proc . returncode , command_desc ) raise InstallationError ( exc_msg ) elif on_returncode == 'warn' : subprocess_logger . warning ( 'Command "%s" had error code %s in %s' , command_desc , proc . returncode , cwd , ) elif on_returncode == 'ignore' : pass else : raise ValueError ( 'Invalid value: on_returncode=%s' % repr ( on_returncode ) ) return '' . join ( all_output )