~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to progress.py

  • Committer: Jeff Bailey
  • Date: 2005-06-08 22:30:34 UTC
  • Revision ID: jbailey@ppc64-20050608223034-3cbc9567103c4810
Add Debian directory

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# Copyright (C) 2005 Aaron Bentley
2
 
# <aaron@aaronbentley.com>
 
2
# <aaron.bentley@utoronto.ca>
3
3
#
4
4
#    This program is free software; you can redistribute it and/or modify
5
5
#    it under the terms of the GNU General Public License as published by
17
17
 
18
18
import sys
19
19
import datetime
20
 
from bzrlib.progress import ProgressBar
21
20
 
22
21
class Progress(object):
23
22
    def __init__(self, units, current, total=None):
24
23
        self.units = units
25
24
        self.current = current
26
25
        self.total = total
27
 
 
28
 
    def _get_percent(self):
29
 
        if self.total is None:
30
 
            return None
31
 
        return 100.0 * self.current / self.total
32
 
 
33
 
    percent = property(_get_percent)
 
26
        self.percent = None
 
27
        if self.total is not None:
 
28
            self.percent = 100.0 * current / total
34
29
 
35
30
    def __str__(self):
36
31
        if self.total is not None:
37
32
            return "%i of %i %s %.1f%%" % (self.current, self.total, self.units,
38
33
                                         self.percent)
39
34
        else:
40
 
            return "%i %s" (self.current, self.units)
41
 
 
42
 
def show_progress(pi, prog):
43
 
    pi.update(prog.units, prog.current, prog.total)
 
35
            return "%i %s" (self.current, self.units) 
 
36
 
 
37
class ProgressBar(object):
 
38
    def __init__(self):
 
39
        self.start = None
 
40
        object.__init__(self)
 
41
 
 
42
    def __call__(self, progress):
 
43
        if self.start is None:
 
44
            self.start = datetime.datetime.now()
 
45
        progress_bar(progress, start_time=self.start)
 
46
        
 
47
def divide_timedelta(delt, divisor):
 
48
    """Divides a timedelta object"""
 
49
    return datetime.timedelta(float(delt.days)/divisor, 
 
50
                              float(delt.seconds)/divisor, 
 
51
                              float(delt.microseconds)/divisor)
 
52
 
 
53
def str_tdelta(delt):
 
54
    if delt is None:
 
55
        return "-:--:--"
 
56
    return str(datetime.timedelta(delt.days, delt.seconds))
 
57
 
 
58
def get_eta(start_time, progress, enough_samples=20):
 
59
    if start_time is None or progress.current == 0:
 
60
        return None
 
61
    elif progress.current < enough_samples:
 
62
        return None
 
63
    elapsed = datetime.datetime.now() - start_time
 
64
    total_duration = divide_timedelta((elapsed) * long(progress.total), 
 
65
                                      progress.current)
 
66
    if elapsed < total_duration:
 
67
        eta = total_duration - elapsed
 
68
    else:
 
69
        eta = total_duration - total_duration
 
70
    return eta
 
71
 
 
72
def progress_bar(progress, start_time=None):
 
73
    eta = get_eta(start_time, progress)
 
74
    if start_time is not None:
 
75
        eta_str = " "+str_tdelta(eta)
 
76
    else:
 
77
        eta_str = ""
 
78
 
 
79
    fmt = " %i of %i %s (%.1f%%)"
 
80
    f = fmt % (progress.total, progress.total, progress.units, 100.0)
 
81
    max = len(f)
 
82
    cols = 77 - max
 
83
    if start_time is not None:
 
84
        cols -= len(eta_str)
 
85
    markers = int (float(cols) * progress.current / progress.total)
 
86
    txt = fmt % (progress.current, progress.total, progress.units,
 
87
                 progress.percent)
 
88
    sys.stderr.write("\r[%s%s]%s%s" % ('='*markers, ' '*(cols-markers), txt, 
 
89
                                       eta_str))
44
90
 
45
91
def clear_progress_bar():
46
92
    sys.stderr.write('\r%s\r' % (' '*79))
 
93
 
 
94
def spinner_str(progress, show_text=False):
 
95
    """
 
96
    Produces the string for a textual "spinner" progress indicator
 
97
    :param progress: an object represinting current progress
 
98
    :param show_text: If true, show progress text as well
 
99
    :return: The spinner string
 
100
 
 
101
    >>> spinner_str(Progress("baloons", 0))
 
102
    '|'
 
103
    >>> spinner_str(Progress("baloons", 5))
 
104
    '/'
 
105
    >>> spinner_str(Progress("baloons", 6), show_text=True)
 
106
    '- 6 baloons'
 
107
    """
 
108
    positions = ('|', '/', '-', '\\')
 
109
    text = positions[progress.current % 4]
 
110
    if show_text:
 
111
        text+=" %i %s" % (progress.current, progress.units)
 
112
    return text
 
113
 
 
114
def spinner(progress, show_text=False, output=sys.stderr):
 
115
    """
 
116
    Update a spinner progress indicator on an output
 
117
    :param progress: The progress to display
 
118
    :param show_text: If true, show text as well as spinner
 
119
    :param output: The output to write to
 
120
 
 
121
    >>> spinner(Progress("baloons", 6), show_text=True, output=sys.stdout)
 
122
    \r- 6 baloons
 
123
    """
 
124
    output.write('\r%s' % spinner_str(progress, show_text))
 
125
 
 
126
def run_tests():
 
127
    import doctest
 
128
    result = doctest.testmod()
 
129
    if result[1] > 0:
 
130
        if result[0] == 0:
 
131
            print "All tests passed"
 
132
    else:
 
133
        print "No tests to run"
 
134
if __name__ == "__main__":
 
135
    run_tests()