diff --git a/CHANGES b/CHANGES index 720de5092..8f6d985e1 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,7 @@ Pint Changelog - Add `pint.testing` with functions to compare pint objects in tests (Issue #1421). - Fix handling modulo & floordiv operator in pint_eval (Issue #1470) - Fix `to_compact` and `infer_base_unit` for non-float non_int_type. +- Fix parsing of units string with same canonalized name (Issue #1441 & #1142) ### Breaking Changes diff --git a/pint/registry.py b/pint/registry.py index 6f8ff4039..488189a2d 100644 --- a/pint/registry.py +++ b/pint/registry.py @@ -1193,7 +1193,12 @@ def parse_units( units = self._parse_units(input_string, as_delta, case_sensitive) return self.Unit(units) - def _parse_units(self, input_string, as_delta=True, case_sensitive=None): + def _parse_units( + self, + input_string: str, + as_delta: bool = True, + case_sensitive: Optional[bool] = None, + ) -> UnitsContainerT: """Parse a units expression and returns a UnitContainer with the canonical names. """ @@ -1215,7 +1220,7 @@ def _parse_units(self, input_string, as_delta=True, case_sensitive=None): if units.scale != 1: raise ValueError("Unit expression cannot have a scaling factor.") - ret = {} + ret = self.UnitsContainer({}) many = len(units) > 1 for name in units: cname = self.get_name(name, case_sensitive=case_sensitive) @@ -1226,9 +1231,7 @@ def _parse_units(self, input_string, as_delta=True, case_sensitive=None): definition = self._units[cname] if not definition.is_multiplicative: cname = "delta_" + cname - ret[cname] = value - - ret = self.UnitsContainer(ret) + ret = ret.add(cname, value) if as_delta: cache[input_string] = ret diff --git a/pint/testsuite/test_quantity.py b/pint/testsuite/test_quantity.py index c29fd19f5..b00b601b0 100644 --- a/pint/testsuite/test_quantity.py +++ b/pint/testsuite/test_quantity.py @@ -664,6 +664,17 @@ def test_to_reduced_units(self): q = self.Q_(0.5, "g*t/kg") helpers.assert_quantity_equal(q.to_reduced_units(), self.Q_(0.5, "kg")) + @pytest.mark.parametrize( + ("unit_str", "expected_unit"), + [ + ("hour/hr", {}), + ("cm centimeter cm centimeter", {"centimeter": 4}), + ], + ) + def test_unit_canonical_name_parsing(self, unit_str, expected_unit): + q = self.Q_(1, unit_str) + assert q._units == UnitsContainer(expected_unit) + # TODO: do not subclass from QuantityTestCase class TestQuantityToCompact(QuantityTestCase):