From 7391f63fc1f8bd8044cb4990b4851841e18c3c45 Mon Sep 17 00:00:00 2001 From: Brian Warner Date: Tue, 18 Nov 2008 20:11:42 -0700 Subject: [PATCH] util/abbreviate: little utility to abbreviate seconds and bytes --- src/allmydata/test/test_util.py | 67 +++++++++++++++++++++++++++++++- src/allmydata/util/abbreviate.py | 55 ++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 src/allmydata/util/abbreviate.py diff --git a/src/allmydata/test/test_util.py b/src/allmydata/test/test_util.py index ba74c34f..f44fa09b 100644 --- a/src/allmydata/test/test_util.py +++ b/src/allmydata/test/test_util.py @@ -7,7 +7,7 @@ from twisted.internet import defer, reactor from twisted.python import failure from allmydata.util import base32, idlib, humanreadable, mathutil, hashutil -from allmydata.util import assertutil, fileutil, deferredutil +from allmydata.util import assertutil, fileutil, deferredutil, abbreviate from allmydata.util import limiter, time_format, pollmixin, cachedir class Base32(unittest.TestCase): @@ -445,6 +445,71 @@ class HashUtilTests(unittest.TestCase): h2.update("foo") self.failUnlessEqual(h1, h2.digest()) +class Abbreviate(unittest.TestCase): + def test_time(self): + a = abbreviate.abbreviate_time + self.failUnlessEqual(a(None), "unknown") + self.failUnlessEqual(a(0), "0 seconds") + self.failUnlessEqual(a(1), "1 second") + self.failUnlessEqual(a(2), "2 seconds") + self.failUnlessEqual(a(119), "119 seconds") + MIN = 60 + self.failUnlessEqual(a(2*MIN), "2 minutes") + self.failUnlessEqual(a(60*MIN), "60 minutes") + self.failUnlessEqual(a(179*MIN), "179 minutes") + HOUR = 60*MIN + self.failUnlessEqual(a(180*MIN), "3 hours") + self.failUnlessEqual(a(4*HOUR), "4 hours") + DAY = 24*HOUR + MONTH = 30*DAY + self.failUnlessEqual(a(2*DAY), "2 days") + self.failUnlessEqual(a(2*MONTH), "2 months") + YEAR = 365*DAY + self.failUnlessEqual(a(5*YEAR), "5 years") + + def test_space(self): + tests_si = [(None, "unknown"), + (0, "0 B"), + (1, "1 B"), + (999, "999 B"), + (1000, "1000 B"), + (1023, "1023 B"), + (1024, "1.02 kB"), + (20*1000, "20.00 kB"), + (1024*1024, "1.05 MB"), + (1000*1000, "1.00 MB"), + (1000*1000*1000, "1.00 GB"), + (1000*1000*1000*1000, "1.00 TB"), + (1000*1000*1000*1000*1000, "1.00 PB"), + (1234567890123456, "1.23 PB"), + ] + for (x, expected) in tests_si: + got = abbreviate.abbreviate_space(x, SI=True) + self.failUnlessEqual(got, expected) + + tests_base1024 = [(None, "unknown"), + (0, "0 B"), + (1, "1 B"), + (999, "999 B"), + (1000, "1000 B"), + (1023, "1023 B"), + (1024, "1.00 kiB"), + (20*1024, "20.00 kiB"), + (1000*1000, "976.56 kiB"), + (1024*1024, "1.00 MiB"), + (1024*1024*1024, "1.00 GiB"), + (1024*1024*1024*1024, "1.00 TiB"), + (1000*1000*1000*1000*1000, "909.49 TiB"), + (1024*1024*1024*1024*1024, "1.00 PiB"), + (1234567890123456, "1.10 PiB"), + ] + for (x, expected) in tests_base1024: + got = abbreviate.abbreviate_space(x, SI=False) + self.failUnlessEqual(got, expected) + + self.failUnlessEqual(abbreviate.abbreviate_space_both(1234567), + "(1.23 MB, 1.18 MiB)") + class Limiter(unittest.TestCase): def job(self, i, foo): self.calls.append( (i, foo) ) diff --git a/src/allmydata/util/abbreviate.py b/src/allmydata/util/abbreviate.py new file mode 100644 index 00000000..13c51c78 --- /dev/null +++ b/src/allmydata/util/abbreviate.py @@ -0,0 +1,55 @@ + +HOUR = 3600 +DAY = 24*3600 +WEEK = 7*DAY +MONTH = 30*DAY +YEAR = 365*DAY + +def abbreviate_time(s): + def _plural(count, unit): + count = int(count) + if count == 1: + return "%d %s" % (count, unit) + return "%d %ss" % (count, unit) + if s is None: + return "unknown" + if s < 120: + return _plural(s, "second") + if s < 3*HOUR: + return _plural(s/60, "minute") + if s < 2*DAY: + return _plural(s/HOUR, "hour") + if s < 2*MONTH: + return _plural(s/DAY, "day") + if s < 4*YEAR: + return _plural(s/MONTH, "month") + return _plural(s/YEAR, "year") + +def abbreviate_space(s, SI=True): + if s is None: + return "unknown" + if SI: + U = 1000.0 + isuffix = "B" + else: + U = 1024.0 + isuffix = "iB" + def r(count, suffix): + return "%.2f %s%s" % (count, suffix, isuffix) + + if s < 1024: # 1000-1023 get emitted as bytes, even in SI mode + return "%d B" % s + if s < U*U: + return r(s/U, "k") + if s < U*U*U: + return r(s/(U*U), "M") + if s < U*U*U*U: + return r(s/(U*U*U), "G") + if s < U*U*U*U*U: + return r(s/(U*U*U*U), "T") + return r(s/(U*U*U*U*U), "P") + +def abbreviate_space_both(s): + return "(%s, %s)" % (abbreviate_space(s, True), + abbreviate_space(s, False)) + -- 2.37.2