31
30
from bzrlib import (
37
33
from bzrlib.trace import mutter
38
34
from bzrlib.symbol_versioning import (
44
40
def _supports_progress(f):
45
"""Detect if we can use pretty progress bars on the output stream f.
41
"""Detect if we can use pretty progress bars on file F.
47
43
If this returns true we expect that a human may be looking at that
48
44
output, and that we can repaint a line to update it.
46
This doesn't check the policy for whether we *should* use them.
50
48
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.
55
57
if os.environ.get('TERM') == 'dumb':
56
58
# e.g. emacs compile window
67
69
Code updating the task may also set fields as hints about how to display
68
70
it: show_pct, show_spinner, show_eta, show_count, show_bar. UIs
69
71
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
72
def __init__(self, parent_task=None, ui_factory=None):
83
def __init__(self, parent_task=None, ui_factory=None, progress_view=None):
73
84
"""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.
75
93
Normally you should not call this directly but rather through
76
94
`ui_factory.nested_progress_bar`.
80
98
self.total_cnt = None
81
99
self.current_cnt = None
101
# TODO: deprecate passing ui_factory
83
102
self.ui_factory = ui_factory
103
self.progress_view = progress_view
84
104
self.show_pct = False
85
105
self.show_spinner = True
86
106
self.show_eta = False,
87
107
self.show_count = True
88
108
self.show_bar = True
109
self.update_latency = 0.1
110
self.show_transport_activity = True
90
112
def __repr__(self):
91
113
return '%s(%r/%r, msg=%r)' % (
99
121
self.current_cnt = current_cnt
101
123
self.total_cnt = total_cnt
102
self.ui_factory._progress_updated(self)
124
if self.progress_view:
125
self.progress_view.show_progress(self)
127
self.ui_factory._progress_updated(self)
105
130
self.update(self.msg)
107
132
def finished(self):
108
self.ui_factory._progress_finished(self)
133
if self.progress_view:
134
self.progress_view.task_finished(self)
136
self.ui_factory._progress_finished(self)
110
138
def make_sub_task(self):
111
return ProgressTask(self, self.ui_factory)
139
return ProgressTask(self, ui_factory=self.ui_factory,
140
progress_view=self.progress_view)
113
142
def _overall_completion_fraction(self, child_fraction=0.0):
114
143
"""Return fractional completion of this task and its parents
139
168
# XXX: shouldn't be here; put it in mutter or the ui instead
140
self.ui_factory.clear_term()
169
if self.progress_view:
170
self.progress_view.clear()
172
self.ui_factory.clear_term()
175
@deprecated_function(deprecated_in((1, 16, 0)))
143
176
def ProgressBar(to_file=None, **kwargs):
144
"""Abstract factory"""
177
"""Construct a progress bar.
179
Deprecated; ask the ui_factory for a progress task instead.
145
181
if to_file is None:
146
182
to_file = sys.stderr
147
183
requested_bar_type = os.environ.get('BZR_PROGRESS_BAR')
163
199
return _progress_bar_types[requested_bar_type](to_file=to_file, **kwargs)
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,))
202
# NOTE: This is also deprecated; you should provide a ProgressView instead.
235
203
class _BaseProgressBar(object):
237
205
def __init__(self,
278
246
self.to_messages_file.write(fmt_string % args)
279
247
self.to_messages_file.write('\n')
249
@deprecated_function(deprecated_in((1, 16, 0)))
281
250
def child_progress(self, **kwargs):
282
251
return ChildProgress(**kwargs)
310
279
class DotsProgressBar(_BaseProgressBar):
281
@deprecated_function(deprecated_in((1, 16, 0)))
312
282
def __init__(self, **kwargs):
313
283
_BaseProgressBar.__init__(self, **kwargs)
314
284
self.last_msg = None
360
328
SPIN_CHARS = r'/-\|'
330
@deprecated_function(deprecated_in((1, 16, 0)))
363
331
def __init__(self, **kwargs):
364
332
from bzrlib.osutils import terminal_width
365
333
_BaseProgressBar.__init__(self, **kwargs)
524
492
class ChildProgress(_BaseProgressBar):
525
493
"""A progress indicator that pushes its data to the parent"""
495
@deprecated_function(deprecated_in((1, 16, 0)))
527
496
def __init__(self, _stack, **kwargs):
528
497
_BaseProgressBar.__init__(self, _stack=_stack, **kwargs)
529
498
self.parent = _stack.top()
565
534
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
585
537
def str_tdelta(delt):