blob: c7e32720965769014d23ef264db7735e9c68ef18 [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 Glassa997ea52020-04-17 18:09:04 -06009from patman import terminal
Simon Glassa2b840a2016-07-25 18:59:09 -060010
11# Output verbosity levels that we support
Simon Glass6162f1a2019-07-20 12:23:35 -060012ERROR, WARNING, NOTICE, INFO, DETAIL, DEBUG = range(6)
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."""
33 ClearProgress()
34 return False
35
36def UserIsPresent():
37 """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 """
45 return stdout_is_tty and verbose > 0
46
47def ClearProgress():
48 """Clear any active progress message on the terminal."""
Simon Glasse6dafb82018-10-01 21:12:45 -060049 global in_progress
50 if verbose > 0 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
55def Progress(msg, warning=False, trailer='...'):
56 """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 Glassa2b840a2016-07-25 18:59:09 -060062 ClearProgress()
63 if verbose > 0:
64 _progress = msg + trailer
65 if stdout_is_tty:
66 col = _color.YELLOW if warning else _color.GREEN
67 _stdout.write('\r' + _color.Color(col, _progress))
68 _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
73def _Output(level, msg, color=None):
74 """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:
83 ClearProgress()
84 if color:
85 msg = _color.Color(color, msg)
Simon Glassdc4aeef2019-07-20 12:23:26 -060086 print(msg)
Simon Glassa2b840a2016-07-25 18:59:09 -060087
88def DoOutput(level, msg):
89 """Output a message to the terminal.
90
91 Args:
92 level: Verbosity level for this message. It will only be displayed if
93 this as high as the currently selected level.
94 msg; Message to display.
95 """
96 _Output(level, msg)
97
98def Error(msg):
99 """Display an error message
100
101 Args:
102 msg; Message to display.
103 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600104 _Output(ERROR, msg, _color.RED)
Simon Glassa2b840a2016-07-25 18:59:09 -0600105
106def Warning(msg):
107 """Display a warning message
108
109 Args:
110 msg; Message to display.
111 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600112 _Output(WARNING, msg, _color.YELLOW)
Simon Glassa2b840a2016-07-25 18:59:09 -0600113
114def Notice(msg):
115 """Display an important infomation message
116
117 Args:
118 msg; Message to display.
119 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600120 _Output(NOTICE, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600121
122def Info(msg):
123 """Display an infomation message
124
125 Args:
126 msg; Message to display.
127 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600128 _Output(INFO, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600129
Simon Glass233a26a92019-07-08 14:25:49 -0600130def Detail(msg):
131 """Display a detailed message
132
133 Args:
134 msg; Message to display.
135 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600136 _Output(DETAIL, msg)
Simon Glass233a26a92019-07-08 14:25:49 -0600137
Simon Glassa2b840a2016-07-25 18:59:09 -0600138def Debug(msg):
139 """Display a debug message
140
141 Args:
142 msg; Message to display.
143 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600144 _Output(DEBUG, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600145
146def UserOutput(msg):
147 """Display a message regardless of the current output level.
148
149 This is used when the output was specifically requested by the user.
150 Args:
151 msg; Message to display.
152 """
153 _Output(0, msg)
154
155def Init(_verbose=WARNING, stdout=sys.stdout):
156 """Initialize a new output object.
157
158 Args:
159 verbose: Verbosity level (0-4).
160 stdout: File to use for stdout.
161 """
162 global verbose, _progress, _color, _stdout, stdout_is_tty
163
164 verbose = _verbose
165 _progress = '' # Our last progress message
166 _color = terminal.Color()
167 _stdout = stdout
168
169 # TODO(sjg): Move this into Chromite libraries when we have them
170 stdout_is_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
171
172def Uninit():
173 ClearProgress()
174
175Init()