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.
|
||||
#
|
||||
"""
|
||||
Distance and Area objects to allow for sensible and convienient calculation
|
||||
Distance and Area objects to allow for sensible and convienient calculation
|
||||
and conversions.
|
||||
|
||||
Authors: Robert Coup, Justin Bronn
|
||||
|
@ -70,7 +70,7 @@ class MeasureBase(object):
|
|||
@classmethod
|
||||
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.
|
||||
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)
|
||||
if default_unit and isinstance(default_unit, str):
|
||||
self._default_unit = default_unit
|
||||
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name in self.UNITS:
|
||||
return self.m / self.UNITS[name]
|
||||
else:
|
||||
raise AttributeError('Unknown unit type: %s' % name)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return 'Distance(%s=%s)' % (self._default_unit, getattr(self, self._default_unit))
|
||||
|
||||
def __str__(self):
|
||||
return '%s %s' % (getattr(self, self._default_unit), self._default_unit)
|
||||
|
||||
|
||||
def __cmp__(self, other):
|
||||
if isinstance(other, Distance):
|
||||
return cmp(self.m, other.m)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, Distance):
|
||||
return Distance(default_unit=self._default_unit, m=(self.m + other.m))
|
||||
else:
|
||||
raise TypeError('Distance must be added with Distance')
|
||||
|
||||
|
||||
def __iadd__(self, other):
|
||||
if isinstance(other, Distance):
|
||||
self.m += other.m
|
||||
return self
|
||||
else:
|
||||
raise TypeError('Distance must be added with Distance')
|
||||
|
||||
|
||||
def __sub__(self, other):
|
||||
if isinstance(other, Distance):
|
||||
return Distance(default_unit=self._default_unit, m=(self.m - other.m))
|
||||
else:
|
||||
raise TypeError('Distance must be subtracted from Distance')
|
||||
|
||||
|
||||
def __isub__(self, other):
|
||||
if isinstance(other, Distance):
|
||||
self.m -= other.m
|
||||
return self
|
||||
else:
|
||||
raise TypeError('Distance must be subtracted from Distance')
|
||||
|
||||
|
||||
def __mul__(self, other):
|
||||
if isinstance(other, (int, float, long, Decimal)):
|
||||
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))
|
||||
else:
|
||||
raise TypeError('Distance must be multiplied with number or Distance')
|
||||
|
||||
|
||||
def __imul__(self, other):
|
||||
if isinstance(other, (int, float, long, Decimal)):
|
||||
self.m *= float(other)
|
||||
return self
|
||||
else:
|
||||
raise TypeError('Distance must be multiplied with number')
|
||||
|
||||
|
||||
def __rmul__(self, other):
|
||||
return self * other
|
||||
|
||||
def __div__(self, other):
|
||||
if isinstance(other, (int, float, long, Decimal)):
|
||||
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)
|
||||
if default_unit and isinstance(default_unit, str):
|
||||
self._default_unit = default_unit
|
||||
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name in self.UNITS:
|
||||
return self.sq_m / self.UNITS[name]
|
||||
else:
|
||||
raise AttributeError('Unknown unit type: ' + name)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
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)
|
||||
else:
|
||||
return NotImplemented
|
||||
|
||||
|
||||
def __add__(self, other):
|
||||
if isinstance(other, Area):
|
||||
return Area(default_unit=self._default_unit, sq_m=(self.sq_m + other.sq_m))
|
||||
else:
|
||||
raise TypeError('Area must be added with Area')
|
||||
|
||||
|
||||
def __iadd__(self, other):
|
||||
if isinstance(other, Area):
|
||||
self.sq_m += other.sq_m
|
||||
return self
|
||||
else:
|
||||
raise TypeError('Area must be added with Area')
|
||||
|
||||
|
||||
def __sub__(self, other):
|
||||
if isinstance(other, Area):
|
||||
return Area(default_unit=self._default_unit, sq_m=(self.sq_m - other.sq_m))
|
||||
else:
|
||||
raise TypeError('Area must be subtracted from Area')
|
||||
|
||||
|
||||
def __isub__(self, other):
|
||||
if isinstance(other, Area):
|
||||
self.sq_m -= other.sq_m
|
||||
return self
|
||||
else:
|
||||
raise TypeError('Area must be subtracted from Area')
|
||||
|
||||
|
||||
def __mul__(self, other):
|
||||
if isinstance(other, (int, float, long, Decimal)):
|
||||
return Area(default_unit=self._default_unit, sq_m=(self.sq_m * float(other)))
|
||||
else:
|
||||
raise TypeError('Area must be multiplied with number')
|
||||
|
||||
|
||||
def __imul__(self, other):
|
||||
if isinstance(other, (int, float, long, Decimal)):
|
||||
self.sq_m *= float(other)
|
||||
return self
|
||||
else:
|
||||
raise TypeError('Area must be multiplied with number')
|
||||
|
||||
|
||||
def __rmul__(self, other):
|
||||
return self * other
|
||||
|
||||
def __div__(self, other):
|
||||
if isinstance(other, (int, float, long, Decimal)):
|
||||
return Area(default_unit=self._default_unit, sq_m=(self.sq_m / float(other)))
|
||||
|
@ -324,7 +330,7 @@ class Area(MeasureBase):
|
|||
|
||||
def __nonzero__(self):
|
||||
return bool(self.sq_m)
|
||||
|
||||
|
||||
# Shortcuts
|
||||
D = Distance
|
||||
A = Area
|
||||
|
|
|
@ -95,6 +95,8 @@ class DistanceTest(unittest.TestCase):
|
|||
|
||||
d3 = d1 * 2
|
||||
self.assertEqual(d3.m, 200)
|
||||
d3 = 2 * d1
|
||||
self.assertEqual(d3.m, 200)
|
||||
d3 *= 5
|
||||
self.assertEqual(d3.m, 1000)
|
||||
|
||||
|
@ -248,6 +250,8 @@ class AreaTest(unittest.TestCase):
|
|||
|
||||
a3 = a1 * 2
|
||||
self.assertEqual(a3.sq_m, 200)
|
||||
a3 = 2 * a1
|
||||
self.assertEqual(a3.sq_m, 200)
|
||||
a3 *= 5
|
||||
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(a2), 'Area(sq_km=3.5)')
|
||||
|
||||
|
||||
def suite():
|
||||
s = unittest.TestSuite()
|
||||
s.addTest(unittest.makeSuite(DistanceTest))
|
||||
|
|
Loading…
Reference in New Issue