OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """ | |
7 Package that implements a stream wrapper that has 'meters' as well as | |
8 regular output. A 'meter' is a single line of text that can be erased | |
9 and rewritten repeatedly, without producing multiple lines of output. It | |
10 can be used to produce effects like progress bars. | |
11 """ | |
12 | |
13 | |
14 class MeteredStream: | |
15 """This class is a wrapper around a stream that allows you to implement | |
16 meters. | |
17 | |
18 It can be used like a stream, but calling update() will print | |
19 the string followed by only a carriage return (instead of a carriage | |
20 return and a line feed). This can be used to implement progress bars and | |
21 other sorts of meters. Note that anything written by update() will be | |
22 erased by a subsequent update(), write(), or flush().""" | |
23 | |
24 def __init__(self, verbose, stream): | |
25 """ | |
26 Args: | |
27 verbose: whether update is a no-op | |
28 stream: output stream to write to | |
29 """ | |
30 self._dirty = False | |
31 self._verbose = verbose | |
32 self._stream = stream | |
33 self._last_update = "" | |
34 | |
35 def write(self, txt): | |
36 """Write text directly to the stream, overwriting and resetting the | |
37 meter.""" | |
38 if self._dirty: | |
39 self.update("") | |
40 self._dirty = False | |
41 self._stream.write(txt) | |
42 | |
43 def flush(self): | |
44 """Flush any buffered output.""" | |
45 self._stream.flush() | |
46 | |
47 def update(self, str): | |
48 """Write an update to the stream that will get overwritten by the next | |
49 update() or by a write(). | |
50 | |
51 This is used for progress updates that don't need to be preserved in | |
52 the log. Note that verbose disables this routine; we have this in | |
53 case we are logging lots of output and the update()s will get lost | |
54 or won't work properly (typically because verbose streams are | |
55 redirected to files. | |
56 | |
57 TODO(dpranke): figure out if there is a way to detect if we're writing | |
58 to a stream that handles CRs correctly (e.g., terminals). That might | |
59 be a cleaner way of handling this. | |
60 """ | |
61 if self._verbose: | |
62 return | |
63 | |
64 # Print the necessary number of backspaces to erase the previous | |
65 # message. | |
66 self._stream.write("\b" * len(self._last_update)) | |
67 self._stream.write(str) | |
68 num_remaining = len(self._last_update) - len(str) | |
69 if num_remaining > 0: | |
70 self._stream.write(" " * num_remaining + "\b" * num_remaining) | |
71 self._last_update = str | |
72 self._dirty = True | |
OLD | NEW |