Skip to content

Commit

Permalink
Fix #1189
Browse files Browse the repository at this point in the history
Make is_compatible_with function with dimensionless types & string parsing errors.
is_compatible_with was not consistent with dimensionless types when switching arguments.
String processing was not allowing strings with any magnitude.

- Updated registry.py managing dimensionless types & discarding types not managed by pint.
- Updated unit.py using parse_expression instead of parse_units.
  • Loading branch information
jules-ch committed Oct 15, 2020
1 parent 5e59f37 commit 3481378
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 4 deletions.
2 changes: 1 addition & 1 deletion CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Pint Changelog
0.17 (unreleased)
-----------------

- Nothing changed yet.
- Fix bugs on `is_compatible_with` with dimensionless types & string parsing errors. (Issue #1189)


0.16.1 (2020-09-22)
Expand Down
3 changes: 2 additions & 1 deletion pint/quantity.py
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,8 @@ def is_compatible_with(self, other, *contexts, **ctx_kwargs):

if isinstance(other, str):
return (
self.dimensionality == self._REGISTRY.parse_units(other).dimensionality
self.dimensionality
== self._REGISTRY.parse_expression(other).dimensionality
)

return self.dimensionless
Expand Down
10 changes: 9 additions & 1 deletion pint/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,11 @@ def is_compatible_with(self, obj1, obj2, *contexts, **ctx_kwargs):
-------
bool
"""
if isinstance(obj1, (dict, bool, type(None))) or isinstance(
obj2, (dict, bool, type(None))
):
raise TypeError("Type can't be casted to Quantity")

if isinstance(obj1, (self.Quantity, self.Unit)):
return obj1.is_compatible_with(obj2, *contexts, **ctx_kwargs)

Expand All @@ -922,7 +927,10 @@ def is_compatible_with(self, obj1, obj2, *contexts, **ctx_kwargs):
obj2, *contexts, **ctx_kwargs
)

return not isinstance(obj2, (self.Quantity, self.Unit))
if isinstance(obj2, (self.Quantity, self.Unit, str)):
return self.is_compatible_with(obj2, obj1, *contexts, **ctx_kwargs)
else:
return self.Quantity(obj1).is_compatible_with(obj2, *contexts, **ctx_kwargs)

def convert(self, value, src, dst, inplace=False):
"""Convert value from some source to destination units.
Expand Down
31 changes: 31 additions & 0 deletions pint/testsuite/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import math
import re

import pytest

from pint import (
DefinitionSyntaxError,
DimensionalityError,
Expand All @@ -12,6 +14,7 @@
from pint.compat import np
from pint.registry import LazyRegistry, UnitRegistry
from pint.testsuite import CaseInsensitveQuantityTestCase, QuantityTestCase, helpers
from pint.testsuite.helpers import requires_numpy
from pint.testsuite.parameterized import ParameterizedTestCase
from pint.util import ParserHelper, UnitsContainer

Expand Down Expand Up @@ -724,6 +727,34 @@ def test_case_sensitivity(self):
ureg.parse_units("j", case_sensitive=False), UnitsContainer(joule=1)
)

@requires_numpy()
def test_is_compatible_with(self):
ureg = self.ureg

assert ureg.is_compatible_with(ureg.deg, 10.0)
assert ureg.is_compatible_with(10.0, ureg.deg)
assert ureg.is_compatible_with(ureg.km, ureg.m)
assert ureg.is_compatible_with([1, 2, 3, 4], 10.0)
assert ureg.is_compatible_with(np.array([1, 2, 3, 4]), ureg.deg)
assert ureg.is_compatible_with(10.0, np.array([1, 2, 3, 4]))
assert ureg.is_compatible_with(999.0, 10.0)
assert ureg.is_compatible_with("80 in", "35000 ft")
assert ureg.is_compatible_with("in", "35000 ft")
assert ureg.is_compatible_with("in", "ft")
assert ureg.is_compatible_with("3500 in", "ft")
assert ureg.is_compatible_with(ureg.m, "35000 ft")

assert not ureg.is_compatible_with(10.0, ureg.m)
assert not ureg.is_compatible_with(ureg.m, 10.0)
assert not ureg.is_compatible_with(ureg.m, "1 N")
assert not ureg.is_compatible_with("1 N", ureg.m)

assert ureg.is_compatible_with(ureg.hertz, ureg.nm, "spectroscopy")
with pytest.raises(TypeError):
ureg.is_compatible_with({}, {})
ureg.is_compatible_with(None, ureg.deg)
ureg.is_compatible_with(True, ureg.deg)


class TestCaseInsensitiveRegistry(CaseInsensitveQuantityTestCase):
def test_case_sensitivity(self):
Expand Down
3 changes: 2 additions & 1 deletion pint/unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ def is_compatible_with(self, other, *contexts, **ctx_kwargs):

if isinstance(other, str):
return (
self.dimensionality == self._REGISTRY.parse_units(other).dimensionality
self.dimensionality
== self._REGISTRY.parse_expression(other).dimensionality
)

return self.dimensionless
Expand Down

0 comments on commit 3481378

Please sign in to comment.