Files
deb-python-sqlalchemy-utils/sqlalchemy_utils/primitives/currency.py
Konsta Vesterinen 204aba376d Fix babel primitive types
- Make babel dependent primitive types to use Locale('en') for data
validation instead of current locale. Using current locale leads to
infinite recursion in cases where the loaded data has dependency to
the loaded object's locale.
2015-06-17 19:36:46 +03:00

109 lines
2.5 KiB
Python

# -*- coding: utf-8 -*-
import six
from sqlalchemy_utils import i18n, ImproperlyConfigured
from sqlalchemy_utils.utils import str_coercible
@str_coercible
class Currency(object):
"""
Currency class wraps a 3-letter currency code. It provides various
convenience properties and methods.
::
from babel import Locale
from sqlalchemy_utils import Currency, i18n
# First lets add a locale getter for testing purposes
i18n.get_locale = lambda: Locale('en')
Currency('USD').name # US Dollar
Currency('USD').symbol # $
Currency(Currency('USD')).code # 'USD'
Currency always validates the given code.
::
Currency(None) # raises TypeError
Currency('UnknownCode') # raises ValueError
Currency supports equality operators.
::
Currency('USD') == Currency('USD')
Currency('USD') != Currency('EUR')
Currencies are hashable.
::
len(set([Currency('USD'), Currency('USD')])) # 1
"""
def __init__(self, code):
if i18n.babel is None:
raise ImproperlyConfigured(
"'babel' package is required in order to use Currency class."
)
if isinstance(code, Currency):
self.code = code
elif isinstance(code, six.string_types):
self.validate(code)
self.code = code
else:
raise TypeError(
'First argument given to Currency constructor should be '
'either an instance of Currency or valid three letter '
'currency code.'
)
@classmethod
def validate(self, code):
try:
i18n.babel.Locale('en').currencies[code]
except KeyError:
raise ValueError("{0}' is not valid currency code.")
@property
def symbol(self):
return i18n.babel.numbers.get_currency_symbol(
self.code,
i18n.get_locale()
)
@property
def name(self):
return i18n.get_locale().currencies[self.code]
def __eq__(self, other):
if isinstance(other, Currency):
return self.code == other.code
elif isinstance(other, six.string_types):
return self.code == other
else:
return NotImplemented
def __ne__(self, other):
return not (self == other)
def __hash__(self):
return hash(self.code)
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, self.code)
def __unicode__(self):
return self.code