Skip to content

Commit ebb4705

Browse files
camillobruniV8 LUCI CQ
authored andcommitted
Reland "Improve ui for non-interactive terminals"
This is a reland of commit 1009ebd Reason for reland: crbug.com/428049900#comment7 Original change's description: > Improve ui for non-interactive terminals > > Timer and Countdown: > - Only show single message line > > Spinner: > - Only print single title and message update lines > - Avoid an additional sleep on the main thread > > Change-Id: Iba56e895638655c23918fa055ffa318d83aa7ce1 > Reviewed-on: https://chromium-review.googlesource.com/c/crossbench/+/6632506 > Commit-Queue: Camillo Bruni <[email protected]> > Reviewed-by: Patrick Thier <[email protected]> Change-Id: If0f9a27c4fa2b30fc474451aa5ffacaa4392e432 Bug: 428049900 Reviewed-on: https://chromium-review.googlesource.com/c/crossbench/+/6696145 Reviewed-by: Camillo Bruni <[email protected]> Auto-Submit: Victor Vianna <[email protected]> Commit-Queue: Camillo Bruni <[email protected]>
1 parent 0bfeda2 commit ebb4705

File tree

2 files changed

+27
-14
lines changed

2 files changed

+27
-14
lines changed

crossbench/cli/ui.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
colorama.init()
2323

24+
IS_ATTY: Final[bool] = hasattr(sys.stdout, "isatty") and sys.stdout.isatty()
2425
COLOR_LOGGING: bool = True
2526

2627

@@ -91,12 +92,14 @@ def clear_indented() -> None:
9192
@contextlib.contextmanager
9293
def timer(msg: str = "Elapsed Time",
9394
update_interval=DEFAULT_INTERVAL_S) -> Iterator[None]:
94-
start_time = dt.datetime.now()
95+
if not IS_ATTY:
96+
yield
97+
return
9598

99+
start_time = dt.datetime.now()
96100
def print_timer():
97101
delta = dt.datetime.now() - start_time
98102
write_indented(f"{msg}: {format_duration(delta)}")
99-
100103
with RepeatTimer(interval=update_interval, function=print_timer):
101104
yield
102105
clear_indented()
@@ -106,13 +109,16 @@ def print_timer():
106109
def countdown(duration: dt.timedelta,
107110
msg: str = "Waiting",
108111
update_interval=DEFAULT_INTERVAL_S) -> Iterator[None]:
109-
start_time = dt.datetime.now()
112+
if not IS_ATTY:
113+
print(f"{msg}: {format_duration(duration)}")
114+
yield
115+
return
110116

117+
start_time = dt.datetime.now()
111118
def print_timer():
112119
delta = dt.datetime.now() - start_time
113120
time_left = duration - delta
114121
write_indented(f"{msg}: {format_duration(time_left)}")
115-
116122
with RepeatTimer(interval=update_interval, function=print_timer):
117123
yield
118124
clear_indented()
@@ -131,5 +137,5 @@ def __exit__(self, *args, **kwargs) -> None:
131137
self.cancel()
132138

133139

134-
def spinner(*args, **kwargs) -> Spinner:
135-
return Spinner(*args, **kwargs)
140+
def spinner(sleep: float = 0.5, title: str = "") -> Spinner:
141+
return Spinner(IS_ATTY, sleep, title)

crossbench/helper/spinner.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,34 +15,35 @@
1515
class Spinner:
1616
CURSORS = "◐◓◑◒"
1717

18-
def __init__(self, sleep: float = 0.5, title: str = "") -> None:
18+
def __init__(self, is_atty: bool, sleep: float, title: str) -> None:
1919
self._is_running: bool = False
20+
# Only enable the spinner if the output is an interactive terminal.
21+
self._is_atty: bool = is_atty
2022
self._sleep_time_seconds: float = sleep
2123
self._title: str = title
2224
self._message: str = ""
2325
self._cursor: str = " "
2426

2527
def __enter__(self) -> None:
26-
# Only enable the spinner if the output is an interactive terminal.
27-
is_atty = hasattr(sys.stdout, "isatty") and sys.stdout.isatty()
28-
if is_atty:
28+
if self._is_atty:
2929
self._is_running = True
3030
threading.Thread(target=self._spin).start()
31+
elif self._title:
32+
# Write single title line.
33+
self._write_message()
3134

3235
def __exit__(self, exc_type, exc_value, traceback) -> None:
33-
if self._is_running:
34-
self._is_running = False
35-
self._sleep()
36+
self._is_running = False
3637

3738
def _cursors(self) -> Iterable[str]:
3839
while True:
3940
yield from Spinner.CURSORS
4041

4142
def _spin(self) -> None:
4243
for cursor in self._cursors():
43-
self._cursor = cursor
4444
if not self._is_running:
4545
return
46+
self._cursor = cursor
4647
self._write_message()
4748
self._sleep()
4849

@@ -63,6 +64,12 @@ def title(self, title: str) -> None:
6364
self._write_message()
6465

6566
def _write_message(self) -> None:
67+
if self._is_atty:
68+
self._write_interactive_message()
69+
else:
70+
print(f"{self._title}{self._message}")
71+
72+
def _write_interactive_message(self) -> None:
6673
stdout = sys.stdout
6774
stdout.write(f"{terminal.STORE_CURSOR_POS} {self._cursor} "
6875
f"{self._title}{self._message}{terminal.CLEAR_END}"

0 commit comments

Comments
 (0)