~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/progress.py

  • Committer: Joe Julian
  • Date: 2010-01-10 02:25:31 UTC
  • mto: (4634.119.7 2.0)
  • mto: This revision was merged to the branch mainline in revision 4959.
  • Revision ID: joe@julianfamily.org-20100110022531-wqk61rsagz8xsiga
Added MANIFEST.in to allow bdist_rpm to have all the required include files and tools. bdist_rpm will still fail to build correctly on some distributions due to a disttools bug http://bugs.python.org/issue644744

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
import sys
26
26
import time
27
27
import os
28
 
import warnings
29
28
 
30
29
 
31
30
from bzrlib import (
32
31
    errors,
33
 
    osutils,
34
 
    trace,
35
 
    ui,
36
32
    )
37
33
from bzrlib.trace import mutter
38
34
from bzrlib.symbol_versioning import (
 
35
    deprecated_function,
39
36
    deprecated_in,
40
 
    deprecated_method,
41
37
    )
42
38
 
43
39
 
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.
46
42
 
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.
 
45
 
 
46
    This doesn't check the policy for whether we *should* use them.
49
47
    """
50
48
    isatty = getattr(f, 'isatty', None)
51
49
    if isatty is None:
52
50
        return False
53
51
    if not isatty():
54
52
        return False
 
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
57
59
        return False
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.
 
72
    
 
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
 
75
        synchronously.
 
76
 
 
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
 
80
        during this task.
70
81
    """
71
82
 
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.
74
85
 
 
86
        :param parent_task: Enclosing ProgressTask or None.
 
87
 
 
88
        :param progress_view: ProgressView to display this ProgressTask.
 
89
 
 
90
        :param ui_factory: The UI factory that will display updates; 
 
91
            deprecated in favor of passing progress_view directly.
 
92
 
75
93
        Normally you should not call this directly but rather through
76
94
        `ui_factory.nested_progress_bar`.
77
95
        """
80
98
        self.total_cnt = None
81
99
        self.current_cnt = None
82
100
        self.msg = ''
 
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
89
111
 
90
112
    def __repr__(self):
91
113
        return '%s(%r/%r, msg=%r)' % (
99
121
        self.current_cnt = current_cnt
100
122
        if total_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)
 
126
        else:
 
127
            self.ui_factory._progress_updated(self)
103
128
 
104
129
    def tick(self):
105
130
        self.update(self.msg)
106
131
 
107
132
    def finished(self):
108
 
        self.ui_factory._progress_finished(self)
 
133
        if self.progress_view:
 
134
            self.progress_view.task_finished(self)
 
135
        else:
 
136
            self.ui_factory._progress_finished(self)
109
137
 
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)
112
141
 
113
142
    def _overall_completion_fraction(self, child_fraction=0.0):
114
143
        """Return fractional completion of this task and its parents
137
166
 
138
167
    def clear(self):
139
168
        # XXX: shouldn't be here; put it in mutter or the ui instead
140
 
        self.ui_factory.clear_term()
141
 
 
142
 
 
 
169
        if self.progress_view:
 
170
            self.progress_view.clear()
 
171
        else:
 
172
            self.ui_factory.clear_term()
 
173
 
 
174
 
 
175
@deprecated_function(deprecated_in((1, 16, 0)))
143
176
def ProgressBar(to_file=None, **kwargs):
144
 
    """Abstract factory"""
 
177
    """Construct a progress bar.
 
178
 
 
179
    Deprecated; ask the ui_factory for a progress task instead.
 
180
    """
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)
164
200
 
165
201
 
166
 
class ProgressBarStack(object):
167
 
    """A stack of progress bars.
168
 
 
169
 
    This class is deprecated: instead, ask the ui factory for a new progress
170
 
    task and finish it when it's done.
171
 
    """
172
 
 
173
 
    @deprecated_method(deprecated_in((1, 12, 0)))
174
 
    def __init__(self,
175
 
                 to_file=None,
176
 
                 show_pct=False,
177
 
                 show_spinner=True,
178
 
                 show_eta=False,
179
 
                 show_bar=True,
180
 
                 show_count=True,
181
 
                 to_messages_file=None,
182
 
                 klass=None):
183
 
        """Setup the stack with the parameters the progress bars should have."""
184
 
        if to_file is None:
185
 
            to_file = sys.stderr
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
195
 
        self._stack = []
196
 
        self._klass = klass or ProgressBar
197
 
 
198
 
    def top(self):
199
 
        if len(self._stack) != 0:
200
 
            return self._stack[-1]
201
 
        else:
202
 
            return None
203
 
 
204
 
    def bottom(self):
205
 
        if len(self._stack) != 0:
206
 
            return self._stack[0]
207
 
        else:
208
 
            return None
209
 
 
210
 
    def get_nested(self):
211
 
        """Return a nested progress bar."""
212
 
        if len(self._stack) == 0:
213
 
            func = self._klass
214
 
        else:
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,
223
 
                       _stack=self)
224
 
        self._stack.append(new_bar)
225
 
        return new_bar
226
 
 
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,))
231
 
        else:
232
 
            self._stack.pop()
233
 
 
234
 
 
 
202
# NOTE: This is also deprecated; you should provide a ProgressView instead.
235
203
class _BaseProgressBar(object):
236
204
 
237
205
    def __init__(self,
278
246
        self.to_messages_file.write(fmt_string % args)
279
247
        self.to_messages_file.write('\n')
280
248
 
 
249
    @deprecated_function(deprecated_in((1, 16, 0)))
281
250
    def child_progress(self, **kwargs):
282
251
        return ChildProgress(**kwargs)
283
252
 
309
278
 
310
279
class DotsProgressBar(_BaseProgressBar):
311
280
 
 
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
335
305
        self.tick()
336
306
 
337
307
 
338
 
 
339
 
 
340
308
class TTYProgressBar(_BaseProgressBar):
341
309
    """Progress bar display object.
342
310
 
359
327
    """
360
328
    SPIN_CHARS = r'/-\|'
361
329
 
362
 
 
 
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)
520
488
 
521
489
 
522
490
 
523
 
 
 
491
# DEPRECATED
524
492
class ChildProgress(_BaseProgressBar):
525
493
    """A progress indicator that pushes its data to the parent"""
526
494
 
 
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)
566
535
 
567
536
 
568
 
class InstrumentedProgress(TTYProgressBar):
569
 
    """TTYProgress variant that tracks outcomes"""
570
 
 
571
 
    def __init__(self, *args, **kwargs):
572
 
        self.always_throttled = True
573
 
        self.never_throttle = False
574
 
        TTYProgressBar.__init__(self, *args, **kwargs)
575
 
 
576
 
    def throttle(self, old_message):
577
 
        if self.never_throttle:
578
 
            result =  False
579
 
        else:
580
 
            result = TTYProgressBar.throttle(self, old_message)
581
 
        if result is False:
582
 
            self.always_throttled = False
583
 
 
584
 
 
585
537
def str_tdelta(delt):
586
538
    if delt is None:
587
539
        return "-:--:--"