From 4d2f22f112c37c889e4147ba8781435913361e58 Mon Sep 17 00:00:00 2001 From: Scott Gasch Date: Wed, 15 Jan 2020 12:23:05 -0800 Subject: [PATCH] Add money.py, a class I'd like to start using in here instead of floats. --- money.py | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 money.py diff --git a/money.py b/money.py new file mode 100644 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)) -- 2.46.1