Fixed #12390 -- `Distance` and `Area` objects now support multiplication when they are the right-hand side.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@11898 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
5bd63663a9
commit
fed3081caf
|
@ -27,7 +27,7 @@
|
||||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
"""
|
"""
|
||||||
Distance and Area objects to allow for sensible and convienient calculation
|
Distance and Area objects to allow for sensible and convienient calculation
|
||||||
and conversions.
|
and conversions.
|
||||||
|
|
||||||
Authors: Robert Coup, Justin Bronn
|
Authors: Robert Coup, Justin Bronn
|
||||||
|
@ -70,7 +70,7 @@ class MeasureBase(object):
|
||||||
@classmethod
|
@classmethod
|
||||||
def unit_attname(cls, unit_str):
|
def unit_attname(cls, unit_str):
|
||||||
"""
|
"""
|
||||||
Retrieves the unit attribute name for the given unit string.
|
Retrieves the unit attribute name for the given unit string.
|
||||||
For example, if the given unit string is 'metre', 'm' would be returned.
|
For example, if the given unit string is 'metre', 'm' would be returned.
|
||||||
An exception is raised if an attribute cannot be found.
|
An exception is raised if an attribute cannot be found.
|
||||||
"""
|
"""
|
||||||
|
@ -165,51 +165,51 @@ class Distance(MeasureBase):
|
||||||
self.m, self._default_unit = self.default_units(kwargs)
|
self.m, self._default_unit = self.default_units(kwargs)
|
||||||
if default_unit and isinstance(default_unit, str):
|
if default_unit and isinstance(default_unit, str):
|
||||||
self._default_unit = default_unit
|
self._default_unit = default_unit
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name in self.UNITS:
|
if name in self.UNITS:
|
||||||
return self.m / self.UNITS[name]
|
return self.m / self.UNITS[name]
|
||||||
else:
|
else:
|
||||||
raise AttributeError('Unknown unit type: %s' % name)
|
raise AttributeError('Unknown unit type: %s' % name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'Distance(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
|
return 'Distance(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '%s %s' % (getattr(self, self._default_unit), self._default_unit)
|
return '%s %s' % (getattr(self, self._default_unit), self._default_unit)
|
||||||
|
|
||||||
def __cmp__(self, other):
|
def __cmp__(self, other):
|
||||||
if isinstance(other, Distance):
|
if isinstance(other, Distance):
|
||||||
return cmp(self.m, other.m)
|
return cmp(self.m, other.m)
|
||||||
else:
|
else:
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
if isinstance(other, Distance):
|
if isinstance(other, Distance):
|
||||||
return Distance(default_unit=self._default_unit, m=(self.m + other.m))
|
return Distance(default_unit=self._default_unit, m=(self.m + other.m))
|
||||||
else:
|
else:
|
||||||
raise TypeError('Distance must be added with Distance')
|
raise TypeError('Distance must be added with Distance')
|
||||||
|
|
||||||
def __iadd__(self, other):
|
def __iadd__(self, other):
|
||||||
if isinstance(other, Distance):
|
if isinstance(other, Distance):
|
||||||
self.m += other.m
|
self.m += other.m
|
||||||
return self
|
return self
|
||||||
else:
|
else:
|
||||||
raise TypeError('Distance must be added with Distance')
|
raise TypeError('Distance must be added with Distance')
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
if isinstance(other, Distance):
|
if isinstance(other, Distance):
|
||||||
return Distance(default_unit=self._default_unit, m=(self.m - other.m))
|
return Distance(default_unit=self._default_unit, m=(self.m - other.m))
|
||||||
else:
|
else:
|
||||||
raise TypeError('Distance must be subtracted from Distance')
|
raise TypeError('Distance must be subtracted from Distance')
|
||||||
|
|
||||||
def __isub__(self, other):
|
def __isub__(self, other):
|
||||||
if isinstance(other, Distance):
|
if isinstance(other, Distance):
|
||||||
self.m -= other.m
|
self.m -= other.m
|
||||||
return self
|
return self
|
||||||
else:
|
else:
|
||||||
raise TypeError('Distance must be subtracted from Distance')
|
raise TypeError('Distance must be subtracted from Distance')
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
if isinstance(other, (int, float, long, Decimal)):
|
if isinstance(other, (int, float, long, Decimal)):
|
||||||
return Distance(default_unit=self._default_unit, m=(self.m * float(other)))
|
return Distance(default_unit=self._default_unit, m=(self.m * float(other)))
|
||||||
|
@ -217,14 +217,17 @@ class Distance(MeasureBase):
|
||||||
return Area(default_unit='sq_' + self._default_unit, sq_m=(self.m * other.m))
|
return Area(default_unit='sq_' + self._default_unit, sq_m=(self.m * other.m))
|
||||||
else:
|
else:
|
||||||
raise TypeError('Distance must be multiplied with number or Distance')
|
raise TypeError('Distance must be multiplied with number or Distance')
|
||||||
|
|
||||||
def __imul__(self, other):
|
def __imul__(self, other):
|
||||||
if isinstance(other, (int, float, long, Decimal)):
|
if isinstance(other, (int, float, long, Decimal)):
|
||||||
self.m *= float(other)
|
self.m *= float(other)
|
||||||
return self
|
return self
|
||||||
else:
|
else:
|
||||||
raise TypeError('Distance must be multiplied with number')
|
raise TypeError('Distance must be multiplied with number')
|
||||||
|
|
||||||
|
def __rmul__(self, other):
|
||||||
|
return self * other
|
||||||
|
|
||||||
def __div__(self, other):
|
def __div__(self, other):
|
||||||
if isinstance(other, (int, float, long, Decimal)):
|
if isinstance(other, (int, float, long, Decimal)):
|
||||||
return Distance(default_unit=self._default_unit, m=(self.m / float(other)))
|
return Distance(default_unit=self._default_unit, m=(self.m / float(other)))
|
||||||
|
@ -251,13 +254,13 @@ class Area(MeasureBase):
|
||||||
self.sq_m, self._default_unit = self.default_units(kwargs)
|
self.sq_m, self._default_unit = self.default_units(kwargs)
|
||||||
if default_unit and isinstance(default_unit, str):
|
if default_unit and isinstance(default_unit, str):
|
||||||
self._default_unit = default_unit
|
self._default_unit = default_unit
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
if name in self.UNITS:
|
if name in self.UNITS:
|
||||||
return self.sq_m / self.UNITS[name]
|
return self.sq_m / self.UNITS[name]
|
||||||
else:
|
else:
|
||||||
raise AttributeError('Unknown unit type: ' + name)
|
raise AttributeError('Unknown unit type: ' + name)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'Area(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
|
return 'Area(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
|
||||||
|
|
||||||
|
@ -269,46 +272,49 @@ class Area(MeasureBase):
|
||||||
return cmp(self.sq_m, other.sq_m)
|
return cmp(self.sq_m, other.sq_m)
|
||||||
else:
|
else:
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __add__(self, other):
|
def __add__(self, other):
|
||||||
if isinstance(other, Area):
|
if isinstance(other, Area):
|
||||||
return Area(default_unit=self._default_unit, sq_m=(self.sq_m + other.sq_m))
|
return Area(default_unit=self._default_unit, sq_m=(self.sq_m + other.sq_m))
|
||||||
else:
|
else:
|
||||||
raise TypeError('Area must be added with Area')
|
raise TypeError('Area must be added with Area')
|
||||||
|
|
||||||
def __iadd__(self, other):
|
def __iadd__(self, other):
|
||||||
if isinstance(other, Area):
|
if isinstance(other, Area):
|
||||||
self.sq_m += other.sq_m
|
self.sq_m += other.sq_m
|
||||||
return self
|
return self
|
||||||
else:
|
else:
|
||||||
raise TypeError('Area must be added with Area')
|
raise TypeError('Area must be added with Area')
|
||||||
|
|
||||||
def __sub__(self, other):
|
def __sub__(self, other):
|
||||||
if isinstance(other, Area):
|
if isinstance(other, Area):
|
||||||
return Area(default_unit=self._default_unit, sq_m=(self.sq_m - other.sq_m))
|
return Area(default_unit=self._default_unit, sq_m=(self.sq_m - other.sq_m))
|
||||||
else:
|
else:
|
||||||
raise TypeError('Area must be subtracted from Area')
|
raise TypeError('Area must be subtracted from Area')
|
||||||
|
|
||||||
def __isub__(self, other):
|
def __isub__(self, other):
|
||||||
if isinstance(other, Area):
|
if isinstance(other, Area):
|
||||||
self.sq_m -= other.sq_m
|
self.sq_m -= other.sq_m
|
||||||
return self
|
return self
|
||||||
else:
|
else:
|
||||||
raise TypeError('Area must be subtracted from Area')
|
raise TypeError('Area must be subtracted from Area')
|
||||||
|
|
||||||
def __mul__(self, other):
|
def __mul__(self, other):
|
||||||
if isinstance(other, (int, float, long, Decimal)):
|
if isinstance(other, (int, float, long, Decimal)):
|
||||||
return Area(default_unit=self._default_unit, sq_m=(self.sq_m * float(other)))
|
return Area(default_unit=self._default_unit, sq_m=(self.sq_m * float(other)))
|
||||||
else:
|
else:
|
||||||
raise TypeError('Area must be multiplied with number')
|
raise TypeError('Area must be multiplied with number')
|
||||||
|
|
||||||
def __imul__(self, other):
|
def __imul__(self, other):
|
||||||
if isinstance(other, (int, float, long, Decimal)):
|
if isinstance(other, (int, float, long, Decimal)):
|
||||||
self.sq_m *= float(other)
|
self.sq_m *= float(other)
|
||||||
return self
|
return self
|
||||||
else:
|
else:
|
||||||
raise TypeError('Area must be multiplied with number')
|
raise TypeError('Area must be multiplied with number')
|
||||||
|
|
||||||
|
def __rmul__(self, other):
|
||||||
|
return self * other
|
||||||
|
|
||||||
def __div__(self, other):
|
def __div__(self, other):
|
||||||
if isinstance(other, (int, float, long, Decimal)):
|
if isinstance(other, (int, float, long, Decimal)):
|
||||||
return Area(default_unit=self._default_unit, sq_m=(self.sq_m / float(other)))
|
return Area(default_unit=self._default_unit, sq_m=(self.sq_m / float(other)))
|
||||||
|
@ -324,7 +330,7 @@ class Area(MeasureBase):
|
||||||
|
|
||||||
def __nonzero__(self):
|
def __nonzero__(self):
|
||||||
return bool(self.sq_m)
|
return bool(self.sq_m)
|
||||||
|
|
||||||
# Shortcuts
|
# Shortcuts
|
||||||
D = Distance
|
D = Distance
|
||||||
A = Area
|
A = Area
|
||||||
|
|
|
@ -95,6 +95,8 @@ class DistanceTest(unittest.TestCase):
|
||||||
|
|
||||||
d3 = d1 * 2
|
d3 = d1 * 2
|
||||||
self.assertEqual(d3.m, 200)
|
self.assertEqual(d3.m, 200)
|
||||||
|
d3 = 2 * d1
|
||||||
|
self.assertEqual(d3.m, 200)
|
||||||
d3 *= 5
|
d3 *= 5
|
||||||
self.assertEqual(d3.m, 1000)
|
self.assertEqual(d3.m, 1000)
|
||||||
|
|
||||||
|
@ -248,6 +250,8 @@ class AreaTest(unittest.TestCase):
|
||||||
|
|
||||||
a3 = a1 * 2
|
a3 = a1 * 2
|
||||||
self.assertEqual(a3.sq_m, 200)
|
self.assertEqual(a3.sq_m, 200)
|
||||||
|
a3 = 2 * a1
|
||||||
|
self.assertEqual(a3.sq_m, 200)
|
||||||
a3 *= 5
|
a3 *= 5
|
||||||
self.assertEqual(a3.sq_m, 1000)
|
self.assertEqual(a3.sq_m, 1000)
|
||||||
|
|
||||||
|
@ -319,7 +323,6 @@ class AreaTest(unittest.TestCase):
|
||||||
self.assertEqual(repr(a1), 'Area(sq_m=100.0)')
|
self.assertEqual(repr(a1), 'Area(sq_m=100.0)')
|
||||||
self.assertEqual(repr(a2), 'Area(sq_km=3.5)')
|
self.assertEqual(repr(a2), 'Area(sq_km=3.5)')
|
||||||
|
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
s = unittest.TestSuite()
|
s = unittest.TestSuite()
|
||||||
s.addTest(unittest.makeSuite(DistanceTest))
|
s.addTest(unittest.makeSuite(DistanceTest))
|
||||||
|
|
Loading…
Reference in New Issue