1
# Copyright (C) 2005, 2008, 2009 Canonical Ltd
1
# Copyright (C) 2005, 2008, 2009, 2010 Canonical Ltd
3
3
# This program is free software; you can redistribute it and/or modify
4
4
# it under the terms of the GNU General Public License as published by
60
61
# paints progress, network activity, etc
61
62
self._progress_view = self.make_progress_view()
64
def be_quiet(self, state):
65
if state and not self._quiet:
67
UIFactory.be_quiet(self, state)
68
self._progress_view = self.make_progress_view()
63
70
def clear_term(self):
64
71
"""Prepare the terminal for output.
145
152
def make_progress_view(self):
146
153
"""Construct and return a new ProgressView subclass for this UI.
148
# if the user specifically requests either text or no progress bars,
149
# always do that. otherwise, guess based on $TERM and tty presence.
150
if os.environ.get('BZR_PROGRESS_BAR') == 'text':
155
# with --quiet, never any progress view
156
# <https://bugs.edge.launchpad.net/bzr/+bug/320035>. Otherwise if the
157
# user specifically requests either text or no progress bars, always
158
# do that. otherwise, guess based on $TERM and tty presence.
160
return NullProgressView()
161
elif os.environ.get('BZR_PROGRESS_BAR') == 'text':
151
162
return TextProgressView(self.stderr)
152
163
elif os.environ.get('BZR_PROGRESS_BAR') == 'none':
153
164
return NullProgressView()
203
214
self._progress_view.show_transport_activity(transport,
204
215
direction, byte_count)
217
def log_transport_activity(self, display=False):
218
"""See UIFactory.log_transport_activity()"""
219
log = getattr(self._progress_view, 'log_transport_activity', None)
206
223
def show_error(self, msg):
207
224
self.clear_term()
208
225
self.stderr.write("bzr: error: %s\n" % msg)
257
274
self._last_task = None
258
275
self._total_byte_count = 0
259
276
self._bytes_since_update = 0
277
self._bytes_by_direction = {'unknown': 0, 'read': 0, 'write': 0}
278
self._first_byte_time = None
260
279
self._fraction = 0
261
280
# force the progress bar to be off, as at the moment it doesn't
262
281
# correspond reliably to overall command progress
369
388
This may update a progress bar, spinner, or similar display.
370
389
By default it does nothing.
372
# XXX: Probably there should be a transport activity model, and that
373
# too should be seen by the progress view, rather than being poked in
391
# XXX: there should be a transport activity model, and that too should
392
# be seen by the progress view, rather than being poked in here.
393
self._total_byte_count += byte_count
394
self._bytes_since_update += byte_count
395
if self._first_byte_time is None:
396
# Note that this isn't great, as technically it should be the time
397
# when the bytes started transferring, not when they completed.
398
# However, we usually start with a small request anyway.
399
self._first_byte_time = time.time()
400
if direction in self._bytes_by_direction:
401
self._bytes_by_direction[direction] += byte_count
403
self._bytes_by_direction['unknown'] += byte_count
375
404
if 'no_activity' in debug.debug_flags:
376
405
# Can be used as a workaround if
377
406
# <https://launchpad.net/bugs/321935> reappears and transport
378
407
# activity is cluttering other output. However, thanks to
379
408
# TextUIOutputStream this shouldn't be a problem any more.
381
self._total_byte_count += byte_count
382
self._bytes_since_update += byte_count
383
410
now = time.time()
384
411
if self._total_byte_count < 2000:
385
412
# a little resistance at first, so it doesn't stay stuck at 0
399
426
self._last_transport_msg = msg
429
def _format_bytes_by_direction(self):
430
if self._first_byte_time is None:
433
transfer_time = time.time() - self._first_byte_time
434
if transfer_time < 0.001:
435
transfer_time = 0.001
436
bps = self._total_byte_count / transfer_time
438
msg = ('Transferred: %.0fKiB'
439
' (%.1fK/s r:%.0fK w:%.0fK'
440
% (self._total_byte_count / 1024.,
442
self._bytes_by_direction['read'] / 1024.,
443
self._bytes_by_direction['write'] / 1024.,
445
if self._bytes_by_direction['unknown'] > 0:
446
msg += ' u:%.0fK)' % (
447
self._bytes_by_direction['unknown'] / 1024.
453
def log_transport_activity(self, display=False):
454
msg = self._format_bytes_by_direction()
456
if display and self._total_byte_count > 0:
458
self._term_file.write(msg + '\n')
403
461
class TextUIOutputStream(object):
404
462
"""Decorates an output stream so that the terminal is cleared before writing.