File: UI.py

package info (click to toggle)
atheist 0.20110402-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 1,348 kB
  • sloc: python: 4,764; xml: 626; makefile: 113; cpp: 54; ansic: 5; sh: 5
file content (151 lines) | stat: -rw-r--r-- 3,864 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# -*- mode: python; coding: utf-8 -*-

"""
Command line User Interface utilities

.. moduleauthor:: Arco Research Group
"""

import sys, os, string
import time
import logging
import locale

from pyarco.Conio import *
from pyarco.Pattern import Singleton

Log = logging.getLogger('pyarco.UI')

class ProgressBar:
    def __init__(self, max_val=100, width=80, label='', disable=False):
        self.max = max_val     # total item amount
        self.label = label       # prefix for the bar
        self.width = min(100, width - 37)  # bar width

        disable = disable or max_val<4
        if disable:
            self.__disable()

        self.alfa = 0.2
        self.logger = None

        self.clean_len = 0
        self.reset()

    def reset(self):
        self.val = 0
        self.blk = 0
        self.pct = 0

        self.tinit = time.time()
        self.tlast = self.tinit
        self.eta = '~'
        self.lasteta = 0
#        self.inc()

    def __disable(self):
        self._render = lambda x:None
        self.clean = lambda:None
        self.inc =  lambda:None
        self.abort = lambda:None


    def inc(self, val=1, cad=''):
        self.val += val
        if self.val > self.max:
            self.reset()

        self.blk = self.val * self.width / self.max
        self.pct = self.val * 100 / self.max
        current = time.time()
        if self.val > 3 and (current - self.lasteta > 1):
            per_item = (1-self.alfa) * ((current - self.tinit) / self.val) \
                + self.alfa * (current-self.tlast)
            remain = self.max  - self.val
            self.eta = 1 + int(1.1 * remain * per_item)
            self.lasteta = current
        self._render(cad)
        self.tlast = current


    def _render(self, ustr):
        cad = ':%4s [ %s' % (self.label[:4], self.blk * '#')
        cad += (self.width - self.blk) * '-'
        cad += " ] {0:{1}}/{2} ({3:0>3}%) {4:>3}s:{5:>3}s {6}\r".format(
            self.val,
            len(str(self.max)),
            self.max,
            self.pct,
            int(time.time() - self.tinit),
            self.eta,
            ellipsis(unicode(ustr)))

        self.clean_len = max(self.clean_len, len(cad))
        sys.__stdout__.write(cad)
        sys.__stdout__.flush()


    def clean(self):
        "clean the whole bar from screen"
#        clean_line = "%s%s\r" % (' ' * self.clean_len, '&')
        clean_line = "%s\r" % (' ' * self.clean_len)
        sys.__stdout__.write(clean_line)
        sys.__stdout__.flush()


    def listen_logger(self, logger, level):
        '''
        Register a monitor handler in the given logger.
        If it is invoqued, progress bar is aborted.
        '''
        class DummyHandler(logging.Handler):
            def __init__(self, pb, level):
                self._pb = pb
                self.level = level

            def handle(self, *args):
                self._pb.abort()

        if self.logger is None:
            self.logger = logger
            logger.addHandler(DummyHandler(self, level))


    def abort(self):
        print "progress-bar canceled by logging events."
        self.__disable()


def ellipsis(text, width=None, just=False, char=u'…'):
    """
    >>> ellipsis("this is a sentence", width=10, char='_')
    u'this is a_'
    >>> ellipsis("this is a ", width=12, just=True, char='_')
    u'this is a   '
    """

    if not text:
        text = u''

    if not isinstance(text, unicode):
        text = unicode(text, encoding='utf-8', errors='replace')

    cad = text.strip()
    retval = cad.split('\n')[0]

    if width is not None:
        width = int(width)
        retval = retval[:width-1]

    if retval != cad:
        retval += char

    if just and width is not None:
        retval = retval.ljust(width)

    return retval


def cls():
    sys.stdout.write(CLS)
    sys.stdout.flush()