File: test_choice.py

package info (click to toggle)
python-sqlalchemy-utils 0.30.12-2~bpo8%2B1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 1,056 kB
  • sloc: python: 10,350; makefile: 160
file content (181 lines) | stat: -rw-r--r-- 5,193 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
import sqlalchemy as sa
from flexmock import flexmock
from pytest import mark, raises

from sqlalchemy_utils import Choice, ChoiceType, ImproperlyConfigured
from sqlalchemy_utils.types.choice import Enum
from tests import TestCase


class TestChoice(object):
    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_python_type(self):
        type_ = self.User.__table__.c.type.type
        assert type_.python_type

    def test_string_processing(self):
        flexmock(ChoiceType).should_receive('_coerce').and_return(
            u'admin'
        )
        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_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([])


class TestChoiceTypeWithCustomUnderlyingType(TestCase):
    def test_init_type(self):
        type_ = ChoiceType([(1, u'something')], impl=sa.Integer)
        assert type_.impl == sa.Integer


@mark.skipif('Enum is None')
class TestEnumType(TestCase):
    def create_models(self):
        class OrderStatus(Enum):
            unpaid = 0
            paid = 1

        class Order(self.Base):
            __tablename__ = 'order'
            id_ = sa.Column(sa.Integer, primary_key=True)
            status = sa.Column(
                ChoiceType(OrderStatus, impl=sa.Integer()),
                default=OrderStatus.unpaid,
            )

            def __repr__(self):
                return 'Order(%r, %r)' % (self.id_, self.status)

        class OrderNullable(self.Base):
            __tablename__ = 'order_nullable'
            id_ = sa.Column(sa.Integer, primary_key=True)
            status = sa.Column(
                ChoiceType(OrderStatus, impl=sa.Integer()),
                nullable=True,
            )

        self.OrderStatus = OrderStatus
        self.Order = Order
        self.OrderNullable = OrderNullable

    def test_parameter_initialization(self):
        order = self.Order()

        self.session.add(order)
        self.session.commit()

        order = self.session.query(self.Order).first()
        assert order.status is self.OrderStatus.unpaid
        assert order.status.value == 0

    def test_setting_by_value(self):
        order = self.Order()
        order.status = 1

        self.session.add(order)
        self.session.commit()

        order = self.session.query(self.Order).first()
        assert order.status is self.OrderStatus.paid

    def test_setting_by_enum(self):
        order = self.Order()
        order.status = self.OrderStatus.paid

        self.session.add(order)
        self.session.commit()

        order = self.session.query(self.Order).first()
        assert order.status is self.OrderStatus.paid

    def test_setting_value_that_resolves_to_none(self):
        order = self.Order()
        order.status = 0

        self.session.add(order)
        self.session.commit()

        order = self.session.query(self.Order).first()
        assert order.status is self.OrderStatus.unpaid

    def test_setting_to_wrong_enum_raises_valueerror(self):
        class WrongEnum(Enum):
            foo = 0
            bar = 1

        order = self.Order()

        with raises(ValueError):
            order.status = WrongEnum.foo

    def test_setting_to_uncoerceable_type_raises_valueerror(self):
        order = self.Order()
        with raises(ValueError):
            order.status = 'Bad value'

    def test_order_nullable_stores_none(self):
        # With nullable=False as in `Order`, a `None` value is always
        # converted to the default value, unless we explicitly set it to
        # sqlalchemy.sql.null(), so we use this class to test our ability
        # to set and retrive `None`.
        order_nullable = self.OrderNullable()
        assert order_nullable.status is None

        order_nullable.status = None

        self.session.add(order_nullable)
        self.session.commit()

        assert order_nullable.status is None