From 78e06a136756bf4ba676266a64166c00570899df Mon Sep 17 00:00:00 2001 From: Wes Turner Date: Sat, 21 Dec 2019 11:03:09 -0500 Subject: [PATCH 1/2] WIP: __floordiv__, __mod__, __divmod__ #943 --- pint/quantity.py | 34 +++++++++++++++++++++++++-------- pint/testsuite/test_quantity.py | 10 +++++----- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/pint/quantity.py b/pint/quantity.py index 9fddf2fc6..1c6babe4f 100644 --- a/pint/quantity.py +++ b/pint/quantity.py @@ -664,6 +664,8 @@ def __int__(self): def __float__(self): if self.dimensionless: return float(self._convert_magnitude_not_inplace(UnitsContainer())) + # else: # ( for math.floor !? ) + # return float(self._magnitude) raise DimensionalityError(self._units, "dimensionless") def __complex__(self): @@ -1099,7 +1101,11 @@ def __ifloordiv__(self, other): elif self.dimensionless: self._magnitude = self.to("")._magnitude // other else: - raise DimensionalityError(self._units, "dimensionless") + if not hasattr(other, "dimensionless"): + magnitude = self._magnitude // other + return self.__class__(magnitude, self._units) + else: + raise DimensionalityError(self._units, "dimensionless") self._units = UnitsContainer({}) return self @@ -1110,7 +1116,11 @@ def __floordiv__(self, other): elif self.dimensionless: magnitude = self.to("")._magnitude // other else: - raise DimensionalityError(self._units, "dimensionless") + if not hasattr(other, "dimensionless"): + magnitude = self._magnitude // other + return self.__class__(magnitude, self._units) + else: + raise DimensionalityError(self._units, "dimensionless") return self.__class__(magnitude, UnitsContainer({})) @check_implemented @@ -1131,9 +1141,11 @@ def __imod__(self, other): @check_implemented def __mod__(self, other): - if not self._check(other): - other = self.__class__(other, UnitsContainer({})) - magnitude = self._magnitude % other.to(self._units)._magnitude + if self._check(other): + magnitude = self._magnitude % other.to(self._units)._magnitude + else: + # other = self.__class__(other, UnitsContainer({})) + magnitude = self._magnitude % other return self.__class__(magnitude, self._units) @check_implemented @@ -1149,9 +1161,15 @@ def __rmod__(self, other): @check_implemented def __divmod__(self, other): - if not self._check(other): - other = self.__class__(other, UnitsContainer({})) - q, r = divmod(self._magnitude, other.to(self._units)._magnitude) + if self._check(other): + q, r = divmod(self._magnitude, other.to(self._units)._magnitude) + else: + if not hasattr(other, "dimensionless"): + q, r = divmod(self._magnitude, other) + return (self.__class__(q, self._units), self.__class__(r, self._units)) + else: + other = self.__class__(other, UnitsContainer({})) + q, r = divmod(self._magnitude, other.to(self._units)._magnitude) return (self.__class__(q, UnitsContainer({})), self.__class__(r, self._units)) @check_implemented diff --git a/pint/testsuite/test_quantity.py b/pint/testsuite/test_quantity.py index 9f02eaccb..fd46a00eb 100644 --- a/pint/testsuite/test_quantity.py +++ b/pint/testsuite/test_quantity.py @@ -717,23 +717,23 @@ def _test_quantity_floordiv(self, unit, func): b = self.Q_("3*second") self.assertRaises(DimensionalityError, op.floordiv, a, b) self.assertRaises(DimensionalityError, op.floordiv, 3, b) - self.assertRaises(DimensionalityError, op.floordiv, a, 3) self.assertRaises(DimensionalityError, op.ifloordiv, a, b) self.assertRaises(DimensionalityError, op.ifloordiv, 3, b) - self.assertRaises(DimensionalityError, op.ifloordiv, a, 3) func(op.floordiv, unit * 10.0, "4.2*meter/meter", 2, unit) func(op.floordiv, "10*meter", "4.2*inch", 93, unit) + func(op.floordiv, unit * 10.0, 3, 3 * unit, unit) + func(op.ifloordiv, unit * 10, 3, 3 * unit, unit) def _test_quantity_mod(self, unit, func): a = self.Q_("10*meter") b = self.Q_("3*second") self.assertRaises(DimensionalityError, op.mod, a, b) self.assertRaises(DimensionalityError, op.mod, 3, b) - self.assertRaises(DimensionalityError, op.mod, a, 3) self.assertRaises(DimensionalityError, op.imod, a, b) self.assertRaises(DimensionalityError, op.imod, 3, b) - self.assertRaises(DimensionalityError, op.imod, a, 3) func(op.mod, unit * 10.0, "4.2*meter/meter", 1.6, unit) + func(op.mod, unit * 10.0, 3, 1 * unit, unit) + func(op.imod, unit * 10.0, 3, 1 * unit, unit) def _test_quantity_ifloordiv(self, unit, func): func(op.ifloordiv, 10.0, "4.2*meter/meter", 2, unit) @@ -782,7 +782,7 @@ def _test_quantity_divmod(self): b = self.Q_("3*second") self.assertRaises(DimensionalityError, divmod, a, b) self.assertRaises(DimensionalityError, divmod, 3, b) - self.assertRaises(DimensionalityError, divmod, a, 3) + self._test_quantity_divmod_one("10*meter", 3) def _test_numeric(self, unit, ifunc): self._test_quantity_add_sub(unit, self._test_not_inplace) From 6336206f52d4095ba590284c64bb1d8f11255f0e Mon Sep 17 00:00:00 2001 From: Giulio Malventi Date: Mon, 23 Dec 2019 14:40:58 +0100 Subject: [PATCH 2/2] ENH: quantity.py: add __ceil__ & __floor__ methods (from https://github.com/westurner/pint/pull/1 ) --- pint/quantity.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pint/quantity.py b/pint/quantity.py index 1c6babe4f..60ca45df7 100644 --- a/pint/quantity.py +++ b/pint/quantity.py @@ -1094,6 +1094,12 @@ def __rtruediv__(self, other): __div__ = __truediv__ __rdiv__ = __rtruediv__ __idiv__ = __itruediv__ + + def __ceil__(self): + return self.__floordiv__(1) + self.__class__(1, self._units) + + def __floor__(self): + return self.__floordiv__(1) def __ifloordiv__(self, other): if self._check(other):