summaryrefslogtreecommitdiff
path: root/apt/progress/text.py
blob: 6024f124e1c33ac4c9cc607fb16b5f590996a2a3 (plain)
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
# Copyright (c) 2009 Julian Andres Klode <jak@debian.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
# USA
"""Progress reporting for text interfaces."""
import sys

import apt_pkg

__all__ = ['AcquireProgress', 'OpProgress']


class TextProgress(object):
    """Internal Base class for text progress classes."""

    def __init__(self, outfile=None):
        self._file = outfile or sys.stdout
        self._width = 0

    def _write(self, msg, newline=True):
        """Write the message on the terminal, fill remaining space."""
        self._file.write("\r")
        self._file.write(msg)
        # Fill remaining stuff with whitespace
        if self._width > len(msg):
            self._file.write((self._width - len(msg)) * ' ')
        else:
            self._width = max(self._width, len(msg))
        if newline:
            self._file.write("\n")
        else:
            self._file.write("\r")
            self._file.flush()


class OpProgress(apt_pkg.OpProgress, TextProgress):
    """Operation progress reporting.

    This closely resembles OpTextProgress in libapt-pkg.
    """

    def __init__(self, outfile=None):
        TextProgress.__init__(self, outfile)
        apt_pkg.OpProgress.__init__(self)
        self.old_op = ""

    def update(self, percent=None):
        """Called periodically to update the user interface."""
        if percent:
            self.percent = percent
        apt_pkg.OpProgress.update(self)
        if self.major_change and self.old_op:
            self._write(self.old_op)
        self._write("%s... %i%%" % (self.op, self.percent), False)
        self.old_op = self.op

    def done(self):
        """Called once an operation has been completed."""
        apt_pkg.OpProgress.done(self)
        if self.old_op:
            self._write("%s... Done" % self.old_op)
        self.old_op = ""


class AcquireProgress(apt_pkg.AcquireProgress, TextProgress):
    """AcquireProgress for the text interface."""

    def ims_hit(self, item):
        """Called when an item is update (e.g. not modified on the server)."""
        self._write("Hit   %s" % item.description)

    def done(self, item):
        """Called when an item is completely fetched."""
        self._write("Done  %s" % item.description)

    def fail(self, item):
        """Called when an item is failed."""
        self._write("Fail  %s" % item.description)

    def fetch(self, item):
        """Called when some of the item's data is fetched."""
        self._write("Fetch %s" % item.description)

    def pulse(self, owner):
        """Periodically invoked while the Acquire process is underway.

        Return False if the user asked to cancel the whole Acquire process."""

        percent = (((self.current_bytes + self.current_items) * 100.0) /
                        float(self.total_bytes + self.total_items))
        if self.current_cps > 0:
            eta = ((self.total_bytes - self.current_bytes) /
                        float(self.current_cps))
            self._write("[%2.f%%] %sB/s %s" % (percent,
                                    apt_pkg.size_to_str(int(self.current_cps)),
                                    apt_pkg.time_to_str(int(eta))), False)
        else:
            self._write("%2.f%% [Working]" % (percent), False)
        return True

    def media_change(self, medium, drive):
        """Prompt the user to change the inserted removable media."""
        print ("Media change: please insert the disc labeled "
               "'%s' in the drive '%s' and press enter") % (medium, drive)

        return raw_input() not in ('c', 'C')

    def stop(self):
        """Invoked when the Acquire process stops running."""
        self._write("Done downloading")