]> 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:18:37 +0000 (19:18 -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.

Identified a bit of cleanup for the PostgreSQL provisioning
as a result.

Fixes: #7599
Change-Id: Ibcf09af25228d39ee5a943fda82d8a9302433726
(cherry picked from commit a0f1914b903de6c130ab1c3267138b8ad208e144)

35 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_defaults.py
test/sql/test_metadata.py
test/sql/test_operators.py
test/sql/test_types.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 68a01e483c2f72df9650baf0e295757d4b10bbaa..98470f36eb97a29f6d0ad50bdd9c5b8f821b0c86 100644 (file)
@@ -19,10 +19,7 @@ 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 30babae83def3ef8b656bb75550b22a10d1f767d..80d344faf1eff483b2e8f48c384587eba58cc10c 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 02e688022829e5b29569e8a9ba3df32959f5f61e..aa8edd9affbc3b8b17e195eca5c48421b9b95f65 100644 (file)
@@ -143,14 +143,16 @@ def _expect_warnings(
     exc_cls,
     messages,
     regex=True,
+    search_msg=False,
     assert_=True,
     py2konly=False,
     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)
@@ -188,19 +190,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), mock.patch(
             "sqlalchemy.util.SQLALCHEMY_WARN_20", True
@@ -357,6 +363,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
 ):
@@ -378,6 +418,15 @@ class _ErrorContainer(object):
 
 @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 41e683070636df90810858355af83c4b45b7f6f2..5a51582925da864adfa66c83da068280cba94343 100644 (file)
@@ -14,16 +14,10 @@ import operator
 import os
 import re
 import sys
+import uuid
 
 import pytest
 
-try:
-    import xdist  # noqa
-
-    has_xdist = True
-except ImportError:
-    has_xdist = False
-
 
 py2k = sys.version_info < (3, 0)
 if py2k:
@@ -84,6 +78,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"])
@@ -157,10 +154,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(object):
+    def pytest_configure_node(self, node):
         from sqlalchemy.testing import provision
         from sqlalchemy.testing import asyncio
 
@@ -175,7 +170,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 db780f4003036889cff3a1da3db31444b4ed8c1c..3e783872d6255d95e8b2b85c129e55c315137b0b 100644 (file)
@@ -14,8 +14,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):
@@ -25,28 +30,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
     )
 
     # ignore things that are deprecated *as of* 2.0 :)
@@ -67,7 +65,7 @@ def setup_filters():
         pass
     else:
         warnings.filterwarnings(
-            "once", category=pytest.PytestDeprecationWarning
+            "once", category=pytest.PytestDeprecationWarning, module=origin
         )
 
 
index acf7d75d549785c4b3085948519ccf05263c2ac4..b287e1024de02c210c828c5edd7650fcfcfb96ea 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 5ee11ccd8c93f2878bccb447f99ffbdca2f21f39..3502c745b268deb533839cf1c0f1522b9fa08864 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 43ec9cc3ffaccfafbb5e607f5c44d85fc11e9235..320a9bb585409334da29886a77d7997b5f575568 100644 (file)
@@ -14,7 +14,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
@@ -1821,7 +1821,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 51da845b397456a47f0ea8424ded31381e7c9a3d..9579d6c2dc9d3b90c7f70005e8921a246ff6f945 100644 (file)
@@ -15,6 +15,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
@@ -967,6 +968,7 @@ class CursorErrTest(fixtures.TestBase):
                 util.warn("Exception attempting to detect")
 
         eng.dialect._get_default_schema_name = get_default_schema_name
+        eng.dialect._check_unicode_description = mock.Mock()
         return eng
 
     def test_cursor_explode(self):
@@ -982,11 +984,13 @@ 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
         )
+        # there's legacy py2k stuff happening here making this
+        # less smooth and probably buggy
         eq_(
-            db.pool.logger.error.mock_calls,
+            db.pool.logger.error.mock_calls[0:1],
             [call("Error closing cursor", exc_info=True)],
         )
 
index a405b9f2c6a93c7e7d2c21743e3ce60c234fe633..2ab787aa676f7a0ba50cf88255c6aff38c732109 100644 (file)
@@ -406,7 +406,13 @@ class DeclarativeTest(DeclarativeTestBase):
                 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"
 
@@ -414,15 +420,14 @@ class DeclarativeTest(DeclarativeTestBase):
                 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"
 
@@ -431,13 +436,6 @@ class DeclarativeTest(DeclarativeTestBase):
                 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"
