move msger.run to utils.runner module and more apis
[tools/mic.git] / mic / msger.py
1 #!/usr/bin/python -tt
2 # vim: ai ts=4 sts=4 et sw=4
3 #
4 # Copyright 2009, 2010, 2011 Intel, Inc.
5 #
6 # This copyrighted material is made available to anyone wishing to use, modify,
7 # copy, or redistribute it subject to the terms and conditions of the GNU
8 # General Public License v.2.  This program is distributed in the hope that it
9 # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
10 # implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 # See the GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License along with
14 # this program; if not, write to the Free Software Foundation, Inc., 51
15 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  Any Red Hat
16 # trademarks that are incorporated in the source code or documentation are not
17 # subject to the GNU General Public License and may only be used or replicated
18 # with the express permission of Red Hat, Inc.
19 #
20
21 import os,sys
22 import re
23
24 __ALL__ = ['set_mode', 'get_loglevel', 'set_loglevel', 'raw' 'debug', 'verbose', 'info', 'warning', 'error', 'ask', 'pause']
25
26 # COLORs in ANSI
27 INFO_COLOR = 32 # green
28 WARN_COLOR = 33 # yellow
29 ERR_COLOR  = 31 # red
30 ASK_COLOR  = 34 # blue
31 NO_COLOR = 0
32
33 PREFIX_RE = re.compile('^<(.*?)>\s*(.*)')
34
35 INTERACTIVE = True
36
37 LOG_LEVELS = {
38                 'quiet': 0,
39                 'normal': 1,
40                 'verbose': 2,
41                 'debug': 3,
42                 'never': 4,
43              }
44 LOG_LEVEL = 1
45
46 def _color_print(head, color, msg = None, stream = sys.stdout, level = 'normal'):
47     if LOG_LEVELS[level] > LOG_LEVEL:
48         # skip
49         return
50
51     colored = True
52     if color == NO_COLOR or \
53        not stream.isatty() or \
54        os.getenv('ANSI_COLORS_DISABLED') is not None:
55         colored = False
56
57     if head.startswith('\r'):
58         # need not \n at last
59         newline = False
60     else:
61         newline = True
62
63     if colored:
64         head = '\033[%dm%s:\033[0m ' %(color, head)
65         if not newline:
66             # ESC cmd to clear line
67             head = '\033[2K' + head
68     else:
69         if head:
70             head += ': '
71             if head.startswith('\r'):
72                 head = head.lstrip()
73                 newline = True
74
75     if msg is not None:
76         stream.write('%s%s' % (head, msg))
77         if newline:
78             stream.write('\n')
79
80     stream.flush()
81
82 def _color_perror(head, color, msg, level = 'normal'):
83     _color_print(head, color, msg, sys.stderr, level)
84
85 def _split_msg(head, msg):
86     if isinstance(msg, list):
87         msg = '\n'.join(map(str, msg))
88
89     if msg.startswith('\n'):
90         # means print \n at first
91         msg = msg.lstrip()
92         head = '\n' + head
93
94     elif msg.startswith('\r'):
95         # means print \r at first
96         msg = msg.lstrip()
97         head = '\r' + head
98
99     m = PREFIX_RE.match(msg)
100     if m:
101         head += ' <%s>' % m.group(1)
102         msg = m.group(2)
103
104     return head, msg
105
106 def get_loglevel():
107     return (k for k,v in LOG_LEVELS.items() if v==LOG_LEVEL).next()
108
109 def set_loglevel(level):
110     global LOG_LEVEL
111     if level not in LOG_LEVELS:
112         # no effect
113         return
114
115     LOG_LEVEL = LOG_LEVELS[level]
116
117 def set_mode(interactive):
118     global INTERACTIVE
119     if interactive:
120         INTERACTIVE = True
121     else:
122         INTERACTIVE = False
123
124 def raw(msg=None):
125     if msg:
126         sys.stdout.write(msg)
127     sys.stdout.write('\n')
128     sys.stdout.flush()
129
130 def info(msg):
131     head, msg = _split_msg('Info', msg)
132     _color_print(head, INFO_COLOR, msg)
133
134 def verbose(msg):
135     head, msg = _split_msg('Verbose', msg)
136     _color_print(head, INFO_COLOR, msg, level = 'verbose')
137
138 def warning(msg):
139     head, msg = _split_msg('Warning', msg)
140     _color_perror(head, WARN_COLOR, msg)
141
142 def debug(msg):
143     head, msg = _split_msg('Debug', msg)
144     _color_perror(head, ERR_COLOR, msg, level = 'debug')
145
146 def error(msg):
147     head, msg = _split_msg('Error', msg)
148     _color_perror(head, ERR_COLOR, msg)
149     sys.exit(1)
150
151 def ask(msg, default=True):
152     _color_print('\rQ', ASK_COLOR, '')
153     try:
154         if default:
155             msg += '(Y/n) '
156         else:
157             msg += '(y/N) '
158         if INTERACTIVE:
159             while True:
160                 repl = raw_input(msg)
161                 if repl.lower() == 'y':
162                     return True
163                 elif repl.lower() == 'n':
164                     return False
165                 elif not repl.strip():
166                     # <Enter>
167                     return default
168
169                 # else loop
170         else:
171             sys.stdout.write('%s ' % msg)
172             if default:
173                 sys.stdout.write('Y\n')
174             else:
175                 sys.stdout.write('N\n')
176             return default
177     except KeyboardInterrupt:
178         sys.stdout.write('\n')
179         sys.exit(2)
180
181 def pause(msg=None):
182     if INTERACTIVE:
183         _color_print('\rQ', ASK_COLOR, '')
184         if msg is None:
185             msg = 'press <ENTER> to continue ...'
186         raw_input(msg)
187