/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/progress.py

  • Committer: Jelmer Vernooij
  • Date: 2009-01-20 16:07:55 UTC
  • mfrom: (3946.2.1 bzr.dev)
  • mto: (3920.2.35 dpush)
  • mto: This revision was merged to the branch mainline in revision 4281.
  • Revision ID: jelmer@samba.org-20090120160755-9v9advsk6zevtggg
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 Aaron Bentley <aaron.bentley@utoronto.ca>
2
 
# Copyright (C) 2005, 2006 Canonical Ltd
 
1
# Copyright (C) 2005, 2006, 2008 Canonical Ltd
3
2
#
4
3
# This program is free software; you can redistribute it and/or modify
5
4
# it under the terms of the GNU General Public License as published by
28
27
bzrlib it really is best to use bzrlib.ui.ui_factory.
29
28
"""
30
29
 
31
 
# TODO: Optionally show elapsed time instead/as well as ETA; nicer
32
 
# when the rate is unpredictable
33
30
 
34
31
import sys
35
32
import time
36
33
import os
37
 
 
38
 
from bzrlib.lazy_import import lazy_import
39
 
lazy_import(globals(), """
 
34
import warnings
 
35
 
 
36
 
40
37
from bzrlib import (
41
38
    errors,
 
39
    osutils,
 
40
    trace,
 
41
    ui,
42
42
    )
43
 
""")
44
 
 
45
43
from bzrlib.trace import mutter
46
44
 
47
45
 
62
60
    return True
63
61
 
64
62
 
65
 
_progress_bar_types = {}
 
63
class ProgressTask(object):
 
64
    """Model component of a progress indicator.
 
65
 
 
66
    Most code that needs to indicate progress should update one of these, 
 
67
    and it will in turn update the display, if one is present.
 
68
 
 
69
    Code updating the task may also set fields as hints about how to display
 
70
    it: show_pct, show_spinner, show_eta, show_count, show_bar.  UIs
 
71
    will not necessarily respect all these fields.
 
72
    """
 
73
 
 
74
    def __init__(self, parent_task=None, ui_factory=None):
 
75
        self._parent_task = parent_task
 
76
        self._last_update = 0
 
77
        self.total_cnt = None
 
78
        self.current_cnt = None
 
79
        self.msg = ''
 
80
        self.ui_factory = ui_factory
 
81
        self.show_pct = False
 
82
        self.show_spinner = True
 
83
        self.show_eta = False,
 
84
        self.show_count = True
 
85
        self.show_bar = True
 
86
 
 
87
    def update(self, msg, current_cnt=None, total_cnt=None):
 
88
        self.msg = msg
 
89
        self.current_cnt = current_cnt
 
90
        if total_cnt:
 
91
            self.total_cnt = total_cnt
 
92
        self.ui_factory.show_progress(self)
 
93
 
 
94
    def tick(self):
 
95
        self.update(self.msg)
 
96
 
 
97
    def finished(self):
 
98
        self.ui_factory.progress_finished(self)
 
99
 
 
100
    def make_sub_task(self):
 
101
        return ProgressTask(self, self.ui_factory)
 
102
 
 
103
    def _overall_completion_fraction(self, child_fraction=0.0):
 
104
        """Return fractional completion of this task and its parents
 
