Country enhancements
* Make Country validate itself during object initialization * Make Country string coercible
This commit is contained in:
@@ -8,6 +8,8 @@ Here you can see the full list of changes between each SQLAlchemy-Utils release.
|
|||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
- Added __hash__ method to Country class
|
- Added __hash__ method to Country class
|
||||||
|
- Made Country validate itself during object initialization
|
||||||
|
- Made Country string coercible
|
||||||
|
|
||||||
|
|
||||||
0.29.9 (2015-04-07)
|
0.29.9 (2015-04-07)
|
||||||
|
@@ -1,18 +1,37 @@
|
|||||||
import six
|
import six
|
||||||
from sqlalchemy_utils import i18n
|
from sqlalchemy_utils import i18n
|
||||||
|
from sqlalchemy_utils.utils import str_coercible
|
||||||
|
|
||||||
|
|
||||||
|
@str_coercible
|
||||||
class Country(object):
|
class Country(object):
|
||||||
def __init__(self, code_or_country):
|
def __init__(self, code_or_country):
|
||||||
if isinstance(code_or_country, Country):
|
if isinstance(code_or_country, Country):
|
||||||
self.code = code_or_country.code
|
self.code = code_or_country.code
|
||||||
else:
|
elif isinstance(code_or_country, six.string_types):
|
||||||
|
self.validate(code_or_country)
|
||||||
self.code = code_or_country
|
self.code = code_or_country
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
"Country() argument must be a string or a country, not '{0}'"
|
||||||
|
.format(
|
||||||
|
type(code_or_country).__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return i18n.get_locale().territories[self.code]
|
return i18n.get_locale().territories[self.code]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate(self, code):
|
||||||
|
try:
|
||||||
|
i18n.get_locale().territories[code]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError(
|
||||||
|
'Could not convert string to country code: {0}'.format(code)
|
||||||
|
)
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, Country):
|
if isinstance(other, Country):
|
||||||
return self.code == other.code
|
return self.code == other.code
|
||||||
|
@@ -1,18 +1,68 @@
|
|||||||
from sqlalchemy_utils import Country
|
import six
|
||||||
|
from pytest import mark, raises
|
||||||
|
|
||||||
|
from sqlalchemy_utils import Country, i18n
|
||||||
|
from sqlalchemy_utils.primitives.currency import babel # noqa
|
||||||
|
|
||||||
|
|
||||||
|
@mark.skipif('babel is None')
|
||||||
class TestCountry(object):
|
class TestCountry(object):
|
||||||
|
def setup_method(self, method):
|
||||||
|
i18n.get_locale = lambda: babel.Locale('en')
|
||||||
|
|
||||||
def test_init(self):
|
def test_init(self):
|
||||||
assert Country(u'fi') == Country(Country(u'fi'))
|
assert Country(u'FI') == Country(Country(u'FI'))
|
||||||
|
|
||||||
|
def test_constructor_with_wrong_type(self):
|
||||||
|
with raises(TypeError) as e:
|
||||||
|
Country(None)
|
||||||
|
assert str(e.value) == (
|
||||||
|
"Country() argument must be a string or a country, not 'NoneType'"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_constructor_with_invalid_code(self):
|
||||||
|
with raises(ValueError) as e:
|
||||||
|
Country('SomeUnknownCode')
|
||||||
|
assert str(e.value) == (
|
||||||
|
'Could not convert string to country code: SomeUnknownCode'
|
||||||
|
)
|
||||||
|
|
||||||
|
@mark.parametrize(
|
||||||
|
'code',
|
||||||
|
(
|
||||||
|
'FI',
|
||||||
|
'US',
|
||||||
|
)
|
||||||
|
)
|
||||||
|
def test_validate_with_valid_codes(self, code):
|
||||||
|
Country.validate(code)
|
||||||
|
|
||||||
|
def test_validate_with_invalid_code(self):
|
||||||
|
with raises(ValueError) as e:
|
||||||
|
Country.validate('SomeUnknownCode')
|
||||||
|
assert str(e.value) == (
|
||||||
|
'Could not convert string to country code: SomeUnknownCode'
|
||||||
|
)
|
||||||
|
|
||||||
def test_equality_operator(self):
|
def test_equality_operator(self):
|
||||||
assert Country(u'fi') == u'fi'
|
assert Country(u'FI') == u'FI'
|
||||||
assert u'fi' == Country(u'fi')
|
assert u'FI' == Country(u'FI')
|
||||||
assert Country(u'fi') == Country(u'fi')
|
assert Country(u'FI') == Country(u'FI')
|
||||||
|
|
||||||
def test_non_equality_operator(self):
|
def test_non_equality_operator(self):
|
||||||
assert Country(u'fi') != u'sv'
|
assert Country(u'FI') != u'sv'
|
||||||
assert not (Country(u'fi') != u'fi')
|
assert not (Country(u'FI') != u'FI')
|
||||||
|
|
||||||
def test_hash(self):
|
def test_hash(self):
|
||||||
return hash(Country('fi')) == hash('fi')
|
return hash(Country('FI')) == hash('FI')
|
||||||
|
|
||||||
|
def test_repr(self):
|
||||||
|
return repr(Country('FI')) == "Country('FI')"
|
||||||
|
|
||||||
|
def test_unicode(self):
|
||||||
|
country = Country('FI')
|
||||||
|
assert six.text_type(country) == u'Finland'
|
||||||
|
|
||||||
|
def test_str(self):
|
||||||
|
country = Country('FI')
|
||||||
|
assert str(country) == 'Finland'
|
||||||
|
@@ -18,7 +18,7 @@ class TestCountryType(TestCase):
|
|||||||
|
|
||||||
def test_parameter_processing(self):
|
def test_parameter_processing(self):
|
||||||
user = self.User(
|
user = self.User(
|
||||||
country=Country(u'fi')
|
country=Country(u'FI')
|
||||||
)
|
)
|
||||||
|
|
||||||
self.session.add(user)
|
self.session.add(user)
|
||||||
@@ -28,6 +28,6 @@ class TestCountryType(TestCase):
|
|||||||
assert user.country.name == u'Finland'
|
assert user.country.name == u'Finland'
|
||||||
|
|
||||||
def test_scalar_attributes_get_coerced_to_objects(self):
|
def test_scalar_attributes_get_coerced_to_objects(self):
|
||||||
user = self.User(country='fi')
|
user = self.User(country='FI')
|
||||||
|
|
||||||
assert isinstance(user.country, Country)
|
assert isinstance(user.country, Country)
|
||||||
|
Reference in New Issue
Block a user