From: Mike Bayer Date: Fri, 21 Jan 2022 23:46:37 +0000 (-0500) Subject: dont use exception catches for warnings; modernize xdist detection X-Git-Tag: rel_2_0_0b1~518^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=de0b4db838e26fe61953c7765f35d5b7be581646;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git dont use exception catches for warnings; modernize xdist detection Improvements to the test suite's integration with pytest such that the "warnings" plugin, if manually enabled, will not interfere with the test suite, such that third parties can enable the warnings plugin or make use of the ``-W`` parameter and SQLAlchemy's test suite will continue to pass. Additionally, modernized the detection of the "pytest-xdist" plugin so that plugins can be globally disabled using PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 without breaking the test suite if xdist were still installed. Warning filters that promote deprecation warnings to errors are now localized to SQLAlchemy-specific warnings, or within SQLAlchemy-specific sources for general Python deprecation warnings, so that non-SQLAlchemy deprecation warnings emitted from pytest plugins should also not impact the test suite. Fixes: #7599 Change-Id: Ibcf09af25228d39ee5a943fda82d8a9302433726 --- diff --git a/doc/build/changelog/unreleased_14/7599.rst b/doc/build/changelog/unreleased_14/7599.rst new file mode 100644 index 0000000000..db69ace466 --- /dev/null +++ b/doc/build/changelog/unreleased_14/7599.rst @@ -0,0 +1,16 @@ +.. change:: + :tags: bug, tests + :tickets: 7599 + + Improvements to the test suite's integration with pytest such that the + "warnings" plugin, if manually enabled, will not interfere with the test + suite, such that third parties can enable the warnings plugin or make use + of the ``-W`` parameter and SQLAlchemy's test suite will continue to pass. + Additionally, modernized the detection of the "pytest-xdist" plugin so that + plugins can be globally disabled using PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 + without breaking the test suite if xdist were still installed. Warning + filters that promote deprecation warnings to errors are now localized to + SQLAlchemy-specific warnings, or within SQLAlchemy-specific sources for + general Python deprecation warnings, so that non-SQLAlchemy deprecation + warnings emitted from pytest plugins should also not impact the test suite. + diff --git a/lib/sqlalchemy/dialects/postgresql/provision.py b/lib/sqlalchemy/dialects/postgresql/provision.py index 289dda4b6b..29926ee3da 100644 --- a/lib/sqlalchemy/dialects/postgresql/provision.py +++ b/lib/sqlalchemy/dialects/postgresql/provision.py @@ -19,10 +19,6 @@ def _pg_create_db(cfg, eng, ident): template_db = cfg.options.postgresql_templatedb with eng.execution_options(isolation_level="AUTOCOMMIT").begin() as conn: - try: - _pg_drop_db(cfg, conn, ident) - except Exception: - pass if not template_db: template_db = conn.exec_driver_sql( "select current_database()" diff --git a/lib/sqlalchemy/testing/__init__.py b/lib/sqlalchemy/testing/__init__.py index 87208d3f4c..fd6ddf5931 100644 --- a/lib/sqlalchemy/testing/__init__.py +++ b/lib/sqlalchemy/testing/__init__.py @@ -12,6 +12,8 @@ from .assertions import assert_raises from .assertions import assert_raises_context_ok from .assertions import assert_raises_message from .assertions import assert_raises_message_context_ok +from .assertions import assert_warns +from .assertions import assert_warns_message from .assertions import AssertsCompiledSQL from .assertions import AssertsExecutionResults from .assertions import ComparesTables diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index f268b6fc32..2a00f1c140 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -139,13 +139,15 @@ def _expect_warnings( exc_cls, messages, regex=True, + search_msg=False, assert_=True, raise_on_any_unexpected=False, + squelch_other_warnings=False, ): global _FILTERS, _SEEN, _EXC_CLS - if regex: + if regex or search_msg: filters = [re.compile(msg, re.I | re.S) for msg in messages] else: filters = list(messages) @@ -183,19 +185,23 @@ def _expect_warnings( exception = None if not exception or not issubclass(exception, _EXC_CLS): - return real_warn(msg, *arg, **kw) + if not squelch_other_warnings: + return real_warn(msg, *arg, **kw) if not filters and not raise_on_any_unexpected: return for filter_ in filters: - if (regex and filter_.match(msg)) or ( - not regex and filter_ == msg + if ( + (search_msg and filter_.search(msg)) + or (regex and filter_.match(msg)) + or (not regex and filter_ == msg) ): seen.discard(filter_) break else: - real_warn(msg, *arg, **kw) + if not squelch_other_warnings: + real_warn(msg, *arg, **kw) with mock.patch("warnings.warn", our_warn): try: @@ -343,6 +349,40 @@ def assert_raises_message(except_cls, msg, callable_, *args, **kwargs): ) +def assert_warns(except_cls, callable_, *args, **kwargs): + """legacy adapter function for functions that were previously using + assert_raises with SAWarning or similar. + + has some workarounds to accommodate the fact that the callable completes + with this approach rather than stopping at the exception raise. + + + """ + with _expect_warnings(except_cls, [".*"], squelch_other_warnings=True): + return callable_(*args, **kwargs) + + +def assert_warns_message(except_cls, msg, callable_, *args, **kwargs): + """legacy adapter function for functions that were previously using + assert_raises with SAWarning or similar. + + has some workarounds to accommodate the fact that the callable completes + with this approach rather than stopping at the exception raise. + + Also uses regex.search() to match the given message to the error string + rather than regex.match(). + + """ + with _expect_warnings( + except_cls, + [msg], + search_msg=True, + regex=False, + squelch_other_warnings=True, + ): + return callable_(*args, **kwargs) + + def assert_raises_message_context_ok( except_cls, msg, callable_, *args, **kwargs ): @@ -364,6 +404,15 @@ class _ErrorContainer: @contextlib.contextmanager def _expect_raises(except_cls, msg=None, check_context=False): + if ( + isinstance(except_cls, type) + and issubclass(except_cls, Warning) + or isinstance(except_cls, Warning) + ): + raise TypeError( + "Use expect_warnings for warnings, not " + "expect_raises / assert_raises" + ) ec = _ErrorContainer() if check_context: are_we_already_in_a_traceback = sys.exc_info()[0] diff --git a/lib/sqlalchemy/testing/plugin/pytestplugin.py b/lib/sqlalchemy/testing/plugin/pytestplugin.py index 7a62ad0083..2ae6730bbe 100644 --- a/lib/sqlalchemy/testing/plugin/pytestplugin.py +++ b/lib/sqlalchemy/testing/plugin/pytestplugin.py @@ -13,16 +13,10 @@ import itertools import operator import os import re +import uuid import pytest -try: - import xdist # noqa - - has_xdist = True -except ImportError: - has_xdist = False - def pytest_addoption(parser): group = parser.getgroup("sqlalchemy") @@ -75,6 +69,9 @@ def pytest_addoption(parser): def pytest_configure(config): + if config.pluginmanager.hasplugin("xdist"): + config.pluginmanager.register(XDistHooks()) + if hasattr(config, "workerinput"): plugin_base.restore_important_follower_config(config.workerinput) plugin_base.configure_follower(config.workerinput["follower_ident"]) @@ -148,10 +145,8 @@ def pytest_collection_finish(session): collect_types.init_types_collection(filter_filename=_filter) -if has_xdist: - import uuid - - def pytest_configure_node(node): +class XDistHooks: + def pytest_configure_node(self, node): from sqlalchemy.testing import provision from sqlalchemy.testing import asyncio @@ -166,7 +161,7 @@ if has_xdist: provision.create_follower_db, node.workerinput["follower_ident"] ) - def pytest_testnodedown(node, error): + def pytest_testnodedown(self, node, error): from sqlalchemy.testing import provision from sqlalchemy.testing import asyncio diff --git a/lib/sqlalchemy/testing/warnings.py b/lib/sqlalchemy/testing/warnings.py index 34b23d6757..1c20396024 100644 --- a/lib/sqlalchemy/testing/warnings.py +++ b/lib/sqlalchemy/testing/warnings.py @@ -11,8 +11,13 @@ from .. import exc as sa_exc from ..util.langhelpers import _warnings_warn -class SATestSuiteWarning(sa_exc.SAWarning): - """warning for a condition detected during tests that is non-fatal""" +class SATestSuiteWarning(Warning): + """warning for a condition detected during tests that is non-fatal + + Currently outside of SAWarning so that we can work around tools like + Alembic doing the wrong thing with warnings. + + """ def warn_test_suite(message): @@ -22,28 +27,21 @@ def warn_test_suite(message): def setup_filters(): """Set global warning behavior for the test suite.""" + # TODO: at this point we can use the normal pytest warnings plugin, + # if we decide the test suite can be linked to pytest only + + origin = r"^(?:test|sqlalchemy)\..*" + warnings.filterwarnings( "ignore", category=sa_exc.SAPendingDeprecationWarning ) warnings.filterwarnings("error", category=sa_exc.SADeprecationWarning) warnings.filterwarnings("error", category=sa_exc.SAWarning) - warnings.filterwarnings("always", category=SATestSuiteWarning) - # some selected deprecations... - warnings.filterwarnings("error", category=DeprecationWarning) - warnings.filterwarnings( - "ignore", category=DeprecationWarning, message=r".*StopIteration" - ) - warnings.filterwarnings( - "ignore", - category=DeprecationWarning, - message=r".*inspect.get.*argspec", - ) + warnings.filterwarnings("always", category=SATestSuiteWarning) warnings.filterwarnings( - "ignore", - category=DeprecationWarning, - message="The loop argument is deprecated", + "error", category=DeprecationWarning, module=origin ) try: @@ -52,7 +50,7 @@ def setup_filters(): pass else: warnings.filterwarnings( - "once", category=pytest.PytestDeprecationWarning + "once", category=pytest.PytestDeprecationWarning, module=origin ) diff --git a/test/dialect/oracle/test_reflection.py b/test/dialect/oracle/test_reflection.py index 7dcd5bb1dc..df8dff30f8 100644 --- a/test/dialect/oracle/test_reflection.py +++ b/test/dialect/oracle/test_reflection.py @@ -23,7 +23,7 @@ from sqlalchemy.dialects.oracle.base import BINARY_DOUBLE from sqlalchemy.dialects.oracle.base import BINARY_FLOAT from sqlalchemy.dialects.oracle.base import DOUBLE_PRECISION from sqlalchemy.dialects.oracle.base import NUMBER -from sqlalchemy.testing import assert_raises +from sqlalchemy.testing import assert_warns from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures @@ -352,7 +352,7 @@ class ConstraintTest(fixtures.TablesTest): "foo_id", Integer, ForeignKey("foo.id", onupdate="CASCADE") ), ) - assert_raises(exc.SAWarning, bar.create, connection) + assert_warns(exc.SAWarning, bar.create, connection) bat = Table( "bat", @@ -361,7 +361,7 @@ class ConstraintTest(fixtures.TablesTest): Column("foo_id", Integer), ForeignKeyConstraint(["foo_id"], ["foo.id"], onupdate="CASCADE"), ) - assert_raises(exc.SAWarning, bat.create, connection) + assert_warns(exc.SAWarning, bat.create, connection) def test_reflect_check_include_all(self, connection): insp = inspect(connection) diff --git a/test/dialect/postgresql/test_reflection.py b/test/dialect/postgresql/test_reflection.py index fa04dee480..9c286145b7 100644 --- a/test/dialect/postgresql/test_reflection.py +++ b/test/dialect/postgresql/test_reflection.py @@ -34,6 +34,7 @@ from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import fixtures from sqlalchemy.testing import mock from sqlalchemy.testing.assertions import assert_raises +from sqlalchemy.testing.assertions import assert_warns from sqlalchemy.testing.assertions import AssertsExecutionResults from sqlalchemy.testing.assertions import eq_ from sqlalchemy.testing.assertions import is_ @@ -486,7 +487,7 @@ class DomainReflectionTest(fixtures.TestBase, AssertsExecutionResults): base.PGDialect.ischema_names = {} try: m2 = MetaData() - assert_raises( + assert_warns( exc.SAWarning, Table, "testtable", m2, autoload_with=connection ) diff --git a/test/engine/test_pool.py b/test/engine/test_pool.py index 324b971b65..0c89752025 100644 --- a/test/engine/test_pool.py +++ b/test/engine/test_pool.py @@ -18,7 +18,7 @@ from sqlalchemy.pool.base import _AsyncConnDialect from sqlalchemy.pool.base import _ConnDialect from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_context_ok -from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import eq_ from sqlalchemy.testing import expect_raises from sqlalchemy.testing import fixtures @@ -1816,7 +1816,7 @@ class QueuePoolTest(PoolTestBase): c1 = p.connect() rec = c1._connection_record c1.close() - assert_raises_message( + assert_warns_message( Warning, "Double checkin attempted on %s" % rec, rec.checkin ) diff --git a/test/engine/test_reconnect.py b/test/engine/test_reconnect.py index 74b5b2df5a..cccf668210 100644 --- a/test/engine/test_reconnect.py +++ b/test/engine/test_reconnect.py @@ -17,6 +17,7 @@ from sqlalchemy.engine import url from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message from sqlalchemy.testing import assert_raises_message_context_ok +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import engines from sqlalchemy.testing import eq_ from sqlalchemy.testing import expect_raises @@ -961,7 +962,7 @@ class CursorErrTest(fixtures.TestBase): def test_cursor_shutdown_in_initialize(self): db = self._fixture(True, True) - assert_raises_message_context_ok( + assert_warns_message( exc.SAWarning, "Exception attempting to detect", db.connect ) eq_( diff --git a/test/orm/declarative/test_basic.py b/test/orm/declarative/test_basic.py index 4fb2765432..9651f6dbfd 100644 --- a/test/orm/declarative/test_basic.py +++ b/test/orm/declarative/test_basic.py @@ -806,7 +806,13 @@ class DeclarativeMultiBaseTest( id = Column(Integer, primary_key=True) def test_column_named_twice(self): - def go(): + with assertions.expect_deprecated( + "A column with name 'x' is already present in table 'foo'" + ), expect_warnings( + "On class 'Foo', Column object 'x' named directly multiple times, " + "only one will be used: x, y", + ): + class Foo(Base): __tablename__ = "foo" @@ -814,15 +820,14 @@ class DeclarativeMultiBaseTest( x = Column("x", Integer) y = Column("x", Integer) - assert_raises_message( - sa.exc.SAWarning, + def test_column_repeated_under_prop(self): + with assertions.expect_deprecated( + "A column with name 'x' is already present in table 'foo'" + ), expect_warnings( "On class 'Foo', Column object 'x' named directly multiple times, " - "only one will be used: x, y", - go, - ) + "only one will be used: x, y, z", + ): - def test_column_repeated_under_prop(self): - def go(): class Foo(Base): __tablename__ = "foo" @@ -831,13 +836,6 @@ class DeclarativeMultiBaseTest( y = column_property(x) z = Column("x", Integer) - assert_raises_message( - sa.exc.SAWarning, - "On class 'Foo', Column object 'x' named directly multiple times, " - "only one will be used: x, y, z", - go, - ) - def test_using_explicit_prop_in_schema_objects(self): class Foo(Base): __tablename__ = "foo" @@ -2416,15 +2414,14 @@ class DeclarativeMultiBaseTest( __tablename__ = "a" id = Column(Integer, primary_key=True) - assert_raises_message( - sa.exc.SAWarning, + with expect_warnings( "This declarative base already contains a class with ", - lambda: type(Base)( + ): + type(Base)( "Test", (Base,), dict(__tablename__="b", id=Column(Integer, primary_key=True)), - ), - ) + ) @testing.teardown_events(MapperEvents) @testing.teardown_events(InstrumentationEvents) diff --git a/test/orm/declarative/test_clsregistry.py b/test/orm/declarative/test_clsregistry.py index 8c63814759..f192761262 100644 --- a/test/orm/declarative/test_clsregistry.py +++ b/test/orm/declarative/test_clsregistry.py @@ -7,6 +7,7 @@ from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import mock +from sqlalchemy.testing.assertions import expect_warnings from sqlalchemy.testing.util import gc_collect @@ -34,16 +35,16 @@ class ClsRegistryTest(fixtures.TestBase): clsregistry.add_class("Foo", f1, base._class_registry) gc_collect() - assert_raises_message( - exc.SAWarning, + with expect_warnings( "This declarative base already contains a class with the " "same class name and module name as foo.bar.Foo, and " - "will be replaced in the string-lookup table.", - clsregistry.add_class, - "Foo", - f2, - base._class_registry, - ) + "will be replaced in the string-lookup table." + ): + clsregistry.add_class( + "Foo", + f2, + base._class_registry, + ) def test_resolve(self): base = registry() diff --git a/test/orm/declarative/test_mixin.py b/test/orm/declarative/test_mixin.py index 3bad55d312..97f0d560e4 100644 --- a/test/orm/declarative/test_mixin.py +++ b/test/orm/declarative/test_mixin.py @@ -1856,14 +1856,11 @@ class DeclaredAttrTest(DeclarativeTestBase, testing.AssertsCompiledSQL): def my_prop(cls): return Column("x", Integer) - assert_raises_message( - sa.exc.SAWarning, + with expect_warnings( "Unmanaged access of declarative attribute my_prop " - "from non-mapped class Mixin", - getattr, - Mixin, - "my_prop", - ) + "from non-mapped class Mixin" + ): + Mixin.my_prop def test_can_we_access_the_mixin_straight_special_names(self): class Mixin: diff --git a/test/orm/inheritance/test_basic.py b/test/orm/inheritance/test_basic.py index 5fc69bf9ee..67abc8971b 100644 --- a/test/orm/inheritance/test_basic.py +++ b/test/orm/inheritance/test_basic.py @@ -35,6 +35,7 @@ from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import mock +from sqlalchemy.testing.assertions import assert_warns_message from sqlalchemy.testing.assertsql import AllOf from sqlalchemy.testing.assertsql import CompiledSQL from sqlalchemy.testing.assertsql import Conditional @@ -903,7 +904,7 @@ class PolymorphicAttributeManagementTest(fixtures.MappedTest): c1 = C() c1.class_name = "b" sess.add(c1) - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "Flushing object %s with incompatible " "polymorphic identity 'b'; the object may not " @@ -922,7 +923,7 @@ class PolymorphicAttributeManagementTest(fixtures.MappedTest): b1 = B() b1.class_name = "c" sess.add(b1) - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "Flushing object %s with incompatible " "polymorphic identity 'c'; the object may not " @@ -938,7 +939,7 @@ class PolymorphicAttributeManagementTest(fixtures.MappedTest): b1 = B() b1.class_name = "xyz" sess.add(b1) - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "Flushing object %s with incompatible " "polymorphic identity 'xyz'; the object may not " @@ -968,7 +969,7 @@ class PolymorphicAttributeManagementTest(fixtures.MappedTest): sess.expire(c1) c1.class_name = "b" - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "Flushing object %s with incompatible " "polymorphic identity 'b'; the object may not " @@ -2231,7 +2232,7 @@ class DistinctPKTest(fixtures.MappedTest): properties=dict(id=[employee_table.c.eid, person_table.c.id]), primary_key=[person_table.c.id, employee_table.c.eid], ) - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, r"On mapper Mapper\[Employee\(employees\)\], " "primary key column 'persons.id' is being " @@ -2529,7 +2530,7 @@ class OverrideColKeyTest(fixtures.MappedTest): Sub, subtable_two, inherits=Base ) - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "Implicitly combining column base.base_id with " "column subtable_two.base_id under attribute 'base_id'", @@ -3181,7 +3182,7 @@ class NoPKOnSubTableWarningTest(fixtures.MappedTest): pass self.mapper_registry.map_imperatively(P, parent) - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "Could not assemble any primary keys for locally mapped " "table 'child' - no rows will be persisted in this Table.", diff --git a/test/orm/test_attributes.py b/test/orm/test_attributes.py index 3a174ffd9f..8e6ddf9d4e 100644 --- a/test/orm/test_attributes.py +++ b/test/orm/test_attributes.py @@ -19,6 +19,7 @@ from sqlalchemy.testing import is_false from sqlalchemy.testing import is_not from sqlalchemy.testing import is_true from sqlalchemy.testing import not_in +from sqlalchemy.testing.assertions import assert_warns from sqlalchemy.testing.util import all_partial_orderings from sqlalchemy.testing.util import gc_collect @@ -3769,7 +3770,7 @@ class TestUnlink(fixtures.TestBase): a1.bs.append(B()) state = attributes.instance_state(a1) state._expire(state.dict, set()) - assert_raises(Warning, coll.append, B()) + assert_warns(Warning, coll.append, B()) def test_replaced(self): A, B = self.A, self.B @@ -3790,7 +3791,7 @@ class TestUnlink(fixtures.TestBase): a1.bs.append(B()) state = attributes.instance_state(a1) state._reset(state.dict, "bs") - assert_raises(Warning, coll.append, B()) + assert_warns(Warning, coll.append, B()) def test_ad_hoc_lazy(self): A, B = self.A, self.B @@ -3799,4 +3800,4 @@ class TestUnlink(fixtures.TestBase): a1.bs.append(B()) state = attributes.instance_state(a1) _set_callable(state, state.dict, "bs", lambda: B()) - assert_raises(Warning, coll.append, B()) + assert_warns(Warning, coll.append, B()) diff --git a/test/orm/test_cascade.py b/test/orm/test_cascade.py index 6de346aced..51f37f0286 100644 --- a/test/orm/test_cascade.py +++ b/test/orm/test_cascade.py @@ -23,6 +23,7 @@ from sqlalchemy.orm.collections import attribute_mapped_collection from sqlalchemy.orm.decl_api import declarative_base from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import in_ @@ -93,7 +94,7 @@ class CascadeArgTest(fixtures.MappedTest): def test_delete_orphan_without_delete(self): Address = self.classes.Address - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "The 'delete-orphan' cascade option requires 'delete'.", relationship, @@ -1208,7 +1209,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.add(u1) assert u1 in sess assert a1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_o2m_only_child_persistent(self): User, Address = self.classes.User, self.classes.Address @@ -1226,7 +1227,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.add(u1) assert u1 in sess assert a1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_o2m_backref_child_pending(self): User, Address = self.classes.User, self.classes.Address @@ -1252,7 +1253,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.add(u1) assert u1 in sess assert a1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_o2m_backref_child_transient_nochange(self): User, Address = self.classes.User, self.classes.Address @@ -1288,7 +1289,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.expunge(a1) assert u1 in sess assert a1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_o2m_backref_child_expunged_nochange(self): User, Address = self.classes.User, self.classes.Address @@ -1337,7 +1338,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.add(a1) assert u1 not in sess assert a1 in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_m2o_only_child_expunged(self): User, Address = self.classes.User, self.classes.Address @@ -1354,7 +1355,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.expunge(u1) assert u1 not in sess assert a1 in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_m2o_backref_child_pending(self): User, Address = self.classes.User, self.classes.Address @@ -1380,7 +1381,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.add(a1) assert u1 not in sess assert a1 in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_m2o_backref_child_expunged(self): User, Address = self.classes.User, self.classes.Address @@ -1397,7 +1398,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.expunge(u1) assert u1 not in sess assert a1 in sess - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "not in session", sess.flush ) @@ -1417,7 +1418,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.expunge(u1) assert u1 not in sess assert a1 in sess - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, "not in session", sess.flush ) @@ -1517,7 +1518,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.add(i1) assert i1 in sess assert k1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_m2m_only_child_persistent(self): Item, Keyword = self.classes.Item, self.classes.Keyword @@ -1535,7 +1536,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.add(i1) assert i1 in sess assert k1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_m2m_backref_child_pending(self): Item, Keyword = self.classes.Item, self.classes.Keyword @@ -1561,7 +1562,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.add(i1) assert i1 in sess assert k1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_m2m_backref_child_transient_nochange(self): Item, Keyword = self.classes.Item, self.classes.Keyword @@ -1597,7 +1598,7 @@ class NoSaveCascadeFlushTest(_fixtures.FixtureTest): sess.expunge(k1) assert i1 in sess assert k1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.flush) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.flush) def test_m2m_backref_child_expunged_nochange(self): Item, Keyword = self.classes.Item, self.classes.Keyword @@ -2775,7 +2776,7 @@ class NoBackrefCascadeTest(_fixtures.FixtureTest): a1 = Address(email_address="a1") a1.user = u1 - assert_raises_message(sa_exc.SAWarning, "not in session", sess.commit) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.commit) assert a1 not in sess @@ -2828,7 +2829,7 @@ class NoBackrefCascadeTest(_fixtures.FixtureTest): a1.dingalings.append(d1) assert a1 not in sess - assert_raises_message(sa_exc.SAWarning, "not in session", sess.commit) + assert_warns_message(sa_exc.SAWarning, "not in session", sess.commit) class PendingOrphanTestSingleLevel(fixtures.MappedTest): diff --git a/test/orm/test_dynamic.py b/test/orm/test_dynamic.py index 5ea6131976..2eaafb9533 100644 --- a/test/orm/test_dynamic.py +++ b/test/orm/test_dynamic.py @@ -15,6 +15,7 @@ from sqlalchemy.orm import Query from sqlalchemy.orm import relationship from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import eq_ from sqlalchemy.testing import expect_raises_message @@ -321,7 +322,7 @@ class DynamicTest(_DynamicFixture, _fixtures.FixtureTest, AssertsCompiledSQL): }, ) self.mapper_registry.map_imperatively(User, users) - assert_raises_message( + assert_warns_message( exc.SAWarning, "On relationship Address.user, 'dynamic' loaders cannot be " "used with many-to-one/one-to-one relationships and/or " diff --git a/test/orm/test_eager_relations.py b/test/orm/test_eager_relations.py index 42b3bd1ea5..8c82450da0 100644 --- a/test/orm/test_eager_relations.py +++ b/test/orm/test_eager_relations.py @@ -31,8 +31,8 @@ from sqlalchemy.orm import Session from sqlalchemy.orm import undefer from sqlalchemy.sql import operators from sqlalchemy.sql.selectable import LABEL_STYLE_TABLENAME_PLUS_COL -from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns from sqlalchemy.testing import eq_ from sqlalchemy.testing import expect_raises_message from sqlalchemy.testing import fixtures @@ -2142,7 +2142,7 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL): ) self.mapper_registry.map_imperatively(Order, orders) s = fixture_session() - assert_raises( + assert_warns( sa.exc.SAWarning, s.query(User).options(joinedload(User.order)).all ) diff --git a/test/orm/test_events.py b/test/orm/test_events.py index 37b4d0ae1f..79b20e285a 100644 --- a/test/orm/test_events.py +++ b/test/orm/test_events.py @@ -35,8 +35,10 @@ from sqlalchemy.orm import UserDefinedOption from sqlalchemy.sql.cache_key import NO_CACHE from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import eq_ +from sqlalchemy.testing import expect_raises from sqlalchemy.testing import expect_warnings from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_not @@ -1059,7 +1061,7 @@ class MapperEventsTest(_RemoveListeners, _fixtures.FixtureTest): m1 = Mock() self.mapper_registry.map_imperatively(User, users) - assert_raises_message( + assert_warns_message( sa.exc.SAWarning, r"before_configured' and 'after_configured' ORM events only " r"invoke with the Mapper class as " @@ -1070,7 +1072,7 @@ class MapperEventsTest(_RemoveListeners, _fixtures.FixtureTest): m1, ) - assert_raises_message( + assert_warns_message( sa.exc.SAWarning, r"before_configured' and 'after_configured' ORM events only " r"invoke with the Mapper class as " @@ -2197,7 +2199,12 @@ class SessionEventsTest(_RemoveListeners, _fixtures.FixtureTest): u2 = User(name="u1", id=1) sess.add(u2) - assert_raises(sa.exc.SAWarning, sess.commit) + + with expect_raises(sa.exc.IntegrityError), expect_warnings( + "New instance" + ): + sess.commit() + sess.rollback() eq_( canary, @@ -2249,7 +2256,11 @@ class SessionEventsTest(_RemoveListeners, _fixtures.FixtureTest): u2 = User(name="u1", id=1) sess.add(u2) - assert_raises(sa.exc.SAWarning, sess.commit) + with expect_raises(sa.exc.IntegrityError), expect_warnings( + "New instance" + ): + sess.commit() + sess.rollback() eq_(assertions, [True, True]) diff --git a/test/orm/test_instrumentation.py b/test/orm/test_instrumentation.py index 8f5455850c..3b10103001 100644 --- a/test/orm/test_instrumentation.py +++ b/test/orm/test_instrumentation.py @@ -9,7 +9,7 @@ from sqlalchemy.orm import clear_mappers from sqlalchemy.orm import instrumentation from sqlalchemy.orm import relationship from sqlalchemy.testing import assert_raises -from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import ne_ @@ -524,7 +524,7 @@ class MapperInitTest(fixtures.MappedTest): def __del__(self): pass - assert_raises_message( + assert_warns_message( sa.exc.SAWarning, r"__del__\(\) method on class " r" will cause " diff --git a/test/orm/test_lazy_relations.py b/test/orm/test_lazy_relations.py index ee6d53652d..ed636ae422 100644 --- a/test/orm/test_lazy_relations.py +++ b/test/orm/test_lazy_relations.py @@ -25,6 +25,7 @@ from sqlalchemy.orm import relationship from sqlalchemy.orm import Session from sqlalchemy.orm import with_parent from sqlalchemy.testing import assert_raises +from sqlalchemy.testing import assert_warns from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ @@ -369,7 +370,7 @@ class LazyTest(_fixtures.FixtureTest): self.mapper_registry.map_imperatively(Order, orders) s = fixture_session() u1 = s.query(User).filter(User.id == 7).one() - assert_raises(sa.exc.SAWarning, getattr, u1, "order") + assert_warns(sa.exc.SAWarning, getattr, u1, "order") def test_callable_bind(self): Address, addresses, users, User = ( diff --git a/test/orm/test_mapper.py b/test/orm/test_mapper.py index fc7406b816..de211cf63b 100644 --- a/test/orm/test_mapper.py +++ b/test/orm/test_mapper.py @@ -31,6 +31,7 @@ from sqlalchemy.orm import synonym from sqlalchemy.orm.persistence import _sort_states from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import eq_ from sqlalchemy.testing import expect_raises_message @@ -818,7 +819,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): ) self.mapper(Address, addresses) - assert_raises_message( + assert_warns_message( sa.exc.SAWarning, "Property User.addresses on Mapper|User|users being replaced " "with new property User.addresses; the old property will " @@ -1001,7 +1002,7 @@ class MapperTest(_fixtures.FixtureTest, AssertsCompiledSQL): polymorphic_on=users.c.name, polymorphic_identity="user", ) - assert_raises_message( + assert_warns_message( sa.exc.SAWarning, "Reassigning polymorphic association for identity 'user'", self.mapper_registry.map_imperatively, diff --git a/test/orm/test_query.py b/test/orm/test_query.py index a53c90ed4e..e7fdf661a6 100644 --- a/test/orm/test_query.py +++ b/test/orm/test_query.py @@ -73,6 +73,7 @@ from sqlalchemy.testing import is_true from sqlalchemy.testing import mock from sqlalchemy.testing.assertions import assert_raises from sqlalchemy.testing.assertions import assert_raises_message +from sqlalchemy.testing.assertions import assert_warns_message from sqlalchemy.testing.assertions import eq_ from sqlalchemy.testing.assertions import expect_raises from sqlalchemy.testing.assertions import expect_warnings @@ -1315,7 +1316,7 @@ class GetTest(QueryTest): User = self.classes.User s = fixture_session() - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, r"fully NULL primary key identity cannot load any object. " "This condition may raise an error in a future release.", @@ -1329,7 +1330,7 @@ class GetTest(QueryTest): s = fixture_session() - assert_raises_message( + assert_warns_message( sa_exc.SAWarning, r"fully NULL primary key identity cannot load any object. " "This condition may raise an error in a future release.", diff --git a/test/orm/test_rel_fn.py b/test/orm/test_rel_fn.py index ea292a43e4..f5da7aa814 100644 --- a/test/orm/test_rel_fn.py +++ b/test/orm/test_rel_fn.py @@ -17,11 +17,13 @@ from sqlalchemy.orm import remote from sqlalchemy.orm.interfaces import MANYTOONE from sqlalchemy.orm.interfaces import ONETOMANY from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import mock +from sqlalchemy.testing.assertions import expect_raises_message class _JoinFixtures: @@ -573,7 +575,7 @@ class _JoinFixtures: ) def _assert_non_simple_warning(self, fn): - assert_raises_message( + assert_warns_message( exc.SAWarning, "Non-simple column elements in " "primary join condition for property " @@ -818,9 +820,12 @@ class ColumnCollectionsTest( self._join_fixture_o2m_composite_selfref_func_remote_side() def test_determine_local_remote_pairs_o2m_overlap_func_warning(self): - self._assert_non_simple_warning( - self._join_fixture_m2o_sub_to_joined_sub_func - ) + with expect_raises_message( + exc.ArgumentError, "Could not locate any relevant" + ): + self._assert_non_simple_warning( + self._join_fixture_m2o_sub_to_joined_sub_func + ) def test_determine_local_remote_pairs_o2m_composite_selfref_func_annotated( self, diff --git a/test/orm/test_relationships.py b/test/orm/test_relationships.py index f91e7e8d54..fd192ab519 100644 --- a/test/orm/test_relationships.py +++ b/test/orm/test_relationships.py @@ -33,13 +33,14 @@ from sqlalchemy.orm.interfaces import MANYTOONE from sqlalchemy.orm.interfaces import ONETOMANY from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import AssertsCompiledSQL from sqlalchemy.testing import eq_ +from sqlalchemy.testing import expect_raises_message +from sqlalchemy.testing import expect_warnings from sqlalchemy.testing import fixtures from sqlalchemy.testing import in_ from sqlalchemy.testing import is_ -from sqlalchemy.testing.assertions import expect_raises_message -from sqlalchemy.testing.assertions import expect_warnings from sqlalchemy.testing.assertsql import assert_engine from sqlalchemy.testing.assertsql import CompiledSQL from sqlalchemy.testing.fixtures import fixture_session @@ -873,7 +874,7 @@ class OverlappingFksSiblingTest(fixtures.MappedTest): @testing.provide_metadata def test_simple_warn(self): - assert_raises_message( + assert_warns_message( exc.SAWarning, r"relationship '(?:Child.parent|Parent.children)' will copy " r"column parent.id to column child.parent_id, which conflicts " @@ -964,7 +965,7 @@ class OverlappingFksSiblingTest(fixtures.MappedTest): @testing.provide_metadata def test_double_rel_same_mapper_warns(self): - assert_raises_message( + assert_warns_message( exc.SAWarning, r"relationship 'Parent.child[12]' will copy column parent.id to " r"column child.parent_id, which conflicts with relationship\(s\): " @@ -984,7 +985,7 @@ class OverlappingFksSiblingTest(fixtures.MappedTest): @testing.provide_metadata def test_warn_one(self): - assert_raises_message( + assert_warns_message( exc.SAWarning, r"relationship '(?:BSub1.a|BSub2.a_member|B.a)' will copy column " r"(?:a.id|a_member.a_id) to column b.a_id", @@ -995,7 +996,7 @@ class OverlappingFksSiblingTest(fixtures.MappedTest): @testing.provide_metadata def test_warn_two(self): - assert_raises_message( + assert_warns_message( exc.SAWarning, r"relationship '(?:BSub1.a|B.a_member)' will copy column " r"(?:a.id|a_member.a_id) to column b.a_id", @@ -1006,7 +1007,7 @@ class OverlappingFksSiblingTest(fixtures.MappedTest): @testing.provide_metadata def test_warn_three(self): - assert_raises_message( + assert_warns_message( exc.SAWarning, r"relationship '(?:BSub1.a|B.a_member|B.a)' will copy column " r"(?:a.id|a_member.a_id) to column b.a_id", @@ -1018,7 +1019,7 @@ class OverlappingFksSiblingTest(fixtures.MappedTest): @testing.provide_metadata def test_warn_four(self): - assert_raises_message( + assert_warns_message( exc.SAWarning, r"relationship '(?:B.a|BSub2.a_member|B.a)' will copy column " r"(?:a.id|a_member.a_id) to column b.a_id", @@ -1302,7 +1303,7 @@ class CompositeSelfRefFKTest(fixtures.MappedTest, AssertsCompiledSQL): }, ) - assert_raises_message( + assert_warns_message( exc.SAWarning, r"relationship .* will copy column .* to column " r"employee_t.company_id, which conflicts with relationship\(s\)", diff --git a/test/orm/test_scoping.py b/test/orm/test_scoping.py index 9b255bf5e6..f2d7d8569a 100644 --- a/test/orm/test_scoping.py +++ b/test/orm/test_scoping.py @@ -11,6 +11,7 @@ from sqlalchemy.orm import scoped_session from sqlalchemy.orm import Session from sqlalchemy.orm import sessionmaker from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ @@ -102,7 +103,7 @@ class ScopedSessionTest(fixtures.MappedTest): bind=testing.db, ) - assert_raises_message( + assert_warns_message( sa.exc.SAWarning, "At least one scoped session is already present. ", Session.configure, diff --git a/test/orm/test_selectin_relations.py b/test/orm/test_selectin_relations.py index 1daf7b0538..0458d616ed 100644 --- a/test/orm/test_selectin_relations.py +++ b/test/orm/test_selectin_relations.py @@ -18,8 +18,8 @@ from sqlalchemy.orm import Session from sqlalchemy.orm import subqueryload from sqlalchemy.orm import undefer from sqlalchemy.orm import with_polymorphic -from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ @@ -1458,7 +1458,7 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL): ) self.mapper_registry.map_imperatively(Order, orders) s = fixture_session() - assert_raises( + assert_warns( sa.exc.SAWarning, s.query(User).options(selectinload(User.order)).all, ) diff --git a/test/orm/test_session.py b/test/orm/test_session.py index a53756d63a..d146612a5a 100644 --- a/test/orm/test_session.py +++ b/test/orm/test_session.py @@ -25,6 +25,7 @@ from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import was_deleted from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import assertions from sqlalchemy.testing import config from sqlalchemy.testing import engines @@ -1062,7 +1063,7 @@ class SessionStateTest(_fixtures.FixtureTest): def test_extra_dirty_state_post_flush_warning(self): s, a1, a2 = self._test_extra_dirty_state() - assert_raises_message( + assert_warns_message( sa.exc.SAWarning, "Attribute history events accumulated on 1 previously " "clean instances", @@ -2309,7 +2310,8 @@ class FlushWarningsTest(fixtures.MappedTest): def evt(mapper, conn, instance): instance.addresses[0].user = User(name="u2") - self._test(evt, "related attribute set") + with expect_raises_message(orm_exc.FlushError, ".*Over 100"): + self._test(evt, "related attribute set") def test_m2o_cascade_remove(self): def evt(mapper, conn, instance): @@ -2340,7 +2342,10 @@ class FlushWarningsTest(fixtures.MappedTest): def evt(mapper, conn, instance): object_session(instance).delete(Address(email="x1")) - self._test(evt, r"Session.delete\(\)") + with expect_raises_message( + sa.exc.InvalidRequestError, ".*is not persisted" + ): + self._test(evt, r"Session.delete\(\)") def _test(self, fn, method): User = self.classes.User @@ -2351,6 +2356,6 @@ class FlushWarningsTest(fixtures.MappedTest): u1 = User(name="u1", addresses=[Address(name="a1")]) s.add(u1) - assert_raises_message( + assert_warns_message( sa.exc.SAWarning, "Usage of the '%s'" % method, s.commit ) diff --git a/test/orm/test_subquery_relations.py b/test/orm/test_subquery_relations.py index c48fe45881..6da0e90108 100644 --- a/test/orm/test_subquery_relations.py +++ b/test/orm/test_subquery_relations.py @@ -20,8 +20,8 @@ from sqlalchemy.orm import Session from sqlalchemy.orm import subqueryload from sqlalchemy.orm import undefer from sqlalchemy.orm import with_polymorphic -from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns from sqlalchemy.testing import eq_ from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ @@ -1510,7 +1510,7 @@ class EagerTest(_fixtures.FixtureTest, testing.AssertsCompiledSQL): ) self.mapper_registry.map_imperatively(Order, orders) s = fixture_session() - assert_raises( + assert_warns( sa.exc.SAWarning, s.query(User).options(subqueryload(User.order)).all, ) diff --git a/test/orm/test_unitofworkv2.py b/test/orm/test_unitofworkv2.py index c93cc2edfc..7f4c046521 100644 --- a/test/orm/test_unitofworkv2.py +++ b/test/orm/test_unitofworkv2.py @@ -28,6 +28,7 @@ from sqlalchemy.orm import relationship from sqlalchemy.orm import Session from sqlalchemy.orm import unitofwork from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import config from sqlalchemy.testing import engines from sqlalchemy.testing import eq_ @@ -1920,7 +1921,7 @@ class BasicStaleChecksTest(fixtures.MappedTest): sess.delete(p1) - assert_raises_message( + assert_warns_message( exc.SAWarning, r"DELETE statement on table 'parent' expected to " r"delete 1 row\(s\); 0 were matched.", @@ -1940,7 +1941,7 @@ class BasicStaleChecksTest(fixtures.MappedTest): sess.delete(p1) sess.delete(p2) - assert_raises_message( + assert_warns_message( exc.SAWarning, r"DELETE statement on table 'parent' expected to " r"delete 2 row\(s\); 0 were matched.", @@ -2005,7 +2006,7 @@ class BasicStaleChecksTest(fixtures.MappedTest): with patch.object( config.db.dialect, "supports_sane_multi_rowcount", False ): - assert_raises_message( + assert_warns_message( exc.SAWarning, r"DELETE statement on table 'parent' expected to " r"delete 1 row\(s\); 0 were matched.", diff --git a/test/orm/test_versioning.py b/test/orm/test_versioning.py index b5955e4a6b..9f23073d41 100644 --- a/test/orm/test_versioning.py +++ b/test/orm/test_versioning.py @@ -21,6 +21,8 @@ from sqlalchemy.orm import relationship from sqlalchemy.orm import Session from sqlalchemy.testing import assert_raises from sqlalchemy.testing import assert_raises_message +from sqlalchemy.testing import assert_warns +from sqlalchemy.testing import assert_warns_message from sqlalchemy.testing import config from sqlalchemy.testing import engines from sqlalchemy.testing import eq_ @@ -193,7 +195,7 @@ class VersioningTest(fixtures.MappedTest): s1.commit() f1.value = "f1rev2" - assert_raises(sa.exc.SAWarning, s1.commit) + assert_warns(sa.exc.SAWarning, s1.commit) finally: testing.db.dialect.supports_sane_rowcount = save @@ -1328,7 +1330,7 @@ class InheritanceTwoVersionIdsTest(fixtures.MappedTest): Base, base, version_id_col=base.c.version_id ) - assert_raises_message( + assert_warns_message( exc.SAWarning, "Inheriting version_id_col 'version_id' does not " "match inherited version_id_col 'version_id' and will not " diff --git a/test/sql/test_metadata.py b/test/sql/test_metadata.py index 8a9c868be3..e02f0e2ed5 100644 --- a/test/sql/test_metadata.py +++ b/test/sql/test_metadata.py @@ -53,6 +53,7 @@ from sqlalchemy.testing import is_ from sqlalchemy.testing import is_false from sqlalchemy.testing import is_true from sqlalchemy.testing import mock +from sqlalchemy.testing.assertions import expect_warnings class MetaDataTest(fixtures.TestBase, ComparesTables): @@ -1822,32 +1823,35 @@ class TableTest(fixtures.TestBase, AssertsCompiledSQL): def test_pk_col_mismatch_one(self): m = MetaData() - assert_raises_message( - exc.SAWarning, + + with expect_warnings( "Table 't' specifies columns 'x' as primary_key=True, " - "not matching locally specified columns 'q'", - Table, - "t", - m, - Column("x", Integer, primary_key=True), - Column("q", Integer), - PrimaryKeyConstraint("q"), - ) + "not matching locally specified columns 'q'" + ): + Table( + "t", + m, + Column("x", Integer, primary_key=True), + Column("q", Integer), + PrimaryKeyConstraint("q"), + ) def test_pk_col_mismatch_two(self): m = MetaData() - assert_raises_message( - exc.SAWarning, + + with expect_warnings( "Table 't' specifies columns 'a', 'b', 'c' as primary_key=True, " - "not matching locally specified columns 'b', 'c'", - Table, - "t", - m, - Column("a", Integer, primary_key=True), - Column("b", Integer, primary_key=True), - Column("c", Integer, primary_key=True), - PrimaryKeyConstraint("b", "c"), - ) + "not matching locally specified columns 'b', 'c'" + ): + + Table( + "t", + m, + Column("a", Integer, primary_key=True), + Column("b", Integer, primary_key=True), + Column("c", Integer, primary_key=True), + PrimaryKeyConstraint("b", "c"), + ) @testing.emits_warning("Table 't'") def test_pk_col_mismatch_three(self): diff --git a/test/sql/test_operators.py b/test/sql/test_operators.py index e72ab6ac92..e5176713ab 100644 --- a/test/sql/test_operators.py +++ b/test/sql/test_operators.py @@ -60,6 +60,7 @@ from sqlalchemy.testing import expect_warnings from sqlalchemy.testing import fixtures from sqlalchemy.testing import is_ from sqlalchemy.testing import is_not +from sqlalchemy.testing.assertions import expect_deprecated from sqlalchemy.types import ARRAY from sqlalchemy.types import Boolean from sqlalchemy.types import Concatenable @@ -1221,15 +1222,14 @@ class ConjunctionTest(fixtures.TestBase, testing.AssertsCompiledSQL): # these warning classes will change to ArgumentError when the # deprecated behavior is disabled - assert_raises_message( - exc.SADeprecationWarning, + with expect_deprecated( r"Invoking %(str_op)s\(\) without arguments is deprecated, and " r"will be disallowed in a future release. For an empty " r"%(str_op)s\(\) construct, use " r"%(str_op)s\(%(str_continue)s, \*args\)\." - % {"str_op": str_op, "str_continue": str_continue}, - op, - ) + % {"str_op": str_op, "str_continue": str_continue} + ): + op() def test_empty_and_raw(self): self.assert_compile(