Repository: hgrecco/pint

Issue:
Unit object gives wrong unit when mixing aliases
When creating a unit object with mixed aliases (`ureg.Unit('hour/hr')`), it returns a wrong unit. It seems like part of it gets ignored. This does not happen when creating a quantity as `ureg.Quantity('1 hour/hr')`.

Replicating code:
```
import pint
ureg = pint.UnitRegistry()
print(ureg.Unit('hour/hr'))       # prints "<Unit('1 / hour')>"

print(ureg.Quantity('1 hour/hr')) # prints "<Quantity(1.0, 'dimensionless')>"
```

In my model, the user sometimes uses units like "Gt CO2/yr" and "trillion USD/year". Costs per gigaton of CO2 become messed up because the "yr/year" doesn't disappear. I cannot switch to `Quantity`, since I use pint through the optimisation package Pyomo, which uses `Unit`.

Discussion:

Patch:
diff --git a/CHANGES b/CHANGES
index 720de50..8f6d985 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 6f8ff40..488189a 100644
--- a/pint/registry.py
+++ b/pint/registry.py
@@ -1193,7 +1193,12 @@ class BaseRegistry(metaclass=RegistryMeta):
         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 @@ class BaseRegistry(metaclass=RegistryMeta):
         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 @@ class BaseRegistry(metaclass=RegistryMeta):
                 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


Test patch:
diff --git a/pint/testsuite/test_quantity.py b/pint/testsuite/test_quantity.py
index c29fd19..b00b601 100644
--- a/pint/testsuite/test_quantity.py
+++ b/pint/testsuite/test_quantity.py
@@ -664,6 +664,17 @@ class TestQuantity(QuantityTestCase):
         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):