blob: 2a384851b0d186fe1ecd7ddd273e201dd94495bf [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
Simon Glassdc4aeef2019-07-20 12:23:26 -06007from __future__ import print_function
8
Simon Glassa2b840a2016-07-25 18:59:09 -06009import sys
10
11import terminal
12
13# Output verbosity levels that we support
Simon Glass6162f1a2019-07-20 12:23:35 -060014ERROR, WARNING, NOTICE, INFO, DETAIL, DEBUG = range(6)
Simon Glassa2b840a2016-07-25 18:59:09 -060015
Simon Glasse6dafb82018-10-01 21:12:45 -060016in_progress = False
17
Simon Glassa2b840a2016-07-25 18:59:09 -060018"""
19This class handles output of progress and other useful information
20to the user. It provides for simple verbosity level control and can
21output nothing but errors at verbosity zero.
22
23The idea is that modules set up an Output object early in their years and pass
24it around to other modules that need it. This keeps the output under control
25of a single class.
26
27Public properties:
28 verbose: Verbosity level: 0=silent, 1=progress, 3=full, 4=debug
29"""
30def __enter__():
31 return
32
33def __exit__(unused1, unused2, unused3):
34 """Clean up and remove any progress message."""
35 ClearProgress()
36 return False
37
38def UserIsPresent():
39 """This returns True if it is likely that a user is present.
40
41 Sometimes we want to prompt the user, but if no one is there then this
42 is a waste of time, and may lock a script which should otherwise fail.
43
44 Returns:
45 True if it thinks the user is there, and False otherwise
46 """
47 return stdout_is_tty and verbose > 0
48
49def ClearProgress():
50 """Clear any active progress message on the terminal."""
Simon Glasse6dafb82018-10-01 21:12:45 -060051 global in_progress
52 if verbose > 0 and stdout_is_tty and in_progress:
Simon Glassa2b840a2016-07-25 18:59:09 -060053 _stdout.write('\r%s\r' % (" " * len (_progress)))
54 _stdout.flush()
Simon Glasse6dafb82018-10-01 21:12:45 -060055 in_progress = False
Simon Glassa2b840a2016-07-25 18:59:09 -060056
57def Progress(msg, warning=False, trailer='...'):
58 """Display progress information.
59
60 Args:
61 msg: Message to display.
62 warning: True if this is a warning."""
Simon Glasse6dafb82018-10-01 21:12:45 -060063 global in_progress
Simon Glassa2b840a2016-07-25 18:59:09 -060064 ClearProgress()
65 if verbose > 0:
66 _progress = msg + trailer
67 if stdout_is_tty:
68 col = _color.YELLOW if warning else _color.GREEN
69 _stdout.write('\r' + _color.Color(col, _progress))
70 _stdout.flush()
Simon Glasse6dafb82018-10-01 21:12:45 -060071 in_progress = True
Simon Glassa2b840a2016-07-25 18:59:09 -060072 else:
73 _stdout.write(_progress + '\n')
74
75def _Output(level, msg, color=None):
76 """Output a message to the terminal.
77
78 Args:
79 level: Verbosity level for this message. It will only be displayed if
80 this as high as the currently selected level.
81 msg; Message to display.
82 error: True if this is an error message, else False.
83 """
84 if verbose >= level:
85 ClearProgress()
86 if color:
87 msg = _color.Color(color, msg)
Simon Glassdc4aeef2019-07-20 12:23:26 -060088 print(msg)
Simon Glassa2b840a2016-07-25 18:59:09 -060089
90def DoOutput(level, msg):
91 """Output a message to the terminal.
92
93 Args:
94 level: Verbosity level for this message. It will only be displayed if
95 this as high as the currently selected level.
96 msg; Message to display.
97 """
98 _Output(level, msg)
99
100def Error(msg):
101 """Display an error message
102
103 Args:
104 msg; Message to display.
105 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600106 _Output(ERROR, msg, _color.RED)
Simon Glassa2b840a2016-07-25 18:59:09 -0600107
108def Warning(msg):
109 """Display a warning message
110
111 Args:
112 msg; Message to display.
113 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600114 _Output(WARNING, msg, _color.YELLOW)
Simon Glassa2b840a2016-07-25 18:59:09 -0600115
116def Notice(msg):
117 """Display an important infomation message
118
119 Args:
120 msg; Message to display.
121 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600122 _Output(NOTICE, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600123
124def Info(msg):
125 """Display an infomation message
126
127 Args:
128 msg; Message to display.
129 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600130 _Output(INFO, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600131
Simon Glass233a26a92019-07-08 14:25:49 -0600132def Detail(msg):
133 """Display a detailed message
134
135 Args:
136 msg; Message to display.
137 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600138 _Output(DETAIL, msg)
Simon Glass233a26a92019-07-08 14:25:49 -0600139
Simon Glassa2b840a2016-07-25 18:59:09 -0600140def Debug(msg):
141 """Display a debug message
142
143 Args:
144 msg; Message to display.
145 """
Simon Glass6162f1a2019-07-20 12:23:35 -0600146 _Output(DEBUG, msg)
Simon Glassa2b840a2016-07-25 18:59:09 -0600147
148def UserOutput(msg):
149 """Display a message regardless of the current output level.
150
151 This is used when the output was specifically requested by the user.
152 Args:
153 msg; Message to display.
154 """
155 _Output(0, msg)
156
157def Init(_verbose=WARNING, stdout=sys.stdout):
158 """Initialize a new output object.
159
160 Args:
161 verbose: Verbosity level (0-4).
162 stdout: File to use for stdout.
163 """
164 global verbose, _progress, _color, _stdout, stdout_is_tty
165
166 verbose = _verbose
167 _progress = '' # Our last progress message
168 _color = terminal.Color()
169 _stdout = stdout
170
171 # TODO(sjg): Move this into Chromite libraries when we have them
172 stdout_is_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
173
174def Uninit():
175 ClearProgress()
176
177Init()