
- 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.
109 lines
2.5 KiB
Python
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
|