[tor-commits] [stem/master] Normalize label input arguments

atagar at torproject.org atagar at torproject.org
Sun Oct 18 00:02:00 UTC 2020


commit c90e87ca9a8b70319a58d2222ee7e328f8af00d3
Author: Damian Johnson <atagar at torproject.org>
Date:   Sat Oct 17 16:37:51 2020 -0700

    Normalize label input arguments
    
    Functions like size_label() and time_label() are documented as taking an int
    argument, but getting a float shouldn't make them choke. Especially in such an
    unhelpful way...
    
      ======================================================================
      ERROR: test_time_label
      Checks the time_label() function.
      ----------------------------------------------------------------------
      Traceback (most recent call last):
        File "/home/atagar/Desktop/stem/test/unit/util/str_tools.py", line 99, in test_time_label
          self.assertEqual('0s', str_tools.time_label(0.1))
        File "/home/atagar/Desktop/stem/stem/util/str_tools.py", line 366, in time_label
          return _get_label(TIME_UNITS, seconds, decimal, is_long)
        File "/home/atagar/Desktop/stem/stem/util/str_tools.py", line 595, in _get_label
          raise ValueError('BUG: %s should always be divisible by a unit (%s)' % (count, str(units)))
      ValueError: BUG: 0.1 should always be divisible by a unit (((86400.0, 'd', ' day'), (3600.0, 'h', ' hour'), (60.0, 'm', ' minute'), (1.0, 's', ' second')))
---
 stem/util/str_tools.py      | 35 ++++++++++++++++++++++++-----------
 test/unit/util/str_tools.py |  1 +
 2 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/stem/util/str_tools.py b/stem/util/str_tools.py
index 64bcfc46..9803d437 100644
--- a/stem/util/str_tools.py
+++ b/stem/util/str_tools.py
@@ -329,6 +329,9 @@ def size_label(byte_count: int, decimal: int = 0, is_long: bool = False, is_byte
   :returns: **str** with human readable representation of the size
   """
 
+  if isinstance(byte_count, float):
+    byte_count = int(byte_count)
+
   if is_bytes:
     return _get_label(SIZE_UNITS_BYTES, byte_count, decimal, is_long, round)
   else:
@@ -363,6 +366,9 @@ def time_label(seconds: int, decimal: int = 0, is_long: bool = False) -> str:
   :returns: **str** with human readable representation of the time
   """
 
+  if isinstance(seconds, float):
+    seconds = int(seconds)
+
   return _get_label(TIME_UNITS, seconds, decimal, is_long)
 
 
@@ -386,6 +392,9 @@ def time_labels(seconds: int, is_long: bool = False) -> Sequence[str]:
   :returns: **list** of strings with human readable representations of the time
   """
 
+  if isinstance(seconds, float):
+    seconds = int(seconds)
+
   time_labels = []
 
   for count_per_unit, _, _ in TIME_UNITS:
@@ -416,6 +425,9 @@ def short_time_label(seconds: int) -> str:
   :raises: **ValueError** if the input is negative
   """
 
+  if isinstance(seconds, float):
+    seconds = int(seconds)
+
   if seconds < 0:
     raise ValueError("Input needs to be a non-negative integer, got '%i'" % seconds)
 
@@ -560,35 +572,36 @@ def _get_label(units: Sequence[Tuple[float, str, str]], count: int, decimal: int
 
   # formatted string for the requested number of digits
   label_format = '%%.%if' % decimal
+  remainder = count
 
-  if count < 0:
+  if remainder < 0:
     label_format = '-' + label_format
-    count = abs(count)
-  elif count == 0:
+    remainder = abs(remainder)
+  elif remainder == 0:
     units_label = units[-1][2] + 's' if is_long else units[-1][1]
     return '%s%s' % (label_format % count, units_label)
 
   for count_per_unit, short_label, long_label in units:
-    if count >= count_per_unit:
+    if remainder >= count_per_unit:
       if not round:
-        # Rounding down with a '%f' is a little clunky. Reducing the count so
-        # it'll divide evenly as the rounded down value.
+        # Rounding down with a '%f' is a little clunky. Reducing the remainder
+        # so it'll divide evenly as the rounded down value.
 
-        count -= count % (count_per_unit / (10 ** decimal))
+        remainder -= remainder % (count_per_unit / (10 ** decimal))
 
-      count_label = label_format % (count / count_per_unit)
+      count_label = label_format % (remainder / count_per_unit)
 
       if is_long:
         # Pluralize if any of the visible units make it greater than one. For
         # instance 1.0003 is plural but 1.000 isn't.
 
         if decimal > 0:
-          is_plural = count > count_per_unit
+          is_plural = remainder > count_per_unit
         else:
-          is_plural = count >= count_per_unit * 2
+          is_plural = remainder >= count_per_unit * 2
 
         return count_label + long_label + ('s' if is_plural else '')
       else:
         return count_label + short_label
 
-  raise ValueError('BUG: value should always be divisible by a unit (%s)' % str(units))
+  raise ValueError('BUG: %s should always be divisible by a unit (%s)' % (count, str(units)))
diff --git a/test/unit/util/str_tools.py b/test/unit/util/str_tools.py
index ee270717..8b0365f7 100644
--- a/test/unit/util/str_tools.py
+++ b/test/unit/util/str_tools.py
@@ -96,6 +96,7 @@ class TestStrTools(unittest.TestCase):
     self.assertEqual('1.01 minutes', str_tools.time_label(61, 2, True))
 
     self.assertEqual('0s', str_tools.time_label(0))
+    self.assertEqual('0s', str_tools.time_label(0.1))
     self.assertEqual('0 seconds', str_tools.time_label(0, is_long = True))
     self.assertEqual('0.00s', str_tools.time_label(0, 2))
     self.assertEqual('-10s', str_tools.time_label(-10))





More information about the tor-commits mailing list