root / elixir / tags / 0.7.0 / tests / test_inherit.py

Revision 467, 6.8 kB (checked in by ged, 3 years ago)

sed 's/sqlite:\/\/\//sqlite:\/\//' *.py

Line 
1"""
2test inheritance
3"""
4
5from elixir import *
6import elixir
7from elixir.py23compat import sort_list
8
9def setup():
10    metadata.bind = 'sqlite://'
11#    metadata.bind = 'postgres://@/test'
12#    metadata.bind.echo = True
13    elixir.options_defaults['shortnames'] = True
14
15def teardown():
16    elixir.options_defaults['shortnames'] = False
17
18def do_tst(inheritance, polymorphic, expected_res):
19    class A(Entity):
20        using_options(inheritance=inheritance, polymorphic=polymorphic)
21        data1 = Field(String(20))
22
23    class B(A):
24        using_options(inheritance=inheritance, polymorphic=polymorphic)
25        data2 = Field(String(20))
26        some_e = ManyToOne('E')
27
28    class C(B):
29        using_options(inheritance=inheritance, polymorphic=polymorphic)
30        data3 = Field(String(20))
31
32    class D(A):
33        using_options(inheritance=inheritance, polymorphic=polymorphic)
34        data4 = Field(String(20))
35
36    class E(A):
37        using_options(inheritance=inheritance, polymorphic=polymorphic)
38        many_b = OneToMany('B')
39
40    setup_all(True)
41
42    e1 = E(data1='e1')
43    a1 = A(data1='a1')
44    b1 = B(data1='b1', data2='b2', some_e=e1)
45    if polymorphic:
46        c1 = C(data1='c1', data2='c2', data3='c3', some_e=e1)
47    else:
48        c1 = C(data1='c1', data2='c2', data3='c3')
49    d1 = D(data1='d1', data4='d4')
50
51    session.commit()
52    session.clear()
53
54    res = {}
55    for class_ in (A, B, C, D, E):
56        res[class_.__name__] = class_.query.all()
57        sort_list(res[class_.__name__], key=lambda o: o.__class__.__name__)
58
59    for query_class in ('A', 'B', 'C', 'D', 'E'):
60#        print res[query_class], expected_res[query_class]
61        assert len(res[query_class]) == len(expected_res[query_class])
62        for real, expected in zip(res[query_class], expected_res[query_class]):
63            assert real.__class__.__name__ == expected
64
65
66class TestInheritance(object):
67    def teardown(self):
68        cleanup_all(True)
69
70    # this is related to SA ticket 866
71    # http://www.sqlalchemy.org/trac/ticket/866
72    # the problem was caused by the fact that the attribute-based syntax left
73    # the class-attributes in place after initialization (in Elixir 0.4).
74    def test_missing_value(self):
75        class A(Entity):
76            pass
77
78        class B(A):
79            name = Field(String(30))
80            other = Field(Text)
81
82        setup_all()
83        create_all()
84
85        b1 = B(name="b1") # no value for other
86
87        session.commit()
88
89    def test_delete_parent(self):
90        class A(Entity):
91            using_options(inheritance='multi')
92
93        class B(A):
94            using_options(inheritance='multi')
95            name = Field(String(30))
96
97        setup_all(True)
98
99        b1 = B(name='b1')
100
101        session.commit()
102
103        A.table.delete().execute()
104
105        # this doesn't work on sqlite (because it relies on the database
106        # enforcing the foreign key constraint cascade rule).
107#        assert not B.table.select().execute().fetchall()
108
109    def test_inheritance_wh_schema(self):
110        # I can only test schema stuff on postgres
111        if metadata.bind.name != 'postgres':
112            print "schema test skipped"
113            return
114
115        class A(Entity):
116            using_options(inheritance="multi")
117            using_table_options(schema="test")
118
119            row_id = Field(Integer, primary_key=True)
120            thing1 = Field(String(20))
121
122        class B(A):
123            using_options(inheritance="multi")
124            using_table_options(schema="test")
125
126            thing2 = Field(String(20))
127
128        setup_all(True)
129
130    def test_inverse_matching_on_parent(self):
131        class Person(Entity):
132            using_options(inheritance='multi')
133            name = Field(UnicodeText)
134
135        class Parent(Person):
136            using_options(inheritance='multi')
137            childs = ManyToMany('Child', tablename='child_parent',
138                                inverse='parents')
139
140        class Child(Person):
141            using_options(inheritance='multi')
142            parents = ManyToMany('Parent', tablename='child_parent',
143                                 inverse='childs')
144
145        setup_all()
146
147    def test_multitable_polymorphic_load(self):
148        class A(Entity):
149            using_options(inheritance='multi')
150            # we want to load children's specific data along the parent (A)
151            # data when querying the parent. If we don't specify this, the
152            # children data is loaded lazily
153            using_mapper_options(with_polymorphic='*')
154            name = Field(String(50))
155
156        class B(A):
157            using_options(inheritance='multi')
158            data = Field(String(50))
159            some_c = ManyToOne('C')
160            some_a = ManyToOne('A')
161
162        class C(A):
163            using_options(inheritance='multi')
164
165            data = Field(String(50))
166            many_b = OneToMany('B')
167        setup_all(True)
168        a1 = A(name='a1')
169        c1 = C(name='c1', data="c")
170        b1 = B(name='b1', data="b", some_c=c1)
171
172        session.commit()
173        session.clear()
174
175        for a in A.query.all():
176            if isinstance(a, (B, C)):
177                # On SA 0.4.x, this test works whether with_polymorphic is
178                # specified or not, because in 0.4.x, without with_polymorphic,
179                # it issues as many queries as necessary to load all data,
180                # while in 0.5, columns are "deferred".
181                assert 'data' in a.__dict__
182
183    def test_singletable_inheritance(self):
184        do_tst('single', False, {
185            'A': ('A', 'A', 'A', 'A', 'A'),
186            'B': ('B', 'B', 'B', 'B', 'B'),
187            'C': ('C', 'C', 'C', 'C', 'C'),
188            'D': ('D', 'D', 'D', 'D', 'D'),
189            'E': ('E', 'E', 'E', 'E', 'E')
190        })
191
192    def test_polymorphic_singletable_inheritance(self):
193        do_tst('single', True, {
194            'A': ('A', 'B', 'C', 'D', 'E'),
195            'B': ('B', 'C'),
196            'C': ('C',),
197            'D': ('D',),
198            'E': ('E',),
199        })
200
201    def test_concrete_inheritance(self):
202        do_tst('concrete', False, {
203            'A': ('A',),
204            'B': ('B',),
205            'C': ('C',),
206            'D': ('D',),
207            'E': ('E',),
208        })
209
210#    def test_polymorphic_concrete_inheritance(self):
211#        do_tst('concrete', True, {
212#            'A': ('A', 'B', 'C', 'D', 'E'),
213#            'B': ('B', 'C'),
214#            'C': ('C',),
215#            'D': ('D',),
216#            'E': ('E',),
217#        })
218
219    def test_multitable_inheritance(self):
220        do_tst('multi', False, {
221            'A': ('A', 'A', 'A', 'A', 'A'),
222            'B': ('B', 'B'),
223            'C': ('C',),
224            'D': ('D',),
225            'E': ('E',),
226        })
227
228    def test_polymorphic_multitable_inheritance(self):
229        do_tst('multi', True, {
230            'A': ('A', 'B', 'C', 'D', 'E'),
231            'B': ('B', 'C'),
232            'C': ('C',),
233            'D': ('D',),
234            'E': ('E',),
235        })
Note: See TracBrowser for help on using the browser.