OLD | NEW |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 # Copyright 2014 Google Inc. All Rights Reserved. | 2 # Copyright 2014 Google Inc. All Rights Reserved. |
3 # | 3 # |
4 # Licensed under the Apache License, Version 2.0 (the "License"); | 4 # Licensed under the Apache License, Version 2.0 (the "License"); |
5 # you may not use this file except in compliance with the License. | 5 # you may not use this file except in compliance with the License. |
6 # You may obtain a copy of the License at | 6 # You may obtain a copy of the License at |
7 # | 7 # |
8 # http://www.apache.org/licenses/LICENSE-2.0 | 8 # http://www.apache.org/licenses/LICENSE-2.0 |
9 # | 9 # |
10 # Unless required by applicable law or agreed to in writing, software | 10 # Unless required by applicable law or agreed to in writing, software |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 url_string = '...%s' % url_string[ | 113 url_string = '...%s' % url_string[ |
114 -(MAX_PROGRESS_INDICATOR_COLUMNS - start_len - end_len - ellipsis_len):] | 114 -(MAX_PROGRESS_INDICATOR_COLUMNS - start_len - end_len - ellipsis_len):] |
115 base_announce_text = '%s%s:' % (justified_op_string, url_string) | 115 base_announce_text = '%s%s:' % (justified_op_string, url_string) |
116 format_str = '{0:%ds}' % MAX_PROGRESS_INDICATOR_COLUMNS | 116 format_str = '{0:%ds}' % MAX_PROGRESS_INDICATOR_COLUMNS |
117 return format_str.format(base_announce_text.encode(UTF8)) | 117 return format_str.format(base_announce_text.encode(UTF8)) |
118 | 118 |
119 | 119 |
120 class FileProgressCallbackHandler(object): | 120 class FileProgressCallbackHandler(object): |
121 """Outputs progress info for large operations like file copy or hash.""" | 121 """Outputs progress info for large operations like file copy or hash.""" |
122 | 122 |
123 def __init__(self, announce_text, logger): | 123 def __init__(self, announce_text, logger, start_byte=0, |
| 124 override_total_size=None): |
124 """Initializes the callback handler. | 125 """Initializes the callback handler. |
125 | 126 |
126 Args: | 127 Args: |
127 announce_text: String describing the operation. | 128 announce_text: String describing the operation. |
128 logger: For outputting log messages. | 129 logger: For outputting log messages. |
| 130 start_byte: The beginning of the file component, if one is being used. |
| 131 override_total_size: The size of the file component, if one is being used. |
129 """ | 132 """ |
130 self._announce_text = announce_text | 133 self._announce_text = announce_text |
131 self._logger = logger | 134 self._logger = logger |
| 135 self._start_byte = start_byte |
| 136 self._override_total_size = override_total_size |
132 # Ensures final newline is written once even if we get multiple callbacks. | 137 # Ensures final newline is written once even if we get multiple callbacks. |
133 self._last_byte_written = False | 138 self._last_byte_written = False |
134 | 139 |
135 # Function signature is in boto callback format, which cannot be changed. | 140 # Function signature is in boto callback format, which cannot be changed. |
136 def call(self, # pylint: disable=invalid-name | 141 def call(self, # pylint: disable=invalid-name |
137 total_bytes_processed, | 142 last_byte_processed, |
138 total_size): | 143 total_size): |
139 """Prints an overwriting line to stderr describing the operation progress. | 144 """Prints an overwriting line to stderr describing the operation progress. |
140 | 145 |
141 Args: | 146 Args: |
142 total_bytes_processed: Number of bytes processed so far. | 147 last_byte_processed: The last byte processed in the file. For file |
| 148 components, this number should be in the range |
| 149 [start_byte:start_byte + override_total_size]. |
143 total_size: Total size of the ongoing operation. | 150 total_size: Total size of the ongoing operation. |
144 """ | 151 """ |
145 if not self._logger.isEnabledFor(logging.INFO) or self._last_byte_written: | 152 if not self._logger.isEnabledFor(logging.INFO) or self._last_byte_written: |
146 return | 153 return |
147 | 154 |
148 # Handle streaming case specially where we don't know the total size: | 155 if self._override_total_size: |
| 156 total_size = self._override_total_size |
| 157 |
149 if total_size: | 158 if total_size: |
150 total_size_string = '/%s' % MakeHumanReadable(total_size) | 159 total_size_string = '/%s' % MakeHumanReadable(total_size) |
151 else: | 160 else: |
152 total_size_string = '' | 161 total_size_string = '' |
153 # Use sys.stderr.write instead of self.logger.info so progress messages | 162 # Use sys.stderr.write instead of self.logger.info so progress messages |
154 # output on a single continuously overwriting line. | 163 # output on a single continuously overwriting line. |
155 # TODO: Make this work with logging.Logger. | 164 # TODO: Make this work with logging.Logger. |
156 sys.stderr.write('%s%s%s \r' % ( | 165 sys.stderr.write('%s%s%s \r' % ( |
157 self._announce_text, | 166 self._announce_text, |
158 MakeHumanReadable(total_bytes_processed), | 167 MakeHumanReadable(last_byte_processed - self._start_byte), |
159 total_size_string)) | 168 total_size_string)) |
160 if total_size and total_bytes_processed == total_size: | 169 if total_size and last_byte_processed - self._start_byte == total_size: |
161 self._last_byte_written = True | 170 self._last_byte_written = True |
162 sys.stderr.write('\n') | 171 sys.stderr.write('\n') |
OLD | NEW |