102 float(self.ui.config( |
102 float(self.ui.config( |
103 'progress', 'changedelay'))) |
103 'progress', 'changedelay'))) |
104 self.order = self.ui.configlist( |
104 self.order = self.ui.configlist( |
105 'progress', 'format', |
105 'progress', 'format', |
106 default=['topic', 'bar', 'number', 'estimate']) |
106 default=['topic', 'bar', 'number', 'estimate']) |
|
107 self.estimateinterval = self.ui.configwith( |
|
108 float, 'progress', 'estimateinterval') |
107 |
109 |
108 def show(self, now, topic, pos, item, unit, total): |
110 def show(self, now, topic, pos, item, unit, total): |
109 if not shouldprint(self.ui): |
111 if not shouldprint(self.ui): |
110 return |
112 return |
111 termwidth = self.width() |
113 termwidth = self.width() |
236 or now - self.lastprint >= self.changedelay): |
238 or now - self.lastprint >= self.changedelay): |
237 return True |
239 return True |
238 else: |
240 else: |
239 return False |
241 return False |
240 |
242 |
|
243 def _calibrateestimate(self, topic, now, pos): |
|
244 '''Adjust starttimes and startvals for topic so ETA works better |
|
245 |
|
246 If progress is non-linear (ex. get much slower in the last minute), |
|
247 it's more friendly to only use a recent time span for ETA and speed |
|
248 calculation. |
|
249 |
|
250 [======================================> ] |
|
251 ^^^^^^^ |
|
252 estimateinterval, only use this for estimation |
|
253 ''' |
|
254 interval = self.estimateinterval |
|
255 if interval <= 0: |
|
256 return |
|
257 elapsed = now - self.starttimes[topic] |
|
258 if elapsed > interval: |
|
259 delta = pos - self.startvals[topic] |
|
260 newdelta = delta * interval / elapsed |
|
261 # If a stall happens temporarily, ETA could change dramatically |
|
262 # frequently. This is to avoid such dramatical change and make ETA |
|
263 # smoother. |
|
264 if newdelta < 0.1: |
|
265 return |
|
266 self.startvals[topic] = pos - newdelta |
|
267 self.starttimes[topic] = now - interval |
|
268 |
241 def progress(self, topic, pos, item='', unit='', total=None): |
269 def progress(self, topic, pos, item='', unit='', total=None): |
242 now = time.time() |
270 now = time.time() |
243 self._refreshlock.acquire() |
271 self._refreshlock.acquire() |
244 try: |
272 try: |
245 if pos is None: |
273 if pos is None: |
266 self.starttimes[topic] = now |
294 self.starttimes[topic] = now |
267 self.startvals[topic] = pos |
295 self.startvals[topic] = pos |
268 self.topics.append(topic) |
296 self.topics.append(topic) |
269 self.topicstates[topic] = pos, item, unit, total |
297 self.topicstates[topic] = pos, item, unit, total |
270 self.curtopic = topic |
298 self.curtopic = topic |
|
299 self._calibrateestimate(topic, now, pos) |
271 if now - self.lastprint >= self.refresh and self.topics: |
300 if now - self.lastprint >= self.refresh and self.topics: |
272 if self._oktoprint(now): |
301 if self._oktoprint(now): |
273 self.lastprint = now |
302 self.lastprint = now |
274 self.show(now, topic, *self.topicstates[topic]) |
303 self.show(now, topic, *self.topicstates[topic]) |
275 finally: |
304 finally: |