source: rtems-source-builder/source-builder/sb/log.py @ 3b0032d

5
Last change on this file since 3b0032d was 3b0032d, checked in by Chris Johns <chrisj@…>, on 03/04/20 at 09:32:12

sb/options: Let --source-only-download download releases

  • The release procedure uses the sb-set-sources command now.

Closes #3896

  • Property mode set to 100755
File size: 6.3 KB
Line 
1#
2# RTEMS Tools Project (http://www.rtems.org/)
3# Copyright 2010-2017 Chris Johns (chrisj@rtems.org)
4# All rights reserved.
5#
6# This file is part of the RTEMS Tools package in 'rtems-testing'.
7#
8# Permission to use, copy, modify, and/or distribute this software for any
9# purpose with or without fee is hereby granted, provided that the above
10# copyright notice and this permission notice appear in all copies.
11#
12# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20#
21# Log output to stdout and/or a file.
22#
23
24from __future__ import print_function
25
26import os
27import sys
28
29import error
30
31#
32# A global log.
33#
34default = None
35
36#
37# A global capture handler.
38#
39capture = None
40
41#
42# Global parameters.
43#
44tracing = False
45quiet = False
46
47def set_default_once(log):
48    global default
49    if default is None:
50        default = log
51
52def _output(text = os.linesep, log = None):
53    """Output the text to a log if provided else send it to stdout."""
54    if text is None:
55        text = os.linesep
56    if type(text) is list:
57        _text = ''
58        for l in text:
59            _text += l + os.linesep
60        text = _text
61    if log:
62        log.output(text)
63    elif default is not None:
64        default.output(text)
65    else:
66        for l in text.replace(chr(13), '').splitlines():
67            print(l)
68        sys.stdout.flush()
69
70def stdout_raw(text = os.linesep):
71    print(text, end = '')
72    sys.stdout.flush()
73
74def stderr(text = os.linesep, log = None):
75    for l in text.replace(chr(13), '').splitlines():
76        print(l, file = sys.stderr)
77        sys.stderr.flush()
78    if capture is not None:
79        capture(text)
80
81def output(text = os.linesep, log = None):
82    if not quiet:
83        _output(text, log)
84
85def notice(text = os.linesep, log = None):
86    if not quiet and default is not None and not default.has_stdout():
87        for l in text.replace(chr(13), '').splitlines():
88            print(l)
89        sys.stdout.flush()
90        if capture is not None:
91            capture(text)
92    _output(text, log)
93
94def trace(text = os.linesep, log = None):
95    if not quiet and tracing:
96        _output(text, log)
97
98def warning(text = os.linesep, log = None):
99    for l in text.replace(chr(13), '').splitlines():
100        notice('warning: %s' % (l), log)
101
102def flush(log = None):
103    if log:
104        log.flush()
105    elif default is not None:
106        default.flush()
107
108def tail(log = None):
109    if log is not None:
110        return log.tail
111    if default is not None:
112        return default.tail
113    return 'No log output'
114
115class log:
116    """Log output to stdout or a file."""
117    def __init__(self, streams = None, tail_size = 400):
118        self.tail = []
119        self.tail_size = tail_size
120        self.fhs = [None, None]
121        if streams:
122            for s in streams:
123                if s == 'stdout':
124                    self.fhs[0] = sys.stdout
125                elif s == 'stderr':
126                    self.fhs[1] = sys.stderr
127                else:
128                    try:
129                        self.fhs.append(open(s, 'w'))
130                    except IOError as ioe:
131                         raise error.general("creating log file '" + s + \
132                                             "': " + str(ioe))
133
134    def __del__(self):
135        for f in range(2, len(self.fhs)):
136            self.fhs[f].close()
137
138    def __str__(self):
139        t = ''
140        for tl in self.tail:
141            t += tl + os.linesep
142        return t[:-len(os.linesep)]
143
144    def _tail(self, text):
145        if type(text) is not list:
146            text = text.splitlines()
147        self.tail += text
148        if len(self.tail) > self.tail_size:
149            self.tail = self.tail[-self.tail_size:]
150
151    def has_stdout(self):
152        return self.fhs[0] is not None
153
154    def has_stderr(self):
155        return self.fhs[1] is not None
156
157    def output(self, text):
158        """Output the text message to all the logs."""
159        # Reformat the text to have local line types.
160        text = text.replace(chr(13), '').splitlines()
161        self._tail(text)
162        out = ''
163        for l in text:
164            out += l + os.linesep
165        for f in range(0, len(self.fhs)):
166            if self.fhs[f] is not None:
167                self.fhs[f].write(out)
168        self.flush()
169
170    def flush(self):
171        """Flush the output."""
172        for f in range(0, len(self.fhs)):
173            if self.fhs[f] is not None:
174                self.fhs[f].flush()
175
176if __name__ == "__main__":
177    l = log(['stdout', 'log.txt'], tail_size = 20)
178    for i in range(0, 10):
179        l.output('log: hello world: %d\n' % (i))
180    l.output('log: hello world CRLF\r\n')
181    l.output('log: hello world NONE')
182    l.flush()
183    print('=-' * 40)
184    print('tail: %d' % (len(l.tail)))
185    print(l)
186    print('=-' * 40)
187    for i in range(0, 10):
188        l.output('log: hello world 2: %d\n' % (i))
189    l.flush()
190    print('=-' * 40)
191    print('tail: %d' % (len(l.tail)))
192    print(l)
193    print('=-' * 40)
194    for i in [0, 1]:
195        quiet = False
196        tracing = False
197        print('- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30))
198        trace('trace with quiet and trace off')
199        notice('notice with quiet and trace off')
200        quiet = True
201        tracing = False
202        print('- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30))
203        trace('trace with quiet on and trace off')
204        notice('notice with quiet on and trace off')
205        quiet = False
206        tracing = True
207        print('- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30))
208        trace('trace with quiet off and trace on')
209        notice('notice with quiet off and trace on')
210        quiet = True
211        tracing = True
212        print('- quiet:%s - trace:%s %s' % (str(quiet), str(tracing), '-' * 30))
213        trace('trace with quiet on and trace on')
214        notice('notice with quiet on and trace on')
215        default = l
216    print('=-' * 40)
217    print('tail: %d' % (len(l.tail)))
218    print(l)
219    print('=-' * 40)
220    del l
Note: See TracBrowser for help on using the repository browser.