Beispiel #1
0
        def run_in_thread(tox_env, os_env):
            res = None
            env_name = tox_env.envconfig.envname
            try:
                os_env[str(PARALLEL_ENV_VAR_KEY)] = str(env_name)
                args_sub = list(args)
                if hasattr(tox_env, "package"):
                    args_sub.insert(position, str(tox_env.package))
                    args_sub.insert(position, "--installpkg")
                process = subprocess.Popen(
                    args_sub,
                    env=os_env,
                    stdout=sink,
                    stderr=sink,
                    stdin=None,
                    universal_newlines=True,
                )
                res = process.wait()
            finally:
                semaphore.release()
                finished.set()
                tox_env.status = (
                    "skipped tests"
                    if config.option.notest
                    else ("parallel child exit code {}".format(res) if res else res)
                )
                done.add(env_name)
                outcome = spinner.succeed
                if config.option.notest:
                    outcome = spinner.skip
                elif res:
                    outcome = spinner.fail
                outcome(env_name)

            if not live_out:
                out, err = process.communicate()
                if res or tox_env.envconfig.parallel_show_output:
                    outcome = (
                        "Failed {} under process {}, stdout:\n".format(env_name, process.pid)
                        if res
                        else ""
                    )
                    message = "{}{}{}".format(
                        outcome, out, "\nstderr:\n{}".format(err) if err else ""
                    ).rstrip()
                    reporter.quiet(message)
Beispiel #2
0
 def popen(
     self,
     args,
     cwd=None,
     env=None,
     redirect=True,
     returnout=False,
     ignore_ret=False,
     capture_err=True,
     callback=None,
     report_fail=True,
 ):
     """this drives an interaction with a subprocess"""
     cwd = py.path.local() if cwd is None else cwd
     cmd_args = [str(x) for x in self._rewrite_args(cwd, args)]
     cmd_args_shell = " ".join(pipes.quote(i) for i in cmd_args)
     stream_getter = self._get_standard_streams(
         capture_err,
         cmd_args_shell,
         redirect,
         returnout,
         cwd,
     )
     exit_code, output = None, None
     with stream_getter as (fin, out_path, stderr, stdout):
         try:
             process = self.via_popen(
                 cmd_args,
                 stdout=stdout,
                 stderr=stderr,
                 cwd=str(cwd),
                 env=os.environ.copy() if env is None else env,
                 universal_newlines=True,
                 shell=False,
                 creationflags=(
                     subprocess.CREATE_NEW_PROCESS_GROUP
                     if sys.platform == "win32" else 0
                     # needed for Windows signal send ability (CTRL+C)
                 ),
             )
         except OSError as exception:
             exit_code = exception.errno
         else:
             if callback is not None:
                 callback(process)
             reporter.log_popen(cwd, out_path, cmd_args_shell, process.pid)
             output = self.evaluate_cmd(fin, process, redirect)
             exit_code = process.returncode
         finally:
             if out_path is not None and out_path.exists():
                 lines = out_path.read_text("UTF-8").split("\n")
                 # first three lines are the action, cwd, and cmd - remove it
                 output = "\n".join(lines[3:])
             try:
                 if exit_code and not ignore_ret:
                     if report_fail:
                         msg = "invocation failed (exit code {:d})".format(
                             exit_code)
                         if out_path is not None:
                             msg += ", logfile: {}".format(out_path)
                             if not out_path.exists():
                                 msg += " warning log file missing"
                         reporter.error(msg)
                         if out_path is not None and out_path.exists():
                             reporter.separator("=", "log start",
                                                Verbosity.QUIET)
                             reporter.quiet(output)
                             reporter.separator("=", "log end",
                                                Verbosity.QUIET)
                     raise InvocationError(cmd_args_shell, exit_code,
                                           output)
             finally:
                 self.command_log.add_command(cmd_args, output, exit_code)
     return output