]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
dont use exception catches for warnings; modernize xdist detection
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 21 Jan 2022 23:46:37 +0000 (18:46 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 23 Jan 2022 00:17:10 +0000 (19:17 -0500)
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

33 files changed:
doc/build/changelog/unreleased_14/7599.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/postgresql/provision.py
lib/sqlalchemy/testing/__init__.py
lib/sqlalchemy/testing/assertions.py
lib/sqlalchemy/testing/plugin/pytestplugin.py
lib/sqlalchemy/testing/warnings.py
test/dialect/oracle/test_reflection.py
test/dialect/postgresql/test_reflection.py
test/engine/test_pool.py
test/engine/test_reconnect.py
test/orm/declarative/test_basic.py
test/orm/declarative/test_clsregistry.py
test/orm/declarative/test_mixin.py
test/orm/inheritance/test_basic.py
test/orm/test_attributes.py
test/orm/test_cascade.py
test/orm/test_dynamic.py
test/orm/test_eager_relations.py
test/orm/test_events.py
test/orm/test_instrumentation.py
test/orm/test_lazy_relations.py
test/orm/test_mapper.py
test/orm/test_query.py
test/orm/test_rel_fn.py
test/orm/test_relationships.py
test/orm/test_scoping.py
test/orm/test_selectin_relations.py
test/orm/test_session.py
test/orm/test_subquery_relations.py
test/orm/test_unitofworkv2.py
test/orm/test_versioning.py
test/sql/test_metadata.py
test/sql/test_operators.py

diff --git a/doc/build/changelog/unreleased_14/7599.rst b/doc/build/changelog/unreleased_14/7599.rst
new file mode 100644 (file)
index 0000000..db69ace
--- /dev/null
@@ -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.
+
index 289dda4b6b150cfa5f8e4fe1a565b9c5b7374e69..29926ee3daed93f08d7f7c4c00e9fa15e524ab99 100644 (file)
@@ -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()"
index 87208d3f4cb14054797f3da5dea2e783dad3c625..fd6ddf59314d08d1b4aaa399026aa07df494de0e 100644 (file)
@@ -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
index f268b6fc32ebc2538b2032f823805fec0d40db24..2a00f1c140e2eb16b4ef219719b198c6eaa34534 100644 (file)
@@ -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]
index 7a62ad0083c66b251a0baefaaedc68decd138e2e..2ae6730bbe6697e73203b79a96d55d53e65a0fc0 100644 (file)
@@ -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
 
index 34b23d6757b8d39ac374e9c9aa9398f6dd21fe9b..1c20396024792289fbdbf75cfea46db7021265aa 100644 (file)
@@ -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
         )
 
 
index 7dcd5bb1dc6dbf3de0df8826678e3eb0a3803e48..df8dff30f80168a4ce29e4ccd6755b5acc1a1fdd 100644 (file)
@@ -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)
index fa04dee480837564a0c9b417dc011504d2e6df2d..9c286145b7a3a417ce817535ef511c7e913f387f 100644 (file)
@@ -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
             )
 
index 324b971b6596fe04a65ea899a8175e31d4d25849..0c897520254fb6492487d4ff83f5fdba111cea14 100644 (file)
@@ -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
         )
 
index 74b5b2df5a005c8cad12d7de53f0adc026aab2b4..cccf668210c1655b4fdc89b180d8cb33c06feacf 100644 (file)
@@ -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_(
index 4fb27654326b107bf2f963bfe728e47c453d9e9d..9651f6dbfd6b2d8c29a6ee372a2b64b22775eb23 100644 (file)
@@ -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)
index 8c638147590c73a1a3f8e5602cd6ea38e20f08ff..f19276126268d4d800b98ba5fd7c2ea298d49e62 100644 (file)
@@ -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()
index 3bad55d31217fb4a1d5ebda7c5642fb23e4668ca..97f0d560e4cd2026886c07e095d27bbc3f8da47b 100644 (file)
@@ -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:
index 5fc69bf9eeed67fbb40997572b2bb30d292b854c..67abc8971bfcda08ceacb7ad5ce4dde3ae330e8e 100644 (file)
@@ -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.",
index 3a174ffd9f85fe598b936bc5f629fedb6c404dbc..8e6ddf9d4e717af0ac742761dabc29eb28ec858e 100644 (file)
@@ -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())
index 6de346acedc73b38b5a43c17a0e46327b67fa872..51f37f02861d9e4ed7f92ad344bc9810c823aa05 100644 (file)
@@ -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):
index 5ea6131976fdd0bb2b0434974c82125df7653074..2eaafb95330e53afa0f6e10d454e838b2861c69d 100644 (file)
@@ -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 "
index 42b3bd1ea5bea023f8bb054ac241b1ef9fb9b007..8c82450da0efc6ebf637841d8b0bf8f1bcacba0d 100644 (file)
@@ -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
         )
 
index 37b4d0ae1f58f5f485fd61ef1b45ffee493cbdce..79b20e285a40a045a3fe1e3217a2b6b8ae863d61 100644 (file)
@@ -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])
 
index 8f5455850cc855fd5c690f5171eacc822e8b384d..3b10103001e719e5f8a5074707a5981d9f01404d 100644 (file)
@@ -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"<class '.*\.A'> will cause "
index ee6d53652dbb0e2ff2b92666ca3b29cfbd54d853..ed636ae422e2fc473eedbcdb04e4d3ce5c92f917 100644 (file)
@@ -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 = (
index fc7406b8164a331267c21f0d2ef732591dcb3349..de211cf63b8c77f3182f9716352362f3e6689bc8 100644 (file)
@@ -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,
index a53c90ed4e4428effa8a50481e40d89260dfe8eb..e7fdf661a68be86b3531557c98e8e2cea7cf29f6 100644 (file)
@@ -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.",
index ea292a43e40a8d8c75ecca9bba60bff5242eef24..f5da7aa8149c1f331920233e2195b6bc5dd5028e 100644 (file)
@@ -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,
index f91e7e8d5422b368c0b1109197eda8d3decad4f9..fd192ab51907f1e562cc5eb1ba7253909a99d78b 100644 (file)
@@ -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\)",
index 9b255bf5e6b152089e8cfa8455620c89f7346d19..f2d7d8569a4037b9125736ef1eef608b900ab6dc 100644 (file)
@@ -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,
index 1daf7b05384ca6bea225dd87bc9a5636a42dd224..0458d616edc245eb678d7841565a6a95d55e92c7 100644 (file)
@@ -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,
         )
index a53756d63a7608335fcf0d5c4e7e60ea14f5b026..d146612a5a159e10426a0cd9ff9d1939891c81c5 100644 (file)
@@ -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
         )
index c48fe458815f31993e0a54de38bb1529a3a434b3..6da0e90108ef6efbd6674c5bc104645426aa54dd 100644 (file)
@@ -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,
         )
index c93cc2edfc33502bbc4206a4568b8fc9fb79dda2..7f4c0465212b5e743f70daa4e39098eec0025a58 100644 (file)
@@ -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.",
index b5955e4a6bfda8353611c93f587cb8de09684571..9f23073d41269a0f0a6c28414b56c92492af6f03 100644 (file)
@@ -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 "
index 8a9c868be3009d462982ed5cbd6afd4aebad3bd9..e02f0e2ed52e7845f1b6c55c66441c2d8578899b 100644 (file)
@@ -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):
index e72ab6ac9230a45bc41a5b4abfac62d20d178bd0..e5176713aba5e79ccbe49483546b16220e7ceb6b 100644 (file)
@@ -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(