Add money.py, a class I'd like to start using in here instead of floats.
authorScott Gasch <[email protected]>
Wed, 15 Jan 2020 20:23:05 +0000 (12:23 -0800)
committerScott Gasch <[email protected]>
Wed, 15 Jan 2020 20:23:05 +0000 (12:23 -0800)
money.py [new file with mode: 0644]

diff --git a/money.py b/money.py
new file mode 100644 (file)
index 0000000..52fe32b
--- /dev/null
+++ b/money.py
@@ -0,0 +1,154 @@
+import decimal
+
+class money(object):
+    def __init__(self, amount="0"):
+        try:
+            self.amount = decimal.Decimal(amount)
+        except decimal.InvalidOperation:
+            raise ValueError("amount value could not be converted to "
+                             "Decimal(): '{}'".format(amount))
+
+    @property
+    def amount(self):
+        return self.amount
+
+    def __hash__(self):
+        return hash(self._amount)
+
+    def __repr__(self):
+        return "{}".format(self._amount)
+
+    def __str__(self):
+        return self.__unicode__().encode('utf-8')
+
+    def __unicode__(self):
+        return u"${:,.2f}".format(self._amount)
+
+    def __lt__(self, other):
+        if not isinstance(other, money):
+            raise InvalidOperandType(other, '<')
+        return self.amount < other.amount
+
+    def __le__(self, other):
+        if not isinstance(other, money):
+            raise InvalidOperandType(other, '<=')
+        return self._amount <= other.amount
+
+    def __eq__(self, other):
+        if isinstance(other, money):
+            return self._amount == other.amount
+        return False
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __gt__(self, other):
+        if not isinstance(other, money):
+            raise InvalidOperandType(other, '>')
+        return self._amount > other.amount
+
+    def __ge__(self, other):
+        if not isinstance(other, money):
+            raise InvalidOperandType(other, '>=')
+        return self._amount >= other.amount
+
+    def __add__(self, other):
+        if not isinstance(other, money):
+            raise InvalidOperandType(other, '+')
+        other = other.amount
+        amount = self.amount + other
+        return self.__class__(amount)
+
+    def __radd__(self, other):
+        return self.__add__(other)
+
+    def __sub__(self, other):
+        if not isinstance(other, money):
+            raise InvalidOperandType(other, '-')
+        other = other.amount
+        amount = self._amount - other
+        return self.__class__(amount)
+
+    def __rsub__(self, other):
+        return (-self).__add__(other)
+
+    def __mul__(self, other):
+        if isinstance(other, money):
+            raise TypeError("multiplication is unsupported between "
+                            "two money objects")
+        amount = self._amount * other
+        return self.__class__(amount)
+
+    def __rmul__(self, other):
+        return self.__mul__(other)
+
+    def __div__(self, other):
+        return self.__truediv__(other)
+
+    def __truediv__(self, other):
+        if isinstance(other, money):
+            if other.amount == 0:
+                raise ZeroDivisionError()
+            return self.amount / other.amount
+        else:
+            if other == 0:
+                raise ZeroDivisionError()
+            amount = self.amount / other
+            return self.__class__(amount)
+
+    def __floordiv__(self, other):
+        if isinstance(other, money):
+            if other.amount == 0:
+                raise ZeroDivisionError()
+            return self._amount // other.amount
+        else:
+            if other == 0:
+                raise ZeroDivisionError()
+            amount = self.amount // other
+            return self.__class__(amount)
+
+    def __mod__(self, other):
+        if isinstance(other, money):
+            raise TypeError("modulo is unsupported between two '{}' "
+                            "objects".format(self.__class__.__name__))
+        if other == 0:
+            raise ZeroDivisionError()
+        amount = self.amount % other
+        return self.__class__(amount)
+
+    def __divmod__(self, other):
+        if isinstance(other, money):
+            if other.amount == 0:
+                raise ZeroDivisionError()
+            return divmod(self._amount, other.amount)
+        else:
+            if other == 0:
+                raise ZeroDivisionError()
+            whole, remainder = divmod(self._amount, other)
+            return (self.__class__(whole),
+                    self.__class__(remainder))
+
+    def __pow__(self, other):
+        if isinstance(other, money):
+            raise TypeError("power operator is unsupported between two '{}' "
+                            "objects".format(self.__class__.__name__))
+        amount = self.amount ** other
+        return self.__class__(amount)
+
+    def __neg__(self):
+        return self.__class__(-self.amount)
+
+    def __pos__(self):
+        return self.__class__(+self._amount)
+
+    def __abs__(self):
+        return self.__class__(abs(self.amount))
+
+    def __int__(self):
+        return int(self.amount)
+
+    def __float__(self):
+        return float(self.amount)
+
+    def __round__(self, ndigits=0):
+        return self.__class__(round(self.amount, ndigits))