diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-01-21 18:46:37 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2022-01-22 19:18:37 -0500 |
commit | 4a99fc26ab5f95ef605d975b7c8d003dc28c205b (patch) | |
tree | 3e8747ee46e4c42a99568a0ee54928343df92767 /lib/sqlalchemy/testing/assertions.py | |
parent | 328041d21d9f96db12caac79bbf7251a0dbd01e1 (diff) | |
download | sqlalchemy-4a99fc26ab5f95ef605d975b7c8d003dc28c205b.tar.gz |
dont use exception catches for warnings; modernize xdist detection
Improvements to the test suite's integration with pytest such that the
"warnings" plugin, if manually enabled, will not interfere with the test
suite, such that third parties can enable the warnings plugin or make use
of the ``-W`` parameter and SQLAlchemy's test suite will continue to pass.
Additionally, modernized the detection of the "pytest-xdist" plugin so that
plugins can be globally disabled using PYTEST_DISABLE_PLUGIN_AUTOLOAD=1
without breaking the test suite if xdist were still installed. Warning
filters that promote deprecation warnings to errors are now localized to
SQLAlchemy-specific warnings, or within SQLAlchemy-specific sources for
general Python deprecation warnings, so that non-SQLAlchemy deprecation
warnings emitted from pytest plugins should also not impact the test suite.
Identified a bit of cleanup for the PostgreSQL provisioning
as a result.
Fixes: #7599
Change-Id: Ibcf09af25228d39ee5a943fda82d8a9302433726
(cherry picked from commit a0f1914b903de6c130ab1c3267138b8ad208e144)
Diffstat (limited to 'lib/sqlalchemy/testing/assertions.py')
-rw-r--r-- | lib/sqlalchemy/testing/assertions.py | 59 |
1 files changed, 54 insertions, 5 deletions
diff --git a/lib/sqlalchemy/testing/assertions.py b/lib/sqlalchemy/testing/assertions.py index 02e688022..aa8edd9af 100644 --- a/lib/sqlalchemy/testing/assertions.py +++ b/lib/sqlalchemy/testing/assertions.py @@ -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] |