##// END OF EJS Templates
progress: remove useless statement left by bab267e7fc1a
Patrick Mezard -
r14247:c9720ada default
parent child Browse files
Show More
@@ -1,274 +1,273 b''
1 1 # progress.py show progress bars for some actions
2 2 #
3 3 # Copyright (C) 2010 Augie Fackler <durin42@gmail.com>
4 4 #
5 5 # This program is free software; you can redistribute it and/or modify it
6 6 # under the terms of the GNU General Public License as published by the
7 7 # Free Software Foundation; either version 2 of the License, or (at your
8 8 # option) any later version.
9 9 #
10 10 # This program is distributed in the hope that it will be useful, but
11 11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 13 # Public License for more details.
14 14 #
15 15 # You should have received a copy of the GNU General Public License along
16 16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 18
19 19 """show progress bars for some actions
20 20
21 21 This extension uses the progress information logged by hg commands
22 22 to draw progress bars that are as informative as possible. Some progress
23 23 bars only offer indeterminate information, while others have a definite
24 24 end point.
25 25
26 26 The following settings are available::
27 27
28 28 [progress]
29 29 delay = 3 # number of seconds (float) before showing the progress bar
30 30 refresh = 0.1 # time in seconds between refreshes of the progress bar
31 31 format = topic bar number estimate # format of the progress bar
32 32 width = <none> # if set, the maximum width of the progress information
33 33 # (that is, min(width, term width) will be used)
34 34 clear-complete = True # clear the progress bar after it's done
35 35 disable = False # if true, don't show a progress bar
36 36 assume-tty = False # if true, ALWAYS show a progress bar, unless
37 37 # disable is given
38 38
39 39 Valid entries for the format field are topic, bar, number, unit,
40 40 estimate, and item. item defaults to the last 20 characters of the
41 41 item, but this can be changed by adding either ``-<num>`` which would
42 42 take the last num characters, or ``+<num>`` for the first num
43 43 characters.
44 44 """
45 45
46 46 import sys
47 47 import time
48 48
49 49 from mercurial.i18n import _
50 50
51 51 def spacejoin(*args):
52 52 return ' '.join(s for s in args if s)
53 53
54 54 def shouldprint(ui):
55 55 return (getattr(sys.stderr, 'isatty', None) and
56 56 (sys.stderr.isatty() or ui.configbool('progress', 'assume-tty')))
57 57
58 58 def fmtremaining(seconds):
59 59 if seconds < 60:
60 60 # i18n: format XX seconds as "XXs"
61 61 return _("%02ds") % (seconds)
62 62 minutes = seconds // 60
63 63 if minutes < 60:
64 64 seconds -= minutes * 60
65 65 # i18n: format X minutes and YY seconds as "XmYYs"
66 66 return _("%dm%02ds") % (minutes, seconds)
67 67 # we're going to ignore seconds in this case
68 68 minutes += 1
69 69 hours = minutes // 60
70 70 minutes -= hours * 60
71 71 if hours < 30:
72 72 # i18n: format X hours and YY minutes as "XhYYm"
73 73 return _("%dh%02dm") % (hours, minutes)
74 74 # we're going to ignore minutes in this case
75 75 hours += 1
76 76 days = hours // 24
77 77 hours -= days * 24
78 78 if days < 15:
79 79 # i18n: format X days and YY hours as "XdYYh"
80 80 return _("%dd%02dh") % (days, hours)
81 81 # we're going to ignore hours in this case
82 82 days += 1
83 83 weeks = days // 7
84 84 days -= weeks * 7
85 85 if weeks < 55:
86 86 # i18n: format X weeks and YY days as "XwYYd"
87 87 return _("%dw%02dd") % (weeks, days)
88 88 # we're going to ignore days and treat a year as 52 weeks
89 89 weeks += 1
90 90 years = weeks // 52
91 91 weeks -= years * 52
92 92 # i18n: format X years and YY weeks as "XyYYw"
93 93 return _("%dy%02dw") % (years, weeks)
94 94
95 95 class progbar(object):
96 96 def __init__(self, ui):
97 97 self.ui = ui
98 98 self.resetstate()
99 99
100 100 def resetstate(self):
101 101 self.topics = []
102 102 self.topicstates = {}
103 103 self.starttimes = {}
104 104 self.startvals = {}
105 105 self.printed = False
106 106 self.lastprint = time.time() + float(self.ui.config(
107 107 'progress', 'delay', default=3))
108 108 self.indetcount = 0
109 109 self.refresh = float(self.ui.config(
110 110 'progress', 'refresh', default=0.1))
111 111 self.order = self.ui.configlist(
112 112 'progress', 'format',
113 113 default=['topic', 'bar', 'number', 'estimate'])
114 114
115 115 def show(self, now, topic, pos, item, unit, total):
116 116 if not shouldprint(self.ui):
117 117 return
118 118 termwidth = self.width()
119 119 self.printed = True
120 120 head = ''
121 121 needprogress = False
122 122 tail = ''
123 123 for indicator in self.order:
124 124 add = ''
125 125 if indicator == 'topic':
126 126 add = topic
127 127 elif indicator == 'number':
128 128 if total:
129 129 add = ('% ' + str(len(str(total))) +
130 130 's/%s') % (pos, total)
131 131 else:
132 132 add = str(pos)
133 133 elif indicator.startswith('item') and item:
134 134 slice = 'end'
135 135 if '-' in indicator:
136 136 wid = int(indicator.split('-')[1])
137 137 elif '+' in indicator:
138 138 slice = 'beginning'
139 139 wid = int(indicator.split('+')[1])
140 140 else:
141 141 wid = 20
142 142 if slice == 'end':
143 143 add = item[-wid:]
144 144 else:
145 145 add = item[:wid]
146 146 add += (wid - len(add)) * ' '
147 147 elif indicator == 'bar':
148 148 add = ''
149 149 needprogress = True
150 150 elif indicator == 'unit' and unit:
151 151 add = unit
152 152 elif indicator == 'estimate':
153 153 add = self.estimate(topic, pos, total, now)
154 154 if not needprogress:
155 155 head = spacejoin(head, add)
156 156 else:
157 157 tail = spacejoin(tail, add)
158 158 if needprogress:
159 159 used = 0
160 160 if head:
161 161 used += len(head) + 1
162 162 if tail:
163 163 used += len(tail) + 1
164 164 progwidth = termwidth - used - 3
165 165 if total and pos <= total:
166 166 amt = pos * progwidth // total
167 167 bar = '=' * (amt - 1)
168 168 if amt > 0:
169 169 bar += '>'
170 170 bar += ' ' * (progwidth - amt)
171 171 else:
172 172 progwidth -= 3
173 173 self.indetcount += 1
174 174 # mod the count by twice the width so we can make the
175 175 # cursor bounce between the right and left sides
176 176 amt = self.indetcount % (2 * progwidth)
177 177 amt -= progwidth
178 178 bar = (' ' * int(progwidth - abs(amt)) + '<=>' +
179 179 ' ' * int(abs(amt)))
180 180 prog = ''.join(('[', bar , ']'))
181 181 out = spacejoin(head, prog, tail)
182 182 else:
183 183 out = spacejoin(head, tail)
184 184 sys.stderr.write('\r' + out[:termwidth])
185 185 sys.stderr.flush()
186 186
187 187 def clear(self):
188 188 if not shouldprint(self.ui):
189 189 return
190 190 sys.stderr.write('\r%s\r' % (' ' * self.width()))
191 191
192 192 def complete(self):
193 193 if not shouldprint(self.ui):
194 194 return
195 195 if self.ui.configbool('progress', 'clear-complete', default=True):
196 196 self.clear()
197 197 else:
198 198 sys.stderr.write('\n')
199 199 sys.stderr.flush()
200 200
201 201 def width(self):
202 202 tw = self.ui.termwidth()
203 203 return min(int(self.ui.config('progress', 'width', default=tw)), tw)
204 204
205 205 def estimate(self, topic, pos, total, now):
206 206 if total is None:
207 207 return ''
208 208 initialpos = self.startvals[topic]
209 209 target = total - initialpos
210 210 delta = pos - initialpos
211 211 if delta > 0:
212 212 elapsed = now - self.starttimes[topic]
213 213 if elapsed > float(
214 214 self.ui.config('progress', 'estimate', default=2)):
215 215 seconds = (elapsed * (target - delta)) // delta + 1
216 216 return fmtremaining(seconds)
217 217 return ''
218 218
219 219 def progress(self, topic, pos, item='', unit='', total=None):
220 220 now = time.time()
221 221 if pos is None:
222 222 self.starttimes.pop(topic, None)
223 223 self.startvals.pop(topic, None)
224 224 self.topicstates.pop(topic, None)
225 225 # reset the progress bar if this is the outermost topic
226 226 if self.topics and self.topics[0] == topic and self.printed:
227 227 self.complete()
228 228 self.resetstate()
229 229 # truncate the list of topics assuming all topics within
230 230 # this one are also closed
231 231 if topic in self.topics:
232 232 self.topics = self.topics[:self.topics.index(topic)]
233 233 else:
234 234 if topic not in self.topics:
235 235 self.starttimes[topic] = now
236 236 self.startvals[topic] = pos
237 237 self.topics.append(topic)
238 238 self.topicstates[topic] = pos, item, unit, total
239 239 if now - self.lastprint >= self.refresh and self.topics:
240 240 self.lastprint = now
241 self.topics[-1]
242 241 self.show(now, topic, *self.topicstates[topic])
243 242
244 243 def uisetup(ui):
245 244 class progressui(ui.__class__):
246 245 _progbar = None
247 246
248 247 def progress(self, *args, **opts):
249 248 self._progbar.progress(*args, **opts)
250 249 return super(progressui, self).progress(*args, **opts)
251 250
252 251 def write(self, *args, **opts):
253 252 if self._progbar.printed:
254 253 self._progbar.clear()
255 254 return super(progressui, self).write(*args, **opts)
256 255
257 256 def write_err(self, *args, **opts):
258 257 if self._progbar.printed:
259 258 self._progbar.clear()
260 259 return super(progressui, self).write_err(*args, **opts)
261 260
262 261 # Apps that derive a class from ui.ui() can use
263 262 # setconfig('progress', 'disable', 'True') to disable this extension
264 263 if ui.configbool('progress', 'disable'):
265 264 return
266 265 if shouldprint(ui) and not ui.debugflag and not ui.quiet:
267 266 ui.__class__ = progressui
268 267 # we instantiate one globally shared progress bar to avoid
269 268 # competing progress bars when multiple UI objects get created
270 269 if not progressui._progbar:
271 270 progressui._progbar = progbar(ui)
272 271
273 272 def reposetup(ui, repo):
274 273 uisetup(repo.ui)
General Comments 0
You need to be logged in to leave comments. Login now