diff options
author | Bernát Gábor <bgabor8@bloomberg.net> | 2021-02-13 16:40:10 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-13 16:40:10 +0000 |
commit | efed58a8c02f3c11dd21de2d61f0df80ac65c116 (patch) | |
tree | 4c9c50702c9d3384f6bc4a129e4827a174da5bc3 /src | |
parent | 15605d0696c8468f593b334264dab9fd698b0f50 (diff) | |
download | tox-git-efed58a8c02f3c11dd21de2d61f0df80ac65c116.tar.gz |
Smarter tox env finish status report (#1910)
- do not report when interrupted
- do not report for the final env
Signed-off-by: Bernát Gábor <bgabor8@bloomberg.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/tox/session/cmd/run/common.py | 51 | ||||
-rw-r--r-- | src/tox/session/cmd/run/parallel.py | 2 | ||||
-rw-r--r-- | src/tox/session/cmd/run/sequential.py | 2 | ||||
-rw-r--r-- | src/tox/util/spinner.py | 14 |
4 files changed, 43 insertions, 26 deletions
diff --git a/src/tox/session/cmd/run/common.py b/src/tox/session/cmd/run/common.py index fcfdd49d..d39b0279 100644 --- a/src/tox/session/cmd/run/common.py +++ b/src/tox/session/cmd/run/common.py @@ -163,7 +163,7 @@ def report(start: float, runs: List[ToxEnvRunResult], is_colored: bool) -> int: logger = logging.getLogger(__name__) -def execute(state: State, max_workers: Optional[int], spinner: bool, live: bool) -> int: +def execute(state: State, max_workers: Optional[int], has_spinner: bool, live: bool) -> int: interrupt, done = Event(), Event() results: List[ToxEnvRunResult] = [] future_to_env: Dict["Future[ToxEnvRunResult]", ToxEnv] = {} @@ -173,6 +173,7 @@ def execute(state: State, max_workers: Optional[int], spinner: bool, live: bool) to_run_list.append(env) previous, has_previous = None, False try: + spinner = ToxSpinner(has_spinner, state, len(to_run_list)) try: thread = Thread( target=_queue_and_wait, @@ -183,6 +184,7 @@ def execute(state: State, max_workers: Optional[int], spinner: bool, live: bool) thread.join() except KeyboardInterrupt: previous, has_previous = signal(SIGINT, Handlers.SIG_IGN), True + spinner.print_report = False # no need to print reports at this point, final report coming up logger.error(f"[{os.getpid()}] KeyboardInterrupt - teardown started") interrupt.set() for future, tox_env in list(future_to_env.items()): @@ -236,12 +238,12 @@ def _queue_and_wait( interrupt: Event, done: Event, max_workers: Optional[int], - has_spinner: bool, + spinner: ToxSpinner, live: bool, ) -> None: try: options = state.options - with ToxSpinner(has_spinner, state, len(to_run_list)) as spinner: + with spinner: max_workers = len(to_run_list) if max_workers is None else max_workers completed: Set[str] = set() envs_to_run_generator = ready_to_run_envs(state, to_run_list, completed) @@ -252,11 +254,8 @@ def _queue_and_wait( try: executor = ThreadPoolExecutor(max_workers=max_workers, thread_name_prefix="tox-driver") + env_list: List[str] = [] while True: - env_list: List[str] = next(envs_to_run_generator, []) - if not env_list and not future_to_env: - break - for env in env_list: # queue all available tox_env_to_run = state.tox_env(env) if interrupt.is_set(): # queue the rest as failed upfront @@ -267,17 +266,33 @@ def _queue_and_wait( else: future = executor.submit(_run, tox_env_to_run) future_to_env[future] = tox_env_to_run - future = next(as_completed(future_to_env)) - tox_env_done = future_to_env.pop(future) - try: - result: ToxEnvRunResult = future.result() - except CancelledError: - tox_env_done.teardown() - name = tox_env_done.conf.name - result = ToxEnvRunResult(name=name, skipped=False, code=-3, outcomes=[], duration=MISS_DURATION) - results.append(result) - completed.add(result.name) - _handle_one_run_done(result, spinner, state, live) + + if not future_to_env: + result: Optional[ToxEnvRunResult] = None + else: # if we have queued wait for completed + future = next(as_completed(future_to_env)) + tox_env_done = future_to_env.pop(future) + try: + result = future.result() + except CancelledError: + tox_env_done.teardown() + name = tox_env_done.conf.name + result = ToxEnvRunResult( + name=name, skipped=False, code=-3, outcomes=[], duration=MISS_DURATION + ) + results.append(result) + completed.add(result.name) + + env_list = next(envs_to_run_generator, []) + # if nothing running and nothing more to run we're done + final_run = not env_list and not future_to_env + if final_run: # disable report on final env + spinner.print_report = False + if result is not None: + _handle_one_run_done(result, spinner, state, live) + if final_run: + break + except BaseException: # pragma: no cover # noqa logging.exception("Internal Error") # pragma: no cover raise # pragma: no cover diff --git a/src/tox/session/cmd/run/parallel.py b/src/tox/session/cmd/run/parallel.py index ffab1a3e..d68d84ba 100644 --- a/src/tox/session/cmd/run/parallel.py +++ b/src/tox/session/cmd/run/parallel.py @@ -74,6 +74,6 @@ def run_parallel(state: State) -> int: return execute( state, max_workers=state.options.parallel, - spinner=state.options.parallel_no_spinner is False and state.options.parallel_live is False, + has_spinner=state.options.parallel_no_spinner is False and state.options.parallel_live is False, live=state.options.parallel_live, ) diff --git a/src/tox/session/cmd/run/sequential.py b/src/tox/session/cmd/run/sequential.py index e2f1ef8e..ee935e56 100644 --- a/src/tox/session/cmd/run/sequential.py +++ b/src/tox/session/cmd/run/sequential.py @@ -17,4 +17,4 @@ def tox_add_option(parser: ToxParser) -> None: def run_sequential(state: State) -> int: - return execute(state, max_workers=1, spinner=False, live=True) + return execute(state, max_workers=1, has_spinner=False, live=True) diff --git a/src/tox/util/spinner.py b/src/tox/util/spinner.py index 527e2914..19cb0e33 100644 --- a/src/tox/util/spinner.py +++ b/src/tox/util/spinner.py @@ -54,6 +54,7 @@ class Spinner: self.frames = self.UNICODE_FRAMES if _file_support_encoding(self.UNICODE_FRAMES, stream) else self.ASCII_FRAMES self.stream = stream self.total = total + self.print_report = True self._envs: Dict[str, float] = OrderedDict() self._frame_index = 0 @@ -128,12 +129,13 @@ class Spinner: start_at = self._envs.pop(key, None) if self.enabled: self.clear() - duration = MISS_DURATION if start_at is None else time.monotonic() - start_at - base = f"{key}: {status} in {td_human_readable(duration)}" - if self.is_colored: - base = f"{color}{base}{Fore.RESET}" - base += os.linesep - self.stream.write(base) + if self.print_report: + duration = MISS_DURATION if start_at is None else time.monotonic() - start_at + base = f"{key}: {status} in {td_human_readable(duration)}" + if self.is_colored: + base = f"{color}{base}{Fore.RESET}" + base += os.linesep + self.stream.write(base) def disable_cursor(self) -> None: if self.stream.isatty(): |