def test_auto_detach_on_gc_session(self): users, User = self.tables.users, self.classes.User mapper(User, users) sess = Session() u1 = User(name='u1') sess.add(u1) sess.commit() # can't add u1 to Session, # already belongs to u2 s2 = Session() assert_raises_message(sa.exc.InvalidRequestError, r".*is already attached to session", s2.add, u1) # garbage collect sess del sess gc_collect() # s2 lets it in now despite u1 having # session_key s2.add(u1) assert u1 in s2
def test_set_illegal(self): f1 = Foo() assert_raises_message( ValueError, "Attribute 'data' does not accept objects", setattr, f1, 'data', 'foo' )
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_refresh_collection_exception(self): """test graceful failure for currently unsupported immediate refresh of a collection""" users, Address, addresses, User = (self.tables.users, self.classes.Address, self.tables.addresses, self.classes.User) 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_versioncheck(self): """query.with_lockmode performs a 'version check' on an already loaded instance""" Foo = self.classes.Foo s1 = self._fixture() 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_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_no_table_needs_pl(self): Subset = self.classes.Subset selectable = select(["x", "y", "z"]).alias() assert_raises_message(sa.exc.ArgumentError, "could not assemble any primary key columns", mapper, Subset, selectable)
def test_child_row_switch_two(self): P = self.classes.P 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' if testing.db.dialect.supports_sane_rowcount: assert_raises_message( orm.exc.StaleDataError, r"UPDATE statement on table 'p' expected to update " r"1 row\(s\); 0 were matched.", sess2.commit) else: sess2.commit
def test_star_must_be_alone(self): sess = self._downgrade_fixture() User = self.classes.User assert_raises_message( sa.exc.ArgumentError, "Wildcard identifier '\*' must be specified alone.", sa.orm.subqueryload, '*', User.addresses)
def test_invalid_level(self): eng = testing_engine(options=dict(isolation_level='FOO')) assert_raises_message( exc.ArgumentError, "Invalid value '%s' for isolation_level. " "Valid isolation levels for %s are %s" % ("FOO", eng.dialect.name, ", ".join( eng.dialect._isolation_lookup)), eng.connect)
def test_invalidate_trans(self): conn = db.connect() trans = conn.begin() dbapi.shutdown() try: conn.execute(select([1])) assert False except tsa.exc.DBAPIError: pass # assert was invalidated gc_collect() assert len(dbapi.connections) == 0 assert not conn.closed assert conn.invalidated assert trans.is_active assert_raises_message( tsa.exc.StatementError, "Can't reconnect until invalid transaction is rolled back", conn.execute, select([1])) assert trans.is_active try: trans.commit() assert False except tsa.exc.InvalidRequestError, e: assert str(e) \ == "Can't reconnect until invalid transaction is "\ "rolled back"
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_cant_parse_datetime_message(self): for (typ, disp) in [(Time, "time"), (DateTime, "datetime"), (Date, "date")]: assert_raises_message( ValueError, "Couldn't parse %s string." % disp, lambda: testing.db.execute(text("select 'ASDF' as value", typemap={"value": typ})).scalar(), )
def test_versioncheck(self): """query.with_lockmode performs a 'version check' on an already loaded instance""" Foo = self.classes.Foo s1 = self._fixture() 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_invalidate_trans(self): conn = db.connect() trans = conn.begin() dbapi.shutdown() try: conn.execute(select([1])) assert False except tsa.exc.DBAPIError: pass # assert was invalidated gc_collect() assert len(dbapi.connections) == 0 assert not conn.closed assert conn.invalidated assert trans.is_active assert_raises_message( tsa.exc.StatementError, "Can't reconnect until invalid transaction is rolled back", conn.execute, select([1]), ) assert trans.is_active try: trans.commit() assert False except tsa.exc.InvalidRequestError, e: assert str(e) == "Can't reconnect until invalid transaction is " "rolled back"
def test_auto_detach_on_gc_session(self): users, User = self.tables.users, self.classes.User mapper(User, users) sess = Session() u1 = User(name='u1') sess.add(u1) sess.commit() # can't add u1 to Session, # already belongs to u2 s2 = Session() assert_raises_message( sa.exc.InvalidRequestError, r".*is already attached to session", s2.add, u1 ) # garbage collect sess del sess gc_collect() # s2 lets it in now despite u1 having # session_key s2.add(u1) assert u1 in s2
def test_child_row_switch_two(self): P = self.classes.P 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' if testing.db.dialect.supports_sane_rowcount: assert_raises_message( orm.exc.StaleDataError, r"UPDATE statement on table 'p' expected to update " r"1 row\(s\); 0 were matched.", sess2.commit ) else: sess2.commit
def test_persistence_check(self): users, User = self.tables.users, self.classes.User 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_update_multi_elem_varg(self): a1 = self.A() assert_raises_message( TypeError, "update expected at most 1 arguments, got 2", a1.elements.update, (("B", 3), 'elem2'), (("C", 4), "elem3") )
def test_update_one_elem_varg(self): a1 = self.A() assert_raises_message( ValueError, "dictionary update sequence requires " "2-element tuples", a1.elements.update, (("B", 3), 'elem2') )
def test_missing_many_param(self): assert_raises_message(exc.StatementError, "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_star_must_be_alone(self): sess = self._downgrade_fixture() User = self.classes.User assert_raises_message( sa.exc.ArgumentError, "Wildcard identifier '\*' must be specified alone.", sa.orm.subqueryload, '*', User.addresses )
def test_nonassignable(self): A = self._fixture(False) a1 = A(_value=5) assert_raises_message( AttributeError, "can't set attribute", setattr, a1, 'value', 10 )
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_nondeletable(self): A = self._fixture(False) a1 = A(_value=5) assert_raises_message( AttributeError, "can't delete attribute", delattr, a1, 'value' )
def test_dupe_column(self): c = Column('x', Integer) t = Table('t', MetaData(), c) assert_raises_message( exc.ArgumentError, "Column object already assigned to Table 't'", Table, 'q', MetaData(), c)
def test_transient_no_load(self): users, User = self.tables.users, self.classes.User 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_cant_parse_datetime_message(self): for (typ, disp) in [(Time, "time"), (DateTime, "datetime"), (Date, "date")]: assert_raises_message( ValueError, "Couldn't parse %s string." % disp, lambda: testing.db.execute( text("select 'ASDF' as value", typemap={"value": typ}) ).scalar())
def test_name_blank(self): c = Column('', Integer) assert_raises_message( exc.ArgumentError, "Column must be constructed with a non-blank name or assign a " "non-blank .name ", Table, 't', MetaData(), c)
def test_invalid_level(self): eng = testing_engine(options=dict(isolation_level='FOO')) assert_raises_message( exc.ArgumentError, "Invalid value '%s' for isolation_level. " "Valid isolation levels for %s are %s" % ("FOO", eng.dialect.name, ", ".join(eng.dialect._isolation_lookup)), eng.connect)
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_session_unbound(self): Foo = self.classes.Foo 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_single_down(self): class A(object): pass instrumentation.register_class(A) mgr_factory = lambda cls: instrumentation.ClassManager(cls) class B(A): __sa_instrumentation_manager__ = staticmethod(mgr_factory) assert_raises_message(TypeError, "multiple instrumentation implementations", instrumentation.register_class, B)
def test_unknown_lock_mode(self): User = self.classes.User sess = Session() assert_raises_message( Exception, "Unknown lockmode 'unknown_mode'", self.assert_compile, sess.query(User.id).with_lockmode('unknown_mode'), None, dialect=default.DefaultDialect() )
def test_per_statement_bzzt(self): assert_raises_message( exc.ArgumentError, r"'isolation_level' execution option may only be specified " r"on Connection.execution_options\(\), or " r"per-engine using the isolation_level " r"argument to create_engine\(\).", select([1]).execution_options, isolation_level=self._non_default_isolation_level() )
def test_nonunicode_default(self): # Py3K # default = b'foo' # Py2K default = "foo" # end Py2K assert_raises_message( sa.exc.SAWarning, "Unicode column received non-unicode default value.", Column, Unicode(32), default=default )
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_per_statement_bzzt(self): assert_raises_message( exc.ArgumentError, r"'isolation_level' execution option may only be specified " r"on Connection.execution_options\(\), or " r"per-engine using the isolation_level " r"argument to create_engine\(\).", select([1]).execution_options, isolation_level=self._non_default_isolation_level())
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_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_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_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_diamond_b1(self): mgr_factory = lambda cls: instrumentation.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", instrumentation.register_class, B1)
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_no_table_needs_pl(self): Subset = self.classes.Subset selectable = select(["x", "y", "z"]).alias() assert_raises_message( sa.exc.ArgumentError, "could not assemble any primary key columns", mapper, Subset, selectable )
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_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_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)