diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-12-21 06:57:20 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2007-12-21 06:57:20 +0000 |
| commit | c114f096bd0bd786916cbc42eaa91e0e1158ccf4 (patch) | |
| tree | 2313856ffc6bfe8a3b61017a58efe98b4be322e7 /test/orm | |
| parent | 2db36bf59c447d4d113cba0ae12f1b739c2ae923 (diff) | |
| download | sqlalchemy-c114f096bd0bd786916cbc42eaa91e0e1158ccf4.tar.gz | |
- reworked all lazy/deferred/expired callables to be
serializable class instances, added pickling tests
- cleaned up "deferred" polymorphic system so that the
mapper handles it entirely
- columns which are missing from a Query's select statement
now get automatically deferred during load.
Diffstat (limited to 'test/orm')
| -rw-r--r-- | test/orm/alltests.py | 1 | ||||
| -rw-r--r-- | test/orm/attributes.py | 60 | ||||
| -rw-r--r-- | test/orm/expire.py | 29 | ||||
| -rw-r--r-- | test/orm/mapper.py | 4 | ||||
| -rw-r--r-- | test/orm/pickled.py | 119 |
5 files changed, 204 insertions, 9 deletions
diff --git a/test/orm/alltests.py b/test/orm/alltests.py index 3748d3f34..dd2bd8446 100644 --- a/test/orm/alltests.py +++ b/test/orm/alltests.py @@ -26,6 +26,7 @@ def suite(): 'orm.relationships', 'orm.association', 'orm.merge', + 'orm.pickled', 'orm.memusage', 'orm.cycles', diff --git a/test/orm/attributes.py b/test/orm/attributes.py index a756566d5..dd15e41e5 100644 --- a/test/orm/attributes.py +++ b/test/orm/attributes.py @@ -95,6 +95,65 @@ class AttributesTest(PersistTest): self.assert_(o4.mt2[0].a == 'abcde') self.assert_(o4.mt2[0].b is None) + def test_deferred(self): + class Foo(object):pass + + data = {'a':'this is a', 'b':12} + def loader(instance, keys): + for k in keys: + instance.__dict__[k] = data[k] + return attributes.ATTR_WAS_SET + + attributes.register_class(Foo, deferred_scalar_loader=loader) + attributes.register_attribute(Foo, 'a', uselist=False, useobject=False) + attributes.register_attribute(Foo, 'b', uselist=False, useobject=False) + + f = Foo() + f._state.expire_attributes(None) + self.assertEquals(f.a, "this is a") + self.assertEquals(f.b, 12) + + f.a = "this is some new a" + f._state.expire_attributes(None) + self.assertEquals(f.a, "this is a") + self.assertEquals(f.b, 12) + + f._state.expire_attributes(None) + f.a = "this is another new a" + self.assertEquals(f.a, "this is another new a") + self.assertEquals(f.b, 12) + + f._state.expire_attributes(None) + self.assertEquals(f.a, "this is a") + self.assertEquals(f.b, 12) + + del f.a + self.assertEquals(f.a, None) + self.assertEquals(f.b, 12) + + f._state.commit_all() + self.assertEquals(f.a, None) + self.assertEquals(f.b, 12) + + def test_deferred_pickleable(self): + data = {'a':'this is a', 'b':12} + def loader(instance, keys): + for k in keys: + instance.__dict__[k] = data[k] + return attributes.ATTR_WAS_SET + + attributes.register_class(MyTest, deferred_scalar_loader=loader) + attributes.register_attribute(MyTest, 'a', uselist=False, useobject=False) + attributes.register_attribute(MyTest, 'b', uselist=False, useobject=False) + + m = MyTest() + m._state.expire_attributes(None) + assert 'a' not in m.__dict__ + m2 = pickle.loads(pickle.dumps(m)) + assert 'a' not in m2.__dict__ + self.assertEquals(m2.a, "this is a") + self.assertEquals(m2.b, 12) + def test_list(self): class User(object):pass class Address(object):pass @@ -860,7 +919,6 @@ class HistoryTest(PersistTest): self.assertEquals(attributes.get_history(f._state, 'bars'), ([bar4], [], [])) lazy_load = [bar1, bar2, bar3] - f._state.trigger = lazyload(f) f._state.expire_attributes(['bars']) self.assertEquals(attributes.get_history(f._state, 'bars'), ([], [bar1, bar2, bar3], [])) diff --git a/test/orm/expire.py b/test/orm/expire.py index be9c881c0..e1c016612 100644 --- a/test/orm/expire.py +++ b/test/orm/expire.py @@ -31,8 +31,6 @@ class ExpireTest(FixtureTest): self.assert_sql_count(testbase.db, go, 1) assert 'name' in u.__dict__ - # we're changing the database here, so if this test fails in the middle, - # it'll screw up the other tests which are hardcoded to 7/'jack' u.name = 'foo' sess.flush() # change the value in the DB @@ -45,9 +43,9 @@ class ExpireTest(FixtureTest): # test that it refreshed assert u.__dict__['name'] == 'jack' - # object should be back to normal now, - # this should *not* produce a SELECT statement (not tested here though....) - assert u.name == 'jack' + def go(): + assert u.name == 'jack' + self.assert_sql_count(testbase.db, go, 0) def test_expire_doesntload_on_set(self): mapper(User, users) @@ -76,6 +74,15 @@ class ExpireTest(FixtureTest): assert o.isopen == 1 self.assert_sql_count(testbase.db, go, 1) assert o.description == 'order 3 modified' + + del o.description + assert "description" not in o.__dict__ + sess.expire(o, ['isopen']) + sess.query(Order).all() + assert o.isopen == 1 + assert "description" not in o.__dict__ + + assert o.description is None def test_expire_committed(self): """test that the committed state of the attribute receives the most recent DB data""" @@ -144,11 +151,16 @@ class ExpireTest(FixtureTest): def go(): assert u.addresses[0].email_address == 'jack@bean.com' assert u.name == 'jack' - # one load - self.assert_sql_count(testbase.db, go, 1) + # two loads, since relation() + scalar are + # separate right now + self.assert_sql_count(testbase.db, go, 2) assert 'name' in u.__dict__ assert 'addresses' in u.__dict__ + sess.expire(u, ['name', 'addresses']) + assert 'name' not in u.__dict__ + assert 'addresses' not in u.__dict__ + def test_partial_expire(self): mapper(Order, orders) @@ -380,6 +392,9 @@ class RefreshTest(FixtureTest): s.expire(u) # get the attribute, it refreshes + print "OK------" +# print u.__dict__ +# print u._state.callables assert u.name == 'jack' assert id(a) not in [id(x) for x in u.addresses] diff --git a/test/orm/mapper.py b/test/orm/mapper.py index 662ac4a29..a7cb3a57d 100644 --- a/test/orm/mapper.py +++ b/test/orm/mapper.py @@ -87,7 +87,9 @@ class MapperTest(MapperSuperTest): a = s.query(Address).from_statement(select([addresses.c.address_id, addresses.c.user_id])).first() assert a.user_id == 7 assert a.address_id == 1 - assert a.email_address is None + # email address auto-defers + assert 'email_addres' not in a.__dict__ + assert a.email_address == 'jack@bean.com' def test_badconstructor(self): """test that if the construction of a mapped class fails, the instnace does not get placed in the session""" diff --git a/test/orm/pickled.py b/test/orm/pickled.py new file mode 100644 index 000000000..eac628024 --- /dev/null +++ b/test/orm/pickled.py @@ -0,0 +1,119 @@ +import testbase +from sqlalchemy import * +from sqlalchemy import exceptions +from sqlalchemy.orm import * +from testlib import * +from testlib.fixtures import * +import pickle + +class EmailUser(User): + pass + +class PickleTest(FixtureTest): + keep_mappers = False + keep_data = False + + def test_transient(self): + mapper(User, users, properties={ + 'addresses':relation(Address, backref="user") + }) + mapper(Address, addresses) + + sess = create_session() + u1 = User(name='ed') + u1.addresses.append(Address(email_address='ed@bar.com')) + + u2 = pickle.loads(pickle.dumps(u1)) + sess.save(u2) + sess.flush() + + sess.clear() + + self.assertEquals(u1, sess.query(User).get(u2.id)) + + def test_class_deferred_cols(self): + mapper(User, users, properties={ + 'name':deferred(users.c.name), + 'addresses':relation(Address, backref="user") + }) + mapper(Address, addresses, properties={ + 'email_address':deferred(addresses.c.email_address) + }) + sess = create_session() + u1 = User(name='ed') + u1.addresses.append(Address(email_address='ed@bar.com')) + sess.save(u1) + sess.flush() + sess.clear() + u1 = sess.query(User).get(u1.id) + assert 'name' not in u1.__dict__ + assert 'addresses' not in u1.__dict__ + + u2 = pickle.loads(pickle.dumps(u1)) + sess2 = create_session() + sess2.update(u2) + self.assertEquals(u2.name, 'ed') + self.assertEquals(u2, User(name='ed', addresses=[Address(email_address='ed@bar.com')])) + + def test_instance_deferred_cols(self): + mapper(User, users, properties={ + 'addresses':relation(Address, backref="user") + }) + mapper(Address, addresses) + + sess = create_session() + u1 = User(name='ed') + u1.addresses.append(Address(email_address='ed@bar.com')) + sess.save(u1) + sess.flush() + sess.clear() + + u1 = sess.query(User).options(defer('name'), defer('addresses.email_address')).get(u1.id) + assert 'name' not in u1.__dict__ + assert 'addresses' not in u1.__dict__ + + u2 = pickle.loads(pickle.dumps(u1)) + sess2 = create_session() + sess2.update(u2) + self.assertEquals(u2.name, 'ed') + assert 'addresses' not in u1.__dict__ + ad = u2.addresses[0] + assert 'email_address' not in ad.__dict__ + self.assertEquals(ad.email_address, 'ed@bar.com') + self.assertEquals(u2, User(name='ed', addresses=[Address(email_address='ed@bar.com')])) + +class PolymorphicDeferredTest(ORMTest): + def define_tables(self, metadata): + global users, email_users + users = Table('users', metadata, + Column('id', Integer, primary_key=True), + Column('name', String(30)), + Column('type', String(30)), + ) + email_users = Table('email_users', metadata, + Column('id', Integer, ForeignKey('users.id'), primary_key=True), + Column('email_address', String(30)) + ) + + def test_polymorphic_deferred(self): + mapper(User, users, polymorphic_identity='user', polymorphic_on=users.c.type, polymorphic_fetch='deferred') + mapper(EmailUser, email_users, inherits=User, polymorphic_identity='emailuser') + + eu = EmailUser(name="user1", email_address='foo@bar.com') + sess = create_session() + sess.save(eu) + sess.flush() + sess.clear() + + eu = sess.query(User).first() + eu2 = pickle.loads(pickle.dumps(eu)) + sess2 = create_session() + sess2.update(eu2) + assert 'email_address' not in eu2.__dict__ + self.assertEquals(eu2.email_address, 'foo@bar.com') + + + + +if __name__ == '__main__': + testbase.main()
\ No newline at end of file |
