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_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_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_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_double(self): """tests lazy loading with two relations simulatneously, from the same table, using aliases. """ openorders = sa.alias(orders, 'openorders') closedorders = sa.alias(orders, 'closedorders') mapper(Address, addresses) mapper(Order, orders) open_mapper = mapper(Order, openorders, non_primary=True) closed_mapper = mapper(Order, closedorders, non_primary=True) mapper(User, users, properties=dict(addresses=relation(Address, lazy=True), open_orders=relation( open_mapper, primaryjoin=sa.and_( openorders.c.isopen == 1, users.c.id == openorders.c.user_id), lazy=True), closed_orders=relation( closed_mapper, primaryjoin=sa.and_( closedorders.c.isopen == 0, users.c.id == closedorders.c.user_id), lazy=True))) q = create_session().query(User) assert [ User(id=7, addresses=[Address(id=1)], open_orders=[Order(id=3)], closed_orders=[Order(id=1), Order(id=5)]), User(id=8, addresses=[Address(id=2), Address(id=3), Address(id=4)], open_orders=[], closed_orders=[]), User(id=9, addresses=[Address(id=5)], open_orders=[Order(id=4)], closed_orders=[Order(id=2)]), User(id=10) ] == q.all() sess = create_session() user = sess.query(User).get(7) assert [Order(id=1), Order(id=5) ] == create_session().query(closed_mapper).with_parent( user, property='closed_orders').all() assert [Order(id=3) ] == create_session().query(open_mapper).with_parent( user, property='open_orders').all()
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_rekey(self): meta = MetaData(testing.db) class User(Base, ComparableEntity): __tablename__ = 'users' __autoload__ = True nom = Column('name', String(50), key='nom') addresses = relation("Address", backref="user") class Address(Base, ComparableEntity): __tablename__ = 'addresses' __autoload__ = True u1 = User(nom='u1', addresses=[ Address(email='one'), Address(email='two'), ]) sess = create_session() sess.add(u1) sess.flush() sess.clear() eq_(sess.query(User).all(), [User(nom='u1', addresses=[ Address(email='one'), Address(email='two'), ])]) a1 = sess.query(Address).filter(Address.email == 'two').one() eq_(a1, Address(email='two')) eq_(a1.user, User(nom='u1')) self.assertRaises(TypeError, User, name='u3')
def test_string_dependency_resolution(self): from sqlalchemy.sql import desc class User(Base, ComparableEntity): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(50)) addresses = relation("Address", order_by="desc(Address.email)", primaryjoin="User.id==Address.user_id", foreign_keys="[Address.user_id]") class Address(Base, ComparableEntity): __tablename__ = 'addresses' id = Column(Integer, primary_key=True) email = Column(String(50)) user_id = Column(Integer) # note no foreign key Base.metadata.create_all() sess = create_session() u1 = User(name='ed', addresses=[Address(email='abc'), Address(email='def'), Address(email='xyz')]) sess.add(u1) sess.flush() sess.clear() self.assertEquals(sess.query(User).filter(User.name == 'ed').one(), User(name='ed', addresses=[Address(email='xyz'), Address(email='def'), Address(email='abc')]) ) class Foo(Base, ComparableEntity): __tablename__ = 'foo' id = Column(Integer, primary_key=True) rel = relation("User", primaryjoin="User.addresses==Foo.id") self.assertRaisesMessage(exc.InvalidRequestError, "'addresses' is not an instance of ColumnProperty", compile_mappers)
def test_reentrant_compile_via_foreignkey(self): class User(Base, ComparableEntity): __tablename__ = 'users' id = Column('id', Integer, primary_key=True) name = Column('name', String(50)) addresses = relation("Address", backref="user") class Address(Base, ComparableEntity): __tablename__ = 'addresses' id = Column('id', Integer, primary_key=True) email = Column('email', String(50)) user_id = Column('user_id', Integer, ForeignKey(User.id)) # this forces a re-entrant compile() due to the User.id within the # ForeignKey sa.orm.compile_mappers() Base.metadata.create_all() u1 = User(name='u1', addresses=[ Address(email='one'), Address(email='two'), ]) sess = create_session() sess.add(u1) sess.flush() sess.clear() eq_(sess.query(User).all(), [User(name='u1', addresses=[ Address(email='one'), Address(email='two'), ])])
def test_order_by_multi(self): class Address(Base, ComparableEntity): __tablename__ = 'addresses' id = Column('id', Integer, primary_key=True) email = Column('email', String(50)) user_id = Column('user_id', Integer, ForeignKey('users.id')) class User(Base, ComparableEntity): __tablename__ = 'users' id = Column('id', Integer, primary_key=True) name = Column('name', String(50)) addresses = relation("Address", order_by=(Address.email, Address.id)) Base.metadata.create_all() u1 = User(name='u1', addresses=[ Address(email='two'), Address(email='one'), ]) sess = create_session() sess.add(u1) sess.flush() sess.clear() u = sess.query(User).filter(User.name == 'u1').one() a = u.addresses
def test_uncompiled_attributes_in_relation(self): class Address(Base, ComparableEntity): __tablename__ = 'addresses' id = Column(Integer, primary_key=True) email = Column(String(50)) user_id = Column(Integer, ForeignKey('users.id')) class User(Base, ComparableEntity): __tablename__ = 'users' id = Column(Integer, primary_key=True) name = Column(String(50)) addresses = relation("Address", order_by=Address.email, foreign_keys=Address.user_id, remote_side=Address.user_id, ) # get the mapper for User. User mapper will compile, # "addresses" relation will call upon Address.user_id for # its clause element. Address.user_id is a _CompileOnAttr, # which then calls class_mapper(Address). But ! We're already # "in compilation", but class_mapper(Address) needs to initialize # regardless, or COA's assertion fails # and things generally go downhill from there. class_mapper(User) Base.metadata.create_all() sess = create_session() u1 = User(name='ed', addresses=[Address(email='abc'), Address(email='xyz'), Address(email='def')]) sess.add(u1) sess.flush() sess.clear() self.assertEquals(sess.query(User).filter(User.name == 'ed').one(), User(name='ed', addresses=[Address(email='abc'), Address(email='def'), Address(email='xyz')]) )
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_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_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_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_modify(self): sess = create_session() item1 = Item('item1') item2 = Item('item2') item1.keywords.append(KeywordAssociation(Keyword('blue'), 'blue_assoc')) item1.keywords.append(KeywordAssociation(Keyword('red'), 'red_assoc')) item2.keywords.append( KeywordAssociation(Keyword('green'), 'green_assoc')) sess.add_all((item1, item2)) sess.flush() red_keyword = item1.keywords[1].keyword del item1.keywords[0] del item1.keywords[0] purple_keyword = Keyword('purple') item1.keywords.append(KeywordAssociation(red_keyword, 'new_red_assoc')) item2.keywords.append( KeywordAssociation(purple_keyword, 'purple_item2_assoc')) item1.keywords.append( KeywordAssociation(purple_keyword, 'purple_item1_assoc')) item1.keywords.append( KeywordAssociation(Keyword('yellow'), 'yellow_assoc')) sess.flush() saved = repr([item1, item2]) sess.clear() l = sess.query(Item).all() loaded = repr(l) eq_(saved, loaded)
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 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_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_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 testone(self): """ Tests eager load of a many-to-one attached to a one-to-many. this testcase illustrated the bug, which is that when the single Company is loaded, no further processing of the rows occurred in order to load the Company's second Address object. """ mapper(Address, addresses) mapper(Company, companies, properties={"addresses": relation(Address, lazy=False)}) mapper(Invoice, invoices, properties={"company": relation(Company, lazy=False)}) a1 = Address(address="a1 address") a2 = Address(address="a2 address") c1 = Company(company_name="company 1", addresses=[a1, a2]) i1 = Invoice(date=datetime.datetime.now(), company=c1) session = create_session() session.add(i1) session.flush() company_id = c1.company_id invoice_id = i1.invoice_id session.clear() c = session.query(Company).get(company_id) session.clear() i = session.query(Invoice).get(invoice_id) eq_(c, i.company)
def test_supplied_fk(self): meta = MetaData(testing.db) class IMHandle(Base, ComparableEntity): __tablename__ = 'imhandles' __autoload__ = True user_id = Column('user_id', Integer, ForeignKey('users.id')) class User(Base, ComparableEntity): __tablename__ = 'users' __autoload__ = True handles = relation("IMHandle", backref="user") u1 = User(name='u1', handles=[ IMHandle(network='blabber', handle='foo'), IMHandle(network='lol', handle='zomg') ]) sess = create_session() sess.add(u1) sess.flush() sess.clear() eq_(sess.query(User).all(), [User(name='u1', handles=[ IMHandle(network='blabber', handle='foo'), IMHandle(network='lol', handle='zomg') ])]) a1 = sess.query(IMHandle).filter(IMHandle.handle == 'zomg').one() eq_(a1, IMHandle(network='lol', handle='zomg')) eq_(a1.user, User(name='u1'))
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_eager_order_by(self): class Address(Base, ComparableEntity): __tablename__ = 'addresses' id = Column('id', Integer, primary_key=True) email = Column('email', String(50)) user_id = Column('user_id', Integer, ForeignKey('users.id')) class User(Base, ComparableEntity): __tablename__ = 'users' id = Column('id', Integer, primary_key=True) name = Column('name', String(50)) addresses = relation("Address", order_by=Address.email) Base.metadata.create_all() u1 = User(name='u1', addresses=[ Address(email='two'), Address(email='one'), ]) sess = create_session() sess.add(u1) sess.flush() sess.clear() eq_(sess.query(User).options(eagerload(User.addresses)).all(), [User(name='u1', addresses=[ Address(email='one'), Address(email='two'), ])])
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_as_declarative(self): class User(ComparableEntity): __tablename__ = 'users' id = Column('id', Integer, primary_key=True) name = Column('name', String(50)) addresses = relation("Address", backref="user") class Address(ComparableEntity): __tablename__ = 'addresses' id = Column('id', Integer, primary_key=True) email = Column('email', String(50)) user_id = Column('user_id', Integer, ForeignKey('users.id')) reg = {} decl.instrument_declarative(User, reg, Base.metadata) decl.instrument_declarative(Address, reg, Base.metadata) Base.metadata.create_all() u1 = User(name='u1', addresses=[ Address(email='one'), Address(email='two'), ]) sess = create_session() sess.add(u1) sess.flush() sess.clear() eq_(sess.query(User).all(), [User(name='u1', addresses=[ Address(email='one'), Address(email='two'), ])])
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_relation_reference(self): class Address(Base, ComparableEntity): __tablename__ = 'addresses' id = Column('id', Integer, primary_key=True) email = Column('email', String(50)) user_id = Column('user_id', Integer, ForeignKey('users.id')) class User(Base, ComparableEntity): __tablename__ = 'users' id = Column('id', Integer, primary_key=True) name = Column('name', String(50)) addresses = relation("Address", backref="user", primaryjoin=id == Address.user_id) User.address_count = sa.orm.column_property( sa.select([sa.func.count(Address.id)]). where(Address.user_id == User.id).as_scalar()) Base.metadata.create_all() u1 = User(name='u1', addresses=[ Address(email='one'), Address(email='two'), ]) sess = create_session() sess.add(u1) sess.flush() sess.clear() eq_(sess.query(User).all(), [User(name='u1', address_count=2, addresses=[ Address(email='one'), Address(email='two')])])
def test_session_unbound(self): sess = create_session() sess.add(Foo()) self.assertRaisesMessage( sa.exc.UnboundExecutionError, ('Could not locate a bind configured on Mapper|Foo|test_table ' 'or this Session'), sess.flush)
def test_basic(self): meta = MetaData(testing.db) class User(Base, ComparableEntity): __tablename__ = 'users' __autoload__ = True addresses = relation("Address", backref="user") class Address(Base, ComparableEntity): __tablename__ = 'addresses' __autoload__ = True u1 = User(name='u1', addresses=[ Address(email='one'), Address(email='two'), ]) sess = create_session() sess.add(u1) sess.flush() sess.clear() eq_(sess.query(User).all(), [User(name='u1', addresses=[ Address(email='one'), Address(email='two'), ])]) a1 = sess.query(Address).filter(Address.email == 'two').one() eq_(a1, Address(email='two')) eq_(a1.user, User(name='u1'))
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 test_reflush_2(self): """A variant on test_reflush()""" o1 = T1() o1.t2 = T2() sess = create_session() sess.add(o1) sess.flush() # in this case, T1, T2, and T3 tasks will all be in the cyclical # tree normally. the dependency processors for T3 are part of the # 'extradeps' collection so they all get assembled into the tree # as well. o1a = T1() o2a = T2() sess.add(o1a) sess.add(o2a) o3b = T3() o3b.t1 = o1a o3b.t2 = o2a sess.add(o3b) o3 = T3() o3.t1 = o1 o3.t2 = o1.t2 sess.add(o3) sess.flush()
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 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_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 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_no_deref(self): session = create_session() user = User() user.name = 'joe' user.fullname = 'Joe User' user.password = '******'s secret' address = Address() address.email_address = '*****@*****.**' address.user = user session.add(user) session.flush() session.clear() def query1(): session = create_session(testing.db) user = session.query(User).first() return user.addresses.all() def query2(): session = create_session(testing.db) return session.query(User).first().addresses.all() def query3(): session = create_session(testing.db) user = session.query(User).first() return session.query(User).first().addresses.all() eq_(query1(), [Address(email_address='*****@*****.**')]) eq_(query2(), [Address(email_address='*****@*****.**')]) eq_(query3(), [Address(email_address='*****@*****.**')])
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_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 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)
def test_basic(self): class C(object): pass class A(object): pass class B(object): pass mapper(B, b) mapper(A, a, properties={ 'tbs': relation(B, primaryjoin=sa.and_(b.c.a1 == a.c.a1, b.c.b2 == True), lazy=False) }) mapper(C, c, properties={ 'a1s': relation(A, secondary=c2a1, lazy=False), 'a2s': relation(A, secondary=c2a2, lazy=False) }) assert create_session().query(C).with_labels().statement