def test_uses_get(self): """test that a simple many-to-one lazyload optimizes to use query.get().""" for pj in (None, users.c.id == addresses.c.user_id, addresses.c.user_id == users.c.id): mapper(Address, addresses, properties=dict(user=relation( mapper(User, users), lazy=True, primaryjoin=pj))) sess = create_session() # load address a1 = sess.query(Address).filter_by( email_address="*****@*****.**").one() # load user that is attached to the address u1 = sess.query(User).get(8) def go(): # lazy load of a1.user should get it from the session assert a1.user is u1 self.assert_sql_count(testing.db, go, 0) sa.orm.clear_mappers()
def test_dontload_with_eager(self): """ This test illustrates that with dont_load=True, we can't just copy the committed_state of the merged instance over; since it references collection objects which themselves are to be merged. This committed_state would instead need to be piecemeal 'converted' to represent the correct objects. However, at the moment I'd rather not support this use case; if you are merging with dont_load=True, you're typically dealing with caching and the merged objects shouldnt be 'dirty'. """ mapper(User, users, properties={ 'addresses':relation(mapper(Address, addresses)) }) sess = create_session() u = User() u.id = 7 u.name = "fred" a1 = Address() a1.email_address='*****@*****.**' u.addresses.append(a1) sess.add(u) sess.flush() sess2 = create_session() u2 = sess2.query(User).options(sa.orm.eagerload('addresses')).get(7) sess3 = create_session() u3 = sess3.merge(u2, dont_load=True) def go(): sess3.flush() self.assert_sql_count(testing.db, go, 0)
def test_backref(self): mapper(User, users, properties={ 'addresses': dynamic_loader(mapper(Address, addresses), backref='user') }) sess = create_session(autoflush=autoflush) u = User(name='buffy') a = Address(email_address='*****@*****.**') a.user = u if saveuser: sess.add(u) else: sess.add(a) if not autoflush: sess.flush() assert u in sess assert a in sess self.assert_(list(u.addresses) == [a]) a.user = None if not autoflush: self.assert_(list(u.addresses) == [a]) if not autoflush: sess.flush() self.assert_(list(u.addresses) == [])
def testcycle(self): mapper(C2, t2, properties={ 'c1s': relation(C1, primaryjoin=t2.c.c1 == t1.c.c2, uselist=True) }) mapper(C1, t1, properties={ 'c2s': relation(C2, primaryjoin=t1.c.c1 == t2.c.c2, uselist=True) }) a = C1() b = C2() c = C1() d = C2() e = C2() f = C2() a.c2s.append(b) d.c1s.append(c) b.c1s.append(c) sess = create_session() sess.add_all((a, b, c, d, e, f)) sess.flush()
def test_detached_to_persistent_collection(self): mapper(User, users, properties={ 'addresses':relation(Address, backref='user', collection_class=OrderedSet)}) mapper(Address, addresses) on_load = self.on_load_tracker(User) self.on_load_tracker(Address, on_load) a = Address(id=1, email_address='fred1') u = User(id=7, name='fred', addresses=OrderedSet([ a, Address(id=2, email_address='fred2'), ])) sess = create_session() sess.add(u) sess.flush() sess.clear() u.name='fred jones' u.addresses.add(Address(id=3, email_address='fred3')) u.addresses.remove(a) eq_(on_load.called, 0) u = sess.merge(u) eq_(on_load.called, 4) sess.flush() sess.clear() eq_(sess.query(User).first(), User(id=7, name='fred jones', addresses=OrderedSet([ Address(id=2, email_address='fred2'), Address(id=3, email_address='fred3')])))
def test_basic(self): mapper(Employee, employees) mapper(Department, departments, properties=dict(employees=relation(Employee, lazy=False, backref="department"))) d1 = Department(name="One") for e in "Jim", "Jack", "John", "Susan": d1.employees.append(Employee(name=e)) d2 = Department(name="Two") for e in "Joe", "Bob", "Mary", "Wally": d2.employees.append(Employee(name=e)) sess = create_session() sess.add_all((d1, d2)) sess.flush() q = ( sess.query(Department) .join("employees") .filter(Employee.name.startswith("J")) .distinct() .order_by([sa.desc(Department.name)]) ) eq_(q.count(), 2) assert q[0] is d2
def test_partially_mapped_inheritance(self): class A(object): pass class B(A): pass class C(B): def __init__(self): pass mapper(A, self.fixture()) a = attributes.instance_state(A()) assert isinstance(a, attributes.InstanceState) assert type(a) is not attributes.InstanceState b = attributes.instance_state(B()) assert isinstance(b, attributes.InstanceState) assert type(b) is not attributes.InstanceState # C is unmanaged cobj = C() self.assertRaises((AttributeError, TypeError), attributes.instance_state, cobj)
def test_class_deferred_cols(self): mapper(User, users, properties={ 'name':sa.orm.deferred(users.c.name), 'addresses':relation(Address, backref="user") }) mapper(Address, addresses, properties={ 'email_address':sa.orm.deferred(addresses.c.email_address) }) sess = create_session() u1 = User(name='ed') u1.addresses.append(Address(email_address='*****@*****.**')) sess.add(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='*****@*****.**')])) u2 = pickle.loads(pickle.dumps(u1)) sess2 = create_session() u2 = sess2.merge(u2, dont_load=True) self.assertEquals(u2.name, 'ed') self.assertEquals(u2, User(name='ed', addresses=[Address(email_address='*****@*****.**')]))
def test_mixed_transaction_control(self): mapper(User, users) sess = create_session(autocommit=True) sess.begin() sess.begin_nested() transaction = sess.begin(subtransactions=True) sess.add(User(name='u1')) transaction.commit() sess.commit() sess.commit() sess.close() self.assertEquals(len(sess.query(User).all()), 1) t1 = sess.begin() t2 = sess.begin_nested() sess.add(User(name='u2')) t2.commit() assert sess.transaction is t1 sess.close()
def test_before_flush_affects_dirty(self): mapper(User, users) class MyExt(sa.orm.session.SessionExtension): def before_flush(self, session, flush_context, objects): for obj in list(session.identity_map.values()): obj.name += " modified" sess = create_session(extension = MyExt(), autoflush=True) u = User(name='u1') sess.add(u) sess.flush() self.assertEquals(sess.query(User).order_by(User.name).all(), [ User(name='u1') ] ) sess.add(User(name='u2')) sess.flush() sess.clear() self.assertEquals(sess.query(User).order_by(User.name).all(), [ User(name='u1 modified'), User(name='u2') ] )
def test_basic(self): Session = scoped_session(sa.orm.sessionmaker()) class CustomQuery(query.Query): pass class SomeObject(_base.ComparableEntity): query = Session.query_property() class SomeOtherObject(_base.ComparableEntity): query = Session.query_property() custom_query = Session.query_property(query_cls=CustomQuery) mapper(SomeObject, table1, properties={ 'options':relation(SomeOtherObject)}) mapper(SomeOtherObject, table2) s = SomeObject(id=1, data="hello") sso = SomeOtherObject() s.options.append(sso) Session.add(s) Session.commit() Session.refresh(sso) Session.remove() eq_(SomeObject(id=1, data="hello", options=[SomeOtherObject(someid=1)]), Session.query(SomeObject).one()) eq_(SomeObject(id=1, data="hello", options=[SomeOtherObject(someid=1)]), SomeObject.query.one()) eq_(SomeOtherObject(someid=1), SomeOtherObject.query.filter( SomeOtherObject.someid == sso.someid).one()) assert isinstance(SomeOtherObject.query, query.Query) assert not isinstance(SomeOtherObject.query, CustomQuery) assert isinstance(SomeOtherObject.custom_query, query.Query)
def test_weak_ref(self): """test the weak-referencing identity map, which strongly-references modified items.""" s = create_session() mapper(User, users) s.add(User(name='ed')) s.flush() assert not s.dirty user = s.query(User).one() del user gc.collect() assert len(s.identity_map) == 0 user = s.query(User).one() user.name = 'fred' del user gc.collect() assert len(s.identity_map) == 1 assert len(s.dirty) == 1 assert None not in s.dirty s.flush() gc.collect() assert not s.dirty assert not s.identity_map user = s.query(User).one() assert user.name == 'fred' assert s.identity_map
def test_is_modified(self): s = create_session() mapper(User, users, properties={'addresses':relation(Address)}) mapper(Address, addresses) # save user u = User(name='fred') s.add(u) s.flush() s.clear() user = s.query(User).one() assert user not in s.dirty assert not s.is_modified(user) user.name = 'fred' assert user in s.dirty assert not s.is_modified(user) user.name = 'ed' assert user in s.dirty assert s.is_modified(user) s.flush() assert user not in s.dirty assert not s.is_modified(user) a = Address() user.addresses.append(a) assert user in s.dirty assert s.is_modified(user) assert not s.is_modified(user, include_collections=False)
def test_bound_connection_transactional(self): mapper(User, users) c = testing.db.connect() sess = create_session(bind=c, autocommit=False) u = User(name='u1') sess.add(u) sess.flush() sess.close() assert not c.in_transaction() assert c.scalar("select count(1) from users") == 0 sess = create_session(bind=c, autocommit=False) u = User(name='u2') sess.add(u) sess.flush() sess.commit() assert not c.in_transaction() assert c.scalar("select count(1) from users") == 1 c.execute("delete from users") assert c.scalar("select count(1) from users") == 0 c = testing.db.connect() trans = c.begin() sess = create_session(bind=c, autocommit=True) u = User(name='u3') sess.add(u) sess.flush() assert c.in_transaction() trans.commit() assert not c.in_transaction() assert c.scalar("select count(1) from users") == 1
def test_one_to_many_scalar(self): mapper(User, users, properties = dict( address = relation(mapper(Address, addresses), lazy=True, uselist=False) )) q = create_session().query(User) l = q.filter(users.c.id == 7).all() assert [User(id=7, address=Address(id=1))] == l
def test_no_autocommit_with_explicit_commit(self): mapper(User, users) session = create_session(autocommit=False) session.add(User(name='ed')) session.transaction.commit() assert session.transaction is not None, "autocommit=False should start a new transaction"
def test_uses_get(self): """test that a simple many-to-one lazyload optimizes to use query.get().""" for pj in ( None, users.c.id==addresses.c.user_id, addresses.c.user_id==users.c.id ): mapper(Address, addresses, properties = dict( user = relation(mapper(User, users), lazy=True, primaryjoin=pj) )) sess = create_session() # load address a1 = sess.query(Address).filter_by(email_address="*****@*****.**").one() # load user that is attached to the address u1 = sess.query(User).get(8) def go(): # lazy load of a1.user should get it from the session assert a1.user is u1 self.assert_sql_count(testing.db, go, 0) sa.orm.clear_mappers()
def test_expired_eager(self): mapper(User, users, properties={ 'addresses':relation(Address, backref='user', lazy=False), }) mapper(Address, addresses) sess = create_session() u = sess.query(User).get(7) sess.expire(u) assert 'name' not in u.__dict__ assert 'addresses' not in u.__dict__ def go(): assert u.addresses[0].email_address == '*****@*****.**' assert u.name == 'jack' # two loads, since relation() + scalar are # separate right now on per-attribute load self.assert_sql_count(testing.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 go(): sess.query(User).filter_by(id=7).one() assert u.addresses[0].email_address == '*****@*****.**' assert u.name == 'jack' # one load, since relation() + scalar are # together when eager load used with Query self.assert_sql_count(testing.db, go, 1)
def test_is_modified(self): s = create_session() mapper(User, users, properties={'addresses':relation(Address)}) mapper(Address, addresses) # save user u = User(name='fred') s.add(u) s.flush() s.expunge_all() user = s.query(User).one() assert user not in s.dirty assert not s.is_modified(user) user.name = 'fred' assert user in s.dirty assert not s.is_modified(user) user.name = 'ed' assert user in s.dirty assert s.is_modified(user) s.flush() assert user not in s.dirty assert not s.is_modified(user) a = Address() user.addresses.append(a) assert user in s.dirty assert s.is_modified(user) assert not s.is_modified(user, include_collections=False)
def test_compileonattr_rel_backref_b(self): m = MetaData() t1 = Table('t1', m, Column('id', Integer, primary_key=True), Column('x', Integer)) t2 = Table('t2', m, Column('id', Integer, primary_key=True), Column('t1_id', Integer, ForeignKey('t1.id'))) class Base(object): def __init__(self): pass class Base_AKW(object): def __init__(self, *args, **kwargs): pass for base in object, Base, Base_AKW: class A(base): pass class B(base): pass mapper(A, t1) mapper(B, t2, properties=dict(a=relation(A, backref='bs'))) a = A() b = B() b.a = a session = create_session() session.add(a) assert b in session, 'base: %s' % base
def testmanytooneonly(self): """ test that the circular dependency sort can assemble a many-to-one dependency processor when only the object on the "many" side is actually in the list of modified objects. this requires that the circular sort add the other side of the relation into the UOWTransaction so that the dependency operation can be tacked onto it. This also affects inheritance relationships since they rely upon circular sort as well. """ mapper(C1, t1, properties={ 'parent': relation(C1, primaryjoin=t1.c.parent_c1 == t1.c.c1, remote_side=t1.c.c1) }) c1 = C1() sess = create_session() sess.add(c1) sess.flush() sess.clear() c1 = sess.query(C1).get(c1.c1) c2 = C1() c2.parent = c1 sess.add(c2) sess.flush() assert c2.parent_c1 == c1.c1
def test_double(self): """test that a mapper can have two eager relations to the same table, via two different association tables. aliases are required.""" Place.mapper = mapper(Place, place, properties = { 'thingies':relation(mapper(PlaceThingy, place_thingy), lazy=False) }) Transition.mapper = mapper(Transition, transition, properties = dict( inputs = relation(Place.mapper, place_output, lazy=False), outputs = relation(Place.mapper, place_input, lazy=False), ) ) tran = Transition('transition1') tran.inputs.append(Place('place1')) tran.outputs.append(Place('place2')) tran.outputs.append(Place('place3')) sess = create_session() sess.add(tran) sess.flush() sess.expunge_all() r = sess.query(Transition).all() self.assert_unordered_result(r, Transition, {'name': 'transition1', 'inputs': (Place, [{'name':'place1'}]), 'outputs': (Place, [{'name':'place2'}, {'name':'place3'}]) })
def test_transient_to_pending_collection(self): mapper(User, users, properties={ 'addresses': relation(Address, backref='user', collection_class=OrderedSet)}) mapper(Address, addresses) on_load = self.on_load_tracker(User) self.on_load_tracker(Address, on_load) u = User(id=7, name='fred', addresses=OrderedSet([ Address(id=1, email_address='fred1'), Address(id=2, email_address='fred2'), ])) eq_(on_load.called, 0) sess = create_session() sess.merge(u) eq_(on_load.called, 3) merged_users = [e for e in sess if isinstance(e, User)] eq_(len(merged_users), 1) assert merged_users[0] is not u sess.flush() sess.clear() eq_(sess.query(User).one(), User(id=7, name='fred', addresses=OrderedSet([ Address(id=1, email_address='fred1'), Address(id=2, email_address='fred2'), ])) )
def test_bidirectional(self): """tests a many-to-many backrefs""" Place.mapper = mapper(Place, place) Transition.mapper = mapper(Transition, transition, properties = dict( inputs = relation(Place.mapper, place_output, lazy=True, backref='inputs'), outputs = relation(Place.mapper, place_input, lazy=True, backref='outputs'), ) ) t1 = Transition('transition1') t2 = Transition('transition2') t3 = Transition('transition3') p1 = Place('place1') p2 = Place('place2') p3 = Place('place3') t1.inputs.append(p1) t1.inputs.append(p2) t1.outputs.append(p3) t2.inputs.append(p1) p2.inputs.append(t2) p3.inputs.append(t2) p1.outputs.append(t1) sess = create_session() sess.add_all((t1, t2, t3,p1, p2, p3)) sess.flush() self.assert_result([t1], Transition, {'outputs': (Place, [{'name':'place3'}, {'name':'place1'}])}) self.assert_result([p2], Place, {'inputs': (Transition, [{'name':'transition1'},{'name':'transition2'}])})
def testmanytooneonly(self): """ test that the circular dependency sort can assemble a many-to-one dependency processor when only the object on the "many" side is actually in the list of modified objects. this requires that the circular sort add the other side of the relation into the UOWTransaction so that the dependency operation can be tacked onto it. This also affects inheritance relationships since they rely upon circular sort as well. """ mapper(C1, t1, properties={ 'parent':relation(C1, primaryjoin=t1.c.parent_c1 == t1.c.c1, remote_side=t1.c.c1)}) c1 = C1() sess = create_session() sess.add(c1) sess.flush() sess.expunge_all() c1 = sess.query(C1).get(c1.c1) c2 = C1() c2.parent = c1 sess.add(c2) sess.flush() assert c2.parent_c1==c1.c1
def test_compileonattr_rel_backref_a(self): m = MetaData() t1 = Table('t1', m, Column('id', Integer, primary_key=True), Column('x', Integer)) t2 = Table('t2', m, Column('id', Integer, primary_key=True), Column('t1_id', Integer, ForeignKey('t1.id'))) class Base(object): def __init__(self, *args, **kwargs): pass for base in object, Base: class A(base): pass class B(base): pass mapper(A, t1, properties=dict(bs=relation(B, backref='a'))) mapper(B, t2) b = B() assert b.a is None a = A() b.a = a session = create_session() session.add(b) assert a in session, "base is %s" % base
def testbasic(self): """ Test that post_update remembers to be involved in update operations as well, since it replaces the normal dependency processing completely [ticket:413] """ mapper(A, a_table, properties={ 'foo': relation(A, remote_side=[a_table.c.id], post_update=True)}) session = create_session() f1 = A(fui="f1") session.add(f1) session.flush() f2 = A(fui="f2", foo=f1) # at this point f1 is already inserted. but we need post_update # to fire off anyway session.add(f2) session.flush() session.expunge_all() f1 = session.query(A).get(f1.id) f2 = session.query(A).get(f2.id) assert f2.foo is f1
def test_correlated_lazyload(self): class User(_base.ComparableEntity): pass class Stuff(_base.ComparableEntity): pass mapper(Stuff, stuff) stuff_view = sa.select([ stuff.c.id ]).where(stuff.c.user_id == user_t.c.id).correlate(user_t).order_by( sa.desc(stuff.c.date)).limit(1) mapper(User, user_t, properties={ 'stuff': relation(Stuff, primaryjoin=sa.and_( user_t.c.id == stuff.c.user_id, stuff.c.id == (stuff_view.as_scalar()))) }) sess = create_session() eq_( sess.query(User).all(), [ User(name='user1', stuff=[Stuff(date=datetime.date(2007, 12, 15), id=2)]), User(name='user2', stuff=[Stuff(id=4, date=datetime.date(2008, 1, 15))]), User(name='user3', stuff=[Stuff(id=5, date=datetime.date(2007, 6, 15))]) ])
def test_basic(self): mapper(Employee, employees) mapper(Department, departments, properties=dict(employees=relation( Employee, lazy=False, backref='department'))) d1 = Department(name='One') for e in 'Jim', 'Jack', 'John', 'Susan': d1.employees.append(Employee(name=e)) d2 = Department(name='Two') for e in 'Joe', 'Bob', 'Mary', 'Wally': d2.employees.append(Employee(name=e)) sess = create_session() sess.add_all((d1, d2)) sess.flush() q = (sess.query(Department).join('employees').filter( Employee.name.startswith('J')).distinct().order_by( [sa.desc(Department.name)])) eq_(q.count(), 2) assert q[0] is d2
def test_basic(self): mapper(User, users, properties={ 'addresses':relation(mapper(Address, addresses), lazy=True) }) sess = create_session() q = sess.query(User) assert [User(id=7, addresses=[Address(id=1, email_address='*****@*****.**')])] == q.filter(users.c.id == 7).all()
def test_nested_joins(self): # this is testing some subtle column resolution stuff, # concerning corresponding_column() being extremely accurate # as well as how mapper sets up its column properties mapper(Task_Type, task_type) tsk_cnt_join = sa.outerjoin(prj, task, task.c.prj_id == prj.c.id) j = sa.outerjoin(task, msg, task.c.id == msg.c.task_id) jj = sa.select([ task.c.id.label('task_id'), sa.func.count(msg.c.id).label('props_cnt') ], from_obj=[j], group_by=[task.c.id]).alias('prop_c_s') jjj = sa.join(task, jj, task.c.id == jj.c.task_id) mapper(Joined, jjj, properties=dict(type=relation(Task_Type, lazy=False))) session = create_session() eq_( session.query(Joined).limit(10).offset(0).one(), Joined(id=1, title=u'task 1', props_cnt=0))
def test_backrefs_dont_lazyload(self): mapper(User, users, properties={ 'addresses':relation(Address, backref='user') }) mapper(Address, addresses) sess = create_session() ad = sess.query(Address).filter_by(id=1).one() assert ad.user.id == 7 def go(): ad.user = None assert ad.user is None self.assert_sql_count(testing.db, go, 0) u1 = sess.query(User).filter_by(id=7).one() def go(): assert ad not in u1.addresses self.assert_sql_count(testing.db, go, 1) sess.expire(u1, ['addresses']) def go(): assert ad in u1.addresses self.assert_sql_count(testing.db, go, 1) sess.expire(u1, ['addresses']) ad2 = Address() def go(): ad2.user = u1 assert ad2.user is u1 self.assert_sql_count(testing.db, go, 0) def go(): assert ad2 in u1.addresses self.assert_sql_count(testing.db, go, 1)
def test_refresh2(self): """test a hang condition that was occuring on expire/refresh""" s = create_session() mapper(Address, addresses) mapper(User, users, properties=dict(addresses=relation( Address, cascade="all, delete-orphan", lazy=False))) u = User() u.name = 'Justin' a = Address(id=10, email_address='lala') u.addresses.append(a) s.add(u) s.flush() s.clear() u = s.query(User).filter(User.name == 'Justin').one() s.expire(u) assert u.name == 'Justin' s.refresh(u)
def test_compileonattr_rel_backref_b(self): m = MetaData() t1 = Table("t1", m, Column("id", Integer, primary_key=True), Column("x", Integer)) t2 = Table("t2", m, Column("id", Integer, primary_key=True), Column("t1_id", Integer, ForeignKey("t1.id"))) class Base(object): def __init__(self): pass class Base_AKW(object): def __init__(self, *args, **kwargs): pass for base in object, Base, Base_AKW: class A(base): pass class B(base): pass mapper(A, t1) mapper(B, t2, properties=dict(a=relation(A, backref="bs"))) a = A() b = B() b.a = a session = create_session() session.add(a) assert b in session, "base: %s" % base
def test_basic(self): mapper(User, users, properties={ 'addresses':dynamic_loader(mapper(Address, addresses)) }) sess = create_session() u1 = User(name='jack') u2 = User(name='ed') u2.addresses.append(Address(email_address='*****@*****.**')) u1.addresses.append(Address(email_address='*****@*****.**')) sess.add_all((u1, u2)) sess.flush() from sqlalchemy.orm import attributes self.assertEquals(attributes.get_history(attributes.instance_state(u1), 'addresses'), ([], [Address(email_address='*****@*****.**')], [])) sess.clear() # test the test fixture a little bit assert User(name='jack', addresses=[Address(email_address='wrong')]) != sess.query(User).first() assert User(name='jack', addresses=[Address(email_address='*****@*****.**')]) == sess.query(User).first() assert [ User(name='jack', addresses=[Address(email_address='*****@*****.**')]), User(name='ed', addresses=[Address(email_address='*****@*****.**')]) ] == sess.query(User).all()
def test_persistence_check(self): mapper(User, users) s = create_session() u = s.query(User).get(7) s.clear() self.assertRaisesMessage(sa.exc.InvalidRequestError, r"is not persistent within this Session", s.expire, u)
def test_delete_cascade(self): mapper(User, users, properties={ 'addresses':dynamic_loader(mapper(Address, addresses), order_by=Address.id, backref='user', cascade="all, delete-orphan") }) sess = create_session(autoflush=True) u = User(name='ed') u.addresses.append(Address(email_address='a')) u.addresses.append(Address(email_address='b')) u.addresses.append(Address(email_address='c')) u.addresses.append(Address(email_address='d')) u.addresses.append(Address(email_address='e')) u.addresses.append(Address(email_address='f')) sess.add(u) assert Address(email_address='c') == u.addresses[2] sess.delete(u.addresses[2]) sess.delete(u.addresses[4]) sess.delete(u.addresses[3]) assert [Address(email_address='a'), Address(email_address='b'), Address(email_address='d')] == list(u.addresses) sess.clear() u = sess.query(User).get(u.id) sess.delete(u) # u.addresses relation will have to force the load # of all addresses so that they can be updated sess.flush() sess.close() assert testing.db.scalar(addresses.count()) ==0
def test_backref(self): mapper(User, users, properties={ 'addresses':dynamic_loader(mapper(Address, addresses), backref='user') }) sess = create_session(autoflush=autoflush) u = User(name='buffy') a = Address(email_address='*****@*****.**') a.user = u if saveuser: sess.add(u) else: sess.add(a) if not autoflush: sess.flush() assert u in sess assert a in sess self.assert_(list(u.addresses) == [a]) a.user = None if not autoflush: self.assert_(list(u.addresses) == [a]) if not autoflush: sess.flush() self.assert_(list(u.addresses) == [])
def test_circular(self): mapper(Student, student) mapper(Course, course, properties={ 'students': relation(Student, enroll, backref='courses') }) sess = create_session() s1 = Student('Student1') c1 = Course('Course1') c2 = Course('Course2') c3 = Course('Course3') s1.courses.append(c1) s1.courses.append(c2) c3.students.append(s1) self.assert_(len(s1.courses) == 3) self.assert_(len(c1.students) == 1) sess.add(s1) sess.flush() sess.clear() s = sess.query(Student).filter_by(name='Student1').one() c = sess.query(Course).filter_by(name='Course3').one() self.assert_(len(s.courses) == 3) del s.courses[1] self.assert_(len(s.courses) == 2)
def test_configured_order_by(self): mapper(User, users, properties={ 'addresses':dynamic_loader(mapper(Address, addresses), order_by=desc(Address.email_address)) }) sess = create_session() u = sess.query(User).get(8) eq_(list(u.addresses), [Address(email_address=u'*****@*****.**'), Address(email_address=u'*****@*****.**'), Address(email_address=u'*****@*****.**')])
def testcycle(self): """ This test has a peculiar aspect in that it doesnt create as many dependent relationships as the other tests, and revealed a small glitch in the circular dependency sorting. """ mapper(Ball, ball) mapper(Person, person, properties=dict( balls=relation(Ball, primaryjoin=ball.c.person_id == person.c.id, remote_side=ball.c.person_id), favorite=relation( Ball, primaryjoin=person.c.favorite_ball_id == ball.c.id, remote_side=ball.c.id))) b = Ball() p = Person() p.balls.append(b) sess = create_session() sess.add(p) sess.flush()
def test_count(self): mapper(User, users, properties={ 'addresses':dynamic_loader(mapper(Address, addresses)) }) sess = create_session() u = sess.query(User).first() eq_(u.addresses.count(), 1)
def testbasic(self): """ Test that post_update remembers to be involved in update operations as well, since it replaces the normal dependency processing completely [ticket:413] """ mapper(A, a_table, properties={ 'foo': relation(A, remote_side=[a_table.c.id], post_update=True) }) session = create_session() f1 = A(fui="f1") session.add(f1) session.flush() f2 = A(fui="f2", foo=f1) # at this point f1 is already inserted. but we need post_update # to fire off anyway session.add(f2) session.flush() session.clear() f1 = session.query(A).get(f1.id) f2 = session.query(A).get(f2.id) assert f2.foo is f1
def test_refresh(self): mapper(User, users, properties={ 'addresses':relation(mapper(Address, addresses), backref='user') }) s = create_session() u = s.query(User).get(7) u.name = 'foo' a = Address() assert sa.orm.object_session(a) is None u.addresses.append(a) assert a.email_address is None assert id(a) in [id(x) for x in u.addresses] s.refresh(u) # its refreshed, so not dirty assert u not in s.dirty # username is back to the DB assert u.name == 'jack' assert id(a) not in [id(x) for x in u.addresses] u.name = 'foo' u.addresses.append(a) # now its dirty assert u in s.dirty assert u.name == 'foo' assert id(a) in [id(x) for x in u.addresses] s.expire(u) # get the attribute, it refreshes assert u.name == 'jack' assert id(a) not in [id(x) for x in u.addresses]
def test_one_to_one_cascade(self): mapper(User, users, properties={ 'address':relation(mapper(Address, addresses),uselist = False) }) on_load = self.on_load_tracker(User) self.on_load_tracker(Address, on_load) sess = create_session() u = User() u.id = 7 u.name = "fred" a1 = Address() a1.email_address='*****@*****.**' u.address = a1 sess.add(u) sess.flush() eq_(on_load.called, 0) sess2 = create_session() u2 = sess2.query(User).get(7) eq_(on_load.called, 1) u2.name = 'fred2' u2.address.email_address = '*****@*****.**' eq_(on_load.called, 2) u3 = sess.merge(u2) eq_(on_load.called, 2) assert u3 is u
def test_custom_query(self): class MyQuery(Query): pass mapper(User, users, properties={ 'addresses': dynamic_loader(mapper(Address, addresses), query_class=MyQuery) }) sess = create_session() u = User() sess.add(u) col = u.addresses assert isinstance(col, Query) assert isinstance(col, MyQuery) assert hasattr(col, 'append') assert type(col).__name__ == 'AppenderMyQuery' q = col.limit(1) assert isinstance(q, Query) assert isinstance(q, MyQuery) assert not hasattr(q, 'append') assert type(q).__name__ == 'MyQuery'
def test_dontload_with_backrefs(self): """dontload populates relations in both directions without requiring a load""" mapper(User, users, properties={ 'addresses':relation(mapper(Address, addresses), backref='user') }) u = User(id=7, name='fred', addresses=[ Address(email_address='ad1'), Address(email_address='ad2')]) sess = create_session() sess.add(u) sess.flush() sess.close() assert 'user' in u.addresses[1].__dict__ sess = create_session() u2 = sess.merge(u, dont_load=True) assert 'user' in u2.addresses[1].__dict__ eq_(u2.addresses[1].user, User(id=7, name='fred')) sess.expire(u2.addresses[1], ['user']) assert 'user' not in u2.addresses[1].__dict__ sess.close() sess = create_session() u = sess.merge(u2, dont_load=True) assert 'user' not in u.addresses[1].__dict__ eq_(u.addresses[1].user, User(id=7, name='fred'))
def test_basic(self): mapper(User, users, properties={ 'addresses': dynamic_loader(mapper(Address, addresses)) }) sess = create_session() u1 = User(name='jack') u2 = User(name='ed') u2.addresses.append(Address(email_address='*****@*****.**')) u1.addresses.append(Address(email_address='*****@*****.**')) sess.add_all((u1, u2)) sess.flush() from sqlalchemy.orm import attributes self.assertEquals( attributes.get_history(attributes.instance_state(u1), 'addresses'), ([], [Address(email_address='*****@*****.**')], [])) sess.clear() # test the test fixture a little bit assert User(name='jack', addresses=[Address(email_address='wrong') ]) != sess.query(User).first() assert User(name='jack', addresses=[Address(email_address='*****@*****.**') ]) == sess.query(User).first() assert [ User(name='jack', addresses=[Address(email_address='*****@*****.**')]), User(name='ed', addresses=[Address(email_address='*****@*****.**')]) ] == sess.query(User).all()
def test_synonym_comparable(self): class User(object): class Comparator(PropComparator): pass def _getValue(self): return self._value def _setValue(self, value): setattr(self, '_value', value) value = property(_getValue, _setValue) mapper(User, users, properties={ 'uid':synonym('id'), 'foobar':comparable_property(User.Comparator,User.value), }) sess = create_session() u = User() u.name = 'ed' sess.save(u) sess.flush() sess.expunge(u) sess.merge(u)