root / elixir / trunk / tests / test_inherit.py @ 349

Revision 349, 5.7 kB (checked in by ged, 6 years ago)

- The default session (elixir.session) uses sessionmaker() instead of

create_session(), which means it has now the following characterisics:

  • autoflush=True
  • autocommit=False (with SA 0.5 -- equivalent to transactional=True with
    SA 0.4)
  • autoexpire=True (with SA 0.5).

- Removed objectstore and some other old cruft (mostly SA 0.3 or earlier

support code)

Line 
1"""
2    simple test case
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    A(data1='a1')
43    B(data1='b1', data2='b2')
44    C(data1='c1', data2='c2', data3='c3')
45    D(data1='d1', data4='d4')
46    E(data1='e1')
47
48    session.commit()
49    session.clear()
50
51    res = {}
52    for class_ in (A, B, C, D, E):
53        res[class_.__name__] = class_.query.all()
54        sort_list(res[class_.__name__], key=lambda o: o.__class__.__name__)
55
56    for query_class in ('A', 'B', 'C', 'D', 'E'):
57#        print res[query_class], expected_res[query_class]
58        assert len(res[query_class]) == len(expected_res[query_class])
59        for real, expected in zip(res[query_class], expected_res[query_class]):
60            assert real.__class__.__name__ == expected
61
62
63class TestInheritance(object):
64    def teardown(self):
65        cleanup_all(True)
66
67    # this is related to SA ticket 866
68    # http://www.sqlalchemy.org/trac/ticket/866
69    # the problem was caused by the fact that the attribute-based syntax left
70    # the class-attributes in place after initialization (in Elixir 0.4).
71    def test_missing_value(self):
72        class A(Entity):
73            pass
74
75        class B(A):
76            name = Field(String(30))
77            other = Field(Text)
78
79        setup_all()
80        create_all()
81
82        b1 = B(name="b1") # no value for other
83
84        session.commit()
85
86    def test_delete_parent(self):
87        class A(Entity):
88            using_options(inheritance='multi')
89
90        class B(A):
91            using_options(inheritance='multi')
92            name = Field(String(30))
93
94        setup_all(True)
95
96        b1 = B(name='b1')
97
98        session.commit()
99
100        A.table.delete().execute()
101
102        # this doesn't work on sqlite (because it relies on the database
103        # enforcing the foreign key constraint cascade rule).
104#        assert not B.table.select().execute().fetchall()
105
106    def test_inheritance_wh_schema(self):
107        # I can only test schema stuff on postgres
108        if metadata.bind.name != 'postgres':
109            print "schema test skipped"
110            return
111
112        class A(Entity):
113            using_options(inheritance="multi")
114            using_table_options(schema="test")
115
116            row_id = Field(Integer, primary_key=True)
117            thing1 = Field(String(20))
118
119        class B(A):
120            using_options(inheritance="multi")
121            using_table_options(schema="test")
122
123            thing2 = Field(String(20))
124
125        setup_all(True)
126
127    def test_inverse_matching_on_parent(self):
128        options_defaults['inheritance'] = 'multi'
129
130        class Person(Entity):
131            using_options(inheritance='multi')
132
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
143            parents = ManyToMany('Parent', tablename='child_parent',
144                                 inverse='childs')
145
146        setup_all()
147
148    def test_singletable_inheritance(self):
149        do_tst('single', False, {
150            'A': ('A', 'A', 'A', 'A', 'A'),
151            'B': ('B', 'B', 'B', 'B', 'B'),
152            'C': ('C', 'C', 'C', 'C', 'C'),
153            'D': ('D', 'D', 'D', 'D', 'D'),
154            'E': ('E', 'E', 'E', 'E', 'E')
155        })
156
157    def test_polymorphic_singletable_inheritance(self):
158        do_tst('single', True, {
159            'A': ('A', 'B', 'C', 'D', 'E'),
160            'B': ('B', 'C'),
161            'C': ('C',),
162            'D': ('D',),
163            'E': ('E',),
164        })
165
166    def test_concrete_inheritance(self):
167        do_tst('concrete', False, {
168            'A': ('A',),
169            'B': ('B',),
170            'C': ('C',),
171            'D': ('D',),
172            'E': ('E',),
173        })
174
175#    def test_polymorphic_concrete_inheritance(self):
176        # to get this test to work, I need to duplicate parent relationships in
177        # the children. The problem is that the properties are setup post
178        # mapper setup, so I'll need to add some logic into the add_property
179        # method which I'm reluctant to do.
180#        do_tst('concrete', True, {
181#            'A': ('A', 'B', 'C', 'D', 'E'),
182#            'B': ('B', 'C'),
183#            'C': ('C',),
184#            'D': ('D',),
185#            'E': ('E',),
186#        })
187
188    def test_multitable_inheritance(self):
189        do_tst('multi', False, {
190            'A': ('A', 'A', 'A', 'A', 'A'),
191            'B': ('B', 'B'),
192            'C': ('C',),
193            'D': ('D',),
194            'E': ('E',),
195        })
196
197    def test_polymorphic_multitable_inheritance(self):
198        do_tst('multi', True, {
199            'A': ('A', 'B', 'C', 'D', 'E'),
200            'B': ('B', 'C'),
201            'C': ('C',),
202            'D': ('D',),
203            'E': ('E',),
204        })
Note: See TracBrowser for help on using the browser.