Просмотр исходного кода

Fixes #18869: Ensure `to_meters()` always returns a clean decimal value (#18883)

* Fixes #18869: Ensure to_meters() always returns a clean decimal value

* Handle float values
Jeremy Stretch 11 месяцев назад
Родитель
Сommit
092f7549ca
2 измененных файлов с 66 добавлено и 12 удалено
  1. 13 12
      netbox/utilities/conversion.py
  2. 53 0
      netbox/utilities/tests/test_conversions.py

+ 13 - 12
netbox/utilities/conversion.py

@@ -1,4 +1,4 @@
-from decimal import Decimal
+from decimal import Decimal, InvalidOperation
 
 
 from django.utils.translation import gettext as _
 from django.utils.translation import gettext as _
 
 
@@ -37,28 +37,29 @@ def to_grams(weight, unit) -> int:
     )
     )
 
 
 
 
-def to_meters(length, unit):
+def to_meters(length, unit) -> Decimal:
     """
     """
-    Convert the given length to meters.
+    Convert the given length to meters, returning a Decimal value.
     """
     """
     try:
     try:
-        if length < 0:
-            raise ValueError(_("Length must be a positive number"))
-    except TypeError:
+        length = Decimal(length)
+    except InvalidOperation:
         raise TypeError(_("Invalid value '{length}' for length (must be a number)").format(length=length))
         raise TypeError(_("Invalid value '{length}' for length (must be a number)").format(length=length))
+    if length < 0:
+        raise ValueError(_("Length must be a positive number"))
 
 
     if unit == CableLengthUnitChoices.UNIT_KILOMETER:
     if unit == CableLengthUnitChoices.UNIT_KILOMETER:
-        return length * 1000
+        return round(Decimal(length * 1000), 4)
     if unit == CableLengthUnitChoices.UNIT_METER:
     if unit == CableLengthUnitChoices.UNIT_METER:
-        return length
+        return round(Decimal(length), 4)
     if unit == CableLengthUnitChoices.UNIT_CENTIMETER:
     if unit == CableLengthUnitChoices.UNIT_CENTIMETER:
-        return length / 100
+        return round(Decimal(length / 100), 4)
     if unit == CableLengthUnitChoices.UNIT_MILE:
     if unit == CableLengthUnitChoices.UNIT_MILE:
-        return length * Decimal(1609.344)
+        return round(length * Decimal(1609.344), 4)
     if unit == CableLengthUnitChoices.UNIT_FOOT:
     if unit == CableLengthUnitChoices.UNIT_FOOT:
-        return length * Decimal(0.3048)
+        return round(length * Decimal(0.3048), 4)
     if unit == CableLengthUnitChoices.UNIT_INCH:
     if unit == CableLengthUnitChoices.UNIT_INCH:
-        return length * Decimal(0.0254)
+        return round(length * Decimal(0.0254), 4)
     raise ValueError(
     raise ValueError(
         _("Unknown unit {unit}. Must be one of the following: {valid_units}").format(
         _("Unknown unit {unit}. Must be one of the following: {valid_units}").format(
             unit=unit,
             unit=unit,

+ 53 - 0
netbox/utilities/tests/test_conversions.py

@@ -0,0 +1,53 @@
+from decimal import Decimal
+
+from dcim.choices import CableLengthUnitChoices
+from netbox.choices import WeightUnitChoices
+from utilities.conversion import to_grams, to_meters
+from utilities.testing.base import TestCase
+
+
+class ConversionsTest(TestCase):
+
+    def test_to_grams(self):
+        self.assertEqual(
+            to_grams(1, WeightUnitChoices.UNIT_KILOGRAM),
+            1000
+        )
+        self.assertEqual(
+            to_grams(1, WeightUnitChoices.UNIT_GRAM),
+            1
+        )
+        self.assertEqual(
+            to_grams(1, WeightUnitChoices.UNIT_POUND),
+            453
+        )
+        self.assertEqual(
+            to_grams(1, WeightUnitChoices.UNIT_OUNCE),
+            28
+        )
+
+    def test_to_meters(self):
+        self.assertEqual(
+            to_meters(1.5, CableLengthUnitChoices.UNIT_KILOMETER),
+            Decimal('1500')
+        )
+        self.assertEqual(
+            to_meters(1, CableLengthUnitChoices.UNIT_METER),
+            Decimal('1')
+        )
+        self.assertEqual(
+            to_meters(1, CableLengthUnitChoices.UNIT_CENTIMETER),
+            Decimal('0.01')
+        )
+        self.assertEqual(
+            to_meters(1, CableLengthUnitChoices.UNIT_MILE),
+            Decimal('1609.344')
+        )
+        self.assertEqual(
+            to_meters(1, CableLengthUnitChoices.UNIT_FOOT),
+            Decimal('0.3048')
+        )
+        self.assertEqual(
+            to_meters(1, CableLengthUnitChoices.UNIT_INCH),
+            Decimal('0.0254')
+        )