def test_versioncheck(self): """query.with_lockmode performs a 'version check' on an already loaded instance""" s1 = create_session(autocommit=False) mapper(Foo, version_table, version_id_col=version_table.c.version_id) f1s1 = Foo(value='f1 value') s1.add(f1s1) s1.commit() s2 = create_session(autocommit=False) f1s2 = s2.query(Foo).get(f1s1.id) f1s2.value='f1 new value' s2.commit() # load, version is wrong assert_raises_message( sa.orm.exc.StaleDataError, r"Instance .* has version id '\d+' which does not " r"match database-loaded version id '\d+'", s1.query(Foo).with_lockmode('read').get, f1s1.id ) # reload it - this expires the old version first s1.refresh(f1s1, lockmode='read') # now assert version OK s1.query(Foo).with_lockmode('read').get(f1s1.id) # assert brand new load is OK too s1.close() s1.query(Foo).with_lockmode('read').get(f1s1.id)
def test_limit_offset_for_update(self): # oracle can't actually do the ROWNUM thing with FOR UPDATE # very well. t = Table('t1', metadata, Column('id', Integer, primary_key=True), Column('data', Integer) ) metadata.create_all() t.insert().execute( {'id':1, 'data':1}, {'id':2, 'data':7}, {'id':3, 'data':12}, {'id':4, 'data':15}, {'id':5, 'data':32}, ) # here, we can't use ORDER BY. eq_( t.select(for_update=True).limit(2).execute().fetchall(), [(1, 1), (2, 7)] ) # here, its impossible. But we'd prefer it to raise ORA-02014 # instead of issuing a syntax error. assert_raises_message( exc.DatabaseError, "ORA-02014", t.select(for_update=True).limit(2).offset(3).execute )
def test_child_row_switch_two(self): Session = sessionmaker() # TODO: not sure this test is # testing exactly what its looking for sess1 = Session() sess1.add(P(id='P1', data='P version 1')) sess1.commit() sess1.close() p1 = sess1.query(P).first() sess2 = Session() p2 = sess2.query(P).first() sess1.delete(p1) sess1.commit() # this can be removed and it still passes sess1.add(P(id='P1', data='P version 2')) sess1.commit() p2.data = 'P overwritten by concurrent tx' assert_raises_message( orm.exc.StaleDataError, r"UPDATE statement on table 'p' expected to update " r"1 row\(s\); 0 were matched.", sess2.commit)
def test_versioncheck(self): """query.with_lockmode performs a 'version check' on an already loaded instance""" s1 = create_session(autocommit=False) mapper(Foo, version_table, version_id_col=version_table.c.version_id) f1s1 = Foo(value='f1 value') s1.add(f1s1) s1.commit() s2 = create_session(autocommit=False) f1s2 = s2.query(Foo).get(f1s1.id) f1s2.value = 'f1 new value' s2.commit() # load, version is wrong assert_raises_message( sa.orm.exc.StaleDataError, r"Instance .* has version id '\d+' which does not " r"match database-loaded version id '\d+'", s1.query(Foo).with_lockmode('read').get, f1s1.id) # reload it - this expires the old version first s1.refresh(f1s1, lockmode='read') # now assert version OK s1.query(Foo).with_lockmode('read').get(f1s1.id) # assert brand new load is OK too s1.close() s1.query(Foo).with_lockmode('read').get(f1s1.id)
def test_orphan_message(self): class Base(_fixtures.Base): pass class SubClass(Base): pass class Parent(_fixtures.Base): pass mapper(Base, single, polymorphic_on=single.c.type, polymorphic_identity='base') mapper(SubClass, inherits=Base, polymorphic_identity='sub') mapper(Parent, parent, properties={ 'related': relationship(Base, cascade="all, delete-orphan") }) sess = create_session() s1 = SubClass(data='s1') sess.add(s1) assert_raises_message( orm_exc.FlushError, r"is not attached to any parent 'Parent' instance via " "that classes' 'related' attribute", sess.flush)
def test_persistence_check(self): mapper(User, users) s = create_session() u = s.query(User).get(7) s.expunge_all() assert_raises_message(sa_exc.InvalidRequestError, r"is not persistent within this Session", s.expire, u)
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.expunge_all() 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.expunge_all() 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).order_by(Order.id).all(), [Order(description="order 3"), Order(description="order 4")]) o5 = Order(description="order 5") sess.add(o5) assert_raises_message(orm_exc.FlushError, "is an orphan", sess.flush)
def test_child_row_switch_two(self): Session = sessionmaker() # TODO: not sure this test is # testing exactly what its looking for sess1 = Session() sess1.add(P(id='P1', data='P version 1')) sess1.commit() sess1.close() p1 = sess1.query(P).first() sess2 = Session() p2 = sess2.query(P).first() sess1.delete(p1) sess1.commit() # this can be removed and it still passes sess1.add(P(id='P1', data='P version 2')) sess1.commit() p2.data = 'P overwritten by concurrent tx' assert_raises_message( orm.exc.StaleDataError, r"UPDATE statement on table 'p' expected to update " r"1 row\(s\); 0 were matched.", sess2.commit )
def test_session_unbound(self): sess = create_session() sess.add(Foo()) assert_raises_message( sa.exc.UnboundExecutionError, ('Could not locate a bind configured on Mapper|Foo|test_table ' 'or this Session'), sess.flush)
def test_missing_many_param(self): assert_raises_message(exc.InvalidRequestError, "A value is required for bind parameter 'col7', in parameter group 1", t.insert().execute, {'col4':7, 'col7':12, 'col8':19}, {'col4':7, 'col8':19}, {'col4':7, 'col7':12, 'col8':19}, )
def test_persistence_check(self): mapper(User, users) s = create_session() u = s.query(User).get(7) s.expunge_all() assert_raises_message(sa.exc.InvalidRequestError, r"is not persistent within this Session", lambda: s.refresh(u))
def test_populate_unmapped_source(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [(b_mapper.c.id, b_mapper.c.id)] assert_raises_message( orm_exc.UnmappedColumnError, "Can't execute sync rule for source column 't2.id'; " r"mapper 'Mapper\|A\|t1' does not map this column.", sync.populate, a1, a_mapper, b1, b_mapper, pairs, uowcommit, False)
def test_map_to_no_pk_selectable(self): db = sqlsoup.SqlSoup(engine) table = Table('users', db._metadata, Column('id', Integer)) assert_raises_message(sqlsoup.PKNotFoundError, "table 'users' does not have a primary ", db.map_to, 'users', selectable=table)
def test_error(self): mapper(Place, place, properties={ 'transitions':relationship(Transition, secondary=place_input, backref='places') }) mapper(Transition, transition, properties={ 'places':relationship(Place, secondary=place_input, backref='transitions') }) assert_raises_message(sa.exc.ArgumentError, "Error creating backref", sa.orm.compile_mappers)
def test_map_to_attr_present(self): db = sqlsoup.SqlSoup(engine) users = db.users assert_raises_message(exc.InvalidRequestError, "Attribute 'users' is already mapped", db.map_to, 'users', tablename='users')
def test_fk_error(self): metadata = MetaData(testing.db) slots_table = Table('slots', metadata, Column('slot_id', sa.Integer, primary_key=True), Column('pkg_id', sa.Integer, sa.ForeignKey('pkgs.pkg_id')), Column('slot', sa.String(128)), ) assert_raises_message(tsa.exc.InvalidRequestError, "Could not find table 'pkgs' with which to generate a foreign key", metadata.create_all)
def test_error(self): mapper(Place, place, properties={ 'transitions':relation(Transition, secondary=place_input, backref='places') }) mapper(Transition, transition, properties={ 'places':relation(Place, secondary=place_input, backref='transitions') }) assert_raises_message(sa.exc.ArgumentError, "Error creating backref", sa.orm.compile_mappers)
def test_map_to_attr_present(self): db = sqlsoup.SqlSoup(engine) users = db.users assert_raises_message( exc.InvalidRequestError, "Attribute 'users' is already mapped", db.map_to, 'users', tablename='users' )
def test_source_modified_no_unmapped(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [(b_mapper.c.id, b_mapper.c.id,)] assert_raises_message( orm_exc.UnmappedColumnError, "Can't execute sync rule for source column 't2.id'; " r"mapper 'Mapper\|A\|t1' does not map this column.", sync.source_modified, uowcommit, a1, a_mapper, pairs )
def test_single_down(self): class A(object): pass attributes.register_class(A) mgr_factory = lambda cls: attributes.ClassManager(cls) class B(A): __sa_instrumentation_manager__ = staticmethod(mgr_factory) assert_raises_message(TypeError, "multiple instrumentation implementations", attributes.register_class, B)
def test_map_to_table_not_string(self): db = sqlsoup.SqlSoup(engine) table = Table('users', db._metadata, Column('id', Integer, primary_key=True)) assert_raises_message( exc.ArgumentError, "'tablename' argument must be a string.", db.map_to, 'users', tablename=table )
def test_map_to_table_or_selectable(self): db = sqlsoup.SqlSoup(engine) table = Table('users', db._metadata, Column('id', Integer, primary_key=True)) assert_raises_message( exc.ArgumentError, "'tablename' and 'selectable' arguments are mutually exclusive", db.map_to, 'users', tablename='users', selectable=table )
def test_map_to_no_pk_selectable(self): db = sqlsoup.SqlSoup(engine) table = Table('users', db._metadata, Column('id', Integer)) assert_raises_message( sqlsoup.PKNotFoundError, "table 'users' does not have a primary ", db.map_to, 'users', selectable=table )
def test_map_to_nothing(self): db = sqlsoup.SqlSoup(engine) assert_raises_message( exc.ArgumentError, "'tablename' or 'selectable' argument is " "required.", db.map_to, 'users', )
def test_no_populate(self): mapper(User, users, properties={ 'addresses':dynamic_loader(mapper(Address, addresses)) }) u1 = User() assert_raises_message( NotImplementedError, "Dynamic attributes don't support collection population.", attributes.set_committed_value, u1, 'addresses', [] )
def test_map_to_string_not_selectable(self): db = sqlsoup.SqlSoup(engine) assert_raises_message(exc.ArgumentError, "'selectable' argument must be a " "table, select, join, or other " "selectable construct.", db.map_to, 'users', selectable='users')
def test_pickled_update(self): mapper(User, users) sess1 = create_session() sess2 = create_session() u1 = User(name='u1') sess1.add(u1) assert_raises_message(sa.exc.InvalidRequestError, 'already attached to session', sess2.add, u1) u2 = pickle.loads(pickle.dumps(u1)) sess2.add(u2)
def test_map_to_table_not_string(self): db = sqlsoup.SqlSoup(engine) table = Table('users', db._metadata, Column('id', Integer, primary_key=True)) assert_raises_message(exc.ArgumentError, "'tablename' argument must be a string.", db.map_to, 'users', tablename=table)
def test_diamond_b1(self): mgr_factory = lambda cls: attributes.ClassManager(cls) class A(object): pass class B1(A): pass class B2(A): __sa_instrumentation_manager__ = staticmethod(mgr_factory) class C(object): pass assert_raises_message(TypeError, "multiple instrumentation implementations", attributes.register_class, B1)
def test_map_to_string_not_selectable(self): db = sqlsoup.SqlSoup(engine) assert_raises_message( exc.ArgumentError, "'selectable' argument must be a " "table, select, join, or other " "selectable construct.", db.map_to, 'users', selectable='users' )
def test_clear_unmapped(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [(a_mapper.c.id, a_mapper.c.foo,)] assert_raises_message( orm_exc.UnmappedColumnError, "Can't execute sync rule for destination " r"column 't1.foo'; mapper 'Mapper\|B\|t2' does not " "map this column.", sync.clear, b1, b_mapper, pairs )
def test_transient_no_load(self): mapper(User, users) sess = create_session() u = User() assert_raises_message(sa.exc.InvalidRequestError, "load=False option does not support", sess.merge, u, load=False)
def test_update_unmapped(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [(b_mapper.c.id, b_mapper.c.id,)] dest = {} assert_raises_message( orm_exc.UnmappedColumnError, "Can't execute sync rule for source column 't2.id'; " r"mapper 'Mapper\|A\|t1' does not map this column.", sync.update, a1, a_mapper, dest, "old_", pairs )
def test_map_to_invalid_schema(self): db = sqlsoup.SqlSoup(engine) table = Table('users', db._metadata, Column('id', Integer)) assert_raises_message( exc.ArgumentError, "'tablename' argument is required when " "using 'schema'.", db.map_to, 'users', selectable=table, schema='hoho' )
def test_clear_pk(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [( a_mapper.c.id, b_mapper.c.id, )] b1.obj().id = 8 eq_(b1.obj().__dict__['id'], 8) assert_raises_message( AssertionError, "Dependency rule tried to blank-out primary key " "column 't2.id' on instance '<B", sync.clear, b1, b_mapper, pairs)
def test_map_to_invalid_schema(self): db = sqlsoup.SqlSoup(engine) table = Table('users', db._metadata, Column('id', Integer)) assert_raises_message(exc.ArgumentError, "'tablename' argument is required when " "using 'schema'.", db.map_to, 'users', selectable=table, schema='hoho')
def test_reentrant_flush(self): mapper(User, users) class MyExt(sa.orm.session.SessionExtension): def before_flush(s, session, flush_context, objects): session.flush() sess = create_session(extension=MyExt()) sess.add(User(name='foo')) assert_raises_message(sa.exc.InvalidRequestError, "already flushing", sess.flush)
def test_save_update_delete(self): s = create_session() mapper(User, users, properties={ 'addresses':relation(Address, cascade="all, delete") }) mapper(Address, addresses) user = User(name='u1') assert_raises_message(sa.exc.InvalidRequestError, "is not persisted", s.update, user) assert_raises_message(sa.exc.InvalidRequestError, "is not persisted", s.delete, user) s.add(user) s.flush() user = s.query(User).one() s.expunge(user) assert user not in s # modify outside of session, assert changes remain/get saved user.name = "fred" s.add(user) assert user in s assert user in s.dirty s.flush() s.expunge_all() assert s.query(User).count() == 1 user = s.query(User).one() assert user.name == 'fred' # ensure its not dirty if no changes occur s.expunge_all() assert user not in s s.add(user) assert user in s assert user not in s.dirty assert_raises_message(sa.exc.InvalidRequestError, "is already persistent", s.save, user) s2 = create_session() assert_raises_message(sa.exc.InvalidRequestError, "is already attached to session", s2.delete, user) u2 = s2.query(User).get(user.id) assert_raises_message(sa.exc.InvalidRequestError, "another instance with key", s.delete, u2) s.expire(user) s.expunge(user) assert user not in s s.delete(user) assert user in s s.flush() assert user not in s assert s.query(User).count() == 0
def test_fk_no_such_parent_col_error(self): meta = MetaData() a = Table('a', meta, Column('a', Integer)) b = Table('b', meta, Column('b', Integer)) def go(): a.append_constraint(ForeignKeyConstraint(['x'], ['b.b'])) assert_raises_message( exc.ArgumentError, "Can't create ForeignKeyConstraint on " "table 'a': no column named 'x' is present.", go)
def test_clear_pk(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [(a_mapper.c.id, b_mapper.c.id,)] b1.obj().id = 8 eq_(b1.obj().__dict__['id'], 8) assert_raises_message( AssertionError, "Dependency rule tried to blank-out primary key " "column 't2.id' on instance '<B", sync.clear, b1, b_mapper, pairs )
def test_no_populate(self): mapper(User, users, properties={ 'addresses': dynamic_loader(mapper(Address, addresses)) }) u1 = User() assert_raises_message( NotImplementedError, "Dynamic attributes don't support collection population.", attributes.set_committed_value, u1, 'addresses', [])
def test_clear_unmapped(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [( a_mapper.c.id, a_mapper.c.foo, )] assert_raises_message( orm_exc.UnmappedColumnError, "Can't execute sync rule for destination " r"column 't1.foo'; mapper 'Mapper\|B\|t2' does not " "map this column.", sync.clear, b1, b_mapper, pairs)
def test_populate_unmapped_dest(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [( a_mapper.c.id, a_mapper.c.id, )] assert_raises_message( orm_exc.UnmappedColumnError, "Can't execute sync rule for destination " r"column 't1.id'; mapper 'Mapper\|B\|t2' does not map this column.", sync.populate, a1, a_mapper, b1, b_mapper, pairs, uowcommit, False)
def test_update_unmapped(self): uowcommit, a1, b1, a_mapper, b_mapper = self._fixture() pairs = [( b_mapper.c.id, b_mapper.c.id, )] dest = {} assert_raises_message( orm_exc.UnmappedColumnError, "Can't execute sync rule for source column 't2.id'; " r"mapper 'Mapper\|A\|t1' does not map this column.", sync.update, a1, a_mapper, dest, "old_", pairs)
def test_explicit_composite_pk(self): person_mapper = mapper(Person, person_table) mapper(Employee, employee_table, inherits=person_mapper, primary_key=[person_table.c.id, employee_table.c.id]) assert_raises_message( sa_exc.SAWarning, r"On mapper Mapper\|Employee\|employees, " "primary key column 'employees.id' is being " "combined with distinct primary key column 'persons.id' " "in attribute 'id'. Use explicit properties to give " "each column its own mapped attribute name.", self._do_test, True)
def test_no_mappers(self): umapper = mapper(User, users) u1 = User(name='ed') u1_pickled = pickle.dumps(u1, -1) clear_mappers() assert_raises_message( orm_exc.UnmappedInstanceError, "Cannot deserialize object of type <class 'test.orm._fixtures.User'> - no mapper()", pickle.loads, u1_pickled)
def test_map_to_table_or_selectable(self): db = sqlsoup.SqlSoup(engine) table = Table('users', db._metadata, Column('id', Integer, primary_key=True)) assert_raises_message( exc.ArgumentError, "'tablename' and 'selectable' arguments are mutually exclusive", db.map_to, 'users', tablename='users', selectable=table)
def test_explicit_composite_pk(self): person_mapper = mapper(Person, person_table) mapper(Employee, employee_table, inherits=person_mapper, primary_key=[person_table.c.id, employee_table.c.id]) assert_raises_message(sa_exc.SAWarning, r"On mapper Mapper\|Employee\|employees, " "primary key column 'employees.id' is being " "combined with distinct primary key column 'persons.id' " "in attribute 'id'. Use explicit properties to give " "each column its own mapped attribute name.", self._do_test, True )
def test_refresh_collection_exception(self): """test graceful failure for currently unsupported immediate refresh of a collection""" mapper(User, users, properties={ 'addresses':relationship(Address, order_by=addresses.c.email_address) }) mapper(Address, addresses) s = create_session(autoflush=True, autocommit=False) u = s.query(User).get(8) assert_raises_message(sa_exc.InvalidRequestError, "properties specified for refresh", s.refresh, u, ['addresses']) # in contrast to a regular query with no columns assert_raises_message(sa_exc.InvalidRequestError, "no columns with which to SELECT", s.query().all)
def test_error_on_using_inactive_session(self): mapper(User, users) sess = create_session(autocommit=True) sess.begin() sess.begin(subtransactions=True) sess.add(User(name='u1')) sess.flush() sess.rollback() assert_raises_message(sa.exc.InvalidRequestError, 'inactive due to a rollback in a ' 'subtransaction', sess.begin, subtransactions=True) sess.close()
def test_fk_no_such_target_col_error(self): meta = MetaData() a = Table('a', meta, Column('a', Integer)) b = Table('b', meta, Column('b', Integer)) a.append_constraint(ForeignKeyConstraint(['a'], ['b.x'])) def go(): list(a.c.a.foreign_keys)[0].column assert_raises_message( exc.NoReferencedColumnError, "Could not create ForeignKey 'b.x' on " "table 'a': table 'b' has no column named 'x'", go)
def test_fk_error(self): metadata = MetaData(testing.db) slots_table = Table( 'slots', metadata, Column('slot_id', sa.Integer, primary_key=True), Column('pkg_id', sa.Integer, sa.ForeignKey('pkgs.pkg_id')), Column('slot', sa.String(128)), ) assert_raises_message( tsa.exc.InvalidRequestError, "Could not find table 'pkgs' with which to generate a foreign key", metadata.create_all)
def test_config_errors(self): Session = scoped_session(sa.orm.sessionmaker()) s = Session() assert_raises_message(sa.exc.InvalidRequestError, "Scoped session is already present", Session, bind=testing.db) assert_raises_message( sa.exc.SAWarning, "At least one scoped session is already present. ", Session.configure, bind=testing.db)