summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Linke <dalito@users.noreply.github.com>2014-06-13 02:37:06 +0200
committerDavid Linke <dalito@users.noreply.github.com>2014-06-13 02:37:06 +0200
commitc06153cbad57e8c33154d1a8e975247f5ec0f12d (patch)
tree92264fd9980ffa3949a32899af90ee89961f85d3
parent8b9ee4776164e5f6d13ceee4cccc8f01debff828 (diff)
downloadpint-c06153cbad57e8c33154d1a8e975247f5ec0f12d.tar.gz
Change: Converted functions to Quantity methods/properties
Also reorganized code in parameterized tests.
-rw-r--r--pint/quantity.py265
-rw-r--r--pint/testsuite/test_quantity.py333
2 files changed, 305 insertions, 293 deletions
diff --git a/pint/quantity.py b/pint/quantity.py
index 71f2816..74e4463 100644
--- a/pint/quantity.py
+++ b/pint/quantity.py
@@ -56,68 +56,6 @@ def _check(q1, other):
return False
-def _is_multiplicative(q): # renamed from _only_multiplicative_units
- """Check if the Quantity object has only multiplicative units.
- """
- # XXX Turn this into a method/property of _Quantity?
- return not _get_non_multiplicative_units(q)
-
-
-def _get_non_multiplicative_units(q):
- """Return a list of the of non-multiplicative units of the Quantity object
- """
- # XXX Turn this into a method/property of _Quantity?
- offset_units = [unit for unit in q.units.keys()
- if not q._REGISTRY._units[unit].is_multiplicative]
- return offset_units
-
-
-def _get_delta_units(q):
- """Return list of delta units ot the Quantity object
- """
- # XXX Turn this into a method/property of _Quantity? a class mathod?
- delta_units = [u for u in q.units.keys() if u.startswith("delta_")]
- return delta_units
-
-
-def _has_compatible_delta(q, unit):
- """"Check if Quantity object has a delta_unit that is compatible with unit
- """
- # XXX Turn this into a method/property of _Quantity?
- deltas = _get_delta_units(q)
- if 'delta_' + unit in deltas:
- return True
- else: # Look for delta units with same dimension as the offset unit
- offset_unit_dim = q._REGISTRY._units[unit].reference
- for d in deltas:
- if q._REGISTRY._units[d].reference == offset_unit_dim:
- return True
- return False
-
-
-def _ok_for_muldiv(q, no_offset_units=None):
- """Checks if Quantity object can be multiplied or divided
-
- :q: quantity object that is checked
- :no_offset_units: number of offset units in q
- """
- # XXX Turn this into a method/property of _Quantity?
- is_ok = True
- if no_offset_units is None:
- no_offset_units = len(_get_non_multiplicative_units(q))
- if no_offset_units > 1:
- is_ok = False
- if no_offset_units == 1:
- if len(q.units) > 1:
- is_ok = False
- if (len(q.units) == 1
- and not q._REGISTRY.autoconvert_offset_to_baseunit):
- is_ok = False
- if q.units.values()[0] != 1:
- is_ok = False
- return is_ok
-
-
class _Quantity(object):
"""Implements a class to describe a physical quantity:
the product of a numerical value and a unit of measurement.
@@ -344,7 +282,8 @@ class _Quantity(object):
:param op: operator function (e.g. operator.add, operator.isub)
:type op: function
"""
- if not _check(self, other): # other not from same Registry or not a Quantity
+ if not _check(self, other):
+ # other not from same Registry or not a Quantity
try:
other_magnitude = _to_magnitude(other, self.force_ndarray)
except TypeError:
@@ -368,14 +307,11 @@ class _Quantity(object):
other.dimensionality)
# Next we define some variables to make if-clauses more readable.
- reg = self._REGISTRY._units
- # For self:
- self_non_mul_units = _get_non_multiplicative_units(self)
+ self_non_mul_units = self._get_non_multiplicative_units()
is_self_multiplicative = len(self_non_mul_units) == 0
if len(self_non_mul_units) == 1:
self_non_mul_unit = self_non_mul_units[0]
- # For other:
- other_non_mul_units = _get_non_multiplicative_units(other)
+ other_non_mul_units = other._get_non_multiplicative_units()
is_other_multiplicative = len(other_non_mul_units) == 0
if len(other_non_mul_units) == 1:
other_non_mul_unit = other_non_mul_units[0]
@@ -383,25 +319,36 @@ class _Quantity(object):
# Presence of non-multiplicative units gives rise to several cases.
if is_self_multiplicative and is_other_multiplicative:
# If only self has a delta unit, other determines unit of result.
- if _get_delta_units(self) and not _get_delta_units(other):
- self._magnitude = op(self.to(other)._magnitude, other._magnitude)
+ if self._get_delta_units() and not other._get_delta_units():
+ self._magnitude = op(self._convert_magnitude(other.units),
+ other._magnitude)
self._units = copy.copy(other.units)
else:
- self._magnitude = op(self._magnitude, other.to(self)._magnitude)
- elif (len(self_non_mul_units) == 1 and len(other_non_mul_units) == 1
- # order of the dimension of offset units == 1 ?
- and reg[self_non_mul_unit].reference.values()[0] == 1
- and reg[other_non_mul_unit].reference.values()[0] == 1
- and self_non_mul_unit == other_non_mul_unit
- and op == operator.isub):
- # subtraction of two quantities with same offset unit is
- # allowed and gives a result in the corresponding delta_unit
- self._magnitude = op(self._magnitude, other._magnitude)
- self._units['delta_' + self_non_mul_unit] = self.units.pop(self_non_mul_unit)
+ self._magnitude = op(self._magnitude,
+ other.to(self.units)._magnitude)
+
+ elif (op == operator.isub and len(self_non_mul_units) == 1
+ and self.units[self_non_mul_unit] == 1
+ and not other._has_compatible_delta(self_non_mul_unit)):
+ if self.units == other.units:
+ self._magnitude = op(self._magnitude, other._magnitude)
+ else:
+ self._magnitude = op(self._magnitude,
+ other.to(self.units)._magnitude)
+ self.units['delta_' + self_non_mul_unit
+ ] = self.units.pop(self_non_mul_unit)
+
+ elif (op == operator.isub and len(other_non_mul_units) == 1
+ and other.units[other_non_mul_unit] == 1
+ and not self._has_compatible_delta(other_non_mul_unit)):
+ # we convert to self directly since it is multiplicative
+ self._magnitude = op(self._magnitude,
+ other.to(self.units)._magnitude)
+
elif (len(self_non_mul_units) == 1
# order of the dimension of offset unit == 1 ?
- and reg[self_non_mul_unit].reference.values()[0] == 1
- and _has_compatible_delta(other, self_non_mul_unit)):
+ and self._units[self_non_mul_unit] == 1
+ and other._has_compatible_delta(self_non_mul_unit)):
tu = copy.copy(self.units)
# Replace offset unit in self by the corresponding delta unit.
# This is done to prevent a shift by offset in the to()-call.
@@ -409,13 +356,13 @@ class _Quantity(object):
self._magnitude = op(self._magnitude, other.to(tu)._magnitude)
elif (len(other_non_mul_units) == 1
# order of the dimension of offset unit == 1 ?
- and reg[other_non_mul_unit].reference.values()[0] == 1
- and _has_compatible_delta(self, other_non_mul_unit)):
+ and other._units[other_non_mul_unit] == 1
+ and self._has_compatible_delta(other_non_mul_unit)):
tu = copy.copy(other.units)
# Replace offset unit in other by the corresponding delta unit.
# This is done to prevent a shift by offset in the to()-call.
tu['delta_' + other_non_mul_unit] = tu.pop(other_non_mul_unit)
- self._magnitude = op(self.to(tu)._magnitude, other._magnitude)
+ self._magnitude = op(self._convert_magnitude(tu), other._magnitude)
self._units = copy.copy(other.units)
else:
raise OffsetUnitCalculusError(self.units, other.units)
@@ -430,7 +377,8 @@ class _Quantity(object):
:param op: operator function (e.g. operator.add, operator.isub)
:type op: function
"""
- if not _check(self, other): # other not from same Registry or not a Quantity
+ if not _check(self, other):
+ # other not from same Registry or not a Quantity
if _eq(other, 0, True):
# If the other value is 0 (but not Quantity 0)
# do the operation without checking units.
@@ -453,14 +401,11 @@ class _Quantity(object):
other.dimensionality)
# Next we define some variables to make if-clauses more readable.
- reg = self._REGISTRY._units
- # For self:
- self_non_mul_units = _get_non_multiplicative_units(self)
+ self_non_mul_units = self._get_non_multiplicative_units()
is_self_multiplicative = len(self_non_mul_units) == 0
if len(self_non_mul_units) == 1:
self_non_mul_unit = self_non_mul_units[0]
- # For other:
- other_non_mul_units = _get_non_multiplicative_units(other)
+ other_non_mul_units = other._get_non_multiplicative_units()
is_other_multiplicative = len(other_non_mul_units) == 0
if len(other_non_mul_units) == 1:
other_non_mul_unit = other_non_mul_units[0]
@@ -468,42 +413,53 @@ class _Quantity(object):
# Presence of non-multiplicative units gives rise to several cases.
if is_self_multiplicative and is_other_multiplicative:
# If only self has a delta unit, other determines unit of result.
- if _get_delta_units(self) and not _get_delta_units(other):
- magnitude = op(self.to(other)._magnitude, other._magnitude)
+ if self._get_delta_units() and not other._get_delta_units():
+ magnitude = op(self._convert_magnitude(other.units),
+ other._magnitude)
units = copy.copy(other.units)
else:
units = copy.copy(self.units)
- magnitude = op(self._magnitude, other.to(self)._magnitude)
- elif (len(self_non_mul_units) == 1 and len(other_non_mul_units) == 1
- # order of the dimension of offset units == 1 ?
- and reg[self_non_mul_unit].reference.values()[0] == 1
- and reg[other_non_mul_unit].reference.values()[0] == 1
- and self_non_mul_unit == other_non_mul_unit
- and op == operator.sub):
- # subtraction of two quantities with same offset unit is
- # allowed and gives a result in the corresponding delta_unit
- magnitude = op(self._magnitude, other._magnitude)
+ magnitude = op(self._magnitude,
+ other.to(self.units).magnitude)
+
+ elif (op == operator.sub and len(self_non_mul_units) == 1
+ and self.units[self_non_mul_unit] == 1
+ and not other._has_compatible_delta(self_non_mul_unit)):
+ if self.units == other.units:
+ magnitude = op(self._magnitude, other._magnitude)
+ else:
+ magnitude = op(self._magnitude,
+ other.to(self.units)._magnitude)
units = copy.copy(self.units)
units['delta_' + self_non_mul_unit] = units.pop(self_non_mul_unit)
+
+ elif (op == operator.sub and len(other_non_mul_units) == 1
+ and other.units[other_non_mul_unit] == 1
+ and not self._has_compatible_delta(other_non_mul_unit)):
+ # we convert to self directly since it is multiplicative
+ magnitude = op(self._magnitude,
+ other.to(self.units)._magnitude)
+ units = copy.copy(self.units)
+
elif (len(self_non_mul_units) == 1
# order of the dimension of offset unit == 1 ?
- and reg[self_non_mul_unit].reference.values()[0] == 1
- and _has_compatible_delta(other, self_non_mul_unit)):
+ and self._units[self_non_mul_unit] == 1
+ and other._has_compatible_delta(self_non_mul_unit)):
tu = copy.copy(self.units)
# Replace offset unit in self by the corresponding delta unit.
# This is done to prevent a shift by offset in the to()-call.
tu['delta_' + self_non_mul_unit] = tu.pop(self_non_mul_unit)
- magnitude = op(self._magnitude, other.to(tu)._magnitude)
+ magnitude = op(self._magnitude, other.to(tu).magnitude)
units = copy.copy(self.units)
elif (len(other_non_mul_units) == 1
# order of the dimension of offset unit == 1 ?
- and reg[other_non_mul_unit].reference.values()[0] == 1
- and _has_compatible_delta(self, other_non_mul_unit)):
+ and other._units[other_non_mul_unit] == 1
+ and self._has_compatible_delta(other_non_mul_unit)):
tu = copy.copy(other.units)
# Replace offset unit in other by the corresponding delta unit.
# This is done to prevent a shift by offset in the to()-call.
tu['delta_' + other_non_mul_unit] = tu.pop(other_non_mul_unit)
- magnitude = op(self.to(tu)._magnitude, other._magnitude)
+ magnitude = op(self._convert_magnitude(tu), other._magnitude)
units = copy.copy(other.units)
else:
raise OffsetUnitCalculusError(self.units, other.units)
@@ -546,11 +502,11 @@ class _Quantity(object):
if units_op is None:
units_op = magnitude_op
- offset_units_self = _get_non_multiplicative_units(self)
+ offset_units_self = self._get_non_multiplicative_units()
no_offset_units_self = len(offset_units_self)
if not _check(self, other):
- if not _ok_for_muldiv(self, no_offset_units_self):
+ if not self._ok_for_muldiv(no_offset_units_self):
raise OffsetUnitCalculusError(self.units,
getattr(other, 'units', ''))
if len(offset_units_self) == 1:
@@ -566,17 +522,17 @@ class _Quantity(object):
self._units = units_op(self._units, UnitsContainer())
return self
- if not _ok_for_muldiv(self, no_offset_units_self):
+ if not self._ok_for_muldiv(no_offset_units_self):
raise OffsetUnitCalculusError(self.units, other.units)
elif no_offset_units_self == 1 and len(self.units) == 1:
self.ito_base_units()
- no_offset_units_other = len(_get_non_multiplicative_units(other))
+ no_offset_units_other = len(other._get_non_multiplicative_units())
- if not _ok_for_muldiv(other, no_offset_units_other):
+ if not other._ok_for_muldiv(no_offset_units_other):
raise OffsetUnitCalculusError(self.units, other.units)
elif no_offset_units_other == 1 and len(other.units) == 1:
- other.ito_base_units()
+ other.ito_base_units()
self._magnitude = magnitude_op(self._magnitude, other._magnitude)
self._units = units_op(self._units, other._units)
@@ -596,11 +552,11 @@ class _Quantity(object):
if units_op is None:
units_op = magnitude_op
- offset_units_self = _get_non_multiplicative_units(self)
+ offset_units_self = self._get_non_multiplicative_units()
no_offset_units_self = len(offset_units_self)
if not _check(self, other):
- if not _ok_for_muldiv(self, no_offset_units_self):
+ if not self._ok_for_muldiv(no_offset_units_self):
raise OffsetUnitCalculusError(self.units,
getattr(other, 'units', ''))
if len(offset_units_self) == 1:
@@ -620,14 +576,14 @@ class _Quantity(object):
new_self = self
- if not _ok_for_muldiv(self, no_offset_units_self):
+ if not self._ok_for_muldiv(no_offset_units_self):
raise OffsetUnitCalculusError(self.units, other.units)
elif no_offset_units_self == 1 and len(self.units) == 1:
new_self = self.to_base_units()
- no_offset_units_other = len(_get_non_multiplicative_units(other))
+ no_offset_units_other = len(other._get_non_multiplicative_units())
- if not _ok_for_muldiv(other, no_offset_units_other):
+ if not other._ok_for_muldiv(no_offset_units_other):
raise OffsetUnitCalculusError(self.units, other.units)
elif no_offset_units_other == 1 and len(other.units) == 1:
other = other.to_base_units()
@@ -672,8 +628,8 @@ class _Quantity(object):
except TypeError:
return NotImplemented
- no_offset_units_self = len(_get_non_multiplicative_units(self))
- if not _ok_for_muldiv(self, no_offset_units_self):
+ no_offset_units_self = len(self._get_non_multiplicative_units())
+ if not self._ok_for_muldiv(no_offset_units_self):
raise OffsetUnitCalculusError(self.units, '')
elif no_offset_units_self == 1 and len(self.units) == 1:
self = self.to_base_units()
@@ -686,8 +642,8 @@ class _Quantity(object):
except TypeError:
return NotImplemented
- no_offset_units_self = len(_get_non_multiplicative_units(self))
- if not _ok_for_muldiv(self, no_offset_units_self):
+ no_offset_units_self = len(self._get_non_multiplicative_units())
+ if not self._ok_for_muldiv(no_offset_units_self):
raise OffsetUnitCalculusError(self.units, '')
elif no_offset_units_self == 1 and len(self.units) == 1:
self = self.to_base_units()
@@ -707,7 +663,7 @@ class _Quantity(object):
except TypeError:
return NotImplemented
else:
- if not _is_multiplicative(self):
+ if not self._is_multiplicative:
self.ito_base_units()
self._magnitude **= _to_magnitude(other, self.force_ndarray)
self._units **= other
@@ -720,7 +676,7 @@ class _Quantity(object):
return NotImplemented
else:
new_self = self
- if not _is_multiplicative(self):
+ if not self._is_multiplicative:
new_self = self.to_base_units()
magnitude = new_self._magnitude ** _to_magnitude(other, self.force_ndarray)
@@ -1141,3 +1097,58 @@ class _Quantity(object):
error = error * abs(self.magnitude)
return self._REGISTRY.Measurement(copy.copy(self.magnitude), error, self.units)
+
+ # methods/properties that help for math operations with offset units
+ @property
+ def _is_multiplicative(self):
+ """Check if the Quantity object has only multiplicative units.
+ """
+ # XXX Turn this into a method/property of _Quantity?
+ return not self._get_non_multiplicative_units()
+
+ def _get_non_multiplicative_units(self):
+ """Return a list of the of non-multiplicative units of the Quantity object
+ """
+ offset_units = [unit for unit in self.units.keys()
+ if not self._REGISTRY._units[unit].is_multiplicative]
+ return offset_units
+
+ def _get_delta_units(self):
+ """Return list of delta units ot the Quantity object
+ """
+ delta_units = [u for u in self.units.keys() if u.startswith("delta_")]
+ return delta_units
+
+ def _has_compatible_delta(self, unit):
+ """"Check if Quantity object has a delta_unit that is compatible with unit
+ """
+ deltas = self._get_delta_units()
+ if 'delta_' + unit in deltas:
+ return True
+ else: # Look for delta units with same dimension as the offset unit
+ offset_unit_dim = self._REGISTRY._units[unit].reference
+ for d in deltas:
+ if self._REGISTRY._units[d].reference == offset_unit_dim:
+ return True
+ return False
+
+ def _ok_for_muldiv(self, no_offset_units=None):
+ """Checks if Quantity object can be multiplied or divided
+
+ :q: quantity object that is checked
+ :no_offset_units: number of offset units in q
+ """
+ is_ok = True
+ if no_offset_units is None:
+ no_offset_units = len(self._get_non_multiplicative_units())
+ if no_offset_units > 1:
+ is_ok = False
+ if no_offset_units == 1:
+ if len(self._units) > 1:
+ is_ok = False
+ if (len(self._units) == 1
+ and not self._REGISTRY.autoconvert_offset_to_baseunit):
+ is_ok = False
+ if self._units.values()[0] != 1:
+ is_ok = False
+ return is_ok
diff --git a/pint/testsuite/test_quantity.py b/pint/testsuite/test_quantity.py
index 7a428fb..8778d73 100644
--- a/pint/testsuite/test_quantity.py
+++ b/pint/testsuite/test_quantity.py
@@ -453,6 +453,10 @@ class TestDimensionsWithDefaultRegistry(TestDimensions):
class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase):
+ def setup(self):
+ self.ureg.autoconvert_offset_to_baseunit = False
+ self.ureg.default_as_delta = True
+
additions = [
# --- input tuple -------------------- | -- expected result --
(((100, 'kelvin'), (10, 'kelvin')), (110, 'kelvin')),
@@ -498,31 +502,69 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase):
(((100, 'delta_degF'), (10, 'delta_degF')), (110, 'delta_degF')),
]
+ @ParameterizedTestCase.parameterize(("input", "expected_output"),
+ additions)
+ def test_addition(self, input_tuple, expected):
+ self.ureg.autoconvert_offset_to_baseunit = False
+ qin1, qin2 = input_tuple
+ q1, q2 = self.Q_(*qin1), self.Q_(*qin2)
+ # update input tuple with new values to have correct values on failure
+ input_tuple = q1, q2
+ if expected == 'error':
+ self.assertRaises(OffsetUnitCalculusError, op.add, q1, q2)
+ else:
+ expected = self.Q_(*expected)
+ self.assertEqual(op.add(q1, q2).units, expected.units)
+ self.assertQuantityAlmostEqual(op.add(q1, q2), expected,
+ atol=0.01)
+
+ @helpers.requires_numpy()
+ @ParameterizedTestCase.parameterize(("input", "expected_output"),
+ additions)
+ def test_inplace_addition(self, input_tuple, expected):
+ self.ureg.autoconvert_offset_to_baseunit = False
+ (q1v, q1u), (q2v, q2u) = input_tuple
+ # update input tuple with new values to have correct values on failure
+ input_tuple = ((np.array([q1v]*2, dtype=np.float), q1u),
+ (np.array([q2v]*2, dtype=np.float), q2u))
+ Q_ = self.Q_
+ qin1, qin2 = input_tuple
+ q1, q2 = Q_(*qin1), Q_(*qin2)
+ q1_cp = copy.copy(q1)
+ if expected == 'error':
+ self.assertRaises(OffsetUnitCalculusError, op.iadd, q1_cp, q2)
+ else:
+ expected = np.array([expected[0]]*2, dtype=np.float), expected[1]
+ self.assertEqual(op.iadd(q1_cp, q2).units, Q_(*expected).units)
+ q1_cp = copy.copy(q1)
+ self.assertQuantityAlmostEqual(op.iadd(q1_cp, q2), Q_(*expected),
+ atol=0.01)
+
subtractions = [
(((100, 'kelvin'), (10, 'kelvin')), (90, 'kelvin')),
- (((100, 'kelvin'), (10, 'degC')), 'error'),
- (((100, 'kelvin'), (10, 'degF')), 'error'),
+ (((100, 'kelvin'), (10, 'degC')), (-183.15, 'kelvin')),
+ (((100, 'kelvin'), (10, 'degF')), (-160.93, 'kelvin')),
(((100, 'kelvin'), (10, 'degR')), (94.44, 'kelvin')),
(((100, 'kelvin'), (10, 'delta_degC')), (90, 'kelvin')),
(((100, 'kelvin'), (10, 'delta_degF')), (94.44, 'kelvin')),
- (((100, 'degC'), (10, 'kelvin')), 'error'),
+ (((100, 'degC'), (10, 'kelvin')), (363.15, 'delta_degC')),
(((100, 'degC'), (10, 'degC')), (90, 'delta_degC')),
- (((100, 'degC'), (10, 'degF')), 'error'),
- (((100, 'degC'), (10, 'degR')), 'error'),
+ (((100, 'degC'), (10, 'degF')), (112.22, 'delta_degC')),
+ (((100, 'degC'), (10, 'degR')), (367.59, 'delta_degC')),
(((100, 'degC'), (10, 'delta_degC')), (90, 'degC')),
(((100, 'degC'), (10, 'delta_degF')), (94.44, 'degC')),
- (((100, 'degF'), (10, 'kelvin')), 'error'),
- (((100, 'degF'), (10, 'degC')), 'error'),
+ (((100, 'degF'), (10, 'kelvin')), (541.67, 'delta_degF')),
+ (((100, 'degF'), (10, 'degC')), (50, 'delta_degF')),
(((100, 'degF'), (10, 'degF')), (90, 'delta_degF')),
- (((100, 'degF'), (10, 'degR')), 'error'),
+ (((100, 'degF'), (10, 'degR')), (549.67, 'delta_degF')),
(((100, 'degF'), (10, 'delta_degC')), (82, 'degF')),
(((100, 'degF'), (10, 'delta_degF')), (90, 'degF')),
(((100, 'degR'), (10, 'kelvin')), (82, 'degR')),
- (((100, 'degR'), (10, 'degC')), 'error'),
- (((100, 'degR'), (10, 'degF')), 'error'),
+ (((100, 'degR'), (10, 'degC')), (-409.67, 'degR')),
+ (((100, 'degR'), (10, 'degF')), (-369.67, 'degR')),
(((100, 'degR'), (10, 'degR')), (90, 'degR')),
(((100, 'degR'), (10, 'delta_degC')), (82, 'degR')),
(((100, 'degR'), (10, 'delta_degF')), (90, 'degR')),
@@ -542,6 +584,44 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase):
(((100, 'delta_degF'), (10, 'delta_degF')), (90, 'delta_degF')),
]
+ @ParameterizedTestCase.parameterize(("input", "expected_output"),
+ subtractions)
+ def test_subtraction(self, input_tuple, expected):
+ self.ureg.autoconvert_offset_to_baseunit = False
+ qin1, qin2 = input_tuple
+ q1, q2 = self.Q_(*qin1), self.Q_(*qin2)
+ input_tuple = q1, q2
+ if expected == 'error':
+ self.assertRaises(OffsetUnitCalculusError, op.sub, q1, q2)
+ else:
+ expected = self.Q_(*expected)
+ self.assertEqual(op.sub(q1, q2).units, expected.units)
+ self.assertQuantityAlmostEqual(op.sub(q1, q2), expected,
+ atol=0.01)
+
+# @unittest.expectedFailure
+ @helpers.requires_numpy()
+ @ParameterizedTestCase.parameterize(("input", "expected_output"),
+ subtractions)
+ def test_inplace_subtraction(self, input_tuple, expected):
+ self.ureg.autoconvert_offset_to_baseunit = False
+ (q1v, q1u), (q2v, q2u) = input_tuple
+ # update input tuple with new values to have correct values on failure
+ input_tuple = ((np.array([q1v]*2, dtype=np.float), q1u),
+ (np.array([q2v]*2, dtype=np.float), q2u))
+ Q_ = self.Q_
+ qin1, qin2 = input_tuple
+ q1, q2 = Q_(*qin1), Q_(*qin2)
+ q1_cp = copy.copy(q1)
+ if expected == 'error':
+ self.assertRaises(OffsetUnitCalculusError, op.isub, q1_cp, q2)
+ else:
+ expected = np.array([expected[0]]*2, dtype=np.float), expected[1]
+ self.assertEqual(op.isub(q1_cp, q2).units, Q_(*expected).units)
+ q1_cp = copy.copy(q1)
+ self.assertQuantityAlmostEqual(op.isub(q1_cp, q2), Q_(*expected),
+ atol=0.01)
+
multiplications = [
(((100, 'kelvin'), (10, 'kelvin')), (1000, 'kelvin**2')),
(((100, 'kelvin'), (10, 'degC')), 'error'),
@@ -586,6 +666,43 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase):
(((100, 'delta_degF'), (10, 'delta_degF')), (1000, 'delta_degF**2')),
]
+ @ParameterizedTestCase.parameterize(("input", "expected_output"),
+ multiplications)
+ def test_multiplication(self, input_tuple, expected):
+ self.ureg.autoconvert_offset_to_baseunit = False
+ qin1, qin2 = input_tuple
+ q1, q2 = self.Q_(*qin1), self.Q_(*qin2)
+ input_tuple = q1, q2
+ if expected == 'error':
+ self.assertRaises(OffsetUnitCalculusError, op.mul, q1, q2)
+ else:
+ expected = self.Q_(*expected)
+ self.assertEqual(op.mul(q1, q2).units, expected.units)
+ self.assertQuantityAlmostEqual(op.mul(q1, q2), expected,
+ atol=0.01)
+
+ @helpers.requires_numpy()
+ @ParameterizedTestCase.parameterize(("input", "expected_output"),
+ multiplications)
+ def test_inplace_multiplication(self, input_tuple, expected):
+ self.ureg.autoconvert_offset_to_baseunit = False
+ (q1v, q1u), (q2v, q2u) = input_tuple
+ # update input tuple with new values to have correct values on failure
+ input_tuple = ((np.array([q1v]*2, dtype=np.float), q1u),
+ (np.array([q2v]*2, dtype=np.float), q2u))
+ Q_ = self.Q_
+ qin1, qin2 = input_tuple
+ q1, q2 = Q_(*qin1), Q_(*qin2)
+ q1_cp = copy.copy(q1)
+ if expected == 'error':
+ self.assertRaises(OffsetUnitCalculusError, op.imul, q1_cp, q2)
+ else:
+ expected = np.array([expected[0]]*2, dtype=np.float), expected[1]
+ self.assertEqual(op.imul(q1_cp, q2).units, Q_(*expected).units)
+ q1_cp = copy.copy(q1)
+ self.assertQuantityAlmostEqual(op.imul(q1_cp, q2), Q_(*expected),
+ atol=0.01)
+
divisions = [
(((100, 'kelvin'), (10, 'kelvin')), (10, '')),
(((100, 'kelvin'), (10, 'degC')), 'error'),
@@ -630,150 +747,6 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase):
(((100, 'delta_degF'), (10, 'delta_degF')), (10, '')),
]
- multiplications_with_autoconvert_to_baseunit = [
- (((100, 'kelvin'), (10, 'degC')), (28315., 'kelvin**2')),
- (((100, 'kelvin'), (10, 'degF')), (26092.78, 'kelvin**2')),
-
- (((100, 'degC'), (10, 'kelvin')), (3731.5, 'kelvin**2')),
- (((100, 'degC'), (10, 'degC')), (105657.42, 'kelvin**2')),
- (((100, 'degC'), (10, 'degF')), (97365.20, 'kelvin**2')),
- (((100, 'degC'), (10, 'degR')), (3731.5, 'kelvin*degR')),
- (((100, 'degC'), (10, 'delta_degC')), (3731.5, 'kelvin*delta_degC')),
- (((100, 'degC'), (10, 'delta_degF')), (3731.5, 'kelvin*delta_degF')),
-
- (((100, 'degF'), (10, 'kelvin')), (3109.28, 'kelvin**2')),
- (((100, 'degF'), (10, 'degC')), (88039.20, 'kelvin**2')),
- (((100, 'degF'), (10, 'degF')), (81129.69, 'kelvin**2')),
- (((100, 'degF'), (10, 'degR')), (3109.28, 'kelvin*degR')),
- (((100, 'degF'), (10, 'delta_degC')), (3109.28, 'kelvin*delta_degC')),
- (((100, 'degF'), (10, 'delta_degF')), (3109.28, 'kelvin*delta_degF')),
-
- (((100, 'degR'), (10, 'degC')), (28315., 'degR*kelvin')),
- (((100, 'degR'), (10, 'degF')), (26092.78, 'degR*kelvin')),
-
- (((100, 'delta_degC'), (10, 'degC')), (28315., 'delta_degC*kelvin')),
- (((100, 'delta_degC'), (10, 'degF')), (26092.78, 'delta_degC*kelvin')),
-
- (((100, 'delta_degF'), (10, 'degC')), (28315., 'delta_degF*kelvin')),
- (((100, 'delta_degF'), (10, 'degF')), (26092.78, 'delta_degF*kelvin')),
- ]
-
- def setup(self):
- self.ureg.autoconvert_offset_to_baseunit = False
- self.ureg.default_as_delta = True
-
- @ParameterizedTestCase.parameterize(("input", "expected_output"),
- additions)
- def test_addition(self, input_tuple, expected):
- self.ureg.autoconvert_offset_to_baseunit = False
- qin1, qin2 = input_tuple
- q1, q2 = self.Q_(*qin1), self.Q_(*qin2)
- # update input tuple with new values to have correct values on failure
- input_tuple = q1, q2
- if expected == 'error':
- self.assertRaises(OffsetUnitCalculusError, op.add, q1, q2)
- else:
- expected = self.Q_(*expected)
- self.assertEqual(op.add(q1, q2).units, expected.units)
- self.assertQuantityAlmostEqual(op.add(q1, q2), expected,
- atol=0.01)
-
- @helpers.requires_numpy()
- @ParameterizedTestCase.parameterize(("input", "expected_output"),
- additions)
- def test_inplace_addition(self, input_tuple, expected):
- self.ureg.autoconvert_offset_to_baseunit = False
- (q1v, q1u), (q2v, q2u) = input_tuple
- # update input tuple with new values to have correct values on failure
- input_tuple = ((np.array([q1v]*2, dtype=np.float), q1u),
- (np.array([q2v]*2, dtype=np.float), q2u))
- Q_ = self.Q_
- qin1, qin2 = input_tuple
- q1, q2 = Q_(*qin1), Q_(*qin2)
- q1_copy = copy.copy(q1)
- if expected == 'error':
- self.assertRaises(OffsetUnitCalculusError, op.iadd, q1, q2)
- else:
- expected = np.array([expected[0]]*2, dtype=np.float), expected[1]
- self.assertEqual(op.iadd(q1, q2).units, Q_(*expected).units)
- q1 = q1_copy
- self.assertQuantityAlmostEqual(op.iadd(q1, q2), Q_(*expected),
- atol=0.01)
-
- @ParameterizedTestCase.parameterize(("input", "expected_output"),
- subtractions)
- def test_subtraction(self, input_tuple, expected):
- self.ureg.autoconvert_offset_to_baseunit = False
- qin1, qin2 = input_tuple
- q1, q2 = self.Q_(*qin1), self.Q_(*qin2)
- input_tuple = q1, q2
- if expected == 'error':
- self.assertRaises(OffsetUnitCalculusError, op.sub, q1, q2)
- else:
- expected = self.Q_(*expected)
- self.assertEqual(op.sub(q1, q2).units, expected.units)
- self.assertQuantityAlmostEqual(op.sub(q1, q2), expected,
- atol=0.01)
-
- @helpers.requires_numpy()
- @ParameterizedTestCase.parameterize(("input", "expected_output"),
- subtractions)
- def test_inplace_subtraction(self, input_tuple, expected):
- self.ureg.autoconvert_offset_to_baseunit = False
- (q1v, q1u), (q2v, q2u) = input_tuple
- # update input tuple with new values to have correct values on failure
- input_tuple = ((np.array([q1v]*2, dtype=np.float), q1u),
- (np.array([q2v]*2, dtype=np.float), q2u))
- Q_ = self.Q_
- qin1, qin2 = input_tuple
- q1, q2 = Q_(*qin1), Q_(*qin2)
- q1_copy = copy.copy(q1)
- if expected == 'error':
- self.assertRaises(OffsetUnitCalculusError, op.isub, q1, q2)
- else:
- expected = np.array([expected[0]]*2, dtype=np.float), expected[1]
- self.assertEqual(op.isub(q1, q2).units, Q_(*expected).units)
- q1 = q1_copy
- self.assertQuantityAlmostEqual(op.isub(q1, q2), Q_(*expected),
- atol=0.01)
-
- @ParameterizedTestCase.parameterize(("input", "expected_output"),
- multiplications)
- def test_multiplication(self, input_tuple, expected):
- self.ureg.autoconvert_offset_to_baseunit = False
- qin1, qin2 = input_tuple
- q1, q2 = self.Q_(*qin1), self.Q_(*qin2)
- input_tuple = q1, q2
- if expected == 'error':
- self.assertRaises(OffsetUnitCalculusError, op.mul, q1, q2)
- else:
- expected = self.Q_(*expected)
- self.assertEqual(op.mul(q1, q2).units, expected.units)
- self.assertQuantityAlmostEqual(op.mul(q1, q2), expected,
- atol=0.01)
-
- @helpers.requires_numpy()
- @ParameterizedTestCase.parameterize(("input", "expected_output"),
- multiplications)
- def test_inplace_multiplication(self, input_tuple, expected):
- self.ureg.autoconvert_offset_to_baseunit = False
- (q1v, q1u), (q2v, q2u) = input_tuple
- # update input tuple with new values to have correct values on failure
- input_tuple = ((np.array([q1v]*2, dtype=np.float), q1u),
- (np.array([q2v]*2, dtype=np.float), q2u))
- Q_ = self.Q_
- qin1, qin2 = input_tuple
- q1, q2 = Q_(*qin1), Q_(*qin2)
- q1_copy = copy.copy(q1)
- if expected == 'error':
- self.assertRaises(OffsetUnitCalculusError, op.imul, q1, q2)
- else:
- expected = np.array([expected[0]]*2, dtype=np.float), expected[1]
- self.assertEqual(op.imul(q1, q2).units, Q_(*expected).units)
- q1 = q1_copy
- self.assertQuantityAlmostEqual(op.imul(q1, q2), Q_(*expected),
- atol=0.01)
-
@ParameterizedTestCase.parameterize(("input", "expected_output"),
divisions)
def test_truedivision(self, input_tuple, expected):
@@ -801,20 +774,48 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase):
Q_ = self.Q_
qin1, qin2 = input_tuple
q1, q2 = Q_(*qin1), Q_(*qin2)
- q1_copy = copy.copy(q1)
+ q1_cp = copy.copy(q1)
if expected == 'error':
- self.assertRaises(OffsetUnitCalculusError, op.itruediv, q1, q2)
+ self.assertRaises(OffsetUnitCalculusError, op.itruediv, q1_cp, q2)
else:
expected = np.array([expected[0]]*2, dtype=np.float), expected[1]
- self.assertEqual(op.itruediv(q1, q2).units, Q_(*expected).units)
- q1 = q1_copy
- self.assertQuantityAlmostEqual(op.itruediv(q1, q2), Q_(*expected),
- atol=0.01)
+ self.assertEqual(op.itruediv(q1_cp, q2).units, Q_(*expected).units)
+ q1_cp = copy.copy(q1)
+ self.assertQuantityAlmostEqual(op.itruediv(q1_cp, q2),
+ Q_(*expected), atol=0.01)
+
+ multiplications_with_autoconvert_to_baseunit = [
+ (((100, 'kelvin'), (10, 'degC')), (28315., 'kelvin**2')),
+ (((100, 'kelvin'), (10, 'degF')), (26092.78, 'kelvin**2')),
+
+ (((100, 'degC'), (10, 'kelvin')), (3731.5, 'kelvin**2')),
+ (((100, 'degC'), (10, 'degC')), (105657.42, 'kelvin**2')),
+ (((100, 'degC'), (10, 'degF')), (97365.20, 'kelvin**2')),
+ (((100, 'degC'), (10, 'degR')), (3731.5, 'kelvin*degR')),
+ (((100, 'degC'), (10, 'delta_degC')), (3731.5, 'kelvin*delta_degC')),
+ (((100, 'degC'), (10, 'delta_degF')), (3731.5, 'kelvin*delta_degF')),
+
+ (((100, 'degF'), (10, 'kelvin')), (3109.28, 'kelvin**2')),
+ (((100, 'degF'), (10, 'degC')), (88039.20, 'kelvin**2')),
+ (((100, 'degF'), (10, 'degF')), (81129.69, 'kelvin**2')),
+ (((100, 'degF'), (10, 'degR')), (3109.28, 'kelvin*degR')),
+ (((100, 'degF'), (10, 'delta_degC')), (3109.28, 'kelvin*delta_degC')),
+ (((100, 'degF'), (10, 'delta_degF')), (3109.28, 'kelvin*delta_degF')),
+
+ (((100, 'degR'), (10, 'degC')), (28315., 'degR*kelvin')),
+ (((100, 'degR'), (10, 'degF')), (26092.78, 'degR*kelvin')),
+
+ (((100, 'delta_degC'), (10, 'degC')), (28315., 'delta_degC*kelvin')),
+ (((100, 'delta_degC'), (10, 'degF')), (26092.78, 'delta_degC*kelvin')),
+
+ (((100, 'delta_degF'), (10, 'degC')), (28315., 'delta_degF*kelvin')),
+ (((100, 'delta_degF'), (10, 'degF')), (26092.78, 'delta_degF*kelvin')),
+ ]
@ParameterizedTestCase.parameterize(
("input", "expected_output"),
multiplications_with_autoconvert_to_baseunit)
- def test_multiplication_with_autconvert(self, input_tuple, expected):
+ def test_multiplication_with_autoconvert(self, input_tuple, expected):
self.ureg.autoconvert_offset_to_baseunit = True
qin1, qin2 = input_tuple
q1, q2 = self.Q_(*qin1), self.Q_(*qin2)
@@ -840,14 +841,14 @@ class TestOffsetUnitMath(QuantityTestCase, ParameterizedTestCase):
Q_ = self.Q_
qin1, qin2 = input_tuple
q1, q2 = Q_(*qin1), Q_(*qin2)
- q1_copy = copy.copy(q1)
+ q1_cp = copy.copy(q1)
if expected == 'error':
- self.assertRaises(OffsetUnitCalculusError, op.imul, q1, q2)
+ self.assertRaises(OffsetUnitCalculusError, op.imul, q1_cp, q2)
else:
expected = np.array([expected[0]]*2, dtype=np.float), expected[1]
- self.assertEqual(op.imul(q1, q2).units, Q_(*expected).units)
- q1 = q1_copy
- self.assertQuantityAlmostEqual(op.imul(q1, q2), Q_(*expected),
+ self.assertEqual(op.imul(q1_cp, q2).units, Q_(*expected).units)
+ q1_cp = copy.copy(q1)
+ self.assertQuantityAlmostEqual(op.imul(q1_cp, q2), Q_(*expected),
atol=0.01)
multiplications_with_scalar = [