Added choice type

This commit is contained in:
Konsta Vesterinen
2013-10-24 13:49:37 +03:00
parent f37d9d6a03
commit de9050cf6f
4 changed files with 119 additions and 0 deletions

View File

@@ -19,6 +19,8 @@ from .generic import generic_relationship
from .proxy_dict import ProxyDict, proxy_dict from .proxy_dict import ProxyDict, proxy_dict
from .types import ( from .types import (
ArrowType, ArrowType,
Choice,
ChoiceType,
ColorType, ColorType,
CountryType, CountryType,
Country, Country,
@@ -65,6 +67,8 @@ __all__ = (
table_name, table_name,
with_backrefs, with_backrefs,
ArrowType, ArrowType,
Choice,
ChoiceType,
ColorType, ColorType,
CountryType, CountryType,
Country, Country,

View File

@@ -1,6 +1,7 @@
from functools import wraps from functools import wraps
from sqlalchemy.orm.collections import InstrumentedList as _InstrumentedList from sqlalchemy.orm.collections import InstrumentedList as _InstrumentedList
from .arrow import ArrowType from .arrow import ArrowType
from .choice import ChoiceType, Choice
from .color import ColorType from .color import ColorType
from .country import CountryType, Country from .country import CountryType, Country
from .email import EmailType from .email import EmailType
@@ -24,6 +25,8 @@ from .weekdays import WeekDay, WeekDays, WeekDaysType
__all__ = ( __all__ = (
ArrowType, ArrowType,
Choice,
ChoiceType,
ColorType, ColorType,
CountryType, CountryType,
Country, Country,

View File

@@ -0,0 +1,56 @@
from sqlalchemy import types
import six
from ..exceptions import ImproperlyConfigured
from .scalar_coercible import ScalarCoercible
class Choice(object):
def __init__(self, code, value):
self.code = code
self.value = value
def __eq__(self, other):
if isinstance(other, Choice):
return self.code == other.code
return other == self.code
def __ne__(self, other):
return not (self == other)
def __unicode__(self):
return six.text_type(self.value)
def __repr__(self):
return 'Choice(code={code}, value={value})'.format(
code=self.code,
value=self.value
)
class ChoiceType(types.TypeDecorator, ScalarCoercible):
impl = types.Unicode(255)
def __init__(self, choices):
if not choices:
raise ImproperlyConfigured(
'ChoiceType needs list of choices defined.'
)
self.choices = choices
self.choices_dict = dict(choices)
def _coerce(self, value):
if value is None:
return value
if isinstance(value, Choice):
return value
return Choice(value, self.choices_dict[value])
def process_bind_param(self, value, dialect):
if value:
return value.code
return value
def process_result_value(self, value, dialect):
if value:
return Choice(value, self.choices_dict[value])
return value

View File

@@ -0,0 +1,56 @@
from pytest import raises
import sqlalchemy as sa
from sqlalchemy_utils import ChoiceType, Choice, ImproperlyConfigured
from tests import TestCase
class TestChoice(object):
# def test_init(self):
# assert Choice(1, 1) == Choice(Choice(1, 1))
def test_equality_operator(self):
assert Choice(1, 1) == 1
assert 1 == Choice(1, 1)
assert Choice(1, 1) == Choice(1, 1)
def test_non_equality_operator(self):
assert Choice(1, 1) != 2
assert not (Choice(1, 1) != 1)
class TestChoiceType(TestCase):
def create_models(self):
class User(self.Base):
TYPES = [
('admin', 'Admin'),
('regular-user', 'Regular user')
]
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
type = sa.Column(ChoiceType(TYPES))
def __repr__(self):
return 'User(%r)' % self.id
self.User = User
def test_parameter_processing(self):
user = self.User(
type=u'admin'
)
self.session.add(user)
self.session.commit()
user = self.session.query(self.User).first()
assert user.type.value == u'Admin'
def test_scalar_attributes_get_coerced_to_objects(self):
user = self.User(type=u'admin')
assert isinstance(user.type, Choice)
def test_throws_exception_if_no_choices_given(self):
with raises(ImproperlyConfigured):
ChoiceType([])