File Explorer

/proc/self/root/proc/self/root/lib/python3.9/site-packages/dnf/cli

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

progress.py7.4 KB · 203 lines
# Copyright (C) 2013-2016 Red Hat, Inc.## This copyrighted material is made available to anyone wishing to use,# modify, copy, or redistribute it subject to the terms and conditions of# the GNU General Public License v.2, or (at your option) any later version.# This program is distributed in the hope that it will be useful, but WITHOUT# ANY WARRANTY expressed or implied, including the implied warranties 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., 51 Franklin Street, Fifth Floor, Boston, MA# 02110-1301, USA.  Any Red Hat trademarks that are incorporated in the# source code or documentation are not subject to the GNU General Public# License and may only be used or replicated with the express permission of# Red Hat, Inc. from __future__ import unicode_literalsfrom dnf.cli.format import format_number, format_timefrom dnf.cli.term import _term_widthfrom dnf.pycomp import unicodefrom time import time import sysimport dnf.callbackimport dnf.util  class MultiFileProgressMeter(dnf.callback.DownloadProgress):    """Multi-file download progress meter"""     STATUS_2_STR = {        dnf.callback.STATUS_FAILED: 'FAILED',        dnf.callback.STATUS_ALREADY_EXISTS: 'SKIPPED',        dnf.callback.STATUS_MIRROR: 'MIRROR',        dnf.callback.STATUS_DRPM: 'DRPM',    }     def __init__(self, fo=sys.stderr, update_period=0.3, tick_period=1.0, rate_average=5.0):        """Creates a new progress meter instance         update_period -- how often to update the progress bar        tick_period -- how fast to cycle through concurrent downloads        rate_average -- time constant for average speed calculation        """        self.fo = fo        self.update_period = update_period        self.tick_period = tick_period        self.rate_average = rate_average        self.unknown_progres = 0        self.total_drpm = 0        self.isatty = sys.stdout.isatty()        self.done_drpm = 0        self.done_files = 0        self.done_size = 0        self.active = []        self.state = {}        self.last_time = 0        self.last_size = 0        self.rate = None        self.total_files = 0        self.total_size = 0     def message(self, msg):        dnf.util._terminal_messenger('write_flush', msg, self.fo)     def start(self, total_files, total_size, total_drpms=0):        self.total_files = total_files        self.total_size = total_size        self.total_drpm = total_drpms         # download state        self.done_drpm = 0        self.done_files = 0        self.done_size = 0        self.active = []        self.state = {}         # rate averaging        self.last_time = 0        self.last_size = 0        self.rate = None     def progress(self, payload, done):        now = time()        text = unicode(payload)        total = int(payload.download_size)        done = int(done)         # update done_size        if text not in self.state:            self.state[text] = now, 0            self.active.append(text)        start, old = self.state[text]        self.state[text] = start, done        self.done_size += done - old         # update screen if enough time has elapsed        if now - self.last_time > self.update_period:            if total > self.total_size:                self.total_size = total            self._update(now)     def _update(self, now):        if self.last_time:            delta_time = now - self.last_time            delta_size = self.done_size - self.last_size            if delta_time > 0 and delta_size > 0:                # update the average rate                rate = delta_size / delta_time                if self.rate is not None:                    weight = min(delta_time/self.rate_average, 1)                    rate = rate*weight + self.rate*(1 - weight)                self.rate = rate        self.last_time = now        self.last_size = self.done_size        if not self.isatty:            return        # pick one of the active downloads        text = self.active[int(now/self.tick_period) % len(self.active)]        if self.total_files > 1:            n = '%d' % (self.done_files + 1)            if len(self.active) > 1:                n += '-%d' % (self.done_files + len(self.active))            text = '(%s/%d): %s' % (n, self.total_files, text)         # average rate, total done size, estimated remaining time        if self.rate and self.total_size:            time_eta = format_time((self.total_size - self.done_size) / self.rate)        else:            time_eta = '--:--'        msg = ' %5sB/s | %5sB %9s ETA\r' % (            format_number(self.rate) if self.rate else '---  ',            format_number(self.done_size),            time_eta)        left = _term_width() - len(msg)        bl = (left - 7)//2        if bl > 8:            # use part of the remaining space for progress bar            if self.total_size:                pct = self.done_size * 100 // self.total_size                n, p = divmod(self.done_size * bl * 2 // self.total_size, 2)                bar = '=' * n + '-' * p                msg = '%3d%% [%-*s]%s' % (pct, bl, bar, msg)                left -= bl + 7            else:                n = self.unknown_progres - 3                p = 3                n = 0 if n < 0 else n                bar = ' ' * n + '=' * p                msg = '     [%-*s]%s' % (bl, bar, msg)                left -= bl + 7                self.unknown_progres = self.unknown_progres + 3 if self.unknown_progres + 3 < bl \                    else 0        self.message('%-*.*s%s' % (left, left, text, msg))     def end(self, payload, status, err_msg):        start = now = time()        text = unicode(payload)        size = int(payload.download_size)        done = 0         # update state        if status == dnf.callback.STATUS_MIRROR:            pass        elif status == dnf.callback.STATUS_DRPM:            self.done_drpm += 1        elif text in self.state:            start, done = self.state.pop(text)            self.active.remove(text)            size -= done            self.done_files += 1            self.done_size += size        elif status == dnf.callback.STATUS_ALREADY_EXISTS:            self.done_files += 1            self.done_size += size         if status:            # the error message, no trimming            if status is dnf.callback.STATUS_DRPM and self.total_drpm > 1:                msg = '[%s %d/%d] %s: ' % (self.STATUS_2_STR[status], self.done_drpm,                                           self.total_drpm, text)            else:                msg = '[%s] %s: ' % (self.STATUS_2_STR[status], text)            left = _term_width() - len(msg) - 1            msg = '%s%-*s\n' % (msg, left, err_msg)        else:            if self.total_files > 1:                text = '(%d/%d): %s' % (self.done_files, self.total_files, text)             # average rate, file size, download time            tm = max(now - start, 0.001)            msg = ' %5sB/s | %5sB %9s    \n' % (                format_number(float(done) / tm),                format_number(done),                format_time(tm))            left = _term_width() - len(msg)            msg = '%-*.*s%s' % (left, left, text, msg)        self.message(msg)         # now there's a blank line. fill it if possible.        if self.active:            self._update(now)