/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
4988.10.5 by John Arbash Meinel
Merge bzr.dev 5021 to resolve NEWS
1
# Copyright (C) 2005-2010 Canonical Ltd
2052.3.1 by John Arbash Meinel
Add tests to cleanup the copyright of all source files
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
4183.7.1 by Sabin Iacob
update FSF mailing address
15
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
648 by Martin Pool
- import aaron's progress-indicator code
16
3006.3.3 by Robert Collins
Docstring improvement and remove TODO's from progres.py.
17
"""Progress indicators.
18
6622.1.34 by Jelmer Vernooij
Rename brzlib => breezy.
19
The usual way to use this is via breezy.ui.ui_factory.nested_progress_bar which
3948.2.4 by Martin Pool
Remove some obsolete progress docstring
20
will manage a conceptual stack of nested activities.
649 by Martin Pool
- some cleanups for the progressbar method
21
"""
22
660 by Martin Pool
- use plain unix time, not datetime module
23
import time
964 by Martin Pool
- show progress on dumb terminals by printing dots
24
import os
649 by Martin Pool
- some cleanups for the progressbar method
25
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
26
649 by Martin Pool
- some cleanups for the progressbar method
27
def _supports_progress(f):
4449.3.1 by Martin Pool
Un-soft-deprecate _supports_progress - still useful
28
    """Detect if we can use pretty progress bars on file F.
2599.1.1 by Martin Pool
Don't show dots progress indicatiors in noninteractive mode
29
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
30
    If this returns true we expect that a human may be looking at that
2599.1.1 by Martin Pool
Don't show dots progress indicatiors in noninteractive mode
31
    output, and that we can repaint a line to update it.
4449.3.1 by Martin Pool
Un-soft-deprecate _supports_progress - still useful
32
33
    This doesn't check the policy for whether we *should* use them.
2599.1.1 by Martin Pool
Don't show dots progress indicatiors in noninteractive mode
34
    """
1843.3.7 by John Arbash Meinel
new env var 'BZR_PROGRESS_BAR' to select the exact progress type
35
    isatty = getattr(f, 'isatty', None)
36
    if isatty is None:
695 by Martin Pool
- don't display progress bars on really dumb terminals
37
        return False
1843.3.7 by John Arbash Meinel
new env var 'BZR_PROGRESS_BAR' to select the exact progress type
38
    if not isatty():
695 by Martin Pool
- don't display progress bars on really dumb terminals
39
        return False
4449.3.18 by Martin Pool
Fuse CLIUIFactory and TextUIFactory and deprecate the old name
40
    # The following case also handles Win32 - on that platform $TERM is
41
    # typically never set, so the case None is treated as a smart terminal,
42
    # not dumb.  <https://bugs.launchpad.net/bugs/334808>  win32 files do have
43
    # isatty methods that return true.
695 by Martin Pool
- don't display progress bars on really dumb terminals
44
    if os.environ.get('TERM') == 'dumb':
45
        # e.g. emacs compile window
46
        return False
47
    return True
649 by Martin Pool
- some cleanups for the progressbar method
48
49
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
50
class ProgressTask(object):
51
    """Model component of a progress indicator.
52
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
53
    Most code that needs to indicate progress should update one of these,
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
54
    and it will in turn update the display, if one is present.
3882.8.5 by Martin Pool
Progress tasks can indicate what kind of display is useful
55
56
    Code updating the task may also set fields as hints about how to display
57
    it: show_pct, show_spinner, show_eta, show_count, show_bar.  UIs
58
    will not necessarily respect all these fields.
6437.57.5 by Martin Packman
Document in bzrlib.progress that task messages must be unicode
59
60
    The message given when updating a task must be unicode, not bytes.
61
4580.3.1 by Martin Pool
ProgressTasks can specify an update latency
62
    :ivar update_latency: The interval (in seconds) at which the PB should be
63
        updated.  Setting this to zero suggests every update should be shown
64
        synchronously.
4580.3.5 by Martin Pool
selftest sets ProgressTask.show_transport_activity off
65
66
    :ivar show_transport_activity: If true (default), transport activity
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
67
        will be shown when this task is drawn.  Disable it if you're sure
4580.3.5 by Martin Pool
selftest sets ProgressTask.show_transport_activity off
68
        that only irrelevant or uninteresting transport activity can occur
69
        during this task.
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
70
    """
71
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
72
    def __init__(self, parent_task=None, ui_factory=None, progress_view=None):
