1# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
2#
3# Copyright (C) 2006 Red Hat
4# see file 'COPYING' for use and warranty information
5#
6# This program is free software; you can redistribute it and/or
7# modify it under the terms of the GNU General Public License as
8# published by the Free Software Foundation; version 2 only
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19import locale
20import sys
21
22
23PY3 = sys.version_info[0] == 3
24
25if PY3:
26    bytes_type=bytes
27    string_type=str
28else:
29    bytes_type=str
30    string_type=unicode
31
32
33class ConsoleProgressBar:
34    def __init__(self, out, steps=100, indicator='#'):
35        self.blocks = 0
36        self.current = 0
37        self.steps = steps
38        self.indicator = indicator
39        self.out = out
40        self.done = False
41
42    def start(self, message=None):
43        self.done = False
44        if message:
45            self.out.write('\n%s:\n' % message)
46        self.out.write('%--10---20---30---40---50---60---70---80---90--100\n')
47
48    def step(self, n=1):
49        self.current += n
50
51        old = self.blocks
52        self.blocks = int(round(self.current / float(self.steps) * 100) / 2)
53
54        if self.blocks > 50:
55            self.blocks = 50
56
57        new = self.blocks - old
58
59        self.out.write(self.indicator * new)
60        self.out.flush()
61
62        if self.blocks == 50 and not self.done:
63            self.done = True
64            self.out.write("\n")
65
66def set_to_list(s):
67    l = []
68    l.extend(s)
69    return l
70
71def first(s, sorted=False):
72    """
73    Return the first element of a set.
74
75    It sometimes useful to return the first element from a set but,
76    because sets are not indexable, this is rather hard. This function
77    will return the first element from a set. If sorted is True, then
78    the set will first be sorted (making this an expensive operation).
79    Otherwise a random element will be returned (as sets are not ordered).
80    """
81    if not len(s):
82        raise IndexError("empty containter")
83
84    if sorted:
85        l = set_to_list(s)
86        l.sort()
87        return l[0]
88    else:
89        for x in s:
90            return x
91
92def encode_input(text):
93    import locale
94    """Encode given text via preferred system encoding"""
95    # locale will often find out the correct encoding
96    encoding = locale.getpreferredencoding()
97    try:
98        encoded_text = text.encode(encoding)
99    except UnicodeError:
100    # if it fails to find correct encoding then ascii is used
101    # which may lead to UnicodeError if `text` contains non ascii signs
102    # utf-8 is our guess to fix the situation
103        encoded_text = text.encode('utf-8')
104    return encoded_text
105
106def decode_input(text):
107    import locale
108    """Decode given text via preferred system encoding"""
109    # locale will often find out the correct encoding
110    encoding = locale.getpreferredencoding()
111    try:
112        decoded_text = text.decode(encoding)
113    except UnicodeError:
114    # if it fails to find correct encoding then ascii is used
115    # which may lead to UnicodeError if `text` contains non ascii signs
116    # utf-8 is our guess to fix the situation
117        decoded_text = text.decode('utf-8')
118    return decoded_text
119
120class Comparison():
121    """Class used when implementing rich comparison.
122
123    Inherit from this class if you want to have a rich
124    comparison withing the class, afterwards implement
125    _compare function within your class."""
126
127    def _compare(self, other, method):
128        raise NotImplemented
129
130    def __eq__(self, other):
131        return self._compare(other, lambda a, b: a == b)
132
133    def __lt__(self, other):
134        return self._compare(other, lambda a, b: a < b)
135
136    def __le__(self, other):
137        return self._compare(other, lambda a, b: a <= b)
138
139    def __ge__(self, other):
140        return self._compare(other, lambda a, b: a >= b)
141
142    def __gt__(self, other):
143        return self._compare(other, lambda a, b: a > b)
144
145    def __ne__(self, other):
146        return self._compare(other, lambda a, b: a != b)
147
148if sys.version_info < (2,7):
149    # cmp_to_key function is missing in python2.6
150    def cmp_to_key(mycmp):
151        'Convert a cmp= function into a key= function'
152        class K:
153            def __init__(self, obj, *args):
154                self.obj = obj
155            def __lt__(self, other):
156                return mycmp(self.obj, other.obj) < 0
157            def __gt__(self, other):
158                return mycmp(self.obj, other.obj) > 0
159            def __eq__(self, other):
160                return mycmp(self.obj, other.obj) == 0
161            def __le__(self, other):
162                return mycmp(self.obj, other.obj) <= 0
163            def __ge__(self, other):
164                return mycmp(self.obj, other.obj) >= 0
165            def __ne__(self, other):
166                return mycmp(self.obj, other.obj) != 0
167        return K
168else:
169    from functools import cmp_to_key
170
171def cmp(first, second):
172    return (first > second) - (second > first)
173
174if __name__ == "__main__":
175    import sys
176    import time
177    p = ConsoleProgressBar(sys.stdout, steps=999)
178    p.start("computing pi")
179    for i in range(999):
180        p.step()
181        time.sleep(0.001)
182
183