From 486d2bb51b3ef9f4d9f8f4fa40a5e0e652525b33 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Wed, 12 Mar 2025 12:58:59 -0400 Subject: [PATCH] Fixes #18869: Ensure to_meters() always returns a clean decimal value --- netbox/utilities/conversion.py | 16 +++---- netbox/utilities/tests/test_conversions.py | 53 ++++++++++++++++++++++ 2 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 netbox/utilities/tests/test_conversions.py diff --git a/netbox/utilities/conversion.py b/netbox/utilities/conversion.py index 6ce32212a..35a8bad5f 100644 --- a/netbox/utilities/conversion.py +++ b/netbox/utilities/conversion.py @@ -37,9 +37,9 @@ 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: if length < 0: @@ -48,17 +48,17 @@ def to_meters(length, unit): raise TypeError(_("Invalid value '{length}' for length (must be a number)").format(length=length)) if unit == CableLengthUnitChoices.UNIT_KILOMETER: - return length * 1000 + return round(Decimal(length * 1000), 4) if unit == CableLengthUnitChoices.UNIT_METER: - return length + return round(Decimal(length), 4) if unit == CableLengthUnitChoices.UNIT_CENTIMETER: - return length / 100 + return round(Decimal(length / 100), 4) if unit == CableLengthUnitChoices.UNIT_MILE: - return length * Decimal(1609.344) + return round(length * Decimal(1609.344), 4) if unit == CableLengthUnitChoices.UNIT_FOOT: - return length * Decimal(0.3048) + return round(length * Decimal(0.3048), 4) if unit == CableLengthUnitChoices.UNIT_INCH: - return length * Decimal(0.0254) + return round(length * Decimal(0.0254), 4) raise ValueError( _("Unknown unit {unit}. Must be one of the following: {valid_units}").format( unit=unit, diff --git a/netbox/utilities/tests/test_conversions.py b/netbox/utilities/tests/test_conversions.py new file mode 100644 index 000000000..ed8955f96 --- /dev/null +++ b/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, CableLengthUnitChoices.UNIT_KILOMETER), + Decimal('1000') + ) + 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') + )