4110.2.13 by Martin Pool
doc
73
        """Construct a new progress task.
74
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
75
        :param parent_task: Enclosing ProgressTask or None.
76
77
        :param progress_view: ProgressView to display this ProgressTask.
78
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
79
        :param ui_factory: The UI factory that will display updates;
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
80
            deprecated in favor of passing progress_view directly.
81
4110.2.13 by Martin Pool
doc
82
        Normally you should not call this directly but rather through
83
        `ui_factory.nested_progress_bar`.
84
        """
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
85
        self._parent_task = parent_task
86
        self._last_update = 0
87
        self.total_cnt = None
88
        self.current_cnt = None
89
        self.msg = ''
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
90
        # TODO: deprecate passing ui_factory
3882.8.2 by Martin Pool
ProgressTask holds a reference to the ui that displays it
91
        self.ui_factory = ui_factory
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
92
        self.progress_view = progress_view
3882.8.5 by Martin Pool
Progress tasks can indicate what kind of display is useful
93
        self.show_pct = False
94
        self.show_spinner = True
95
        self.show_eta = False,
96
        self.show_count = True
97
        self.show_bar = True
4580.3.1 by Martin Pool
ProgressTasks can specify an update latency
98
        self.update_latency = 0.1
4580.3.5 by Martin Pool
selftest sets ProgressTask.show_transport_activity off
99
        self.show_transport_activity = True
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
100
3948.2.1 by Martin Pool
Add ProgressTask repr
101
    def __repr__(self):
102
        return '%s(%r/%r, msg=%r)' % (
103
            self.__class__.__name__,
104
            self.current_cnt,
105
            self.total_cnt,
106
            self.msg)
107
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
108
    def update(self, msg, current_cnt=None, total_cnt=None):
6437.57.5 by Martin Packman
Document in bzrlib.progress that task messages must be unicode
109
        """Report updated task message and if relevent progress counters
110
111
        The message given must be unicode, not a byte string.
112
        """
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
113
        self.msg = msg
114
        self.current_cnt = current_cnt
115
        if total_cnt:
116
            self.total_cnt = total_cnt
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
117
        if self.progress_view:
118
            self.progress_view.show_progress(self)
119
        else:
120
            self.ui_factory._progress_updated(self)
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
121
3882.8.8 by Martin Pool
Progress and UI test cleanups
122
    def tick(self):
123
        self.update(self.msg)
124
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
125
    def finished(self):
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
126
        if self.progress_view:
127
            self.progress_view.task_finished(self)
128
        else:
129
            self.ui_factory._progress_finished(self)
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
130
131
    def make_sub_task(self):
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
132
        return ProgressTask(self, ui_factory=self.ui_factory,
7143.15.2 by Jelmer Vernooij
Run autopep8.
133
                            progress_view=self.progress_view)
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
134
135
    def _overall_completion_fraction(self, child_fraction=0.0):
136
        """Return fractional completion of this task and its parents
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
137
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
138
        Returns None if no completion can be computed."""
4017.1.1 by John Arbash Meinel
Get a pb.tick() to work after calling pb.update()
139
        if self.current_cnt is not None and self.total_cnt:
7143.15.2 by Jelmer Vernooij
Run autopep8.
140
            own_fraction = (float(self.current_cnt) +
141
                            child_fraction) / self.total_cnt
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
142
        else:
4110.2.17 by Martin Pool
If one ProgressTask has no count, it passes through that of its child
143
            # if this task has no estimation, it just passes on directly
144
            # whatever the child has measured...
145
            own_fraction = child_fraction
3882.7.7 by Martin Pool
Change progress bars to a more MVC style
146
        if self._parent_task is None:
147
            return own_fraction
148
        else:
149
            if own_fraction is None:
150
                own_fraction = 0.0
151
            return self._parent_task._overall_completion_fraction(own_fraction)
152
153
    def clear(self):
4471.2.1 by Martin Pool
Comment on deprecating ProgressTask.clear
154
        # TODO: deprecate this method; the model object shouldn't be concerned
155
        # with whether it's shown or not.  Most callers use this because they
156
        # want to write some different non-progress output to the screen, but
157
        # they should probably instead use a stream that's synchronized with
158
        # the progress output.  It may be there is a model-level use for
159
        # saying "this task's not active at the moment" but I don't see it. --
160
        # mbp 20090623
4449.3.4 by Martin Pool
ProgressTask now talks to ProgressView; easier to test
161
        if self.progress_view:
162
            self.progress_view.clear()
163
        else:
164
            self.ui_factory.clear_term()
