This change via git over ssh.
[retire.git] / money.py
1 import decimal
2
3 class money(object):
4     def __init__(self, amount="0"):
5         try:
6             if isinstance(amount, money):
7                 amount = amount.amount
8             self.amount = decimal.Decimal(amount)
9         except decimal.InvalidOperation:
10             raise ValueError("amount value could not be converted to "
11                              "Decimal(): '{}'".format(amount))
12
13     def amount(self):
14         return self.amount
15
16     def __hash__(self):
17         return hash(self.amount)
18
19     def __repr__(self):
20         return "{}".format(self.amount)
21
22     def __str__(self):
23         return self.__unicode__().encode('utf-8')
24
25     def __unicode__(self):
26         return u"${:,.2f}".format(self.amount)
27
28     def __lt__(self, other):
29         if not isinstance(other, money):
30             other = money(other)
31         return self.amount < other.amount
32
33     def __le__(self, other):
34         if not isinstance(other, money):
35             other = money(other)
36         return self.amount <= other.amount
37
38     def __eq__(self, other):
39         if isinstance(other, money):
40             return self.amount == other.amount
41         return False
42
43     def __ne__(self, other):
44         return not self == other
45
46     def __gt__(self, other):
47         if not isinstance(other, money):
48             other = money(other)
49         return self.amount > other.amount
50
51     def __ge__(self, other):
52         if not isinstance(other, money):
53             other = money(other)
54         return self.amount >= other.amount
55
56     def __add__(self, other):
57         if not isinstance(other, money):
58             other = money(other)
59         other = other.amount
60         amount = self.amount + other
61         return self.__class__(amount)
62
63     def __radd__(self, other):
64         return self.__add__(other)
65
66     def __sub__(self, other):
67         if not isinstance(other, money):
68             other = money(other)
69         other = other.amount
70         amount = self.amount - other
71         return self.__class__(amount)
72
73     def __rsub__(self, other):
74         return (-self).__add__(other)
75
76     def __mul__(self, other):
77         if isinstance(other, money):
78             other = other.amount()
79         amount = self.amount * decimal.Decimal(other)
80         return self.__class__(amount)
81
82     def __rmul__(self, other):
83         return self.__mul__(other)
84
85     def __div__(self, other):
86         return self.__truediv__(other)
87
88     def __truediv__(self, other):
89         if isinstance(other, money):
90             if other.amount == 0:
91                 raise ZeroDivisionError()
92             return self.amount / other.amount
93         else:
94             if other == 0:
95                 raise ZeroDivisionError()
96             amount = self.amount / decimal.Decimal(other)
97             return self.__class__(amount)
98
99     def __floordiv__(self, other):
100         if isinstance(other, money):
101             if other.amount == 0:
102                 raise ZeroDivisionError()
103             return self.amount // other.amount
104         else:
105             if other == 0:
106                 raise ZeroDivisionError()
107             amount = self.amount // other
108             return self.__class__(amount)
109
110     def __mod__(self, other):
111         if isinstance(other, money):
112             raise TypeError("modulo is unsupported between two '{}' "
113                             "objects".format(self.__class__.__name__))
114         if other == 0:
115             raise ZeroDivisionError()
116         amount = self.amount % other
117         return self.__class__(amount)
118
119     def __divmod__(self, other):
120         if isinstance(other, money):
121             if other.amount == 0:
122                 raise ZeroDivisionError()
123             return divmod(self.amount, other.amount)
124         else:
125             if other == 0:
126                 raise ZeroDivisionError()
127             whole, remainder = divmod(self.amount, other)
128             return (self.__class__(whole),
129                     self.__class__(remainder))
130
131     def __pow__(self, other):
132         if isinstance(other, money):
133             raise TypeError("power operator is unsupported between two '{}' "
134                             "objects".format(self.__class__.__name__))
135         amount = self.amount ** other
136         return self.__class__(amount)
137
138     def __neg__(self):
139         return self.__class__(-self.amount)
140
141     def __pos__(self):
142         return self.__class__(+self.amount)
143
144     def __abs__(self):
145         return self.__class__(abs(self.amount))
146
147     def __int__(self):
148         return int(self.amount)
149
150     def __float__(self):
151         return float(self.amount)
152
153     def __round__(self, ndigits=0):
154         return self.__class__(round(self.amount, ndigits))