def test_graceful_fetch_on_non_rows(self): """test that calling fetchone() etc. on a result that doesn't return rows fails gracefully. """ # these proxies don't work with no cursor.description present. # so they don't apply to this test at the moment. # result.FullyBufferedResultProxy, # result.BufferedRowResultProxy, # result.BufferedColumnResultProxy users = self.tables.users conn = testing.db.connect() for meth in [ lambda r: r.fetchone(), lambda r: r.fetchall(), lambda r: r.first(), lambda r: r.scalar(), lambda r: r.fetchmany(), lambda r: r._getter('user'), lambda r: r._has_key('user'), ]: trans = conn.begin() result = conn.execute(users.insert(), user_id=1) assert_raises_message( exc.ResourceClosedError, "This result object does not return rows. " "It has been closed automatically.", meth, result, ) trans.rollback()
def test_illegal_operations(self): User = self.classes.User Address = self.classes.Address s = Session() for q, mname in ( (s.query(User).limit(2), r"limit\(\)"), (s.query(User).offset(2), r"offset\(\)"), (s.query(User).limit(2).offset(2), r"limit\(\)"), (s.query(User).order_by(User.id), r"order_by\(\)"), (s.query(User).group_by(User.id), r"group_by\(\)"), (s.query(User).distinct(), r"distinct\(\)"), (s.query(User).join(User.addresses), r"join\(\), outerjoin\(\), select_from\(\), or from_self\(\)"), (s.query(User).outerjoin(User.addresses), r"join\(\), outerjoin\(\), select_from\(\), or from_self\(\)"), (s.query(User).select_from(Address), r"join\(\), outerjoin\(\), select_from\(\), or from_self\(\)"), (s.query(User).from_self(), r"join\(\), outerjoin\(\), select_from\(\), or from_self\(\)"), ): assert_raises_message( exc.InvalidRequestError, r"Can't call Query.update\(\) or Query.delete\(\) when " "%s has been called" % mname, q.update, {'name': 'ed'}) assert_raises_message( exc.InvalidRequestError, r"Can't call Query.update\(\) or Query.delete\(\) when " "%s has been called" % mname, q.delete)
def test_set_illegal(self): f1 = Foo() assert_raises_message( ValueError, "Attribute 'data' does not accept objects", setattr, f1, 'data', 'foo' )
def test_no_table_needs_pl(self): Subset = self.classes.Subset selectable = select([column("x"), column("y"), column("z")]).alias() assert_raises_message( sa.exc.ArgumentError, "could not assemble any primary key columns", mapper, Subset, selectable )
def test_with_transaction(self): conn = self.engine.connect() trans = conn.begin() eq_(conn.execute(select([1])).scalar(), 1) assert not conn.closed self.engine.test_shutdown() _assert_invalidated(conn.execute, select([1])) 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 assert_raises_message( tsa.exc.InvalidRequestError, "Can't reconnect until invalid transaction is rolled back", trans.commit ) assert trans.is_active trans.rollback() assert not trans.is_active assert conn.invalidated eq_(conn.execute(select([1])).scalar(), 1) assert not conn.invalidated
def _assert_raises_no_join(self, fn, relname, secondary_arg, *arg, **kw): if secondary_arg is not None: assert_raises_message( exc.NoForeignKeysError, "Could not determine join condition between " "parent/child tables on relationship %s - " "there are no foreign keys linking these tables " "via secondary table '%s'. " "Ensure that referencing columns are associated " "with a ForeignKey " "or ForeignKeyConstraint, or specify 'primaryjoin' and " "'secondaryjoin' expressions" % (relname, secondary_arg), fn, *arg, **kw) else: assert_raises_message( exc.NoForeignKeysError, "Could not determine join condition between " "parent/child tables on relationship %s - " "there are no foreign keys linking these tables. " "Ensure that referencing columns are associated " "with a ForeignKey " "or ForeignKeyConstraint, or specify a 'primaryjoin' " "expression." % (relname,), fn, *arg, **kw)
def test_bitwise_required_for_empty(self): assert_raises_message( exc.ArgumentError, "Can't use the blank value '' in a SET without setting " "retrieve_as_bitwise=True", mysql.SET, "a", "b", '' )
def test_unconsumed_names_kwargs(self): t = table("t", column("x"), column("y")) assert_raises_message( exc.CompileError, "Unconsumed column names: z", t.insert().values(x=5, z=5).compile, )
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_varchar_raise(self): for type_ in ( String, VARCHAR, String(), VARCHAR(), NVARCHAR(), Unicode, Unicode(), ): type_ = sqltypes.to_instance(type_) assert_raises_message( exc.CompileError, "VARCHAR requires a length on dialect mysql", type_.compile, dialect=mysql.dialect() ) t1 = Table('sometable', MetaData(), Column('somecolumn', type_) ) assert_raises_message( exc.CompileError, r"\(in table 'sometable', column 'somecolumn'\)\: " r"(?:N)?VARCHAR requires a length on dialect mysql", schema.CreateTable(t1).compile, dialect=mysql.dialect() )
def test_unknown_legacy_lock_mode(self): User = self.classes.User sess = Session() assert_raises_message( exc.ArgumentError, "Unknown with_lockmode argument: 'unknown_mode'", sess.query(User.id).with_lockmode, 'unknown_mode' )
def test_concurrent_mod_err_noexpire_on_commit(self): sess = self._fixture(expire_on_commit=False) f1 = self.classes.Foo(value='f1') sess.add(f1) sess.commit() # here, we're not expired overall, so no load occurs and we # stay without a version id, unless we've emitted # a SELECT for it within the flush. f1.value s2 = Session(expire_on_commit=False) f2 = s2.query(self.classes.Foo).first() f2.value = 'f2' s2.commit() f1.value = 'f3' assert_raises_message( orm.exc.StaleDataError, r"UPDATE statement on table 'version_table' expected to " r"update 1 row\(s\); 0 were matched.", sess.commit )
def test_lobs_without_convert_many_rows(self): engine = testing_engine( options=dict(auto_convert_lobs=False, arraysize=1)) result = engine.execute( "select id, data, bindata from z_test order by id") results = result.fetchall() def go(): eq_( [ dict( id=row["id"], data=row["data"].read(), bindata=row["bindata"].read() ) for row in results ], self.data) # this comes from cx_Oracle because these are raw # cx_Oracle.Variable objects if testing.requires.oracle5x.enabled: assert_raises_message( testing.db.dialect.dbapi.ProgrammingError, "LOB variable no longer valid after subsequent fetch", go ) else: go()
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_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_report_primary_error_when_rollback_fails(self): User, users = self.classes.User, self.tables.users mapper(User, users) session = Session(testing.db) with expect_warnings(".*during handling of a previous exception.*"): session.begin_nested() savepoint = session.\ connection()._Connection__transaction._savepoint # force the savepoint to disappear session.connection().dialect.do_release_savepoint( session.connection(), savepoint ) # now do a broken flush session.add_all([User(id=1), User(id=1)]) assert_raises_message( sa_exc.DBAPIError, "ROLLBACK TO SAVEPOINT ", session.flush )
def test_validator_multi_warning(self): users = self.tables.users class Foo(object): @validates("name") def validate_one(self, key, value): pass @validates("name") def validate_two(self, key, value): pass assert_raises_message( exc.InvalidRequestError, "A validation function for mapped attribute " "'name' on mapper Mapper|Foo|users already exists", mapper, Foo, users ) class Bar(object): @validates("id") def validate_three(self, key, value): return value + 10 @validates("id", "name") def validate_four(self, key, value): return value + "foo" assert_raises_message( exc.InvalidRequestError, "A validation function for mapped attribute " "'name' on mapper Mapper|Bar|users already exists", mapper, Bar, 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_no_prepare_wo_twophase(self): sess = create_session(bind=testing.db, autocommit=False) assert_raises_message(sa_exc.InvalidRequestError, "'twophase' mode not enabled, or not root " "transaction; can't prepare.", sess.prepare)
def test_identity_conflict(self): users, User = self.tables.users, self.classes.User mapper(User, users) for s in ( create_session(), create_session(weak_identity_map=False), ): users.delete().execute() u1 = User(name="ed") s.add(u1) s.flush() s.expunge(u1) u2 = s.query(User).first() s.expunge(u2) s.identity_map.add(sa.orm.attributes.instance_state(u1)) assert_raises_message( sa.exc.InvalidRequestError, "Can't attach instance <User.*?>; another instance " "with key .*? is already " "present in this session.", s.identity_map.add, sa.orm.attributes.instance_state(u2) )
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_single_no_table_args(self): class Person(Base, fixtures.ComparableEntity): __tablename__ = 'people' id = Column('id', Integer, primary_key=True) name = Column('name', String(50)) discriminator = Column('type', String(50)) __mapper_args__ = {'polymorphic_on': discriminator} def go(): class Engineer(Person): __mapper_args__ = {'polymorphic_identity': 'engineer'} primary_language = Column('primary_language', String(50)) # this should be on the Person class, as this is single # table inheritance, which is why we test that this # throws an exception! __table_args__ = {'mysql_engine': 'InnoDB'} assert_raises_message(sa.exc.ArgumentError, 'place __table_args__', go)
def test_skip_not_describable(self): @event.listens_for(self.metadata, "before_drop") def cleanup(*arg, **kw): with testing.db.connect() as conn: conn.execute("DROP TABLE IF EXISTS test_t1") conn.execute("DROP TABLE IF EXISTS test_t2") conn.execute("DROP VIEW IF EXISTS test_v") with testing.db.connect() as conn: conn.execute("CREATE TABLE test_t1 (id INTEGER)") conn.execute("CREATE TABLE test_t2 (id INTEGER)") conn.execute("CREATE VIEW test_v AS SELECT id FROM test_t1") conn.execute("DROP TABLE test_t1") m = MetaData() with expect_warnings( "Skipping .* Table or view named .?test_v.? could not be " "reflected: .* references invalid table" ): m.reflect(views=True, bind=conn) eq_(m.tables["test_t2"].name, "test_t2") assert_raises_message( exc.UnreflectableTableError, "references invalid table", Table, "test_v", MetaData(), autoload_with=conn, )
def _assert_unorderable_types(self, callable_): if util.py3k: assert_raises_message( TypeError, 'unorderable types', callable_) else: assert_raises_message( TypeError, 'cannot compare sets using cmp()', callable_)
def test_missing_bind_posn(self): assert_raises_message( exc.ArgumentError, "This text\(\) construct doesn't define a bound parameter named 'bar'", text(":foo").bindparams, bindparam('foo', value=5), bindparam('bar', value=7) )
def test_overlapping_attribute_error(self): place, Transition, place_input, Place, transition = ( self.tables.place, self.classes.Transition, self.tables.place_input, self.classes.Place, self.tables.transition, ) 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, "property of that name exists", sa.orm.configure_mappers, )
def test_with_transaction(self): conn = engine.connect() trans = conn.begin() eq_(conn.execute(select([1])).scalar(), 1) assert not conn.closed engine.test_shutdown() try: conn.execute(select([1])) assert False except tsa.exc.DBAPIError as e: if not e.connection_invalidated: raise 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 as e: assert str(e) \ == "Can't reconnect until invalid transaction is "\ "rolled back" assert trans.is_active trans.rollback() assert not trans.is_active assert conn.invalidated eq_(conn.execute(select([1])).scalar(), 1) assert not conn.invalidated
def test_missing_bind_kw(self): assert_raises_message( exc.ArgumentError, "This text\(\) construct doesn't define a bound parameter named 'bar'", text(":foo").bindparams, foo=5, bar=7 )
def _assert_raises_ambig_join( self, fn, relname, secondary_arg, *arg, **kw ): if secondary_arg is not None: assert_raises_message( exc.AmbiguousForeignKeysError, "Could not determine join condition between " "parent/child tables on relationship %s - " "there are multiple foreign key paths linking the " "tables via secondary table '%s'. " "Specify the 'foreign_keys' argument, providing a list " "of those columns which should be counted as " "containing a foreign key reference from the " "secondary table to each of the parent and child tables." % (relname, secondary_arg), fn, *arg, **kw ) else: assert_raises_message( exc.AmbiguousForeignKeysError, "Could not determine join condition between " "parent/child tables on relationship %s - " "there are no foreign keys linking these tables. " % (relname,), fn, *arg, **kw )
def test_limit_offset_for_update(self): metadata = self.metadata # 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().with_for_update().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().with_for_update().limit(2).offset(3).execute, )
def test_conflicting_backref_one(self): """test that conflicting backrefs raises an exception""" metadata = MetaData(testing.db) order = Table( "orders", metadata, Column("id", Integer, primary_key=True), Column("type", Unicode(16)), ) product = Table("products", metadata, Column("id", Integer, primary_key=True)) orderproduct = Table( "orderproducts", metadata, Column("id", Integer, primary_key=True), Column("order_id", Integer, ForeignKey("orders.id"), nullable=False), Column( "product_id", Integer, ForeignKey("products.id"), nullable=False, ), ) class Order(object): pass class Product(object): pass class OrderProduct(object): pass order_join = order.select().alias("pjoin") order_mapper = mapper( Order, order, with_polymorphic=("*", order_join), polymorphic_on=order_join.c.type, polymorphic_identity="order", properties={ "orderproducts": relationship(OrderProduct, lazy="select", backref="product") }, ) mapper( Product, product, properties={ "orderproducts": relationship(OrderProduct, lazy="select", backref="product") }, ) mapper(OrderProduct, orderproduct) assert_raises_message(sa_exc.ArgumentError, "Error creating backref", configure_mappers)
def _assert_unorderable_types(self, callable_): if util.py3k: assert_raises_message(TypeError, 'unorderable types', callable_) else: assert_raises_message(TypeError, 'cannot compare sets using cmp()', callable_)
def test_result_processor_invalid(self): mssql_date_type = _MSDate() result_processor = mssql_date_type.result_processor(None, None) assert_raises_message(ValueError, "could not parse 'abc' as a date value", result_processor, 'abc')
def test_missing_bind_posn(self): assert_raises_message( exc.ArgumentError, "This text\(\) construct doesn't define a bound parameter named 'bar'", text(":foo").bindparams, bindparam('foo', value=5), bindparam('bar', value=7))
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_nonassignable(self): A = self._fixture(False) a1 = A(_value=5) assert_raises_message(AttributeError, "can't set attribute", setattr, a1, "value", 10)
def test_insert_executemany_insdefault_passed(self, connection): t1 = self.tables.t1 result = connection.execute( t1.insert().return_defaults(), [ { "data": "d1", "insdef": 11 }, { "data": "d2", "insdef": 12 }, { "data": "d3", "insdef": 13 }, { "data": "d4", "insdef": 14 }, { "data": "d5", "insdef": 15 }, { "data": "d6", "insdef": 16 }, ], ) eq_( [row._mapping for row in result.returned_defaults_rows], [ { "id": 1, "upddef": None }, { "id": 2, "upddef": None }, { "id": 3, "upddef": None }, { "id": 4, "upddef": None }, { "id": 5, "upddef": None }, { "id": 6, "upddef": None }, ], ) eq_( result.inserted_primary_key_rows, [(1, ), (2, ), (3, ), (4, ), (5, ), (6, )], ) assert_raises_message( sa_exc.InvalidRequestError, "This statement was an executemany call; " "if return defaults is supported", lambda: result.returned_defaults, ) assert_raises_message( sa_exc.InvalidRequestError, "This statement was an executemany call; " "if primary key returning is supported", lambda: result.inserted_primary_key, )
def test_bitwise_required_for_empty(self): assert_raises_message( exc.ArgumentError, "Can't use the blank value '' in a SET without setting " "retrieve_as_bitwise=True", mysql.SET, "a", "b", '')
def _assert_data_noautoincrement(self, table): self.engine = \ engines.testing_engine(options={'implicit_returning': False}) metadata.bind = self.engine table.insert().execute({'id': 30, 'data': 'd1'}) if self.engine.driver == 'pg8000': exception_cls = exc.ProgrammingError elif self.engine.driver == 'pypostgresql': exception_cls = Exception else: exception_cls = exc.IntegrityError assert_raises_message(exception_cls, 'violates not-null constraint', table.insert().execute, {'data': 'd2'}) assert_raises_message(exception_cls, 'violates not-null constraint', table.insert().execute, {'data': 'd2'}, {'data': 'd3'}) assert_raises_message(exception_cls, 'violates not-null constraint', table.insert().execute, {'data': 'd2'}) assert_raises_message(exception_cls, 'violates not-null constraint', table.insert().execute, {'data': 'd2'}, {'data': 'd3'}) table.insert().execute({'id': 31, 'data': 'd2'}, {'id': 32, 'data': 'd3'}) table.insert(inline=True).execute({'id': 33, 'data': 'd4'}) assert table.select().execute().fetchall() == [ (30, 'd1'), (31, 'd2'), (32, 'd3'), (33, 'd4')] table.delete().execute() # test the same series of events using a reflected version of # the table m2 = MetaData(self.engine) table = Table(table.name, m2, autoload=True) table.insert().execute({'id': 30, 'data': 'd1'}) assert_raises_message(exception_cls, 'violates not-null constraint', table.insert().execute, {'data': 'd2'}) assert_raises_message(exception_cls, 'violates not-null constraint', table.insert().execute, {'data': 'd2'}, {'data': 'd3'}) table.insert().execute({'id': 31, 'data': 'd2'}, {'id': 32, 'data': 'd3'}) table.insert(inline=True).execute({'id': 33, 'data': 'd4'}) assert table.select().execute().fetchall() == [ (30, 'd1'), (31, 'd2'), (32, 'd3'), (33, 'd4')]
def test_with_transaction(self): conn = self.engine.connect() trans = conn.begin() assert trans.is_valid eq_(conn.execute(select(1)).scalar(), 1) assert not conn.closed self.engine.test_shutdown() _assert_invalidated(conn.execute, select(1)) assert not conn.closed assert conn.invalidated assert trans.is_active assert not trans.is_valid assert_raises_message( tsa.exc.PendingRollbackError, "Can't reconnect until invalid transaction is rolled back", conn.execute, select(1), ) assert trans.is_active assert not trans.is_valid assert_raises_message( tsa.exc.PendingRollbackError, "Can't reconnect until invalid transaction is rolled back", trans.commit, ) # becomes inactive assert not trans.is_active assert not trans.is_valid # still asks us to rollback assert_raises_message( tsa.exc.PendingRollbackError, "Can't reconnect until invalid transaction is rolled back", conn.execute, select(1), ) # still asks us.. assert_raises_message( tsa.exc.PendingRollbackError, "Can't reconnect until invalid transaction is rolled back", trans.commit, ) # still...it's being consistent in what it is asking. assert_raises_message( tsa.exc.PendingRollbackError, "Can't reconnect until invalid transaction is rolled back", conn.execute, select(1), ) # OK! trans.rollback() assert not trans.is_active assert not trans.is_valid # conn still invalid but we can reconnect assert conn.invalidated eq_(conn.execute(select(1)).scalar(), 1) assert not conn.invalidated
trans = conn.begin() eq_(conn.execute(select([1])).scalar(), 1) assert not conn.closed engine.test_shutdown() try: conn.execute(select([1])) assert False except tsa.exc.DBAPIError, e: if not e.connection_invalidated: raise 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" assert trans.is_active trans.rollback() assert not trans.is_active assert conn.invalidated eq_(conn.execute(select([1])).scalar(), 1)
def test_coerce_raise(self): assert_raises_message( ValueError, "Attribute 'data' does not accept objects of type", Foo, data=set([1, 2, 3]) )
def test_cycle_unnamed_fks(self): metadata = MetaData() Table( "a", metadata, Column("id", Integer, primary_key=True), Column("bid", Integer, ForeignKey("b.id")), ) Table( "b", metadata, Column("id", Integer, primary_key=True), Column("aid", Integer, ForeignKey("a.id")), ) assertions = [ AllOf( CompiledSQL("CREATE TABLE b (" "id INTEGER NOT NULL, " "aid INTEGER, " "PRIMARY KEY (id)" ")"), CompiledSQL("CREATE TABLE a (" "id INTEGER NOT NULL, " "bid INTEGER, " "PRIMARY KEY (id)" ")"), ), AllOf( CompiledSQL("ALTER TABLE b ADD " "FOREIGN KEY(aid) REFERENCES a (id)"), CompiledSQL("ALTER TABLE a ADD " "FOREIGN KEY(bid) REFERENCES b (id)"), ), ] with self.sql_execution_asserter() as asserter: metadata.create_all(testing.db, checkfirst=False) if testing.db.dialect.supports_alter: asserter.assert_(*assertions) assert_raises_message( exc.CircularDependencyError, "Can't sort tables for DROP; an unresolvable foreign key " "dependency exists between tables: a, b. " "Please ensure that the " "ForeignKey and ForeignKeyConstraint objects involved in the " "cycle have names so that they can be dropped using " "DROP CONSTRAINT.", metadata.drop_all, testing.db, checkfirst=False, ) else: with expect_warnings( "Can't sort tables for DROP; an unresolvable " "foreign key dependency exists between tables"): with self.sql_execution_asserter() as asserter: metadata.drop_all(testing.db, checkfirst=False) asserter.assert_( AllOf(CompiledSQL("DROP TABLE b"), CompiledSQL("DROP TABLE a")))
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_extra_dirty_state_post_flush_warning(self): s, a1, a2 = self._test_extra_dirty_state() assert_raises_message( sa.exc.SAWarning, "Attribute history events accumulated on 1 previously " "clean instances", s.commit)
def _raises(self, expr): assert_raises_message(TypeError, "Boolean value of this clause is not defined", bool, expr)
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_only_str_set(self, argname): u1 = url.URL.create("somedriver") assert_raises_message(TypeError, "%s must be a string" % argname, u1.set, **{argname: 35.8})
def test_set_illegal(self): f1 = Foo() assert_raises_message(ValueError, "Attribute 'data' does not accept objects", setattr, f1, 'data', 'foo')
def _roundtrip( self, Employee, Manager, Engineer, Boss, polymorphic=True, explicit_type=False, ): Base.metadata.create_all(testing.db) sess = fixture_session() e1 = Engineer(name="dilbert", primary_language="java") e2 = Engineer(name="wally", primary_language="c++") m1 = Manager(name="dogbert", golf_swing="fore!") e3 = Engineer(name="vlad", primary_language="cobol") b1 = Boss(name="pointy haired") if polymorphic: for obj in [e1, e2, m1, e3, b1]: if explicit_type: eq_(obj.type, obj.__mapper__.polymorphic_identity) else: assert_raises_message( AttributeError, "does not implement attribute .?'type' " "at the instance level.", getattr, obj, "type", ) else: assert "type" not in Engineer.__dict__ assert "type" not in Manager.__dict__ assert "type" not in Boss.__dict__ sess.add_all([e1, e2, m1, e3, b1]) sess.flush() sess.expunge_all() if polymorphic: eq_( sess.query(Employee).order_by(Employee.name).all(), [ Engineer(name="dilbert"), Manager(name="dogbert"), Boss(name="pointy haired"), Engineer(name="vlad"), Engineer(name="wally"), ], ) else: eq_( sess.query(Engineer).order_by(Engineer.name).all(), [ Engineer(name="dilbert"), Engineer(name="vlad"), Engineer(name="wally"), ], ) eq_(sess.query(Manager).all(), [Manager(name="dogbert")]) eq_(sess.query(Boss).all(), [Boss(name="pointy haired")]) e1 = sess.query(Engineer).order_by(Engineer.name).first() sess.expire(e1) eq_(e1.name, "dilbert")
def test_unary_no_ops(self): assert_raises_message(exc.CompileError, "Unary expression has no operator or modifier", UnaryExpression(literal("x")).compile)
def test_multi_level_no_base(self): pjoin = polymorphic_union( { "manager": managers_table, "engineer": engineers_table, "hacker": hackers_table, }, "type", "pjoin", ) pjoin2 = polymorphic_union( { "engineer": engineers_table, "hacker": hackers_table }, "type", "pjoin2", ) employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type) mapper( Manager, managers_table, inherits=employee_mapper, concrete=True, polymorphic_identity="manager", ) engineer_mapper = mapper( Engineer, engineers_table, with_polymorphic=("*", pjoin2), polymorphic_on=pjoin2.c.type, inherits=employee_mapper, concrete=True, polymorphic_identity="engineer", ) mapper( Hacker, hackers_table, inherits=engineer_mapper, concrete=True, polymorphic_identity="hacker", ) session = create_session() tom = Manager("Tom", "knows how to manage things") assert_raises_message( AttributeError, "does not implement attribute .?'type' at the instance level.", setattr, tom, "type", "sometype", ) jerry = Engineer("Jerry", "knows how to program") hacker = Hacker("Kurt", "Badass", "knows how to hack") assert_raises_message( AttributeError, "does not implement attribute .?'type' at the instance level.", setattr, hacker, "type", "sometype", ) session.add_all((tom, jerry, hacker)) session.flush() # ensure "readonly" on save logic didn't pollute the # expired_attributes collection assert ("nickname" not in attributes.instance_state(jerry).expired_attributes) assert ("name" not in attributes.instance_state(jerry).expired_attributes) assert ("name" not in attributes.instance_state(hacker).expired_attributes) assert ("nickname" not in attributes.instance_state(hacker).expired_attributes) def go(): eq_(jerry.name, "Jerry") eq_(hacker.nickname, "Badass") self.assert_sql_count(testing.db, go, 0) session.expunge_all() assert (repr( session.query(Employee).filter(Employee.name == "Tom").one()) == "Manager Tom knows how to manage things") assert (repr( session.query(Manager).filter(Manager.name == "Tom").one()) == "Manager Tom knows how to manage things") assert set([repr(x) for x in session.query(Employee).all()]) == set([ "Engineer Jerry knows how to program", "Manager Tom knows how to manage things", "Hacker Kurt 'Badass' knows how to hack", ]) assert set([repr(x) for x in session.query(Manager).all() ]) == set(["Manager Tom knows how to manage things"]) assert set([repr(x) for x in session.query(Engineer).all()]) == set([ "Engineer Jerry knows how to program", "Hacker Kurt 'Badass' knows how to hack", ]) assert set([repr(x) for x in session.query(Hacker).all() ]) == set(["Hacker Kurt 'Badass' knows how to hack"])
def test_only_str_constructor(self, argname): assert_raises_message(TypeError, "%s must be a string" % argname, url.URL.create, "somedriver", **{argname: 35.8})
def test_only_str_drivername_no_none(self, value): assert_raises_message(TypeError, "drivername must be a string", url.URL.create, value)
def test_multi_level_no_base(self): pjoin = polymorphic_union( { 'manager': managers_table, 'engineer': engineers_table, 'hacker': hackers_table }, 'type', 'pjoin') pjoin2 = polymorphic_union( { 'engineer': engineers_table, 'hacker': hackers_table }, 'type', 'pjoin2') employee_mapper = mapper(Employee, pjoin, polymorphic_on=pjoin.c.type) manager_mapper = mapper(Manager, managers_table, inherits=employee_mapper, concrete=True, polymorphic_identity='manager') engineer_mapper = mapper( Engineer, engineers_table, with_polymorphic=('*', pjoin2), polymorphic_on=pjoin2.c.type, inherits=employee_mapper, concrete=True, polymorphic_identity='engineer', ) hacker_mapper = mapper(Hacker, hackers_table, inherits=engineer_mapper, concrete=True, polymorphic_identity='hacker') session = create_session() tom = Manager('Tom', 'knows how to manage things') assert_raises_message( AttributeError, "does not implement attribute .?'type' at the instance level.", setattr, tom, "type", "sometype") jerry = Engineer('Jerry', 'knows how to program') hacker = Hacker('Kurt', 'Badass', 'knows how to hack') assert_raises_message( AttributeError, "does not implement attribute .?'type' at the instance level.", setattr, hacker, "type", "sometype") session.add_all((tom, jerry, hacker)) session.flush() # ensure "readonly" on save logic didn't pollute the # expired_attributes collection assert 'nickname' \ not in attributes.instance_state(jerry).expired_attributes assert 'name' \ not in attributes.instance_state(jerry).expired_attributes assert 'name' \ not in attributes.instance_state(hacker).expired_attributes assert 'nickname' \ not in attributes.instance_state(hacker).expired_attributes def go(): eq_(jerry.name, 'Jerry') eq_(hacker.nickname, 'Badass') self.assert_sql_count(testing.db, go, 0) session.expunge_all() assert repr(session.query(Employee).filter(Employee.name == 'Tom').one()) \ == 'Manager Tom knows how to manage things' assert repr( session.query(Manager).filter(Manager.name == 'Tom').one() ) == 'Manager Tom knows how to manage things' assert set([repr(x) for x in session.query(Employee).all()]) \ == set(['Engineer Jerry knows how to program', 'Manager Tom knows how to manage things', "Hacker Kurt 'Badass' knows how to hack"]) assert set([repr(x) for x in session.query(Manager).all()]) \ == set(['Manager Tom knows how to manage things']) assert set([repr(x) for x in session.query(Engineer).all()]) \ == set(['Engineer Jerry knows how to program', "Hacker Kurt 'Badass' knows how to hack"]) assert set([repr(x) for x in session.query(Hacker).all()]) \ == set(["Hacker Kurt 'Badass' knows how to hack"])
def _assert_non_simple_warning(self, fn): assert_raises_message( exc.SAWarning, "Non-simple column elements in " "primary join condition for property " r"None - consider using remote\(\) " "annotations to mark the remote side.", fn)
def test_only_str_drivername_no_none_legacy(self, value): with expect_deprecated(r"Calling URL\(\) directly"): assert_raises_message(TypeError, "drivername must be a string", url.URL, value)
def test_not_supported(self): dialect, connection = self._fixture(None) with expect_warnings("Could not fetch transaction isolation level"): assert_raises_message(NotImplementedError, "Can't fetch isolation", dialect.get_isolation_level, connection)
def test_cursor_shutdown_in_initialize(self): db = self._fixture(True, True) assert_raises_message(exc.SAWarning, "Exception attempting to detect", db.connect) eq_(db.pool.logger.error.mock_calls, [call('Error closing cursor', exc_info=True)])