Repository: hgrecco/pint

Issue:
DimensionalityError with auto_reduce_dimensions=True
I have encountered the following situation: a division between two quantities gives an error depending on the operand's order:
```
>>> from pint import UnitRegistry
>>> ureg = UnitRegistry(auto_reduce_dimensions=True)
>>> velocity = 1 *ureg.m/ureg.s
>>> cross_section = 1 * ureg.um**2
>>> velocity / cross_section
<Quantity(1000000.0, '1 / micrometer / second')>
>>> 1 / (velocity / cross_section)
<Quantity(1e-06, 'micrometer * second')>
>>> cross_section/velocity
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/quantity.py", line 911, in __truediv__
    return self._mul_div(other, operator.truediv)
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/quantity.py", line 75, in wrapped
    result = f(self, *args, **kwargs)
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/quantity.py", line 62, in wrapped
    result.ito_reduced_units()
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/quantity.py", line 443, in ito_reduced_units
    return self.ito(newunits)
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/quantity.py", line 362, in ito
    **ctx_kwargs)
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/quantity.py", line 351, in _convert_magnitude
    inplace=isinstance(self._magnitude, ndarray))
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/registry.py", line 711, in convert
    return self._convert(value, src, dst, inplace)
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/registry.py", line 1242, in _convert
    return super(ContextRegistry, self)._convert(value, src, dst, inplace)
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/registry.py", line 995, in _convert
    return super(NonMultiplicativeRegistry, self)._convert(value, src, dst, inplace)
  File "/home/pcatach/Projects/test/env/lib/python3.7/site-packages/pint/registry.py", line 733, in _convert
    raise DimensionalityError(src, dst, src_dim, dst_dim)
pint.errors.DimensionalityError: Cannot convert from 'micrometer ** 2 * second / meter' ([length] * [time]) to 'second' ([time])
```
The error does not occur when I have `auto_reduce_dimensions` set to `False`. It also does not occur when `cross_section` is set to `1*ureg.m**2` (but it persists if `nm`, `pm`, etc.)
`python=3.7.3`
`pint=0.9`


Discussion:

Patch:
diff --git a/pint/quantity.py b/pint/quantity.py
index 627e3f2..b83a053 100644
--- a/pint/quantity.py
+++ b/pint/quantity.py
@@ -559,7 +559,7 @@ class Quantity(PrettyIPython, SharedRegistryObject):
                 if unit1 != unit2:
                     power = self._REGISTRY._get_dimensionality_ratio(unit1, unit2)
                     if power:
-                        newunits = newunits.add(unit2, exp / power).remove(unit1)
+                        newunits = newunits.add(unit2, exp / power).remove([unit1])
                         break
 
         return self.ito(newunits)
diff --git a/pint/registry.py b/pint/registry.py
index 444b363..e0c1d36 100644
--- a/pint/registry.py
+++ b/pint/registry.py
@@ -1132,11 +1132,11 @@ class NonMultiplicativeRegistry(BaseRegistry):
         # clean src from offset units by converting to reference
         if src_offset_unit:
             value = self._units[src_offset_unit].converter.to_reference(value, inplace)
-
-        src = src.remove([src_offset_unit])
+            src = src.remove([src_offset_unit])
 
         # clean dst units from offset units
-        dst = dst.remove([dst_offset_unit])
+        if dst_offset_unit:
+            dst = dst.remove([dst_offset_unit])
 
         # Convert non multiplicative units to the dst.
         value = super()._convert(value, src, dst, inplace, False)
diff --git a/pint/util.py b/pint/util.py
index 3b6c467..d8d8c09 100644
--- a/pint/util.py
+++ b/pint/util.py
@@ -286,7 +286,7 @@ class UnitsContainer(Mapping):
         if newval:
             new._d[key] = newval
         else:
-            new._d.pop(key, None)
+            new._d.pop(key)
         new._hash = None
         return new
 
@@ -296,7 +296,7 @@ class UnitsContainer(Mapping):
         """
         new = self.copy()
         for k in keys:
-            new._d.pop(k, None)
+            new._d.pop(k)
         new._hash = None
         return new
 


Test patch:
diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py
index 145d0cc..ddbe4b3 100644
--- a/pint/testsuite/test_issues.py
+++ b/pint/testsuite/test_issues.py
@@ -670,6 +670,13 @@ class TestIssues(QuantityTestCase):
         assert a != b
         assert a != c
 
+    def test_issue902(self):
+        ureg = UnitRegistry(auto_reduce_dimensions=True)
+        velocity = 1 * ureg.m / ureg.s
+        cross_section = 1 * ureg.um ** 2
+        result = cross_section / velocity
+        assert result == 1e-12 * ureg.m * ureg.s
+
     def test_issue912(self):
         """pprint.pformat() invokes sorted() on large sets and frozensets and graciously
         handles TypeError, but not generic Exceptions. This test will fail if