def test_non_orphan(self): """test that an entity can have two parent delete-orphan cascades, and persists normally.""" class Address(_fixtures.Base): pass class Home(_fixtures.Base): pass class Business(_fixtures.Base): pass mapper(Address, addresses) mapper(Home, homes, properties={"address": relation(Address, cascade="all,delete-orphan", single_parent=True)}) mapper( Business, businesses, properties={"address": relation(Address, cascade="all,delete-orphan", single_parent=True)}, ) session = create_session() h1 = Home(description="home1", address=Address(street="address1")) b1 = Business(description="business1", address=Address(street="address2")) session.add_all((h1, b1)) session.flush() session.expunge_all() eq_(session.query(Home).get(h1.id), Home(description="home1", address=Address(street="address1"))) eq_(session.query(Business).get(b1.id), Business(description="business1", address=Address(street="address2")))
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_standard(self): class A(object): pass attributes.register_class(A) eq_(type(attributes.manager_of_class(A)), attributes.ClassManager)
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_cascades_onlycollection(self): """Cascade only reaches instances that are still part of the collection, not those that have been removed""" sess = create_session() u = User(name='jack', orders=[Order(description='someorder'), Order(description='someotherorder')]) sess.add(u) sess.flush() o = u.orders[0] del u.orders[0] sess.delete(u) assert u in sess.deleted assert o not in sess.deleted assert o in sess u2 = User(name='newuser', orders=[o]) sess.add(u2) sess.flush() sess.clear() assert users.count().scalar() == 1 assert orders.count().scalar() == 1 eq_(sess.query(User).all(), [User(name='newuser', orders=[Order(description='someorder')])])
def test_custom_mapper(self): class MyExt(sa.orm.MapperExtension): def create_instance(self): return "CHECK" def mymapper(cls, tbl, **kwargs): kwargs['extension'] = MyExt() return sa.orm.mapper(cls, tbl, **kwargs) from sqlalchemy.orm.mapper import Mapper class MyMapper(Mapper): def __init__(self, *args, **kwargs): kwargs['extension'] = MyExt() Mapper.__init__(self, *args, **kwargs) from sqlalchemy.orm import scoping ss = scoping.ScopedSession(create_session) ss.extension = MyExt() ss_mapper = ss.mapper for mapperfunc in (mymapper, MyMapper, ss_mapper): base = decl.declarative_base() class Foo(base): __tablename__ = 'foo' __mapper_cls__ = mapperfunc id = Column(Integer, primary_key=True) eq_(Foo.__mapper__.compile().extension.create_instance(), 'CHECK') base = decl.declarative_base(mapper=mapperfunc) class Foo(base): __tablename__ = 'foo' id = Column(Integer, primary_key=True) eq_(Foo.__mapper__.compile().extension.create_instance(), 'CHECK')
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_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_basic(self): class A(_fixtures.Base): pass class B(_fixtures.Base): pass mapper(A, table_a, properties={"bs": relation(B, cascade="all, delete-orphan")}) mapper(B, table_b) a1 = A(name="a1", bs=[B(name="b1"), B(name="b2"), B(name="b3")]) sess = create_session() sess.add(a1) sess.flush() sess.expunge_all() eq_(sess.query(A).get(a1.id), A(name="a1", bs=[B(name="b1"), B(name="b2"), B(name="b3")])) a1 = sess.query(A).get(a1.id) assert not class_mapper(B)._is_orphan(attributes.instance_state(a1.bs[0])) a1.bs[0].foo = "b2modified" a1.bs[1].foo = "b3modified" sess.flush() sess.expunge_all() eq_(sess.query(A).get(a1.id), A(name="a1", bs=[B(name="b1"), B(name="b2"), B(name="b3")]))
def test_updatemany(self): # MySQL-Python 1.2.2 breaks functions in execute_many :( if (testing.against('mysql') and testing.db.dialect.dbapi.version_info[:3] == (1, 2, 2)): return t.insert().execute({}, {}, {}) t.update(t.c.col1==sa.bindparam('pkval')).execute( {'pkval':51,'col7':None, 'col8':None, 'boolcol1':False}) t.update(t.c.col1==sa.bindparam('pkval')).execute( {'pkval':51,}, {'pkval':52,}, {'pkval':53,}) l = t.select().execute() ctexec = currenttime.scalar() today = datetime.date.today() eq_(l.fetchall(), [(51, 'im the update', f2, ts, ts, ctexec, False, False, 13, today, 'py'), (52, 'im the update', f2, ts, ts, ctexec, True, False, 13, today, 'py'), (53, 'im the update', f2, ts, ts, ctexec, True, False, 13, today, 'py')])
def test_join(self): """Query.join""" session = create_session() q = (session.query(User).join(['orders', 'addresses']). filter(Address.id == 1)) eq_([User(id=7)], q.all())
def test_noorm(self): """test the control case""" # I want to display a list of tests owned by owner 1 # if someoption is false or he hasn't specified it yet (null) # but not if he set it to true (example someoption is for hiding) # desired output for owner 1 # test_id, cat_name # 1 'Some Category' # 3 " # not orm style correct query print "Obtaining correct results without orm" result = ( sa.select( [tests.c.id, categories.c.name], sa.and_(tests.c.owner_id == 1, sa.or_(options.c.someoption == None, options.c.someoption == False)), order_by=[tests.c.id], from_obj=[ tests.join(categories).outerjoin( options, sa.and_(tests.c.id == options.c.test_id, tests.c.owner_id == options.c.owner_id) ) ], ) .execute() .fetchall() ) eq_(result, [(1, u"Some Category"), (3, u"Some Category")])
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.expunge_all() l = sess.query(Item).all() loaded = repr(l) eq_(saved, loaded)
def test_lazyhistory(self): """tests that history functions work with lazy-loading attributes""" class Foo(_base.BasicEntity): pass class Bar(_base.BasicEntity): pass attributes.register_class(Foo) attributes.register_class(Bar) bar1, bar2, bar3, bar4 = [Bar(id=1), Bar(id=2), Bar(id=3), Bar(id=4)] def func1(): return "this is func 1" def func2(): return [bar1, bar2, bar3] attributes.register_attribute(Foo, 'col1', uselist=False, callable_=lambda o:func1, useobject=True) attributes.register_attribute(Foo, 'col2', uselist=True, callable_=lambda o:func2, useobject=True) attributes.register_attribute(Bar, 'id', uselist=False, useobject=True) x = Foo() attributes.instance_state(x).commit_all() x.col2.append(bar4) eq_(attributes.get_history(attributes.instance_state(x), 'col2'), ([bar4], [bar1, bar2, bar3], []))
def test_that_mssql_none_nullability_does_not_emit_nullability(self): schemagenerator = \ mssql.MSSQLDialect().schemagenerator(mssql.MSSQLDialect(), None) self.column.nullable = None column_specification = \ schemagenerator.get_column_specification(self.column) eq_("test_column VARCHAR", column_specification)
def test_that_mssql_specified_not_nullable_emits_not_null(self): schemagenerator = \ mssql.MSSQLDialect().schemagenerator(mssql.MSSQLDialect(), None) self.column.nullable = False column_specification = \ schemagenerator.get_column_specification(self.column) eq_("test_column VARCHAR NOT NULL", column_specification)
def test_popitem(self): data, wim = self._fixture() (needle, idx) = wim.popitem() assert needle in data eq_(len(data), (len(wim) + 1)) assert id(needle) not in wim.by_id
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_autoincrement(self, bind): ids = set() rs = bind.execute(aitable.insert(), int1=1) last = rs.last_inserted_ids()[0] self.assert_(last) self.assert_(last not in ids) ids.add(last) rs = bind.execute(aitable.insert(), str1='row 2') last = rs.last_inserted_ids()[0] self.assert_(last) self.assert_(last not in ids) ids.add(last) rs = bind.execute(aitable.insert(), int1=3, str1='row 3') last = rs.last_inserted_ids()[0] self.assert_(last) self.assert_(last not in ids) ids.add(last) rs = bind.execute(aitable.insert(values={'int1':func.length('four')})) last = rs.last_inserted_ids()[0] self.assert_(last) self.assert_(last not in ids) ids.add(last) eq_(list(bind.execute(aitable.select().order_by(aitable.c.id))), [(1, 1, None), (2, None, 'row 2'), (3, 3, 'row 3'), (4, 4, None)])
def test_length_deprecation(self): self.assertRaises(exc.SADeprecationWarning, Numeric, length=8) @testing.uses_deprecated(".*is deprecated for Numeric") def go(): n = Numeric(length=12) assert n.scale == 12 go() n = Numeric(scale=12) for dialect in engines.all_dialects(): n2 = dialect.type_descriptor(n) eq_(n2.scale, 12, dialect.name) # test colspec generates successfully using 'scale' assert n2.get_col_spec() # test constructor of the dialect-specific type n3 = n2.__class__(scale=5) eq_(n3.scale, 5, dialect.name) @testing.uses_deprecated(".*is deprecated for Numeric") def go(): n3 = n2.__class__(length=6) eq_(n3.scale, 6, dialect.name) go()
def test_update_values(self): r = t.insert().execute() pk = r.last_inserted_ids()[0] t.update(t.c.col1==pk, values={'col3': 55}).execute() l = t.select(t.c.col1==pk).execute() l = l.fetchone() eq_(55, l['col3'])
def test_passive_override(self): """ Primarily for postgres, tests that when we get a primary key column back from reflecting a table which has a default value on it, we pre-execute that DefaultClause upon insert, even though DefaultClause says "let the database execute this", because in postgres we must have all the primary key values in memory before insert; otherwise we can't locate the just inserted row. """ # TODO: move this to dialect/postgres try: meta = MetaData(testing.db) testing.db.execute(""" CREATE TABLE speedy_users ( speedy_user_id SERIAL PRIMARY KEY, user_name VARCHAR NOT NULL, user_password VARCHAR NOT NULL ); """, None) t = Table("speedy_users", meta, autoload=True) t.insert().execute(user_name='user', user_password='******') l = t.select().execute().fetchall() eq_(l, [(1, 'user', 'lala')]) finally: testing.db.execute("drop table speedy_users", None)
def test_nativeext_submanager(self): class Mine(attributes.ClassManager): pass class A(object): __sa_instrumentation_manager__ = Mine attributes.register_class(A) eq_(type(attributes.manager_of_class(A)), Mine)
def test_insert(self): r = t.insert().execute() assert r.lastrow_has_defaults() eq_(set(r.context.postfetch_cols), set([t.c.col3, t.c.col5, t.c.col4, t.c.col6])) r = t.insert(inline=True).execute() assert r.lastrow_has_defaults() eq_(set(r.context.postfetch_cols), set([t.c.col3, t.c.col5, t.c.col4, t.c.col6])) t.insert().execute() ctexec = sa.select([currenttime.label('now')], bind=testing.db).scalar() l = t.select().order_by(t.c.col1).execute() today = datetime.date.today() eq_(l.fetchall(), [ (x, 'imthedefault', f, ts, ts, ctexec, True, False, 12, today, 'py') for x in range(51, 54)]) t.insert().execute(col9=None) assert r.lastrow_has_defaults() eq_(set(r.context.postfetch_cols), set([t.c.col3, t.c.col5, t.c.col4, t.c.col6])) eq_(t.select(t.c.col1==54).execute().fetchall(), [(54, 'imthedefault', f, ts, ts, ctexec, True, False, 12, today, None)])
def test_identity_key_1(self): mapper(User, users) key = util.identity_key(User, 1) eq_(key, (User, (1,))) key = util.identity_key(User, ident=1) eq_(key, (User, (1,)))
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 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_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_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_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): 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_list_assignment(self): sess = create_session() u = User(name='jack', orders=[ Order(description='someorder'), Order(description='someotherorder')]) sess.add(u) sess.flush() sess.clear() u = sess.query(User).get(u.id) eq_(u, User(name='jack', orders=[Order(description='someorder'), Order(description='someotherorder')])) u.orders=[Order(description="order 3"), Order(description="order 4")] sess.flush() sess.clear() u = sess.query(User).get(u.id) eq_(u, User(name='jack', orders=[Order(description="order 3"), Order(description="order 4")])) eq_(sess.query(Order).all(), [Order(description="order 3"), Order(description="order 4")]) o5 = Order(description="order 5") sess.add(o5) try: sess.flush() assert False except orm_exc.FlushError, e: assert "is an orphan" in str(e)
def test_Ai_B_C(self): inits = [] class A(object): def __init__(self): inits.append((A, '__init__')) self.register(A, inits) class B(A): pass self.register(B, inits) class C(B): pass self.register(C, inits) obj = A() eq_(inits, [(A, 'on_init', A), (A, '__init__')]) del inits[:] obj = B() eq_(inits, [(B, 'on_init', B), (A, '__init__')]) del inits[:] obj = C() eq_(inits, [(C, 'on_init', C), (A, '__init__')])
def test_mutators_against_iter(self): # testing a set modified against an iterator o = util.OrderedSet([3, 2, 4, 5]) eq_(o.difference(iter([3, 4])), util.OrderedSet([2, 5])) eq_(o.intersection(iter([3, 4, 6])), util.OrderedSet([3, 4])) eq_(o.union(iter([3, 4, 6])), util.OrderedSet([2, 3, 4, 5, 6]))
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_synonym_no_descriptor(self): from sqlalchemy.orm.properties import ColumnProperty class CustomCompare(ColumnProperty.Comparator): __hash__ = None def __eq__(self, other): return self.__clause_element__() == other + ' FOO' class User(Base, ComparableEntity): __tablename__ = 'users' id = Column('id', Integer, primary_key=True) _name = Column('name', String(50)) name = sa.orm.synonym('_name', comparator_factory=CustomCompare) Base.metadata.create_all() sess = create_session() u1 = User(name='someuser FOO') sess.add(u1) sess.flush() eq_(sess.query(User).filter(User.name == "someuser").one(), u1)
def test_witheagerload(self): """ Test that an eagerload locates the correct "from" clause with which to attach to, when presented with a query that already has a complicated from clause. """ s = create_session() q = s.query(Test).options(sa.orm.eagerload('category')) l = (q.select_from( tests.outerjoin( options, sa.and_(tests.c.id == options.c.test_id, tests.c.owner_id == options.c.owner_id))).filter( sa.and_( tests.c.owner_id == 1, sa.or_(options.c.someoption == None, options.c.someoption == False)))) result = ["%d %s" % (t.id, t.category.name) for t in l] eq_(result, [u'1 Some Category', u'3 Some Category'])
def test_single(self): class A(object): pass class B(object): pass eq_(set(util.class_hierarchy(A)), set((A, object))) eq_(set(util.class_hierarchy(B)), set((B, object))) class C(A, B): pass eq_(set(util.class_hierarchy(A)), set((A, B, C, object))) eq_(set(util.class_hierarchy(B)), set((A, B, C, object)))
def test_non_orphan(self): """test that an entity can have two parent delete-orphan cascades, and persists normally.""" class Address(_fixtures.Base): pass class Home(_fixtures.Base): pass class Business(_fixtures.Base): pass mapper(Address, addresses) mapper(Home, homes, properties={'address':relation(Address, cascade="all,delete-orphan")}) mapper(Business, businesses, properties={'address':relation(Address, cascade="all,delete-orphan")}) session = create_session() h1 = Home(description='home1', address=Address(street='address1')) b1 = Business(description='business1', address=Address(street='address2')) session.add_all((h1,b1)) session.flush() session.clear() eq_(session.query(Home).get(h1.id), Home(description='home1', address=Address(street='address1'))) eq_(session.query(Business).get(b1.id), Business(description='business1', address=Address(street='address2')))
def test_Ai_Bi(self): inits = [] class A(object): def __init__(self): inits.append((A, '__init__')) self.register(A, inits) class B(A): def __init__(self): inits.append((B, '__init__')) super(B, self).__init__() self.register(B, inits) obj = A() eq_(inits, [(A, 'on_init', A), (A, '__init__')]) del inits[:] obj = B() eq_(inits, [(B, 'on_init', B), (B, '__init__'), (A, '__init__')])
def test_unsaved_cascade(self): """Merge of a transient entity with two child transient entities, with a bidirectional relation.""" mapper(User, users, properties={ 'addresses':relation(mapper(Address, addresses), cascade="all", backref="user") }) on_load = self.on_load_tracker(User) self.on_load_tracker(Address, on_load) sess = create_session() u = User(id=7, name='fred') a1 = Address(email_address='*****@*****.**') a2 = Address(email_address='*****@*****.**') u.addresses.append(a1) u.addresses.append(a2) u2 = sess.merge(u) eq_(on_load.called, 3) eq_(u, User(id=7, name='fred', addresses=[ Address(email_address='*****@*****.**'), Address(email_address='*****@*****.**')])) eq_(u2, User(id=7, name='fred', addresses=[ Address(email_address='*****@*****.**'), Address(email_address='*****@*****.**')])) sess.flush() sess.clear() u2 = sess.query(User).get(7) eq_(u2, User(id=7, name='fred', addresses=[ Address(email_address='*****@*****.**'), Address(email_address='*****@*****.**')])) eq_(on_load.called, 6)
def test_weak_clear(self): data, wim = self._fixture() assert len(data) == len(wim) == len(wim.by_id) del data[:] eq_(wim, {}) eq_(wim.by_id, {}) eq_(wim._weakrefs, {})
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_standalone(self): c = testing.db.engine.contextual_connect() x = c.execute(t.c.col1.default) y = t.c.col2.default.execute() z = c.execute(t.c.col3.default) assert 50 <= x <= 57 eq_(y, 'imthedefault') eq_(z, f) eq_(f2, 11)
def test_autoflush_expressions(self): """test that an expression which is dependent on object state is evaluated after the session autoflushes. This is the lambda inside of strategies.py lazy_clause. """ mapper(User, users, properties={ 'addresses':relation(Address, backref="user")}) mapper(Address, addresses) sess = create_session(autoflush=True, autocommit=False) u = User(name='ed', addresses=[Address(email_address='foo')]) sess.add(u) eq_(sess.query(Address).filter(Address.user==u).one(), Address(email_address='foo')) # still works after "u" is garbage collected sess.commit() sess.close() u = sess.query(User).get(u.id) q = sess.query(Address).filter(Address.user==u) del u gc.collect() eq_(q.one(), Address(email_address='foo'))
def test_basic(self): subset_select = select([common.c.id, common.c.data]) subset_mapper = mapper(Subset, subset_select) sess = create_session(bind=testing.db) sess.add(Subset(data=1)) sess.flush() sess.clear() eq_(sess.query(Subset).all(), [Subset(data=1)]) eq_(sess.query(Subset).filter(Subset.data == 1).one(), Subset(data=1)) eq_(sess.query(Subset).filter(Subset.data != 1).first(), None) subset_select = sa.orm.class_mapper(Subset).mapped_table eq_( sess.query(Subset).filter(subset_select.c.data == 1).one(), Subset(data=1))
def test_autoflush(self): bind = self.metadata.bind mapper(User, users) conn1 = bind.connect() conn2 = bind.connect() sess = create_session(bind=conn1, autocommit=False, autoflush=True) u = User() u.name='ed' sess.add(u) u2 = sess.query(User).filter_by(name='ed').one() assert u2 is u eq_(conn1.execute("select count(1) from users").scalar(), 1) eq_(conn2.execute("select count(1) from users").scalar(), 0) sess.commit() eq_(conn1.execute("select count(1) from users").scalar(), 1) eq_(bind.connect().execute("select count(1) from users").scalar(), 1) sess.close()
def test_pop_default(self): data, wim = self._fixture() needle = data[-1] value = wim[needle] x = wim.pop(needle, 123) ne_(x, 123) eq_(x, value) assert needle not in wim assert id(needle) not in wim.by_id eq_(len(data), (len(wim) + 1)) n2 = self.Data() y = wim.pop(n2, 456) eq_(y, 456) assert n2 not in wim assert id(n2) not in wim.by_id eq_(len(data), (len(wim) + 1))
def test_distinct_count(self): query = create_session().query(Obj1) eq_(query.count(), 4) res = query.filter( sa.and_(Table1.c.id == Table2.c.t1id, Table2.c.t1id == 1)) eq_(res.count(), 3) res = query.filter( sa.and_(Table1.c.id == Table2.c.t1id, Table2.c.t1id == 1)).distinct() eq_(res.count(), 1)
def test_cascade_delete(self): sess = create_session() x = T1(data='t1a', t2=T2(data='t2a', t3=T3(data='t3a'))) sess.add(x) sess.flush() sess.delete(x) sess.flush() eq_(sess.query(T1).all(), []) eq_(sess.query(T2).all(), []) eq_(sess.query(T3).all(), [])
def test_finds_orphans_twolevel(self): sess = create_session() x = T1(data='t1a', t2=T2(data='t2a', t3=T3(data='t3a'))) sess.add(x) sess.flush() x.t2.t3 = None sess.flush() eq_(sess.query(T1).all(), [T1()]) eq_(sess.query(T2).all(), [T2()]) eq_(sess.query(T3).all(), [])
def test_deletes_orphans_onelevel(self): sess = create_session() x2 = T1(data='t1b', t2=T2(data='t2b', t3=T3(data='t3b'))) sess.add(x2) sess.flush() x2.t2 = None sess.delete(x2) sess.flush() eq_(sess.query(T1).all(), []) eq_(sess.query(T2).all(), []) eq_(sess.query(T3).all(), [])
def test_cascade_delete_postappend_twolevel(self): sess = create_session() x1 = T1(data='t1', t2=T2(data='t2')) x3 = T3(data='t3') sess.add_all((x1, x3)) sess.flush() sess.delete(x1) x1.t2.t3 = x3 sess.flush() eq_(sess.query(T1).all(), []) eq_(sess.query(T2).all(), []) eq_(sess.query(T3).all(), [])
def test_intersection(self): elem = object eq_ = self.assert_eq a, b, c, d, e, f, g = elem(), elem(), elem(), elem(), elem(), elem( ), elem() s1 = util.OrderedIdentitySet([a, b, c]) s2 = util.OrderedIdentitySet([d, e, f]) s3 = util.OrderedIdentitySet([a, d, f, g]) eq_(s1.intersection(s2), []) eq_(s1.intersection(s3), [a]) eq_(s1.union(s2).intersection(s3), [a, d, f])
def test_oldstyle_mixin(self): class A(object): pass class Mixin: pass class B(A, Mixin): pass eq_(set(util.class_hierarchy(B)), set((A, B, object))) eq_(set(util.class_hierarchy(Mixin)), set()) eq_(set(util.class_hierarchy(A)), set((A, B, object)))
def test_pop(self): data, wim = self._fixture() needle = data[-1] needle = data.pop() assert needle in wim assert id(needle) in wim.by_id eq_(wim[needle], wim.by_id[id(needle)]) eq_(len(wim), (len(data) + 1)) wim.pop(needle) assert needle not in wim assert id(needle) not in wim.by_id eq_(len(wim), len(data))
def test_comparable_using(self): class NameComparator(sa.orm.PropComparator): @property def upperself(self): cls = self.prop.parent.class_ col = getattr(cls, 'name') return sa.func.upper(col) def operate(self, op, other, **kw): return op(self.upperself, other, **kw) class User(Base, ComparableEntity): __tablename__ = 'users' id = Column('id', Integer, primary_key=True) name = Column('name', String(50)) @decl.comparable_using(NameComparator) @property def uc_name(self): return self.name is not None and self.name.upper() or None Base.metadata.create_all() sess = create_session() u1 = User(name='someuser') eq_(u1.name, "someuser", u1.name) eq_(u1.uc_name, 'SOMEUSER', u1.uc_name) sess.add(u1) sess.flush() sess.clear() rt = sess.query(User).filter(User.uc_name == 'SOMEUSER').one() eq_(rt, u1) sess.clear() rt = sess.query(User).filter(User.uc_name.startswith('SOMEUSE')).one() eq_(rt, u1)
def test_setitem(self): data, wim = self._fixture() o1, oid1 = data[-1], id(data[-1]) assert o1 in wim assert oid1 in wim.by_id eq_(wim[o1], wim.by_id[oid1]) id_keys = set(wim.by_id.keys()) wim[o1] = 1234 assert o1 in wim assert oid1 in wim.by_id eq_(wim[o1], wim.by_id[oid1]) eq_(set(wim.by_id.keys()), id_keys) o2 = self.Data() oid2 = id(o2) wim[o2] = 5678 assert o2 in wim assert oid2 in wim.by_id eq_(wim[o2], wim.by_id[oid2])
def test_delitem(self): data, wim = self._fixture() needle = data[-1] assert needle in wim assert id(needle) in wim.by_id eq_(wim[needle], wim.by_id[id(needle)]) del wim[needle] assert needle not in wim assert id(needle) not in wim.by_id eq_(len(wim), (len(data) - 1)) data.remove(needle) assert needle not in wim assert id(needle) not in wim.by_id eq_(len(wim), len(data))
def go(): # load just the first Account. eager loading will actually load # all objects saved thus far, but will not eagerly load the # "accounts" off the immediate "entries"; only the "accounts" off # the entries->transaction->entries acc = (session.query(Account).options( sa.orm.eagerload_all( 'entries.transaction.entries.account')).order_by( Account.account_id)).first() # no sql occurs eq_(acc.name, 'acc1') eq_(acc.entries[0].transaction.entries[0].account.name, 'acc1') eq_(acc.entries[0].transaction.entries[1].account.name, 'acc2') # lazyload triggers but no sql occurs because many-to-one uses # cached query.get() for e in acc.entries: assert e.account is acc