30
31
from bzrlib import (
33
37
from bzrlib.trace import mutter
34
38
from bzrlib.symbol_versioning import (
40
44
def _supports_progress(f):
41
"""Detect if we can use pretty progress bars on file F.
45
"""Detect if we can use pretty progress bars on the output stream f.
43
47
If this returns true we expect that a human may be looking at that
44
48
output, and that we can repaint a line to update it.
46
This doesn't check the policy for whether we *should* use them.
48
50
isatty = getattr(f, 'isatty', None)
53
# The following case also handles Win32 - on that platform $TERM is
54
# typically never set, so the case None is treated as a smart terminal,
55
# not dumb. <https://bugs.launchpad.net/bugs/334808> win32 files do have
56
# isatty methods that return true.
57
55
if os.environ.get('TERM') == 'dumb':
58
56
# e.g. emacs compile window
69
67
Code updating the task may also set fields as hints about how to display
70
68
it: show_pct, show_spinner, show_eta, show_count, show_bar. UIs
71
69
will not necessarily respect all these fields.
73
:ivar update_latency: The interval (in seconds) at which the PB should be
74
updated. Setting this to zero suggests every update should be shown
77
:ivar show_transport_activity: If true (default), transport activity
78
will be shown when this task is drawn. Disable it if you're sure
79
that only irrelevant or uninteresting transport activity can occur
83
def __init__(self, parent_task=None, ui_factory=None, progress_view=None):
72
def __init__(self, parent_task=None, ui_factory=None):
84
73
"""Construct a new progress task.
86
:param parent_task: Enclosing ProgressTask or None.
88
:param progress_view: ProgressView to display this ProgressTask.
90
:param ui_factory: The UI factory that will display updates;
91
deprecated in favor of passing progress_view directly.
93
75
Normally you should not call this directly but rather through
94
76
`ui_factory.nested_progress_bar`.
98
80
self.total_cnt = None
99
81
self.current_cnt = None
101
# TODO: deprecate passing ui_factory
102
83
self.ui_factory = ui_factory
103
self.progress_view = progress_view
104
84
self.show_pct = False
105
85
self.show_spinner = True
106
86
self.show_eta = False,
107
87
self.show_count = True
108
88
self.show_bar = True
109
self.update_latency = 0.1
110
self.show_transport_activity = True
112
90
def __repr__(self):
113
91
return '%s(%r/%r, msg=%r)' % (
121
99
self.current_cnt = current_cnt
123
101
self.total_cnt = total_cnt
124
if self.progress_view:
125
self.progress_view.show_progress(self)
127
self.ui_factory._progress_updated(self)
102
self.ui_factory._progress_updated(self)
130
105
self.update(self.msg)
132
107
def finished(self):
133
if self.progress_view:
134
self.progress_view.task_finished(self)
136
self.ui_factory._progress_finished(self)
108
self.ui_factory._progress_finished(self)
138
110
def make_sub_task(self):
139
return ProgressTask(self, ui_factory=self.ui_factory,
140
progress_view=self.progress_view)
111
return ProgressTask(self, self.ui_factory)
142
113
def _overall_completion_fraction(self, child_fraction=0.0):
143
114
"""Return fractional completion of this task and its parents
168
139
# XXX: shouldn't be here; put it in mutter or the ui instead
169
if self.progress_view:
170
self.progress_view.clear()
172
self.ui_factory.clear_term()
175
@deprecated_function(deprecated_in((1, 16, 0)))
140
self.ui_factory.clear_term()
176
143
def ProgressBar(to_file=None, **kwargs):
177
"""Construct a progress bar.
179
Deprecated; ask the ui_factory for a progress task instead.
144
"""Abstract factory"""
181
145
if to_file is None:
182
146
to_file = sys.stderr
183
147
requested_bar_type = os.environ.get('BZR_PROGRESS_BAR')
199
163
return _progress_bar_types[requested_bar_type](to_file=to_file, **kwargs)
202
# NOTE: This is also deprecated; you should provide a ProgressView instead.
166
class ProgressBarStack(object):
167
"""A stack of progress bars.
169
This class is deprecated: instead, ask the ui factory for a new progress
170
task and finish it when it's done.
173
@deprecated_method(deprecated_in((1, 12, 0)))
181
to_messages_file=None,
183
"""Setup the stack with the parameters the progress bars should have."""
186
if to_messages_file is None:
187
to_messages_file = sys.stdout
188
self._to_file = to_file
189
self._show_pct = show_pct
190
self._show_spinner = show_spinner
191
self._show_eta = show_eta
192
self._show_bar = show_bar
193
self._show_count = show_count
194
self._to_messages_file = to_messages_file
196
self._klass = klass or ProgressBar
199
if len(self._stack) != 0:
200
return self._stack[-1]
205
if len(self._stack) != 0:
206
return self._stack[0]
210
def get_nested(self):
211
"""Return a nested progress bar."""
212
if len(self._stack) == 0:
215
func = self.top().child_progress
216
new_bar = func(to_file=self._to_file,
217
show_pct=self._show_pct,
218
show_spinner=self._show_spinner,
219
show_eta=self._show_eta,
220
show_bar=self._show_bar,
221
show_count=self._show_count,
222
to_messages_file=self._to_messages_file,
224
self._stack.append(new_bar)
227
def return_pb(self, bar):
228
"""Return bar after its been used."""
229
if bar is not self._stack[-1]:
230
warnings.warn("%r is not currently active" % (bar,))
203
235
class _BaseProgressBar(object):
205
237
def __init__(self,
246
278
self.to_messages_file.write(fmt_string % args)
247
279
self.to_messages_file.write('\n')
249
@deprecated_function(deprecated_in((1, 16, 0)))
250
281
def child_progress(self, **kwargs):
251
282
return ChildProgress(**kwargs)
279
310
class DotsProgressBar(_BaseProgressBar):
281
@deprecated_function(deprecated_in((1, 16, 0)))
282
312
def __init__(self, **kwargs):
283
313
_BaseProgressBar.__init__(self, **kwargs)
284
314
self.last_msg = None
328
360
SPIN_CHARS = r'/-\|'
330
@deprecated_function(deprecated_in((1, 16, 0)))
331
363
def __init__(self, **kwargs):
332
364
from bzrlib.osutils import terminal_width
333
365
_BaseProgressBar.__init__(self, **kwargs)
492
524
class ChildProgress(_BaseProgressBar):
493
525
"""A progress indicator that pushes its data to the parent"""
495
@deprecated_function(deprecated_in((1, 16, 0)))
496
527
def __init__(self, _stack, **kwargs):
497
528
_BaseProgressBar.__init__(self, _stack=_stack, **kwargs)
498
529
self.parent = _stack.top()
534
565
self.parent.note(*args, **kwargs)
568
class InstrumentedProgress(TTYProgressBar):
569
"""TTYProgress variant that tracks outcomes"""
571
def __init__(self, *args, **kwargs):
572
self.always_throttled = True
573
self.never_throttle = False
574
TTYProgressBar.__init__(self, *args, **kwargs)
576
def throttle(self, old_message):
577
if self.never_throttle:
580
result = TTYProgressBar.throttle(self, old_message)
582
self.always_throttled = False
537
585
def str_tdelta(delt):