<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def run(args: List[str], env: Dict[str, str] = None, capture_stdout: bool = False, echo_stdout: bool = True, capture_stderr: bool = False, echo_stderr: bool = True, debug_show_env: bool = True, encoding: str = sys.getdefaultencoding(), allow_failure: bool = False, **kwargs) -> Tuple[str, str]: """ Runs an external process, announcing it. Optionally, retrieves its ``stdout`` and/or ``stderr`` output (if not retrieved, the output will be visible to the user). Args: args: list of command-line arguments (the first being the executable) env: operating system environment to use (if ``None``, the current OS environment will be used) capture_stdout: capture the command's ``stdout``? echo_stdout: allow the command's ``stdout`` to go to ``sys.stdout``? capture_stderr: capture the command's ``stderr``? echo_stderr: allow the command's ``stderr`` to go to ``sys.stderr``? debug_show_env: be verbose and show the environment used before calling encoding: encoding to use to translate the command's output allow_failure: if ``True``, continues if the command returns a non-zero (failure) exit code; if ``False``, raises an error if that happens kwargs: additional arguments to :func:`teed_call` Returns: a tuple: ``(stdout, stderr)``. If the output wasn't captured, an empty string will take its place in this tuple. """

    cwd = os.getcwd()
    # log.debug("External command Python form: {}", args)
    copy_paste_cmd = subprocess.list2cmdline(args)
    csep = "=" * 79
    esep = "-" * 79
    effective_env = env or os.environ
    if debug_show_env:
        log.debug(
            "Environment for the command that follows:\n"
            "{esep}\n"
            "{env}\n"
            "{esep}".format(esep=esep, env=make_copy_paste_env(effective_env))
        )
    log.info(
        "Launching external command:\n"
        "{csep}\n"
        "WORKING DIRECTORY: {cwd}\n"
        "PYTHON ARGS: {args!r}\n"
        "COMMAND: {cmd}\n"
        "{csep}".format(csep=csep, cwd=cwd, cmd=copy_paste_cmd,
                        args=args)
    )
    try:
        with io.StringIO() as out, io.StringIO() as err:
            stdout_targets = []  # type: List[TextIO]
            stderr_targets = []  # type: List[TextIO]
            if capture_stdout:
                stdout_targets.append(out)
            if echo_stdout:
                stdout_targets.append(sys.stdout)
            if capture_stderr:
                stderr_targets.append(err)
            if echo_stderr:
                stderr_targets.append(sys.stderr)
            retcode = teed_call(args,
                                stdout_targets=stdout_targets,
                                stderr_targets=stderr_targets,
                                encoding=encoding,
                                env=env,
                                **kwargs)
            stdout = out.getvalue()
            stderr = err.getvalue()
            if retcode != 0 and not allow_failure:
                # subprocess.check_call() and check_output() raise
                # CalledProcessError if the called process returns a non-zero
                # return code.
                raise subprocess.CalledProcessError(returncode=retcode,
                                                    cmd=args,
                                                    output=stdout,
                                                    stderr=stderr)
        log.debug("\n{csep}\nFINISHED SUCCESSFULLY: {cmd}\n{csep}",
                  cmd=copy_paste_cmd, csep=csep)
        return stdout, stderr
    except FileNotFoundError:
        require_executable(args[0])  # which is missing, so we'll see some help
        raise
    except subprocess.CalledProcessError:
        log.critical(
            "Command that failed:\n"
            "[ENVIRONMENT]\n"
            "{env}\n"
            "\n"
            "[DIRECTORY] {cwd}\n"
            "[PYTHON ARGS] {args}\n"
            "[COMMAND] {cmd}".format(
                cwd=cwd,
                env=make_copy_paste_env(effective_env),
                cmd=copy_paste_cmd,
                args=args
            )
        )
        raise