blob: ca72108d6bc7924da0e54bb004e1cb2fe717892b [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001# SPDX-License-Identifier: GPL-2.0+
Simon Glassa2b840a2016-07-25 18:59:09 -06002# Copyright (c) 2016 Google, Inc
3#
Simon Glassa2b840a2016-07-25 18:59:09 -06004# Terminal output logging.
5#
6
7import sys
8
Simon Glass131444f2023-02-23 18:18:04 -07009from u_boot_pylib import terminal
Simon Glassa2b840a2016-07-25 18:59:09 -060010
11# Output verbosity levels that we support
Simon Glass655314e2025-05-11 16:18:20 +020012FATAL, ERROR, WARNING, NOTICE, INFO, DETAIL, DEBUG = range(7)
Simon Glassa2b840a2016-07-25 18:59:09 -060013
Simon Glasse6dafb82018-10-01 21:12:45 -060014in_progress = False
15
Simon Glassa2b840a2016-07-25 18:59:09 -060016"""
17This class handles output of progress and other useful information
18to the user. It provides for simple verbosity level control and can
19output nothing but errors at verbosity zero.
20
21The idea is that modules set up an Output object early in their years and pass
22it around to other modules that need it. This keeps the output under control
23of a single class.
24
25Public properties:
26 verbose: Verbosity level: 0=silent, 1=progress, 3=full, 4=debug
27"""
28def __enter__():
29 return
30
31def __exit__(unused1, unused2, unused3):
32 """Clean up and remove any progress message."""
Simon Glass011f1b32022-01-29 14:14:15 -070033 clear_progress()
Simon Glassa2b840a2016-07-25 18:59:09 -060034 return False
35
Simon Glass011f1b32022-01-29 14:14:15 -070036def user_is_present():
Simon Glassa2b840a2016-07-25 18:59:09 -060037 """This returns True if it is likely that a user is present.
38
39 Sometimes we want to prompt the user, but if no one is there then this
40 is a waste of time, and may lock a script which should otherwise fail.
41
42 Returns:
43 True if it thinks the user is there, and False otherwise
44 """
Simon Glass655314e2025-05-11 16:18:20 +020045 return stdout_is_tty and verbose > ERROR
Simon Glassa2b840a2016-07-25 18:59:09 -060046
Simon Glass011f1b32022-01-29 14:14:15 -070047def clear_progress():
Simon Glassa2b840a2016-07-25 18:59:09 -060048 """Clear any active progress message on the terminal."""
Simon Glasse6dafb82018-10-01 21:12:45 -060049 global in_progress
Simon Glass655314e2025-05-11 16:18:20 +020050 if verbose > ERROR and stdout_is_tty and in_progress:
Simon Glassa2b840a2016-07-25 18:59:09 -060051 _stdout.write('\r%s\r' % (" " * len (_progress)))
52 _stdout.flush()
Simon Glasse6dafb82018-10-01 21:12:45 -060053 in_progress = False
Simon Glassa2b840a2016-07-25 18:59:09 -060054
Simon Glass011f1b32022-01-29 14:14:15 -070055def progress(msg, warning=False, trailer='...'):
Simon Glassa2b840a2016-07-25 18:59:09 -060056 """Display progress information.
57
58 Args:
59 msg: Message to display.
60 warning: True if this is a warning."""
Simon Glasse6dafb82018-10-01 21:12:45 -060061 global in_progress
Simon Glass011f1b32022-01-29 14:14:15 -070062 clear_progress()
Simon Glass655314e2025-05-11 16:18:20 +020063 if verbose > ERROR:
Simon Glassa2b840a2016-07-25 18:59:09 -060064 _progress = msg + trailer
65 if stdout_is_tty:
66 col = _color.YELLOW if warning else _color.GREEN
Simon Glassf45d3742022-01-29 14:14:17 -070067 _stdout.write('\r' + _color.build(col, _progress))
Simon Glassa2b840a2016-07-25 18:59:09 -060068 _stdout.flush()
Simon Glasse6dafb82018-10-01 21:12:45 -060069 in_progress = True
Simon Glassa2b840a2016-07-25 18:59:09 -060070 else:
71 _stdout.write(_progress + '\n')
72
Simon Glass011f1b32022-01-29 14:14:15 -070073def _output(level, msg, color=None):
Simon Glassa2b840a2016-07-25 18:59:09 -060074 """Output a message to the terminal.
75
76 Args:
77 level: Verbosity level for this message. It will only be displayed if
78 this as high as the currently selected level.
79 msg; Message to display.
80 error: True if this is an error message, else False.
81 """
82 if verbose >= level:
Simon Glass011f1b32022-01-29 14:14:15 -070083 clear_progress()
Simon Glassa2b840a2016-07-25 18:59:09 -060084 if color:
Simon Glassf45d3742022-01-29 14:14:17 -070085 msg = _color.build(color, msg)
Simon Glass6e02f7c2020-07-09 18:39:39 -060086 if level < NOTICE:
87 print(msg, file=sys.stderr)
88 else:
89 print(msg)
Simon Glass655314e2025-05-11 16:18:20 +020090 if level == FATAL:
91 sys.exit(1)
Simon Glassa2b840a2016-07-25 18:59:09 -060092
Simon Glass011f1b32022-01-29 14:14:15 -070093def do_output(level, msg):
Simon Glassa2b840a2016-07-25 18:59:09 -060094 """Output a message to the terminal.
95
96 Args:
97 level: Verbosity level for this message. It will only be displayed if
98 this as high as the currently selected level.
99 msg; Message to display.
100 """
Simon Glass011f1b32022-01-29 14:14:15 -0700101 _output(level, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600102
Simon Glass655314e2025-05-11 16:18:20 +0200103def fatal(msg):
104 """Display an error message and exit
105
106 Args:
107 msg; Message to display.
108 """
109 _output(FATAL, msg, _color.RED)
110
Simon Glass011f1b32022-01-29 14:14:15 -0700111def error(msg):
Simon Glassa2b840a2016-07-25 18:59:09 -0600112 """Display an error message
113
114 Args:
115 msg; Message to display.
116 """
Simon Glass011f1b32022-01-29 14:14:15 -0700117 _output(ERROR, msg, _color.RED)
Simon Glassa2b840a2016-07-25 18:59:09 -0600118
Simon Glass011f1b32022-01-29 14:14:15 -0700119def warning(msg):
Simon Glassa2b840a2016-07-25 18:59:09 -0600120 """Display a warning message
121
122 Args:
123 msg; Message to display.
124 """
Simon Glass011f1b32022-01-29 14:14:15 -0700125 _output(WARNING, msg, _color.YELLOW)
Simon Glassa2b840a2016-07-25 18:59:09 -0600126
Simon Glass011f1b32022-01-29 14:14:15 -0700127def notice(msg):
Simon Glassa2b840a2016-07-25 18:59:09 -0600128 """Display an important infomation message
129
130 Args:
131 msg; Message to display.
132 """
Simon Glass011f1b32022-01-29 14:14:15 -0700133 _output(NOTICE, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600134
Simon Glass011f1b32022-01-29 14:14:15 -0700135def info(msg):
Simon Glassa2b840a2016-07-25 18:59:09 -0600136 """Display an infomation message
137
138 Args:
139 msg; Message to display.
140 """
Simon Glass011f1b32022-01-29 14:14:15 -0700141 _output(INFO, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600142
Simon Glass011f1b32022-01-29 14:14:15 -0700143def detail(msg):
Simon Glass233a26a92019-07-08 14:25:49 -0600144 """Display a detailed message
145
146 Args:
147 msg; Message to display.
148 """
Simon Glass011f1b32022-01-29 14:14:15 -0700149 _output(DETAIL, msg)
Simon Glass233a26a92019-07-08 14:25:49 -0600150
Simon Glass011f1b32022-01-29 14:14:15 -0700151def debug(msg):
Simon Glassa2b840a2016-07-25 18:59:09 -0600152 """Display a debug message
153
154 Args:
155 msg; Message to display.
156 """
Simon Glass011f1b32022-01-29 14:14:15 -0700157 _output(DEBUG, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600158
Simon Glass011f1b32022-01-29 14:14:15 -0700159def user_output(msg):
Simon Glassa2b840a2016-07-25 18:59:09 -0600160 """Display a message regardless of the current output level.
161
162 This is used when the output was specifically requested by the user.
163 Args:
164 msg; Message to display.
165 """
Simon Glass655314e2025-05-11 16:18:20 +0200166 _output(ERROR, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600167
Simon Glass9d7f5982025-04-29 07:22:05 -0600168def init(_verbose=WARNING, stdout=sys.stdout, allow_colour=True):
Simon Glassa2b840a2016-07-25 18:59:09 -0600169 """Initialize a new output object.
170
171 Args:
Simon Glass655314e2025-05-11 16:18:20 +0200172 verbose: Verbosity level (0-6).
Simon Glassa2b840a2016-07-25 18:59:09 -0600173 stdout: File to use for stdout.
174 """
175 global verbose, _progress, _color, _stdout, stdout_is_tty
176
177 verbose = _verbose
178 _progress = '' # Our last progress message
Simon Glass9d7f5982025-04-29 07:22:05 -0600179 _color = terminal.Color(terminal.COLOR_IF_TERMINAL if allow_colour
180 else terminal.COLOR_NEVER)
Simon Glassa2b840a2016-07-25 18:59:09 -0600181 _stdout = stdout
182
183 # TODO(sjg): Move this into Chromite libraries when we have them
184 stdout_is_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
Simon Glassa003cd32020-07-09 18:39:40 -0600185 stderr_is_tty = hasattr(sys.stderr, 'isatty') and sys.stderr.isatty()
Simon Glassa2b840a2016-07-25 18:59:09 -0600186
Simon Glass011f1b32022-01-29 14:14:15 -0700187def uninit():
188 clear_progress()
Simon Glassa2b840a2016-07-25 18:59:09 -0600189
Simon Glass011f1b32022-01-29 14:14:15 -0700190init()