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