1843.3.7 by John Arbash Meinel
new env var 'BZR_PROGRESS_BAR' to select the exact progress type
165
6861.4.1 by Jelmer Vernooij
Make progress bars context managers.
166
    def __enter__(self):
167
        return self
168
169
    def __exit__(self, exc_type, exc_val, exc_tb):
170
        self.finished()
171
        return False
172
649 by Martin Pool
- some cleanups for the progressbar method
173
4961.2.9 by Martin Pool
Rip out most remaining uses of DummyProgressBar
174
class DummyProgress(object):
1104 by Martin Pool
- Add a simple UIFactory
175
    """Progress-bar standin that does nothing.
176
4961.2.9 by Martin Pool
Rip out most remaining uses of DummyProgressBar
177
    This was previously often constructed by application code if no progress
178
    bar was explicitly passed in.  That's no longer recommended: instead, just
179
    create a progress task from the ui_factory.  This class can be used in
180
    test code that needs to fake a progress task for some reason.
181
    """
3882.8.8 by Martin Pool
Progress and UI test cleanups
182
1104 by Martin Pool
- Add a simple UIFactory
183
    def tick(self):
184
        pass
185
186
    def update(self, msg=None, current=None, total=None):
187
        pass
188
1551.2.27 by Aaron Bentley
Got propogation under test
189
    def child_update(self, message, current, total):
190
        pass
191
1104 by Martin Pool
- Add a simple UIFactory
192
    def clear(self):
193
        pass
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
194
1551.2.29 by Aaron Bentley
Got stack handling under test
195
    def child_progress(self, **kwargs):
196
        return DummyProgress(**kwargs)
1534.5.9 by Robert Collins
Advise users running upgrade on a checkout to also run it on the branch.
197
1681.1.2 by Robert Collins
* bzrlib.ui.text.TextUIFactory now accepts a bar_type parameter which
198
648 by Martin Pool
- import aaron's progress-indicator code
199
def str_tdelta(delt):
200
    if delt is None:
201
        return "-:--:--"
660 by Martin Pool
- use plain unix time, not datetime module
202
    delt = int(round(delt))
7143.15.2 by Jelmer Vernooij
Run autopep8.
203
    return '%d:%02d:%02d' % (delt / 3600,
204
                             (delt / 60) % 60,
660 by Martin Pool
- use plain unix time, not datetime module
205
                             delt % 60)
206
207
7143.15.5 by Jelmer Vernooij
More PEP8 fixes.
208
def get_eta(start_time, current, total, enough_samples=3, last_updates=None,
209
            n_recent=10):
660 by Martin Pool
- use plain unix time, not datetime module
210
    if start_time is None:
211
        return None
212
213
    if not total:
214
        return None
215
216
    if current < enough_samples:
217
        return None
218
219
    if current > total:
220
        return None                     # wtf?
221
2120.1.1 by John Arbash Meinel
Use time.time() because time.clock() is CPU time, not wall time
222
    elapsed = time.time() - start_time
660 by Martin Pool
- use plain unix time, not datetime module
223
224
    if elapsed < 2.0:                   # not enough time to estimate
225
        return None
3943.8.1 by Marius Kruger
remove all trailing whitespace from bzr source
226
660 by Martin Pool
- use plain unix time, not datetime module
227
    total_duration = float(elapsed) * float(total) / float(current)
228
1185.16.75 by Martin Pool
- improved eta estimation for progress bar
229
    if last_updates and len(last_updates) >= n_recent:
230
        avg = sum(last_updates) / float(len(last_updates))
231
        time_left = avg * (total - current)
232
233
        old_time_left = total_duration - elapsed
234
235
        # We could return the average, or some other value here
236
        return (time_left + old_time_left) / 2
237
660 by Martin Pool
- use plain unix time, not datetime module
238
    return total_duration - elapsed
648 by Martin Pool
- import aaron's progress-indicator code
239
649 by Martin Pool
- some cleanups for the progressbar method
240
1551.2.32 by Aaron Bentley
Handle progress phases more nicely in merge
241
class ProgressPhase(object):
242
    """Update progress object with the current phase"""
7143.15.2 by Jelmer Vernooij
Run autopep8.
243
1551.2.32 by Aaron Bentley
Handle progress phases more nicely in merge
244
    def __init__(self, message, total, pb):
245
        object.__init__(self)
246
        self.pb = pb
247
        self.message = message
248
        self.total = total
249
        self.cur_phase = None
250
251
    def next_phase(self):
252
        if self.cur_phase is None:
253
            self.cur_phase = 0
254
        else:
255
            self.cur_phase += 1
256
        self.pb.update(self.message, self.cur_phase, self.total)