105
        
 
106
        Returns None if no completion can be computed."""
 
107
        if self.total_cnt:
 
108
            own_fraction = (float(self.current_cnt) + child_fraction) / self.total_cnt
 
109
        else:
 
110
            own_fraction = None
 
111
        if self._parent_task is None:
 
112
            return own_fraction
 
113
        else:
 
114
            if own_fraction is None:
 
115
                own_fraction = 0.0
 
116
            return self._parent_task._overall_completion_fraction(own_fraction)
 
117
 
 
118
    def note(self, fmt_string, *args):
 
119
        """Record a note without disrupting the progress bar."""
 
120
        # XXX: shouldn't be here; put it in mutter or the ui instead
 
121
        if args:
 
122
            self.ui_factory.note(fmt_string % args)
 
123
        else:
 
124
            self.ui_factory.note(fmt_string)
 
125
 
 
126
    def clear(self):
 
127
        # XXX: shouldn't be here; put it in mutter or the ui instead
 
128
        self.ui_factory.clear_term()
66
129
 
67
130
 
68
131
def ProgressBar(to_file=None, **kwargs):
87
150
                                                _progress_bar_types.keys())
88
151
        return _progress_bar_types[requested_bar_type](to_file=to_file, **kwargs)
89
152
 
90
 
 
 
153
 
91
154
class ProgressBarStack(object):
92
155
    """A stack of progress bars."""
93
156
 
147
210
    def return_pb(self, bar):
148
211
        """Return bar after its been used."""
149
212
        if bar is not self._stack[-1]:
150
 
            raise errors.MissingProgressBarFinish()
151
 
        self._stack.pop()
 
213
            warnings.warn("%r is not currently active" % (bar,))
 
214
        else:
 
215
            self._stack.pop()
152
216
 
153
217
 
154
218
class _BaseProgressBar(object):
206
270
 
207
271
    This can be used as the default argument for methods that
208
272
    take an optional progress indicator."""
 
273
 
209
274
    def tick(self):
210
275
        pass
211
276
 
225
290
        return DummyProgress(**kwargs)
226
291
 
227
292
 
228
 
_progress_bar_types['dummy'] = DummyProgress
229
 
_progress_bar_types['none'] = DummyProgress
230
 
 
231
 
 
232
293
class DotsProgressBar(_BaseProgressBar):
233
294
 
234
295
    def __init__(self, **kwargs):
257
318
        self.tick()
258
319
 
259
320
 
260
 
_progress_bar_types['dots'] = DotsProgressBar
261
321
 
262
322
    
263
323
class TTYProgressBar(_BaseProgressBar):
329
389
        self.tick()
330
390
 
331
391
    def update(self, msg, current_cnt=None, total_cnt=None,
332
 
               child_fraction=0):
333
 
        """Update and redraw progress bar."""
 
392
            child_fraction=0):
 
393
        """Update and redraw progress bar.
 
394
        """
334
395
        if msg is None:
335
396
            msg = self.last_msg
336
397
 
356
417
        ##     self.child_fraction == child_fraction):
357
418
        ##     return
358
419
 
 
420
        if msg is None:
 
421
            msg = ''
 
422
 
359
423
        old_msg = self.last_msg
360
424
        # save these for the tick() function
361
425
        self.last_msg = msg
401
465
            # make both fields the same size
402
466
            t = '%i' % (self.last_total)
403
467
            c = '%*i' % (len(t), self.last_cnt)
404
 
            count_str = ' ' + c + '/' + t 
 
468
            count_str = ' ' + c + '/' + t
405
469
 
406
470
        if self.show_bar:
407
471
            # progress bar, if present, soaks up all remaining space
425
489
        else:
426
490
            bar_str = ''
427
491
 
428
 
        m = spin_str + bar_str + self.last_msg + count_str + pct_str + eta_str
 
492
        m = spin_str + bar_str + self.last_msg + count_str \
 
493
            + pct_str + eta_str
429
494
        self.to_file.write('\r%-*.*s' % (self.width - 1, self.width - 1, m))
430
495
        self._have_output = True
431
496
        #self.to_file.flush()
437
502
        #self.to_file.flush()        
438
503
 
439
504
 
440
 
_progress_bar_types['tty'] = TTYProgressBar
441
505
 
442
506
 
443
507
class ChildProgress(_BaseProgressBar):
557
621
        else:
558
622
            self.cur_phase += 1
559
623
        self.pb.update(self.message, self.cur_phase, self.total)
 
624
 
 
625
 
 
626
_progress_bar_types = {}
 
627
_progress_bar_types['dummy'] = DummyProgress
 
628
_progress_bar_types['none'] = DummyProgress
 
629
_progress_bar_types['tty'] = TTYProgressBar
 
630
_progress_bar_types['dots'] = DotsProgressBar