Gentoo Archives: gentoo-commits

From: "Zac Medico (zmedico)" <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] portage r13667 - main/trunk/pym/_emerge
Date: Mon, 22 Jun 2009 18:21:59
Message-Id: E1MIo9U-0005H3-RN@stork.gentoo.org
1 Author: zmedico
2 Date: 2009-06-22 18:21:56 +0000 (Mon, 22 Jun 2009)
3 New Revision: 13667
4
5 Added:
6 main/trunk/pym/_emerge/JobStatusDisplay.py
7 main/trunk/pym/_emerge/UninstallFailure.py
8 main/trunk/pym/_emerge/getloadavg.py
9 main/trunk/pym/_emerge/stdout_spinner.py
10 Modified:
11 main/trunk/pym/_emerge/__init__.py
12 Log:
13 Bug #275047 - Split _emerge/__init__.py into smaller pieces (part 2).
14 Thanks to Sebastian Mingramm (few) <s.mingramm@×××.de> for this patch.
15
16
17 Added: main/trunk/pym/_emerge/JobStatusDisplay.py
18 ===================================================================
19 --- main/trunk/pym/_emerge/JobStatusDisplay.py (rev 0)
20 +++ main/trunk/pym/_emerge/JobStatusDisplay.py 2009-06-22 18:21:56 UTC (rev 13667)
21 @@ -0,0 +1,267 @@
22 +import formatter
23 +import os
24 +import sys
25 +import time
26 +
27 +try:
28 + from cStringIO import StringIO
29 +except ImportError:
30 + from StringIO import StringIO
31 +
32 +try:
33 + import portage
34 +except ImportError:
35 + from os import path as osp
36 + sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
37 + import portage
38 +
39 +from portage.output import xtermTitle
40 +
41 +from _emerge.getloadavg import getloadavg
42 +
43 +class JobStatusDisplay(object):
44 +
45 + _bound_properties = ("curval", "failed", "running")
46 + _jobs_column_width = 48
47 +
48 + # Don't update the display unless at least this much
49 + # time has passed, in units of seconds.
50 + _min_display_latency = 2
51 +
52 + _default_term_codes = {
53 + 'cr' : '\r',
54 + 'el' : '\x1b[K',
55 + 'nel' : '\n',
56 + }
57 +
58 + _termcap_name_map = {
59 + 'carriage_return' : 'cr',
60 + 'clr_eol' : 'el',
61 + 'newline' : 'nel',
62 + }
63 +
64 + def __init__(self, out=sys.stdout, quiet=False, xterm_titles=True):
65 + object.__setattr__(self, "out", out)
66 + object.__setattr__(self, "quiet", quiet)
67 + object.__setattr__(self, "xterm_titles", xterm_titles)
68 + object.__setattr__(self, "maxval", 0)
69 + object.__setattr__(self, "merges", 0)
70 + object.__setattr__(self, "_changed", False)
71 + object.__setattr__(self, "_displayed", False)
72 + object.__setattr__(self, "_last_display_time", 0)
73 + object.__setattr__(self, "width", 80)
74 + self.reset()
75 +
76 + isatty = hasattr(out, "isatty") and out.isatty()
77 + object.__setattr__(self, "_isatty", isatty)
78 + if not isatty or not self._init_term():
79 + term_codes = {}
80 + for k, capname in self._termcap_name_map.iteritems():
81 + term_codes[k] = self._default_term_codes[capname]
82 + object.__setattr__(self, "_term_codes", term_codes)
83 + encoding = sys.getdefaultencoding()
84 + for k, v in self._term_codes.items():
85 + if not isinstance(v, basestring):
86 + self._term_codes[k] = v.decode(encoding, 'replace')
87 +
88 + def _init_term(self):
89 + """
90 + Initialize term control codes.
91 + @rtype: bool
92 + @returns: True if term codes were successfully initialized,
93 + False otherwise.
94 + """
95 +
96 + term_type = os.environ.get("TERM", "vt100")
97 + tigetstr = None
98 +
99 + try:
100 + import curses
101 + try:
102 + curses.setupterm(term_type, self.out.fileno())
103 + tigetstr = curses.tigetstr
104 + except curses.error:
105 + pass
106 + except ImportError:
107 + pass
108 +
109 + if tigetstr is None:
110 + return False
111 +
112 + term_codes = {}
113 + for k, capname in self._termcap_name_map.iteritems():
114 + code = tigetstr(capname)
115 + if code is None:
116 + code = self._default_term_codes[capname]
117 + term_codes[k] = code
118 + object.__setattr__(self, "_term_codes", term_codes)
119 + return True
120 +
121 + def _format_msg(self, msg):
122 + return ">>> %s" % msg
123 +
124 + def _erase(self):
125 + self.out.write(
126 + self._term_codes['carriage_return'] + \
127 + self._term_codes['clr_eol'])
128 + self.out.flush()
129 + self._displayed = False
130 +
131 + def _display(self, line):
132 + self.out.write(line)
133 + self.out.flush()
134 + self._displayed = True
135 +
136 + def _update(self, msg):
137 +
138 + out = self.out
139 + if not self._isatty:
140 + out.write(self._format_msg(msg) + self._term_codes['newline'])
141 + self.out.flush()
142 + self._displayed = True
143 + return
144 +
145 + if self._displayed:
146 + self._erase()
147 +
148 + self._display(self._format_msg(msg))
149 +
150 + def displayMessage(self, msg):
151 +
152 + was_displayed = self._displayed
153 +
154 + if self._isatty and self._displayed:
155 + self._erase()
156 +
157 + self.out.write(self._format_msg(msg) + self._term_codes['newline'])
158 + self.out.flush()
159 + self._displayed = False
160 +
161 + if was_displayed:
162 + self._changed = True
163 + self.display()
164 +
165 + def reset(self):
166 + self.maxval = 0
167 + self.merges = 0
168 + for name in self._bound_properties:
169 + object.__setattr__(self, name, 0)
170 +
171 + if self._displayed:
172 + self.out.write(self._term_codes['newline'])
173 + self.out.flush()
174 + self._displayed = False
175 +
176 + def __setattr__(self, name, value):
177 + old_value = getattr(self, name)
178 + if value == old_value:
179 + return
180 + object.__setattr__(self, name, value)
181 + if name in self._bound_properties:
182 + self._property_change(name, old_value, value)
183 +
184 + def _property_change(self, name, old_value, new_value):
185 + self._changed = True
186 + self.display()
187 +
188 + def _load_avg_str(self):
189 + try:
190 + avg = getloadavg()
191 + except OSError:
192 + return 'unknown'
193 +
194 + max_avg = max(avg)
195 +
196 + if max_avg < 10:
197 + digits = 2
198 + elif max_avg < 100:
199 + digits = 1
200 + else:
201 + digits = 0
202 +
203 + return ", ".join(("%%.%df" % digits ) % x for x in avg)
204 +
205 + def display(self):
206 + """
207 + Display status on stdout, but only if something has
208 + changed since the last call.
209 + """
210 +
211 + if self.quiet:
212 + return
213 +
214 + current_time = time.time()
215 + time_delta = current_time - self._last_display_time
216 + if self._displayed and \
217 + not self._changed:
218 + if not self._isatty:
219 + return
220 + if time_delta < self._min_display_latency:
221 + return
222 +
223 + self._last_display_time = current_time
224 + self._changed = False
225 + self._display_status()
226 +
227 + def _display_status(self):
228 + # Don't use len(self._completed_tasks) here since that also
229 + # can include uninstall tasks.
230 + curval_str = str(self.curval)
231 + maxval_str = str(self.maxval)
232 + running_str = str(self.running)
233 + failed_str = str(self.failed)
234 + load_avg_str = self._load_avg_str()
235 +
236 + color_output = StringIO()
237 + plain_output = StringIO()
238 + style_file = portage.output.ConsoleStyleFile(color_output)
239 + style_file.write_listener = plain_output
240 + style_writer = portage.output.StyleWriter(file=style_file, maxcol=9999)
241 + style_writer.style_listener = style_file.new_styles
242 + f = formatter.AbstractFormatter(style_writer)
243 +
244 + number_style = "INFORM"
245 + f.add_literal_data("Jobs: ")
246 + f.push_style(number_style)
247 + f.add_literal_data(curval_str)
248 + f.pop_style()
249 + f.add_literal_data(" of ")
250 + f.push_style(number_style)
251 + f.add_literal_data(maxval_str)
252 + f.pop_style()
253 + f.add_literal_data(" complete")
254 +
255 + if self.running:
256 + f.add_literal_data(", ")
257 + f.push_style(number_style)
258 + f.add_literal_data(running_str)
259 + f.pop_style()
260 + f.add_literal_data(" running")
261 +
262 + if self.failed:
263 + f.add_literal_data(", ")
264 + f.push_style(number_style)
265 + f.add_literal_data(failed_str)
266 + f.pop_style()
267 + f.add_literal_data(" failed")
268 +
269 + padding = self._jobs_column_width - len(plain_output.getvalue())
270 + if padding > 0:
271 + f.add_literal_data(padding * " ")
272 +
273 + f.add_literal_data("Load avg: ")
274 + f.add_literal_data(load_avg_str)
275 +
276 + # Truncate to fit width, to avoid making the terminal scroll if the
277 + # line overflows (happens when the load average is large).
278 + plain_output = plain_output.getvalue()
279 + if self._isatty and len(plain_output) > self.width:
280 + # Use plain_output here since it's easier to truncate
281 + # properly than the color output which contains console
282 + # color codes.
283 + self._update(plain_output[:self.width])
284 + else:
285 + self._update(color_output.getvalue())
286 +
287 + if self.xterm_titles:
288 + xtermTitle(" ".join(plain_output.split()))
289
290
291 Property changes on: main/trunk/pym/_emerge/JobStatusDisplay.py
292 ___________________________________________________________________
293 Name: svn:keywords
294 + Id
295
296 Added: main/trunk/pym/_emerge/UninstallFailure.py
297 ===================================================================
298 --- main/trunk/pym/_emerge/UninstallFailure.py (rev 0)
299 +++ main/trunk/pym/_emerge/UninstallFailure.py 2009-06-22 18:21:56 UTC (rev 13667)
300 @@ -0,0 +1,18 @@
301 +try:
302 + import portage
303 +except ImportError:
304 + from os import path as osp
305 + import sys
306 + sys.path.insert(0, osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym"))
307 + import portage
308 +
309 +class UninstallFailure(portage.exception.PortageException):
310 + """
311 + An instance of this class is raised by unmerge() when
312 + an uninstallation fails.
313 + """
314 + status = 1
315 + def __init__(self, *pargs):
316 + portage.exception.PortageException.__init__(self, pargs)
317 + if pargs:
318 + self.status = pargs[0]
319
320
321 Property changes on: main/trunk/pym/_emerge/UninstallFailure.py
322 ___________________________________________________________________
323 Name: svn:keywords
324 + Id
325
326 Modified: main/trunk/pym/_emerge/__init__.py
327 ===================================================================
328 --- main/trunk/pym/_emerge/__init__.py 2009-06-22 18:12:37 UTC (rev 13666)
329 +++ main/trunk/pym/_emerge/__init__.py 2009-06-22 18:21:56 UTC (rev 13667)
330 @@ -83,87 +83,11 @@
331 from _emerge.PollSelectAdapter import PollSelectAdapter
332 from _emerge.SequentialTaskQueue import SequentialTaskQueue
333 from _emerge.ProgressHandler import ProgressHandler
334 +from _emerge.stdout_spinner import stdout_spinner
335 +from _emerge.UninstallFailure import UninstallFailure
336 +from _emerge.JobStatusDisplay import JobStatusDisplay
337 +from _emerge.getloadavg import getloadavg
338
339 -try:
340 - from cStringIO import StringIO
341 -except ImportError:
342 - from StringIO import StringIO
343 -
344 -class stdout_spinner(object):
345 - scroll_msgs = [
346 - "Gentoo Rocks ("+platform.system()+")",
347 - "Thank you for using Gentoo. :)",
348 - "Are you actually trying to read this?",
349 - "How many times have you stared at this?",
350 - "We are generating the cache right now",
351 - "You are paying too much attention.",
352 - "A theory is better than its explanation.",
353 - "Phasers locked on target, Captain.",
354 - "Thrashing is just virtual crashing.",
355 - "To be is to program.",
356 - "Real Users hate Real Programmers.",
357 - "When all else fails, read the instructions.",
358 - "Functionality breeds Contempt.",
359 - "The future lies ahead.",
360 - "3.1415926535897932384626433832795028841971694",
361 - "Sometimes insanity is the only alternative.",
362 - "Inaccuracy saves a world of explanation.",
363 - ]
364 -
365 - twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
366 -
367 - def __init__(self):
368 - self.spinpos = 0
369 - self.update = self.update_twirl
370 - self.scroll_sequence = self.scroll_msgs[
371 - int(time.time() * 100) % len(self.scroll_msgs)]
372 - self.last_update = 0
373 - self.min_display_latency = 0.05
374 -
375 - def _return_early(self):
376 - """
377 - Flushing ouput to the tty too frequently wastes cpu time. Therefore,
378 - each update* method should return without doing any output when this
379 - method returns True.
380 - """
381 - cur_time = time.time()
382 - if cur_time - self.last_update < self.min_display_latency:
383 - return True
384 - self.last_update = cur_time
385 - return False
386 -
387 - def update_basic(self):
388 - self.spinpos = (self.spinpos + 1) % 500
389 - if self._return_early():
390 - return
391 - if (self.spinpos % 100) == 0:
392 - if self.spinpos == 0:
393 - sys.stdout.write(". ")
394 - else:
395 - sys.stdout.write(".")
396 - sys.stdout.flush()
397 -
398 - def update_scroll(self):
399 - if self._return_early():
400 - return
401 - if(self.spinpos >= len(self.scroll_sequence)):
402 - sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
403 - len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
404 - else:
405 - sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
406 - sys.stdout.flush()
407 - self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
408 -
409 - def update_twirl(self):
410 - self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
411 - if self._return_early():
412 - return
413 - sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
414 - sys.stdout.flush()
415 -
416 - def update_quiet(self):
417 - return
418 -
419 def userquery(prompt, responses=None, colours=None):
420 """Displays a prompt and a set of responses, then waits for a response
421 which is checked against the responses and the first to match is
422 @@ -6569,29 +6493,6 @@
423 return select.poll()
424 return PollSelectAdapter()
425
426 -getloadavg = getattr(os, "getloadavg", None)
427 -if getloadavg is None:
428 - def getloadavg():
429 - """
430 - Uses /proc/loadavg to emulate os.getloadavg().
431 - Raises OSError if the load average was unobtainable.
432 - """
433 - try:
434 - loadavg_str = open('/proc/loadavg').readline()
435 - except IOError:
436 - # getloadavg() is only supposed to raise OSError, so convert
437 - raise OSError('unknown')
438 - loadavg_split = loadavg_str.split()
439 - if len(loadavg_split) < 3:
440 - raise OSError('unknown')
441 - loadavg_floats = []
442 - for i in xrange(3):
443 - try:
444 - loadavg_floats.append(float(loadavg_split[i]))
445 - except ValueError:
446 - raise OSError('unknown')
447 - return tuple(loadavg_floats)
448 -
449 class PollScheduler(object):
450
451 class _sched_iface_class(SlotObject):
452 @@ -6879,253 +6780,6 @@
453 def add(self, task):
454 self._queue.add(task)
455
456 -class JobStatusDisplay(object):
457 -
458 - _bound_properties = ("curval", "failed", "running")
459 - _jobs_column_width = 48
460 -
461 - # Don't update the display unless at least this much
462 - # time has passed, in units of seconds.
463 - _min_display_latency = 2
464 -
465 - _default_term_codes = {
466 - 'cr' : '\r',
467 - 'el' : '\x1b[K',
468 - 'nel' : '\n',
469 - }
470 -
471 - _termcap_name_map = {
472 - 'carriage_return' : 'cr',
473 - 'clr_eol' : 'el',
474 - 'newline' : 'nel',
475 - }
476 -
477 - def __init__(self, out=sys.stdout, quiet=False, xterm_titles=True):
478 - object.__setattr__(self, "out", out)
479 - object.__setattr__(self, "quiet", quiet)
480 - object.__setattr__(self, "xterm_titles", xterm_titles)
481 - object.__setattr__(self, "maxval", 0)
482 - object.__setattr__(self, "merges", 0)
483 - object.__setattr__(self, "_changed", False)
484 - object.__setattr__(self, "_displayed", False)
485 - object.__setattr__(self, "_last_display_time", 0)
486 - object.__setattr__(self, "width", 80)
487 - self.reset()
488 -
489 - isatty = hasattr(out, "isatty") and out.isatty()
490 - object.__setattr__(self, "_isatty", isatty)
491 - if not isatty or not self._init_term():
492 - term_codes = {}
493 - for k, capname in self._termcap_name_map.iteritems():
494 - term_codes[k] = self._default_term_codes[capname]
495 - object.__setattr__(self, "_term_codes", term_codes)
496 - encoding = sys.getdefaultencoding()
497 - for k, v in self._term_codes.items():
498 - if not isinstance(v, basestring):
499 - self._term_codes[k] = v.decode(encoding, 'replace')
500 -
501 - def _init_term(self):
502 - """
503 - Initialize term control codes.
504 - @rtype: bool
505 - @returns: True if term codes were successfully initialized,
506 - False otherwise.
507 - """
508 -
509 - term_type = os.environ.get("TERM", "vt100")
510 - tigetstr = None
511 -
512 - try:
513 - import curses
514 - try:
515 - curses.setupterm(term_type, self.out.fileno())
516 - tigetstr = curses.tigetstr
517 - except curses.error:
518 - pass
519 - except ImportError:
520 - pass
521 -
522 - if tigetstr is None:
523 - return False
524 -
525 - term_codes = {}
526 - for k, capname in self._termcap_name_map.iteritems():
527 - code = tigetstr(capname)
528 - if code is None:
529 - code = self._default_term_codes[capname]
530 - term_codes[k] = code
531 - object.__setattr__(self, "_term_codes", term_codes)
532 - return True
533 -
534 - def _format_msg(self, msg):
535 - return ">>> %s" % msg
536 -
537 - def _erase(self):
538 - self.out.write(
539 - self._term_codes['carriage_return'] + \
540 - self._term_codes['clr_eol'])
541 - self.out.flush()
542 - self._displayed = False
543 -
544 - def _display(self, line):
545 - self.out.write(line)
546 - self.out.flush()
547 - self._displayed = True
548 -
549 - def _update(self, msg):
550 -
551 - out = self.out
552 - if not self._isatty:
553 - out.write(self._format_msg(msg) + self._term_codes['newline'])
554 - self.out.flush()
555 - self._displayed = True
556 - return
557 -
558 - if self._displayed:
559 - self._erase()
560 -
561 - self._display(self._format_msg(msg))
562 -
563 - def displayMessage(self, msg):
564 -
565 - was_displayed = self._displayed
566 -
567 - if self._isatty and self._displayed:
568 - self._erase()
569 -
570 - self.out.write(self._format_msg(msg) + self._term_codes['newline'])
571 - self.out.flush()
572 - self._displayed = False
573 -
574 - if was_displayed:
575 - self._changed = True
576 - self.display()
577 -
578 - def reset(self):
579 - self.maxval = 0
580 - self.merges = 0
581 - for name in self._bound_properties:
582 - object.__setattr__(self, name, 0)
583 -
584 - if self._displayed:
585 - self.out.write(self._term_codes['newline'])
586 - self.out.flush()
587 - self._displayed = False
588 -
589 - def __setattr__(self, name, value):
590 - old_value = getattr(self, name)
591 - if value == old_value:
592 - return
593 - object.__setattr__(self, name, value)
594 - if name in self._bound_properties:
595 - self._property_change(name, old_value, value)
596 -
597 - def _property_change(self, name, old_value, new_value):
598 - self._changed = True
599 - self.display()
600 -
601 - def _load_avg_str(self):
602 - try:
603 - avg = getloadavg()
604 - except OSError:
605 - return 'unknown'
606 -
607 - max_avg = max(avg)
608 -
609 - if max_avg < 10:
610 - digits = 2
611 - elif max_avg < 100:
612 - digits = 1
613 - else:
614 - digits = 0
615 -
616 - return ", ".join(("%%.%df" % digits ) % x for x in avg)
617 -
618 - def display(self):
619 - """
620 - Display status on stdout, but only if something has
621 - changed since the last call.
622 - """
623 -
624 - if self.quiet:
625 - return
626 -
627 - current_time = time.time()
628 - time_delta = current_time - self._last_display_time
629 - if self._displayed and \
630 - not self._changed:
631 - if not self._isatty:
632 - return
633 - if time_delta < self._min_display_latency:
634 - return
635 -
636 - self._last_display_time = current_time
637 - self._changed = False
638 - self._display_status()
639 -
640 - def _display_status(self):
641 - # Don't use len(self._completed_tasks) here since that also
642 - # can include uninstall tasks.
643 - curval_str = str(self.curval)
644 - maxval_str = str(self.maxval)
645 - running_str = str(self.running)
646 - failed_str = str(self.failed)
647 - load_avg_str = self._load_avg_str()
648 -
649 - color_output = StringIO()
650 - plain_output = StringIO()
651 - style_file = portage.output.ConsoleStyleFile(color_output)
652 - style_file.write_listener = plain_output
653 - style_writer = portage.output.StyleWriter(file=style_file, maxcol=9999)
654 - style_writer.style_listener = style_file.new_styles
655 - f = formatter.AbstractFormatter(style_writer)
656 -
657 - number_style = "INFORM"
658 - f.add_literal_data("Jobs: ")
659 - f.push_style(number_style)
660 - f.add_literal_data(curval_str)
661 - f.pop_style()
662 - f.add_literal_data(" of ")
663 - f.push_style(number_style)
664 - f.add_literal_data(maxval_str)
665 - f.pop_style()
666 - f.add_literal_data(" complete")
667 -
668 - if self.running:
669 - f.add_literal_data(", ")
670 - f.push_style(number_style)
671 - f.add_literal_data(running_str)
672 - f.pop_style()
673 - f.add_literal_data(" running")
674 -
675 - if self.failed:
676 - f.add_literal_data(", ")
677 - f.push_style(number_style)
678 - f.add_literal_data(failed_str)
679 - f.pop_style()
680 - f.add_literal_data(" failed")
681 -
682 - padding = self._jobs_column_width - len(plain_output.getvalue())
683 - if padding > 0:
684 - f.add_literal_data(padding * " ")
685 -
686 - f.add_literal_data("Load avg: ")
687 - f.add_literal_data(load_avg_str)
688 -
689 - # Truncate to fit width, to avoid making the terminal scroll if the
690 - # line overflows (happens when the load average is large).
691 - plain_output = plain_output.getvalue()
692 - if self._isatty and len(plain_output) > self.width:
693 - # Use plain_output here since it's easier to truncate
694 - # properly than the color output which contains console
695 - # color codes.
696 - self._update(plain_output[:self.width])
697 - else:
698 - self._update(color_output.getvalue())
699 -
700 - if self.xterm_titles:
701 - xtermTitle(" ".join(plain_output.split()))
702 -
703 class Scheduler(PollScheduler):
704
705 _opts_ignore_blockers = \
706 @@ -8875,17 +8529,6 @@
707
708 self._schedule()
709
710 -class UninstallFailure(portage.exception.PortageException):
711 - """
712 - An instance of this class is raised by unmerge() when
713 - an uninstallation fails.
714 - """
715 - status = 1
716 - def __init__(self, *pargs):
717 - portage.exception.PortageException.__init__(self, pargs)
718 - if pargs:
719 - self.status = pargs[0]
720 -
721 def unmerge(root_config, myopts, unmerge_action,
722 unmerge_files, ldpath_mtimes, autoclean=0,
723 clean_world=1, clean_delay=1, ordered=0, raise_on_error=0,
724
725 Added: main/trunk/pym/_emerge/getloadavg.py
726 ===================================================================
727 --- main/trunk/pym/_emerge/getloadavg.py (rev 0)
728 +++ main/trunk/pym/_emerge/getloadavg.py 2009-06-22 18:21:56 UTC (rev 13667)
729 @@ -0,0 +1,24 @@
730 +import os
731 +
732 +getloadavg = getattr(os, "getloadavg", None)
733 +if getloadavg is None:
734 + def getloadavg():
735 + """
736 + Uses /proc/loadavg to emulate os.getloadavg().
737 + Raises OSError if the load average was unobtainable.
738 + """
739 + try:
740 + loadavg_str = open('/proc/loadavg').readline()
741 + except IOError:
742 + # getloadavg() is only supposed to raise OSError, so convert
743 + raise OSError('unknown')
744 + loadavg_split = loadavg_str.split()
745 + if len(loadavg_split) < 3:
746 + raise OSError('unknown')
747 + loadavg_floats = []
748 + for i in xrange(3):
749 + try:
750 + loadavg_floats.append(float(loadavg_split[i]))
751 + except ValueError:
752 + raise OSError('unknown')
753 + return tuple(loadavg_floats)
754
755
756 Property changes on: main/trunk/pym/_emerge/getloadavg.py
757 ___________________________________________________________________
758 Name: svn:keywords
759 + Id
760
761 Added: main/trunk/pym/_emerge/stdout_spinner.py
762 ===================================================================
763 --- main/trunk/pym/_emerge/stdout_spinner.py (rev 0)
764 +++ main/trunk/pym/_emerge/stdout_spinner.py 2009-06-22 18:21:56 UTC (rev 13667)
765 @@ -0,0 +1,80 @@
766 +import platform
767 +import sys
768 +import time
769 +
770 +from portage.output import darkgreen, green
771 +
772 +class stdout_spinner(object):
773 + scroll_msgs = [
774 + "Gentoo Rocks ("+platform.system()+")",
775 + "Thank you for using Gentoo. :)",
776 + "Are you actually trying to read this?",
777 + "How many times have you stared at this?",
778 + "We are generating the cache right now",
779 + "You are paying too much attention.",
780 + "A theory is better than its explanation.",
781 + "Phasers locked on target, Captain.",
782 + "Thrashing is just virtual crashing.",
783 + "To be is to program.",
784 + "Real Users hate Real Programmers.",
785 + "When all else fails, read the instructions.",
786 + "Functionality breeds Contempt.",
787 + "The future lies ahead.",
788 + "3.1415926535897932384626433832795028841971694",
789 + "Sometimes insanity is the only alternative.",
790 + "Inaccuracy saves a world of explanation.",
791 + ]
792 +
793 + twirl_sequence = "/-\\|/-\\|/-\\|/-\\|\\-/|\\-/|\\-/|\\-/|"
794 +
795 + def __init__(self):
796 + self.spinpos = 0
797 + self.update = self.update_twirl
798 + self.scroll_sequence = self.scroll_msgs[
799 + int(time.time() * 100) % len(self.scroll_msgs)]
800 + self.last_update = 0
801 + self.min_display_latency = 0.05
802 +
803 + def _return_early(self):
804 + """
805 + Flushing ouput to the tty too frequently wastes cpu time. Therefore,
806 + each update* method should return without doing any output when this
807 + method returns True.
808 + """
809 + cur_time = time.time()
810 + if cur_time - self.last_update < self.min_display_latency:
811 + return True
812 + self.last_update = cur_time
813 + return False
814 +
815 + def update_basic(self):
816 + self.spinpos = (self.spinpos + 1) % 500
817 + if self._return_early():
818 + return
819 + if (self.spinpos % 100) == 0:
820 + if self.spinpos == 0:
821 + sys.stdout.write(". ")
822 + else:
823 + sys.stdout.write(".")
824 + sys.stdout.flush()
825 +
826 + def update_scroll(self):
827 + if self._return_early():
828 + return
829 + if(self.spinpos >= len(self.scroll_sequence)):
830 + sys.stdout.write(darkgreen(" \b\b\b" + self.scroll_sequence[
831 + len(self.scroll_sequence) - 1 - (self.spinpos % len(self.scroll_sequence))]))
832 + else:
833 + sys.stdout.write(green("\b " + self.scroll_sequence[self.spinpos]))
834 + sys.stdout.flush()
835 + self.spinpos = (self.spinpos + 1) % (2 * len(self.scroll_sequence))
836 +
837 + def update_twirl(self):
838 + self.spinpos = (self.spinpos + 1) % len(self.twirl_sequence)
839 + if self._return_early():
840 + return
841 + sys.stdout.write("\b\b " + self.twirl_sequence[self.spinpos])
842 + sys.stdout.flush()
843 +
844 + def update_quiet(self):
845 + return
846
847
848 Property changes on: main/trunk/pym/_emerge/stdout_spinner.py
849 ___________________________________________________________________
850 Name: svn:keywords
851 + Id