@@ -2200,15 +2198,14 @@ class DeclarativeTest(DeclarativeTestBase):
             __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 b9d41ee5325b279f7695380e554151a10c962ed5..b77a101e8e1d55be309b043ea7a41da752c068da 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 f3feb5ddf23ac637ba11f983017adf74b5e1bd3a..5a4673a23eda92e0e3cc33516b0e9fc4009fc409 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(object):
index 446a9d9bd929ae08355070dfde0f6ab8808e4585..600726ce38e0f8a12265746bb49d7a5fa9995ea9 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 "
@@ -2143,7 +2144,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 mapped class Employee->employees, "
             "primary key column 'persons.id' is being "
@@ -2441,7 +2442,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'",
@@ -3093,7 +3094,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 130e9807839809e049ae40e14e37db0e01259d3d..70dc0a1295d18ff2263334626f7fa8d8552690d4 100644 (file)
@@ -17,6 +17,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.mock import call
 from sqlalchemy.testing.mock import Mock
 from sqlalchemy.testing.util import all_partial_orderings
@@ -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 cd7e7c111a38ccb6397173e6b06c259a504e3237..c5dd946e75ecc5893b3ec03eb54f16b18467481f 100644 (file)
@@ -24,6 +24,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_
@@ -94,7 +95,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,
@@ -1221,7 +1222,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
@@ -1239,7 +1240,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
@@ -1265,7 +1266,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
@@ -1301,7 +1302,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
@@ -1350,7 +1351,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
@@ -1367,7 +1368,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
@@ -1393,7 +1394,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
@@ -1420,7 +1421,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
             )
 
@@ -1440,7 +1441,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
             )
 
@@ -1544,7 +1545,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
@@ -1562,7 +1563,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
@@ -1588,7 +1589,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
@@ -1624,7 +1625,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
@@ -2808,7 +2809,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
 
@@ -2871,7 +2872,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 8efd4523820eef6d491ded63952107c7c6f75d7c..2a8e3e2dc40d520566b0701269ab5b7d1d32b590 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 d9da36073c07429837f542ab8da8145a3df1a5e6..879cc2b81727483c036f2bdbc2bbd95eb50c373b 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 4dfea6a6de8c9e688dbfcd75e72dca2e7b511209..c0fbaba7d6f73b6f04efe6a14622a361f7e7d2da 100644 (file)
@@ -32,8 +32,10 @@ from sqlalchemy.orm import UserDefinedOption
 from sqlalchemy.sql.traversals 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
@@ -1061,7 +1063,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\(\) function or Mapper class as "
@@ -1072,7 +1074,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\(\) function or Mapper class as "
@@ -2199,7 +2201,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,
@@ -2251,7 +2258,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 a2d4aa9cac23c31f24262e796274aeb477bdd9bd..73aefe1f05a4f6c0761650873a91019016ebffed 100644 (file)
@@ -10,7 +10,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_
@@ -525,7 +525,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 3ebff5f43bc637fe94da99dca90b7337fb784eb7..ee578ff50d1db033b0fc27ff4468559ce60e8549 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 11a762e60b1be69803b4c9f27e377b27fdc104f0..fa837c678f71947d3fa61f207d068518545502c3 100644 (file)
@@ -33,6 +33,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_deprecated_20
@@ -832,7 +833,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 "
@@ -1015,7 +1016,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 a1dbb2f617bfe91fd110515ab7e1ef88821140d0..6d9aee584af41d0214b1587de4203e65379ab1ae 100644 (file)
@@ -72,6 +72,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 6f6b0d56dfefc843038b3f8be96e015cd6bfc9a9..4d8eb88b91cd0fc7a735076848cecf259c3f9095 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(object):
@@ -573,7 +575,7 @@ class _JoinFixtures(object):
         )
 
     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 98de9abad7378e95a029561792cc2c437ad1a73e..acb22ce0f8dbeb5febe1a9a12cf47fbc88bc54d1 100644 (file)
@@ -33,12 +33,13 @@ 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_warnings
 from sqlalchemy.testing import fixtures
 from sqlalchemy.testing import in_
 from sqlalchemy.testing import is_
