summaryrefslogtreecommitdiff
path: root/test/orm/inheritance.py
diff options
context:
space:
mode:
Diffstat (limited to 'test/orm/inheritance.py')
-rw-r--r--test/orm/inheritance.py417
1 files changed, 417 insertions, 0 deletions
diff --git a/test/orm/inheritance.py b/test/orm/inheritance.py
new file mode 100644
index 000000000..095763867
--- /dev/null
+++ b/test/orm/inheritance.py
@@ -0,0 +1,417 @@
+import testbase
+from sqlalchemy import *
+import string
+import sqlalchemy.attributes as attr
+import sys
+
+class Principal( object ):
+ def __init__(self, **kwargs):
+ for key, value in kwargs.iteritems():
+ setattr(self, key, value)
+
+class User( Principal ):
+ pass
+
+class Group( Principal ):
+ pass
+
+class InheritTest(testbase.AssertMixin):
+ """deals with inheritance and many-to-many relationships"""
+ def setUpAll(self):
+ global principals
+ global users
+ global groups
+ global user_group_map
+ global metadata
+ metadata = BoundMetaData(testbase.db)
+ principals = Table(
+ 'principals',
+ metadata,
+ Column('principal_id', Integer, Sequence('principal_id_seq', optional=False), primary_key=True),
+ Column('name', String(50), nullable=False),
+ )
+
+ users = Table(
+ 'prin_users',
+ metadata,
+ Column('principal_id', Integer, ForeignKey('principals.principal_id'), primary_key=True),
+ Column('password', String(50), nullable=False),
+ Column('email', String(50), nullable=False),
+ Column('login_id', String(50), nullable=False),
+
+ )
+
+ groups = Table(
+ 'prin_groups',
+ metadata,
+ Column( 'principal_id', Integer, ForeignKey('principals.principal_id'), primary_key=True),
+
+ )
+
+ user_group_map = Table(
+ 'prin_user_group_map',
+ metadata,
+ Column('user_id', Integer, ForeignKey( "prin_users.principal_id"), primary_key=True ),
+ Column('group_id', Integer, ForeignKey( "prin_groups.principal_id"), primary_key=True ),
+ #Column('user_id', Integer, ForeignKey( "prin_users.principal_id"), ),
+ #Column('group_id', Integer, ForeignKey( "prin_groups.principal_id"), ),
+
+ )
+
+ metadata.create_all()
+
+ def tearDownAll(self):
+ metadata.drop_all()
+
+ def setUp(self):
+ clear_mappers()
+
+ def testbasic(self):
+ mapper( Principal, principals )
+ mapper(
+ User,
+ users,
+ inherits=Principal
+ )
+
+ mapper(
+ Group,
+ groups,
+ inherits=Principal,
+ properties=dict( users = relation(User, secondary=user_group_map, lazy=True, backref="groups") )
+ )
+
+ g = Group(name="group1")
+ g.users.append(User(name="user1", password="pw", email="foo@bar.com", login_id="lg1"))
+ sess = create_session()
+ sess.save(g)
+ sess.flush()
+ # TODO: put an assertion
+
+class InheritTest2(testbase.AssertMixin):
+ """deals with inheritance and many-to-many relationships"""
+ def setUpAll(self):
+ global foo, bar, foo_bar, metadata
+ metadata = BoundMetaData(testbase.db)
+ foo = Table('foo', metadata,
+ Column('id', Integer, Sequence('foo_id_seq'), primary_key=True),
+ Column('data', String(20)),
+ ).create()
+
+ bar = Table('bar', metadata,
+ Column('bid', Integer, ForeignKey('foo.id'), primary_key=True),
+ #Column('fid', Integer, ForeignKey('foo.id'), )
+ ).create()
+
+ foo_bar = Table('foo_bar', metadata,
+ Column('foo_id', Integer, ForeignKey('foo.id')),
+ Column('bar_id', Integer, ForeignKey('bar.bid'))).create()
+ metadata.create_all()
+ def tearDownAll(self):
+ metadata.drop_all()
+
+ def testbasic(self):
+ class Foo(object):
+ def __init__(self, data=None):
+ self.data = data
+ def __str__(self):
+ return "Foo(%s)" % self.data
+ def __repr__(self):
+ return str(self)
+
+ mapper(Foo, foo)
+ class Bar(Foo):
+ def __str__(self):
+ return "Bar(%s)" % self.data
+
+ mapper(Bar, bar, inherits=Foo, properties={
+ 'foos': relation(Foo, secondary=foo_bar, lazy=False)
+ })
+
+ sess = create_session()
+ b = Bar('barfoo', _sa_session=sess)
+ sess.flush()
+
+ f1 = Foo('subfoo1')
+ f2 = Foo('subfoo2')
+ b.foos.append(f1)
+ b.foos.append(f2)
+
+ sess.flush()
+ sess.clear()
+
+ l = sess.query(Bar).select()
+ print l[0]
+ print l[0].foos
+ self.assert_result(l, Bar,
+# {'id':1, 'data':'barfoo', 'bid':1, 'foos':(Foo, [{'id':2,'data':'subfoo1'}, {'id':3,'data':'subfoo2'}])},
+ {'id':b.id, 'data':'barfoo', 'foos':(Foo, [{'id':f1.id,'data':'subfoo1'}, {'id':f2.id,'data':'subfoo2'}])},
+ )
+
+class InheritTest3(testbase.AssertMixin):
+ """deals with inheritance and many-to-many relationships"""
+ def setUpAll(self):
+ global foo, bar, blub, bar_foo, blub_bar, blub_foo,metadata
+ metadata = BoundMetaData(testbase.db)
+ # the 'data' columns are to appease SQLite which cant handle a blank INSERT
+ foo = Table('foo', metadata,
+ Column('id', Integer, Sequence('foo_seq'), primary_key=True),
+ Column('data', String(20)))
+
+ bar = Table('bar', metadata,
+ Column('id', Integer, ForeignKey('foo.id'), primary_key=True),
+ Column('data', String(20)))
+
+ blub = Table('blub', metadata,
+ Column('id', Integer, ForeignKey('bar.id'), primary_key=True),
+ Column('data', String(20)))
+
+ bar_foo = Table('bar_foo', metadata,
+ Column('bar_id', Integer, ForeignKey('bar.id')),
+ Column('foo_id', Integer, ForeignKey('foo.id')))
+
+ blub_bar = Table('bar_blub', metadata,
+ Column('blub_id', Integer, ForeignKey('blub.id')),
+ Column('bar_id', Integer, ForeignKey('bar.id')))
+
+ blub_foo = Table('blub_foo', metadata,
+ Column('blub_id', Integer, ForeignKey('blub.id')),
+ Column('foo_id', Integer, ForeignKey('foo.id')))
+ metadata.create_all()
+ def tearDownAll(self):
+ metadata.drop_all()
+
+ def tearDown(self):
+ for table in metadata.table_iterator():
+ table.delete().execute()
+
+ def testbasic(self):
+ class Foo(object):
+ def __init__(self, data=None):
+ self.data = data
+ def __repr__(self):
+ return "Foo id %d, data %s" % (self.id, self.data)
+ mapper(Foo, foo)
+
+ class Bar(Foo):
+ def __repr__(self):
+ return "Bar id %d, data %s" % (self.id, self.data)
+
+ mapper(Bar, bar, inherits=Foo, properties={
+ 'foos' :relation(Foo, secondary=bar_foo, lazy=True)
+ })
+
+ sess = create_session()
+ b = Bar('bar #1', _sa_session=sess)
+ b.foos.append(Foo("foo #1"))
+ b.foos.append(Foo("foo #2"))
+ sess.flush()
+ compare = repr(b) + repr(b.foos)
+ sess.clear()
+ l = sess.query(Bar).select()
+ self.echo(repr(l[0]) + repr(l[0].foos))
+ self.assert_(repr(l[0]) + repr(l[0].foos) == compare)
+
+ def testadvanced(self):
+ class Foo(object):
+ def __init__(self, data=None):
+ self.data = data
+ def __repr__(self):
+ return "Foo id %d, data %s" % (self.id, self.data)
+ mapper(Foo, foo)
+
+ class Bar(Foo):
+ def __repr__(self):
+ return "Bar id %d, data %s" % (self.id, self.data)
+ mapper(Bar, bar, inherits=Foo)
+
+ class Blub(Bar):
+ def __repr__(self):
+ return "Blub id %d, data %s, bars %s, foos %s" % (self.id, self.data, repr([b for b in self.bars]), repr([f for f in self.foos]))
+
+ mapper(Blub, blub, inherits=Bar, properties={
+ 'bars':relation(Bar, secondary=blub_bar, lazy=False),
+ 'foos':relation(Foo, secondary=blub_foo, lazy=False),
+ })
+
+ sess = create_session()
+ f1 = Foo("foo #1", _sa_session=sess)
+ b1 = Bar("bar #1", _sa_session=sess)
+ b2 = Bar("bar #2", _sa_session=sess)
+ bl1 = Blub("blub #1", _sa_session=sess)
+ bl1.foos.append(f1)
+ bl1.bars.append(b2)
+ sess.flush()
+ compare = repr(bl1)
+ blubid = bl1.id
+ sess.clear()
+
+ l = sess.query(Blub).select()
+ self.echo(l)
+ self.assert_(repr(l[0]) == compare)
+ sess.clear()
+ x = sess.query(Blub).get_by(id=blubid)
+ self.echo(x)
+ self.assert_(repr(x) == compare)
+
+class InheritTest4(testbase.AssertMixin):
+ """deals with inheritance and one-to-many relationships"""
+ def setUpAll(self):
+ global foo, bar, blub, metadata
+ metadata = BoundMetaData(testbase.db)
+ # the 'data' columns are to appease SQLite which cant handle a blank INSERT
+ foo = Table('foo', metadata,
+ Column('id', Integer, Sequence('foo_seq'), primary_key=True),
+ Column('data', String(20)))
+
+ bar = Table('bar', metadata,
+ Column('id', Integer, ForeignKey('foo.id'), primary_key=True),
+ Column('data', String(20)))
+
+ blub = Table('blub', metadata,
+ Column('id', Integer, ForeignKey('bar.id'), primary_key=True),
+ Column('foo_id', Integer, ForeignKey('foo.id'), nullable=False),
+ Column('data', String(20)))
+ metadata.create_all()
+ def tearDownAll(self):
+ metadata.drop_all()
+
+ def tearDown(self):
+ for table in metadata.table_iterator():
+ table.delete().execute()
+
+ def testbasic(self):
+ class Foo(object):
+ def __init__(self, data=None):
+ self.data = data
+ def __repr__(self):
+ return "Foo id %d, data %s" % (self.id, self.data)
+ mapper(Foo, foo)
+
+ class Bar(Foo):
+ def __repr__(self):
+ return "Bar id %d, data %s" % (self.id, self.data)
+
+ mapper(Bar, bar, inherits=Foo)
+
+ class Blub(Bar):
+ def __repr__(self):
+ return "Blub id %d, data %s" % (self.id, self.data)
+
+ mapper(Blub, blub, inherits=Bar, properties={
+ 'parent_foo':relation(Foo)
+ })
+
+ sess = create_session()
+ b1 = Blub("blub #1", _sa_session=sess)
+ b2 = Blub("blub #2", _sa_session=sess)
+ f = Foo("foo #1", _sa_session=sess)
+ b1.parent_foo = f
+ b2.parent_foo = f
+ sess.flush()
+ compare = repr(b1) + repr(b2) + repr(b1.parent_foo) + repr(b2.parent_foo)
+ sess.clear()
+ l = sess.query(Blub).select()
+ result = repr(l[0]) + repr(l[1]) + repr(l[0].parent_foo) + repr(l[1].parent_foo)
+ self.echo(result)
+ self.assert_(compare == result)
+ self.assert_(l[0].parent_foo.data == 'foo #1' and l[1].parent_foo.data == 'foo #1')
+
+class InheritTest5(testbase.AssertMixin):
+ """testing that construction of inheriting mappers works regardless of when extra properties
+ are added to the superclass mapper"""
+ def setUpAll(self):
+ global content_type, content, product, metadata
+ metadata = BoundMetaData(testbase.db)
+ content_type = Table('content_type', metadata,
+ Column('id', Integer, primary_key=True)
+ )
+ content = Table('content', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('content_type_id', Integer, ForeignKey('content_type.id'))
+ )
+ product = Table('product', metadata,
+ Column('id', Integer, ForeignKey('content.id'), primary_key=True)
+ )
+ def tearDownAll(self):
+ pass
+ def tearDown(self):
+ pass
+
+ def testbasic(self):
+ class ContentType(object): pass
+ class Content(object): pass
+ class Product(Content): pass
+
+ content_types = mapper(ContentType, content_type)
+ contents = mapper(Content, content, properties={
+ 'content_type':relation(content_types)
+ })
+ #contents.add_property('content_type', relation(content_types)) #adding this makes the inheritance stop working
+ # shouldnt throw exception
+ products = mapper(Product, product, inherits=contents)
+ # TODO: assertion ??
+
+ def testbackref(self):
+ """tests adding a property to the superclass mapper"""
+ class ContentType(object): pass
+ class Content(object): pass
+ class Product(Content): pass
+
+ contents = mapper(Content, content)
+ products = mapper(Product, product, inherits=contents)
+ content_types = mapper(ContentType, content_type, properties={
+ 'content':relation(contents, backref='contenttype')
+ })
+ p = Product()
+ p.contenttype = ContentType()
+ # TODO: assertion ??
+
+class InheritTest6(testbase.AssertMixin):
+ """tests eager load/lazy load of child items off inheritance mappers, tests that
+ LazyLoader constructs the right query condition."""
+ def setUpAll(self):
+ global foo, bar, bar_foo, metadata
+ metadata=BoundMetaData(testbase.db)
+ foo = Table('foo', metadata, Column('id', Integer, Sequence('foo_seq'), primary_key=True),
+ Column('data', String(30)))
+ bar = Table('bar', metadata, Column('id', Integer, ForeignKey('foo.id'), primary_key=True),
+ Column('data', String(30)))
+
+ bar_foo = Table('bar_foo', metadata,
+ Column('bar_id', Integer, ForeignKey('bar.id')),
+ Column('foo_id', Integer, ForeignKey('foo.id'))
+ )
+ metadata.create_all()
+ def tearDownAll(self):
+ metadata.drop_all()
+
+ def testbasic(self):
+ class Foo(object): pass
+ class Bar(Foo): pass
+
+ foos = mapper(Foo, foo)
+ bars = mapper(Bar, bar, inherits=foos)
+ bars.add_property('lazy', relation(foos, bar_foo, lazy=True))
+ print bars.props['lazy'].primaryjoin, bars.props['lazy'].secondaryjoin
+ bars.add_property('eager', relation(foos, bar_foo, lazy=False))
+
+ foo.insert().execute(data='foo1')
+ bar.insert().execute(id=1, data='bar1')
+
+ foo.insert().execute(data='foo2')
+ bar.insert().execute(id=2, data='bar2')
+
+ foo.insert().execute(data='foo3') #3
+ foo.insert().execute(data='foo4') #4
+
+ bar_foo.insert().execute(bar_id=1, foo_id=3)
+ bar_foo.insert().execute(bar_id=2, foo_id=4)
+
+ sess = create_session()
+ q = sess.query(Bar)
+ self.assert_(len(q.selectfirst().lazy) == 1)
+ self.assert_(len(q.selectfirst().eager) == 1)
+
+if __name__ == "__main__":
+ testbase.main()