blob: 4957c7ae1df1ed645303e51382769d5efcead970 [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
9import terminal
10
11# Output verbosity levels that we support
12ERROR = 0
13WARNING = 1
14NOTICE = 2
15INFO = 3
16DEBUG = 4
17
Simon Glasse6dafb82018-10-01 21:12:45 -060018in_progress = False
19
Simon Glassa2b840a2016-07-25 18:59:09 -060020"""
21This class handles output of progress and other useful information
22to the user. It provides for simple verbosity level control and can
23output nothing but errors at verbosity zero.
24
25The idea is that modules set up an Output object early in their years and pass
26it around to other modules that need it. This keeps the output under control
27of a single class.
28
29Public properties:
30 verbose: Verbosity level: 0=silent, 1=progress, 3=full, 4=debug
31"""
32def __enter__():
33 return
34
35def __exit__(unused1, unused2, unused3):
36 """Clean up and remove any progress message."""
37 ClearProgress()
38 return False
39
40def UserIsPresent():
41 """This returns True if it is likely that a user is present.
42
43 Sometimes we want to prompt the user, but if no one is there then this
44 is a waste of time, and may lock a script which should otherwise fail.
45
46 Returns:
47 True if it thinks the user is there, and False otherwise
48 """
49 return stdout_is_tty and verbose > 0
50
51def ClearProgress():
52 """Clear any active progress message on the terminal."""
Simon Glasse6dafb82018-10-01 21:12:45 -060053 global in_progress
54 if verbose > 0 and stdout_is_tty and in_progress:
Simon Glassa2b840a2016-07-25 18:59:09 -060055 _stdout.write('\r%s\r' % (" " * len (_progress)))
56 _stdout.flush()
Simon Glasse6dafb82018-10-01 21:12:45 -060057 in_progress = False
Simon Glassa2b840a2016-07-25 18:59:09 -060058
59def Progress(msg, warning=False, trailer='...'):
60 """Display progress information.
61
62 Args:
63 msg: Message to display.
64 warning: True if this is a warning."""
Simon Glasse6dafb82018-10-01 21:12:45 -060065 global in_progress
Simon Glassa2b840a2016-07-25 18:59:09 -060066 ClearProgress()
67 if verbose > 0:
68 _progress = msg + trailer
69 if stdout_is_tty:
70 col = _color.YELLOW if warning else _color.GREEN
71 _stdout.write('\r' + _color.Color(col, _progress))
72 _stdout.flush()
Simon Glasse6dafb82018-10-01 21:12:45 -060073 in_progress = True
Simon Glassa2b840a2016-07-25 18:59:09 -060074 else:
75 _stdout.write(_progress + '\n')
76
77def _Output(level, msg, color=None):
78 """Output a message to the terminal.
79
80 Args:
81 level: Verbosity level for this message. It will only be displayed if
82 this as high as the currently selected level.
83 msg; Message to display.
84 error: True if this is an error message, else False.
85 """
86 if verbose >= level:
87 ClearProgress()
88 if color:
89 msg = _color.Color(color, msg)
90 _stdout.write(msg + '\n')
91
92def DoOutput(level, msg):
93 """Output a message to the terminal.
94
95 Args:
96 level: Verbosity level for this message. It will only be displayed if
97 this as high as the currently selected level.
98 msg; Message to display.
99 """
100 _Output(level, msg)
101
102def Error(msg):
103 """Display an error message
104
105 Args:
106 msg; Message to display.
107 """
108 _Output(0, msg, _color.RED)
109
110def Warning(msg):
111 """Display a warning message
112
113 Args:
114 msg; Message to display.
115 """
116 _Output(1, msg, _color.YELLOW)
117
118def Notice(msg):
119 """Display an important infomation message
120
121 Args:
122 msg; Message to display.
123 """
124 _Output(2, msg)
125
126def Info(msg):
127 """Display an infomation message
128
129 Args:
130 msg; Message to display.
131 """
132 _Output(3, msg)
133
134def Debug(msg):
135 """Display a debug message
136
137 Args:
138 msg; Message to display.
139 """
140 _Output(4, msg)
141
142def UserOutput(msg):
143 """Display a message regardless of the current output level.
144
145 This is used when the output was specifically requested by the user.
146 Args:
147 msg; Message to display.
148 """
149 _Output(0, msg)
150
151def Init(_verbose=WARNING, stdout=sys.stdout):
152 """Initialize a new output object.
153
154 Args:
155 verbose: Verbosity level (0-4).
156 stdout: File to use for stdout.
157 """
158 global verbose, _progress, _color, _stdout, stdout_is_tty
159
160 verbose = _verbose
161 _progress = '' # Our last progress message
162 _color = terminal.Color()
163 _stdout = stdout
164
165 # TODO(sjg): Move this into Chromite libraries when we have them
166 stdout_is_tty = hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()
167
168def Uninit():
169 ClearProgress()
170
171Init()