2 Define special types used in BlueChips
5 import sqlalchemy as sa
6 from bluechips.lib.subclass import SmartSubclass
8 from weakref import WeakValueDictionary
10 class Currency(object):
12 Store currency values as an integral number of cents
14 __metaclass__ = SmartSubclass(int)
15 __old_values__ = WeakValueDictionary()
16 def __new__(cls, value):
17 if isinstance(value, str):
18 value = int(float(value) * 100)
22 if value not in cls.__old_values__:
23 new_object = super(cls, cls).__new__(cls)
24 new_object.value = value
25 cls.__old_values__[value] = new_object
28 return cls.__old_values__[value]
32 If I don't define this, SmartSubclass will return
33 Currency(int(self.value))
38 If I don't define this, SmartSubclass will return
39 Currency(float(self.value))
41 return float(self.value)
44 If I don't define this, SmartSubclass will return
45 Currency(long(self.value))
47 return long(self.value)
49 def __cmp__(self, other):
51 This is overridden for when validators compare a Currency to
57 return self.value.__cmp__(int(other))
59 def __mul__(self, other):
61 If I don't define this, SmartSubclass will convert the other
64 return Currency(self.value * other)
65 def __rmul__(self, other):
67 If I don't define this, SmartSubclass will convert the other
70 return self.__mul__(other)
72 def __str_no_dollar__(self):
74 Get to the formatted string without the dollar sign
79 return '%s("%s")' % (self.__class__.__name__, str(self))
81 sign = '-' if self.value < 0 else ''
82 cents = abs(self.value) % 100
83 dollars = (abs(self.value) - cents) / 100
84 return '$%s%s.%.02d' % (sign, dollars, cents)
86 class DBCurrency(sa.types.TypeDecorator):
88 A type which represents monetary amounts internally as integers.
90 This avoids binary/decimal float conversion issues
93 impl = sa.types.Integer
95 def process_bind_param(self, value, engine):
98 def convert_result_value(self, value, engine):
99 return Currency(value)