def test_persistence_states(self): User = self.classes.User u1 = User(name="ed") insp = inspect(u1) eq_( (insp.transient, insp.pending, insp.persistent, insp.detached), (True, False, False, False), ) s = Session(testing.db) s.add(u1) eq_( (insp.transient, insp.pending, insp.persistent, insp.detached), (False, True, False, False), ) s.flush() eq_( (insp.transient, insp.pending, insp.persistent, insp.detached), (False, False, True, False), ) s.expunge(u1) eq_( (insp.transient, insp.pending, insp.persistent, insp.detached), (False, False, False, True), )
def test_partial_load_no_invoke_eagers(self): # test issue #4199 self._fixture_from_geometry( { "a": { "subclasses": { "a1": {"polymorphic_load": "selectin"}, "a2": {"polymorphic_load": "selectin"}, } } } ) a, a1, a2 = self.classes("a", "a1", "a2") sess = Session() a1_obj = a1() a2_obj = a2() sess.add_all([a1_obj, a2_obj]) del a2_obj sess.flush() sess.expire_all() # _with_invoke_all_eagers(False), used by the lazy loader # strategy, will cause one less state to be present such that # the poly loader won't locate a state limited to the "a1" mapper, # needs to test that it has states sess.query(a)._with_invoke_all_eagers(False).all()
def test_identity_key(self): User = self.classes.User u1 = User(name="ed") s = Session(testing.db) s.add(u1) s.flush() insp = inspect(u1) eq_(insp.identity_key, identity_key(User, (u1.id, )))
def _unhashable_fixture(self, metadata, load_on_pending=False): class MyHashType(sa.TypeDecorator): impl = sa.String(100) def process_bind_param(self, value, dialect): return ";".join( "%s=%s" % (k, v) for k, v in sorted(value.items(), key=lambda key: key[0])) def process_result_value(self, value, dialect): return dict(elem.split("=", 1) for elem in value.split(";")) category = Table( "category", metadata, Column("id", Integer, primary_key=True), Column("data", MyHashType()), ) article = Table( "article", metadata, Column("id", Integer, primary_key=True), Column("data", MyHashType()), ) class Category(fixtures.ComparableEntity): pass class Article(fixtures.ComparableEntity): pass mapper(Category, category) mapper( Article, article, properties={ "category": relationship( Category, primaryjoin=orm.foreign(article.c.data) == category.c.data, load_on_pending=load_on_pending, ) }, ) metadata.create_all() sess = Session(autoflush=False) data = {"im": "unhashable"} a1 = Article(id=1, data=data) c1 = Category(id=1, data=data) if load_on_pending: sess.add(c1) else: sess.add_all([c1, a1]) sess.flush() if load_on_pending: sess.add(a1) return Category, Article, sess, a1, c1
def _persistent_m2m_fixture(self, autoflush=True, items_args={}): Order, Item = self._order_item_fixture(items_args=items_args) o1 = Order() i1 = Item(description="i1") s = Session(autoflush=autoflush) s.add(o1) s.flush() return o1, i1, s
def test_replace(self): sess = Session() f1 = Foo(data={"a": "b"}) sess.add(f1) sess.flush() f1.data = {"b": "c"} sess.commit() eq_(f1.data, {"b": "c"})
def test_instance_state_ident_persistent(self): User = self.classes.User u1 = User(name="ed") s = Session(testing.db) s.add(u1) s.flush() insp = inspect(u1) eq_(insp.identity, (u1.id, )) is_(s.query(User).get(insp.identity), u1)
def test_basic(self): sess = Session() f1 = Foo(data=Point(3, 4)) sess.add(f1) sess.flush() f1.data.x = 5 sess.commit() # we didn't get the change. eq_(f1.data.x, 3)
def test_set_composite_values(self): Foobar, FBComposite = self.classes.Foobar, self.classes.FBComposite sess = Session() f1 = Foobar() f1.foob = FBComposite(None, 5, None, None) sess.add(f1) sess.flush() eq_(f1.foob, FBComposite(2, 5, 15, None))
def test_unrelated_flush(self): sess = Session() f1 = Foo(data={"a": "b"}, unrelated_data="unrelated") sess.add(f1) sess.flush() f1.unrelated_data = "unrelated 2" sess.flush() f1.data["a"] = "c" sess.commit() eq_(f1.data["a"], "c")
def _persistent_fixture(self, autoflush=True, addresses_args={}): User, Address = self._user_address_fixture( addresses_args=addresses_args) u1 = User(name="u1") a1 = Address(email_address="a1") s = Session(autoflush=autoflush) s.add(u1) s.flush() return u1, a1, s
def test_unrelated_flush(self): sess = Session() f1 = Foo(data=set([1, 2]), unrelated_data="unrelated") sess.add(f1) sess.flush() f1.unrelated_data = "unrelated 2" sess.flush() f1.data.add(3) sess.commit() eq_(f1.data, set([1, 2, 3]))
def test_replace_itself_still_ok(self): sess = Session() f1 = Foo(data={"a": "b"}) sess.add(f1) sess.flush() f1.data = f1.data f1.data["b"] = "c" sess.commit() eq_(f1.data, {"a": "b", "b": "c"})
def test_unrelated_flush(self): sess = Session() f1 = Foo(data=[1, 2], unrelated_data="unrelated") sess.add(f1) sess.flush() f1.unrelated_data = "unrelated 2" sess.flush() f1.data[0] = 3 sess.commit() eq_(f1.data[0], 3)
def test_unrelated_flush(self): sess = Session() f1 = Foo(data=Point(3, 4), unrelated_data="unrelated") sess.add(f1) sess.flush() f1.unrelated_data = "unrelated 2" sess.flush() f1.data.x = 5 sess.commit() eq_(f1.data.x, 5)
def _fixture(self): User, Address = self.classes.User, self.classes.Address s = Session() u1 = User() a1 = Address() u1.addresses.append(a1) s.add(u1) s.flush() return s, u1, a1
def insert_data(cls, connection): A, B, C = cls.classes("A", "B", "C") s = Session(connection) s.add_all([A(id=i) for i in range(1, 4)]) s.flush() s.add_all([ B(a_id=i, cs=[C(), C()]) for i in range(1, 4) for j in range(1, 21) ]) s.commit()
def test_evt_on_flush_refresh(self): # test for #3427 sess = Session() f1 = Foo() sess.add(f1) sess.flush() assert isinstance(f1.data, self._type_fixture()) assert f1 not in sess.dirty f1.data["foo"] = "bar" assert f1 in sess.dirty
def test_evt_on_flush_refresh(self): # this still worked prior to #3427 being fixed in any case sess = Session() f1 = Foo(data=self.Point(None, None)) sess.add(f1) sess.flush() eq_(f1.data, self.Point(5, 9)) assert f1 not in sess.dirty f1.data.x = 10 assert f1 in sess.dirty
def insert_data(cls, connection): A, B, C, D = cls.classes("A", "B", "C", "D") sess = Session(connection) for obj in [ B(id=1), A(id=1, b_id=1), C(id=1, a_id=1), D(id=1, c_id=1, b_id=1), ]: sess.add(obj) sess.flush() sess.commit()
def test_attributes_with_defaults(self): Foobar, FBComposite = self.classes.Foobar, self.classes.FBComposite sess = Session() f1 = Foobar() f1.foob = FBComposite(None, 5, None, None) sess.add(f1) sess.flush() eq_(f1.foob, FBComposite(2, 5, 15, None)) f2 = Foobar() sess.add(f2) sess.flush() eq_(f2.foob, FBComposite(2, None, 15, None))
def test_expire_lots(self): Parent, Child = self.classes.Parent, self.classes.Child obj = [ Parent(children=[Child() for j in range(10)]) for i in range(10) ] sess = Session() sess.add_all(obj) sess.flush() @profiling.function_call_count() def go(): sess.expire_all() go()
def test_lazy_doesnt_interfere(self): A, B, C = self.classes("A", "B", "C") session = Session() b = B() session.add(b) session.flush() b.parent_id = b.b_id b.zc.append(C()) b.zc.append(C()) session.commit() # If the bug is here, the next line throws an exception session.query(B).options( sa.orm.joinedload("parent").joinedload("zc")).all()
def test_update_attr_names(self): Data = self.classes.Data d1 = Data() sess = Session() sess.add(d1) sess.commit() eq_(d1.cnt, 0) sess.query(Data).update({Data.cnt: Data.cnt + 1}) sess.flush() eq_(d1.cnt, 1) sess.query(Data).update({Data.cnt: Data.cnt + 1}, "fetch") sess.flush() eq_(d1.cnt, 2) sess.close()
def test_basic(self): Subset, common = self.classes.Subset, self.tables.common subset_select = select([common.c.id, common.c.data]).alias() mapper(Subset, subset_select) sess = Session(bind=testing.db) sess.add(Subset(data=1)) sess.flush() sess.expunge_all() 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).persist_selectable eq_( sess.query(Subset).filter(subset_select.c.data == 1).one(), Subset(data=1), )
def test_session_delete(self): self._standard_bidirectional_fixture() A, B = self.classes.A, self.classes.B secondary = self.tables.secondary sess = Session() sess.add_all( [A(data="a1", bs=[B(data="b1")]), A(data="a2", bs=[B(data="b2")])]) sess.commit() a1 = sess.query(A).filter_by(data="a1").one() sess.delete(a1) sess.flush() eq_(sess.query(secondary).count(), 1) a2 = sess.query(A).filter_by(data="a2").one() sess.delete(a2) sess.flush() eq_(sess.query(secondary).count(), 0)
def test_not_none(self): Edge = self.classes.Edge # current contract. the composite is None # when hasn't been populated etc. on a # pending/transient object. e1 = Edge() assert e1.end is None sess = Session() sess.add(e1) # however, once it's persistent, the code as of 0.7.3 # would unconditionally populate it, even though it's # all None. I think this usage contract is inconsistent, # and it would be better that the composite is just # created unconditionally in all cases. # but as we are just trying to fix [ticket:2308] and # [ticket:2309] without changing behavior we maintain # that only "persistent" gets the composite with the # Nones sess.flush() assert e1.end is not None
def test_insert_computed(self, eager): if eager: Thing = self.classes.Thing else: Thing = self.classes.ThingNoEager s = Session() t1, t2 = (Thing(id=1, foo=5), Thing(id=2, foo=10)) s.add_all([t1, t2]) with assert_engine(testing.db) as asserter: s.flush() eq_(t1.bar, 5 + 42) eq_(t2.bar, 10 + 42) if eager and testing.db.dialect.implicit_returning: asserter.assert_( CompiledSQL( "INSERT INTO test (id, foo) VALUES (%(id)s, %(foo)s) " "RETURNING test.bar", [{ "foo": 5, "id": 1 }], dialect="postgresql", ), CompiledSQL( "INSERT INTO test (id, foo) VALUES (%(id)s, %(foo)s) " "RETURNING test.bar", [{ "foo": 10, "id": 2 }], dialect="postgresql", ), ) else: asserter.assert_( CompiledSQL( "INSERT INTO test (id, foo) VALUES (:id, :foo)", [{ "foo": 5, "id": 1 }, { "foo": 10, "id": 2 }], ), CompiledSQL( "SELECT test.bar AS test_bar FROM test " "WHERE test.id = :param_1", [{ "param_1": 1 }], ), CompiledSQL( "SELECT test.bar AS test_bar FROM test " "WHERE test.id = :param_1", [{ "param_1": 2 }], ), )
def test_coerce(self): sess = Session() f1 = Foo(data={"a": "b"}) sess.add(f1) sess.flush() eq_(type(f1.data), self._type_fixture())
def test_update_computed(self, eager): if eager: Thing = self.classes.Thing else: Thing = self.classes.ThingNoEager s = Session() t1, t2 = (Thing(id=1, foo=1), Thing(id=2, foo=2)) s.add_all([t1, t2]) s.flush() t1.foo = 5 t2.foo = 6 with assert_engine(testing.db) as asserter: s.flush() eq_(t1.bar, 5 + 42) eq_(t2.bar, 6 + 42) if eager and testing.db.dialect.implicit_returning: asserter.assert_( CompiledSQL( "UPDATE test SET foo=%(foo)s " "WHERE test.id = %(test_id)s " "RETURNING test.bar", [{ "foo": 5, "test_id": 1 }], dialect="postgresql", ), CompiledSQL( "UPDATE test SET foo=%(foo)s " "WHERE test.id = %(test_id)s " "RETURNING test.bar", [{ "foo": 6, "test_id": 2 }], dialect="postgresql", ), ) elif eager: asserter.assert_( CompiledSQL( "UPDATE test SET foo=:foo WHERE test.id = :test_id", [{ "foo": 5, "test_id": 1 }], ), CompiledSQL( "UPDATE test SET foo=:foo WHERE test.id = :test_id", [{ "foo": 6, "test_id": 2 }], ), CompiledSQL( "SELECT test.bar AS test_bar FROM test " "WHERE test.id = :param_1", [{ "param_1": 1 }], ), CompiledSQL( "SELECT test.bar AS test_bar FROM test " "WHERE test.id = :param_1", [{ "param_1": 2 }], ), ) else: asserter.assert_( CompiledSQL( "UPDATE test SET foo=:foo WHERE test.id = :test_id", [{ "foo": 5, "test_id": 1 }, { "foo": 6, "test_id": 2 }], ), CompiledSQL( "SELECT test.bar AS test_bar FROM test " "WHERE test.id = :param_1", [{ "param_1": 1 }], ), CompiledSQL( "SELECT test.bar AS test_bar FROM test " "WHERE test.id = :param_1", [{ "param_1": 2 }], ), )