-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
@@ -872,7 +873,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 "
@@ -963,7 +964,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\): "
@@ -983,7 +984,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",
@@ -994,7 +995,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",
@@ -1005,7 +1006,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",
@@ -1017,7 +1018,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",
@@ -1301,7 +1302,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 e23f42ac53ee980e1a99c6522c9f19f0a61a923c..b2389ced3086c757c0d2b1a2dbe427732025126b 100644 (file)
@@ -9,6 +9,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_
@@ -101,7 +102,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 7a5bb0e7edbc9921ccb659bcfcac9c02643810bb..3e44abe88f5b252eecdcb8f6236ba4c946c8905d 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 62974b62919aaed52d1409fa4d1980480ee6eaef..607c0a9edcd4e999f17e418ef4eafa412f189abf 100644 (file)
@@ -24,6 +24,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
@@ -1032,7 +1033,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",
@@ -2275,7 +2276,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):
@@ -2306,7 +2308,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
@@ -2317,6 +2322,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 bf14d7212a497cba6fa693eb96bdb7dcfe68f3d7..7b0b4dc9dc429ef38d5eb9399a179c19f5bfe214 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 af38a4bab00a0b9896c279a36d4407ad0cc8955e..4546145396ac2a260f91296e78941d1c98ce7ad1 100644 (file)
@@ -25,6 +25,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_
@@ -1919,7 +1920,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.",
@@ -1939,7 +1940,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.",
@@ -2004,7 +2005,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 45fad9ab7414d681c5737e0f3aef7fc7c119ff2f..ce01cace7f921bc832d2d292502ef8e8fcbc181f 100644 (file)
@@ -20,6 +20,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 ef924e06819282b546b7c8bbb39165c8adbfe862..d967db6aaf926f311223b402a2fd370a65ca4302 100644 (file)
@@ -19,6 +19,7 @@ from sqlalchemy.sql import literal_column
 from sqlalchemy.sql import select
 from sqlalchemy.sql import text
 from sqlalchemy.testing import assert_raises_message
+from sqlalchemy.testing import assert_warns_message
 from sqlalchemy.testing import AssertsCompiledSQL
 from sqlalchemy.testing import engines
 from sqlalchemy.testing import eq_
@@ -1447,7 +1448,7 @@ class UnicodeDefaultsTest(fixtures.TestBase):
 
     def test_nonunicode_default(self):
         default = b("foo")
-        assert_raises_message(
+        assert_warns_message(
             sa.exc.SAWarning,
             "Unicode column 'foobar' has non-unicode "
             "default value b?'foo' specified.",
index bd921364795c54cb7cd7b896b0844a01520f2e46..e193c5ec7af79d933053a21774f4edbe14e0dede 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):
@@ -1824,32 +1825,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 c04078f7372f5ad9bf6a122a422e185991a21e62..4eff872f4f3be11b59e382923da5c60f6b2cbfbf 100644 (file)
@@ -59,6 +59,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
@@ -1220,15 +1221,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(
index 14b1ca1051ba2644a4974e83723b2c47bff704a1..935c2354dd0acdce14a8029e10ff9f012a3cef4d 100644 (file)
@@ -75,6 +75,7 @@ from sqlalchemy.sql import visitors
 from sqlalchemy.sql.sqltypes import TypeEngine
 from sqlalchemy.testing import assert_raises
 from sqlalchemy.testing import assert_raises_message
+from sqlalchemy.testing import assert_warns
 from sqlalchemy.testing import AssertsCompiledSQL
 from sqlalchemy.testing import AssertsExecutionResults
 from sqlalchemy.testing import engines
@@ -1703,10 +1704,10 @@ class UnicodeTest(fixtures.TestBase):
         dialect.supports_unicode_binds = True
         uni = u.dialect_impl(dialect).bind_processor(dialect)
         if util.py3k:
-            assert_raises(exc.SAWarning, uni, b"x")
+            assert_warns(exc.SAWarning, uni, b"x")
             assert isinstance(uni(unicodedata), str)
         else:
-            assert_raises(exc.SAWarning, uni, "x")
+            assert_warns(exc.SAWarning, uni, "x")
             assert isinstance(uni(unicodedata), unicode)  # noqa
 
     def test_unicode_warnings_typelevel_sqla_unicode(self):
@@ -1715,7 +1716,7 @@ class UnicodeTest(fixtures.TestBase):
         dialect = default.DefaultDialect()
         dialect.supports_unicode_binds = False
         uni = u.dialect_impl(dialect).bind_processor(dialect)
-        assert_raises(exc.SAWarning, uni, util.b("x"))
+        assert_warns(exc.SAWarning, uni, util.b("x"))
         assert isinstance(uni(unicodedata), util.binary_type)
 
         eq_(uni(unicodedata), unicodedata.encode("utf-8"))