1 # SPDX-License-Identifier: GPL-2.0+ 2 # Copyright (c) 2016 Google, Inc 3 # 4 # Terminal output logging. 5 # 6 7 import sys 8 9 import terminal 10 11 # Output verbosity levels that we support 12 ERROR = 0 13 WARNING = 1 14 NOTICE = 2 15 INFO = 3 16 DEBUG = 4 17 18 in_progress = False 19 20 """ 21 This class handles output of progress and other useful information 22 to the user. It provides for simple verbosity level control and can 23 output nothing but errors at verbosity zero. 24 25 The idea is that modules set up an Output object early in their years and pass 26 it around to other modules that need it. This keeps the output under control 27 of a single class. 28 29 Public properties: 30 verbose: Verbosity level: 0=silent, 1=progress, 3=full, 4=debug 31 """ 32 def __enter__(): 33 return 34 35 def __exit__(unused1, unused2, unused3): 36 """Clean up and remove any progress message.""" 37 ClearProgress() 38 return False 39 40 def 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 51 def ClearProgress(): 52 """Clear any active progress message on the terminal.""" 53 global in_progress 54 if verbose > 0 and stdout_is_tty and in_progress: 55 _stdout.write('\r%s\r' % (" " * len (_progress))) 56 _stdout.flush() 57 in_progress = False 58 59 def 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.""" 65 global in_progress 66 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() 73 in_progress = True 74 else: 75 _stdout.write(_progress + '\n') 76 77 def _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 92 def 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 102 def Error(msg): 103 """Display an error message 104 105 Args: 106 msg; Message to display. 107 """ 108 _Output(0, msg, _color.RED) 109 110 def Warning(msg): 111 """Display a warning message 112 113 Args: 114 msg; Message to display. 115 """ 116 _Output(1, msg, _color.YELLOW) 117 118 def Notice(msg): 119 """Display an important infomation message 120 121 Args: 122 msg; Message to display. 123 """ 124 _Output(2, msg) 125 126 def Info(msg): 127 """Display an infomation message 128 129 Args: 130 msg; Message to display. 131 """ 132 _Output(3, msg) 133 134 def Debug(msg): 135 """Display a debug message 136 137 Args: 138 msg; Message to display. 139 """ 140 _Output(4, msg) 141 142 def 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 151 def 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 168 def Uninit(): 169 ClearProgress() 170 171 Init() 172