[Common] Refactor unit functions

This commit is contained in:
Calum Lind 2016-11-02 18:06:34 +00:00
commit 03c7a2b108
2 changed files with 110 additions and 113 deletions

View file

@ -272,7 +272,6 @@ def open_url_in_browser(url):
# Formatting text functions # Formatting text functions
# For performance reasons these fsize units are translated outside the function
byte_txt = "B" byte_txt = "B"
kib_txt = "KiB" kib_txt = "KiB"
mib_txt = "MiB" mib_txt = "MiB"
@ -285,6 +284,8 @@ tib_txt_short = "T"
def translate_size_units(): def translate_size_units():
"""For performance reasons these units are translated outside the function"""
global byte_txt, kib_txt, mib_txt, gib_txt, tib_txt global byte_txt, kib_txt, mib_txt, gib_txt, tib_txt
global kib_txt_short, mib_txt_short, gib_txt_short, tib_txt_short global kib_txt_short, mib_txt_short, gib_txt_short, tib_txt_short
@ -300,35 +301,34 @@ def translate_size_units():
def fsize(fsize_b, precision=1, shortform=False): def fsize(fsize_b, precision=1, shortform=False):
""" """Formats the bytes value into a string with KiB, MiB or GiB units.
Formats the bytes value into a string with KiB, MiB or GiB units
:param fsize_b: the filesize in bytes Args:
:type fsize_b: int fsize_b (int): The filesize in bytes.
:param precision: the filesize float precision precision (int): The filesize float precision.
:type precision: int
:returns: formatted string in KiB, MiB or GiB units
:rtype: string
**Usage** Returns:
str: A formatted string in KiB, MiB or GiB units.
Examples:
>>> fsize(112245) >>> fsize(112245)
'109.6 KiB' '109.6 KiB'
>>> fsize(112245, precision=0) >>> fsize(112245, precision=0)
'110 KiB' '110 KiB'
Note:
This function has been refactored for perfomance with the
fsize units being translated outside the function.
""" """
# Bigger than 1 TiB if fsize_b >= 1024 ** 4:
if fsize_b >= 1099511627776: return "%.*f %s" % (precision, fsize_b / 1024 ** 4, tib_txt_short if shortform else tib_txt)
return "%.*f %s" % (precision, fsize_b / 1099511627776, tib_txt_short if shortform else tib_txt) elif fsize_b >= 1024 ** 3:
# Bigger than 1 GiB return "%.*f %s" % (precision, fsize_b / 1024 ** 3, gib_txt_short if shortform else gib_txt)
elif fsize_b >= 1073741824: elif fsize_b >= 1024 ** 2:
return "%.*f %s" % (precision, fsize_b / 1073741824, gib_txt_short if shortform else gib_txt) return "%.*f %s" % (precision, fsize_b / 1024 ** 2, mib_txt_short if shortform else mib_txt)
# Bigger than 1 MiB
elif fsize_b >= 1048576:
return "%.*f %s" % (precision, fsize_b / 1048576, mib_txt_short if shortform else mib_txt)
# Bigger than 1 KiB
elif fsize_b >= 1024: elif fsize_b >= 1024:
return "%.*f %s" % (precision, fsize_b / 1024, kib_txt_short if shortform else kib_txt) return "%.*f %s" % (precision, fsize_b / 1024, kib_txt_short if shortform else kib_txt)
else: else:
@ -336,24 +336,23 @@ def fsize(fsize_b, precision=1, shortform=False):
def fpcnt(dec, precision=2): def fpcnt(dec, precision=2):
""" """Formats a string to display a percentage with <precision> places.
Formats a string to display a percentage with two decimal places
:param dec: the ratio in the range [0.0, 1.0] Args:
:type dec: float dec (float): The ratio in the range [0.0, 1.0].
:param precision: the percentage float precision precision (int): The percentage float precision.
:type precision: int
:returns: a formatted string representing a percentage
:rtype: string
**Usage** Returns:
str: A formatted string representing a percentage.
Examples:
>>> fpcnt(0.9311) >>> fpcnt(0.9311)
'93.11%' '93.11%'
>>> fpcnt(0.9311, precision=0) >>> fpcnt(0.9311, precision=0)
'93%' '93%'
""" """
pcnt = (dec * 100) pcnt = (dec * 100)
if pcnt == 0 or pcnt == 100: if pcnt == 0 or pcnt == 100:
precision = 0 precision = 0
@ -361,47 +360,41 @@ def fpcnt(dec, precision=2):
def fspeed(bps, precision=1, shortform=False): def fspeed(bps, precision=1, shortform=False):
""" """Formats a string to display a transfer speed.
Formats a string to display a transfer speed utilizing :func:`fsize`
:param bps: bytes per second Args:
:type bps: int bps (int): The speed in bytes per second.
:returns: a formatted string representing transfer speed
:rtype: string
**Usage** Returns:
str: A formatted string representing transfer speed.
Examples:
>>> fspeed(43134) >>> fspeed(43134)
'42.1 KiB/s' '42.1 KiB/s'
""" """
fspeed_kb = bps / 1024 if bps < 1024 ** 2:
if fspeed_kb < 1024: return "%.*f %s" % (precision, bps / 1024, _("K/s") if shortform else _("KiB/s"))
return "%.*f %s" % (precision, fspeed_kb, _("K/s") if shortform else _("KiB/s")) elif bps < 1024 ** 3:
fspeed_mb = fspeed_kb / 1024 return "%.*f %s" % (precision, bps / 1024 ** 2, _("M/s") if shortform else _("MiB/s"))
if fspeed_mb < 1024: elif bps < 1024 ** 4:
return "%.*f %s" % (precision, fspeed_mb, _("M/s") if shortform else _("MiB/s")) return "%.*f %s" % (precision, bps / 1024 ** 3, _("G/s") if shortform else _("GiB/s"))
fspeed_gb = fspeed_mb / 1024 else:
if fspeed_gb < 1024: return "%.*f %s" % (precision, bps / 1024 ** 4, _("T/s") if shortform else _("TiB/s"))
return "%.*f %s" % (precision, fspeed_gb, _("G/s") if shortform else _("GiB/s"))
fspeed_tb = fspeed_gb / 1024
return "%.*f %s" % (precision, fspeed_tb, _("T/s") if shortform else _("TiB/s"))
def fpeer(num_peers, total_peers): def fpeer(num_peers, total_peers):
""" """Formats a string to show 'num_peers' ('total_peers').
Formats a string to show 'num_peers' ('total_peers')
:param num_peers: the number of connected peers Args:
:type num_peers: int num_peers (int): The number of connected peers.
:param total_peers: the total number of peers total_peers (int): The total number of peers.
:type total_peers: int
:returns: a formatted string: num_peers (total_peers), if total_peers < 0, then it will not be shown
:rtype: string
**Usage** Returns:
str: A formatted string 'num_peers (total_peers)' or total_peers < 0, just 'num_peers'.
Examples:
>>> fpeer(10, 20) >>> fpeer(10, 20)
'10 (20)' '10 (20)'
>>> fpeer(10, -1) >>> fpeer(10, -1)
@ -409,63 +402,59 @@ def fpeer(num_peers, total_peers):
""" """
if total_peers > -1: if total_peers > -1:
return "%d (%d)" % (num_peers, total_peers) return "{:d} ({:d})".format(num_peers, total_peers)
else: else:
return "%d" % num_peers return "{:d}".format(num_peers)
def ftime(seconds): def ftime(secs):
""" """Formats a string to show time in a human readable form.
Formats a string to show time in a human readable form
:param seconds: the number of seconds Args:
:type seconds: int secs (int): The number of seconds.
:returns: a formatted time string, will return '' if seconds == 0
:rtype: string
**Usage** Returns:
str: A formatted time string or empty string if value is 0.
Examples:
>>> ftime(23011) >>> ftime(23011)
'6h 23m' '6h 23m'
Note:
This function has been refactored for perfomance.
""" """
if seconds == 0:
return "" if secs == 0:
if seconds < 60: time_str = ''
return '%ds' % (seconds) elif secs < 60:
minutes = seconds // 60 time_str = '{:d}s'.format(secs)
if minutes < 60: elif secs < 3600:
seconds = seconds % 60 time_str = '{:d}m {:d}s'.format(secs // 60, secs % 60)
return '%dm %ds' % (minutes, seconds) elif secs < 86400:
hours = minutes // 60 time_str = '{:d}h {:d}m'.format(secs // 3600, secs // 60 % 60)
if hours < 24: elif secs < 604800:
minutes = minutes % 60 time_str = '{:d}d {:d}h'.format(secs // 86400, secs // 3600 % 24)
return '%dh %dm' % (hours, minutes) elif secs < 31449600:
days = hours // 24 time_str = '{:d}w {:d}d'.format(secs // 604800, secs // 86400 % 7)
if days < 7: else:
hours = hours % 24 time_str = '{:d}y {:d}w'.format(secs // 31449600, secs // 604800 % 52)
return '%dd %dh' % (days, hours)
weeks = days // 7 return time_str
if weeks < 52:
days = days % 7
return '%dw %dd' % (weeks, days)
years = weeks // 52
weeks = weeks % 52
return '%dy %dw' % (years, weeks)
def fdate(seconds, date_only=False, precision_secs=False): def fdate(seconds, date_only=False, precision_secs=False):
""" """Formats a date time string in the locale's date representation based on the systems timezone.
Formats a date time string in the locale's date representation based on the systems timezone
:param seconds: time in seconds since the Epoch Args:
:type seconds: float seconds (float): Time in seconds since the Epoch.
:param precision_secs: include seconds in time format precision_secs (bool): Include seconds in time format.
:type precision_secs: bool
:returns: a string in the locale's datetime representation or "" if seconds < 0 Returns:
:rtype: string str: A string in the locale's datetime representation or "" if seconds < 0
""" """
if seconds < 0: if seconds < 0:
return "" return ""
time_format = "%x %X" if precision_secs else "%x %H:%M" time_format = "%x %X" if precision_secs else "%x %H:%M"

View file

@ -40,7 +40,15 @@ class CommonTestCase(unittest.TestCase):
self.failUnless(fpeer(10, -1) == "10") self.failUnless(fpeer(10, -1) == "10")
def test_ftime(self): def test_ftime(self):
self.failUnless(ftime(0) == "")
self.failUnless(ftime(5) == "5s")
self.failUnless(ftime(100) == "1m 40s")
self.failUnless(ftime(3789) == "1h 3m")
self.failUnless(ftime(23011) == "6h 23m") self.failUnless(ftime(23011) == "6h 23m")
self.failUnless(ftime(391187) == "4d 12h")
self.failUnless(ftime(604800) == "1w 0d")
self.failUnless(ftime(13893086) == "22w 6d")
self.failUnless(ftime(59740269) == "1y 46w")
def test_fdate(self): def test_fdate(self):
self.failUnless(fdate(-1) == "") self.failUnless(fdate(-1) == "")