From efd83f40ca3cb9a088f85d2f0e0ff6203c89c0c1 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 13 Jun 2014 07:13:47 +0200 Subject: [PATCH] Print human readable sizes in downloads --- qutebrowser/browser/downloads.py | 10 +++++--- qutebrowser/test/utils/test_misc.py | 38 +++++++++++++++++++++++++++++ qutebrowser/utils/misc.py | 15 ++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/qutebrowser/browser/downloads.py b/qutebrowser/browser/downloads.py index fe2825bba..727aca16c 100644 --- a/qutebrowser/browser/downloads.py +++ b/qutebrowser/browser/downloads.py @@ -26,7 +26,8 @@ import qutebrowser.config.config as config import qutebrowser.utils.message as message from qutebrowser.utils.log import downloads as logger from qutebrowser.utils.usertypes import PromptMode -from qutebrowser.utils.misc import interpolate_color, format_seconds +from qutebrowser.utils.misc import (interpolate_color, format_seconds, + format_size) class DownloadItem(QObject): @@ -94,9 +95,12 @@ class DownloadItem(QObject): remaining = (format_seconds(self.remaining_time) if self.remaining_time is not None else '?') + speed = format_size(self.speed, suffix='B/s') + down = format_size(self.bytes_done, suffix='B') + total = format_size(self.bytes_total, suffix='B') return '{name} [{speed}|{remaining}|{perc: 2}%|{down}/{total}]'.format( - name=self.basename, speed=self.speed, remaining=remaining, - perc=perc, down=self.bytes_done, total=self.bytes_total) + name=self.basename, speed=speed, remaining=remaining, perc=perc, + down=down, total=total) def _die(self, msg): """Abort the download and emit an error.""" diff --git a/qutebrowser/test/utils/test_misc.py b/qutebrowser/test/utils/test_misc.py index 8d7853587..ad197c8c5 100644 --- a/qutebrowser/test/utils/test_misc.py +++ b/qutebrowser/test/utils/test_misc.py @@ -553,5 +553,43 @@ class FormatSecondsTests(TestCase): self.assertEqual(utils.format_seconds(seconds), out, seconds) +class FormatSizeTests(TestCase): + + """Tests for format_size. + + Class attributes: + TESTS: A list of (input, output) tuples. + """ + + TESTS = [ + (-1024, '-1.00k'), + (-1, '-1.00'), + (0, '0.00'), + (1023, '1023.00'), + (1024, '1.00k'), + (1034.24, '1.01k'), + (1024 * 1024 * 2, '2.00M'), + (1024 ** 10, '1024.00Y'), + (None, '?.??'), + ] + + def test_format_size(self): + """Test format_size with several tests.""" + for size, out in self.TESTS: + self.assertEqual(utils.format_size(size), out, size) + + def test_suffix(self): + """Test the suffix option.""" + for size, out in self.TESTS: + self.assertEqual(utils.format_size(size, suffix='B'), out + 'B', + size) + + def test_base(self): + """Test with an alternative base.""" + kilo_tests = [(999, '999.00'), (1000, '1.00k'), (1010, '1.01k')] + for size, out in kilo_tests: + self.assertEqual(utils.format_size(size, base=1000), out, size) + + if __name__ == '__main__': unittest.main() diff --git a/qutebrowser/utils/misc.py b/qutebrowser/utils/misc.py index 782a9d973..dbadd5bb6 100644 --- a/qutebrowser/utils/misc.py +++ b/qutebrowser/utils/misc.py @@ -370,3 +370,18 @@ def format_seconds(total_seconds): chunks.append(min_format.format(minutes)) chunks.append('{:02}'.format(seconds)) return prefix + ':'.join(chunks) + + +def format_size(size, base=1024, suffix=''): + """Format a byte size so it's human readable. + + Inspired by http://stackoverflow.com/q/1094841 + """ + prefixes = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'] + if size is None: + return '?.??' + suffix + for p in prefixes: + if -base < size < base: + return '{:.02f}{}{}'.format(size, p, suffix) + size /= base + return '{:.02f}{}{}'.format(size, prefixes[-1], suffix)