diff --git a/changelog/4013.feature.rst b/changelog/4013.feature.rst new file mode 100644 index 000000000..84c3ab79d --- /dev/null +++ b/changelog/4013.feature.rst @@ -0,0 +1,2 @@ +Deprecation warnings are now shown even if you customize the warnings filters yourself. In the previous version +any customization would override pytest's filters and deprecation warnings would fall back to being hidden by default. diff --git a/doc/en/warnings.rst b/doc/en/warnings.rst index 1f0c3bf97..07aec9855 100644 --- a/doc/en/warnings.rst +++ b/doc/en/warnings.rst @@ -101,22 +101,28 @@ DeprecationWarning and PendingDeprecationWarning ------------------------------------------------ .. versionadded:: 3.8 +.. versionchanged:: 3.9 -By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` if no other warning filters -are configured. +By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning``. -To disable showing ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings, you might define any warnings -filter either in the command-line or in the ini file, or you can use: +Sometimes it is useful to hide some specific deprecation warnings that happen in code that you have no control over +(such as third-party libraries), in which case you might use the standard warning filters options (ini or marks). +For example: .. code-block:: ini [pytest] filterwarnings = - ignore::DeprecationWarning - ignore::PendingDeprecationWarning + ignore:.*U.*mode is deprecated:DeprecationWarning + .. note:: - This makes pytest more compliant with `PEP-0506 `_ which suggests that those warnings should + If warnings are configured at the interpreter level, using + the `PYTHONWARNINGS `_ environment variable or the + ``-W`` command-line option, pytest will not configure any filters by default. + +.. note:: + This feature makes pytest more compliant with `PEP-0506 `_ which suggests that those warnings should be shown by default by test runners, but pytest doesn't follow ``PEP-0506`` completely because resetting all warning filters like suggested in the PEP will break existing test suites that configure warning filters themselves by calling ``warnings.simplefilter`` (see issue `#2430 `_ diff --git a/src/_pytest/warnings.py b/src/_pytest/warnings.py index fb303a20f..5574eee8e 100644 --- a/src/_pytest/warnings.py +++ b/src/_pytest/warnings.py @@ -70,7 +70,11 @@ def catch_warnings_for_item(config, ihook, when, item): cmdline_filters = config.getoption("pythonwarnings") or [] inifilters = config.getini("filterwarnings") with warnings.catch_warnings(record=True) as log: - filters_configured = bool(cmdline_filters or inifilters or sys.warnoptions) + + if not sys.warnoptions: + # if user is not explicitly configuring warning filters, show deprecation warnings by default (#2908) + warnings.filterwarnings("always", category=DeprecationWarning) + warnings.filterwarnings("always", category=PendingDeprecationWarning) # filters should have this precedence: mark, cmdline options, ini # filters should be applied in the inverse order of precedence @@ -84,12 +88,6 @@ def catch_warnings_for_item(config, ihook, when, item): for mark in item.iter_markers(name="filterwarnings"): for arg in mark.args: _setoption(warnings, arg) - filters_configured = True - - if not filters_configured: - # if user is not explicitly configuring warning filters, show deprecation warnings by default (#2908) - warnings.filterwarnings("always", category=DeprecationWarning) - warnings.filterwarnings("always", category=PendingDeprecationWarning) yield diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 975605b5e..7825f2167 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -495,8 +495,18 @@ class TestDeprecationWarningsByDefault: ) ) - def test_shown_by_default(self, testdir): + @pytest.mark.parametrize("customize_filters", [True, False]) + def test_shown_by_default(self, testdir, customize_filters): + """Show deprecation warnings by default, even if user has customized the warnings filters (#4013).""" self.create_file(testdir) + if customize_filters: + testdir.makeini( + """ + [pytest] + filterwarnings = + once::UserWarning + """ + ) result = testdir.runpytest_subprocess() result.stdout.fnmatch_lines( [ @@ -512,7 +522,9 @@ class TestDeprecationWarningsByDefault: testdir.makeini( """ [pytest] - filterwarnings = once::UserWarning + filterwarnings = + ignore::DeprecationWarning + ignore::PendingDeprecationWarning """ ) result = testdir.runpytest_subprocess() @@ -523,7 +535,8 @@ class TestDeprecationWarningsByDefault: be displayed normally. """ self.create_file( - testdir, mark='@pytest.mark.filterwarnings("once::UserWarning")' + testdir, + mark='@pytest.mark.filterwarnings("ignore::PendingDeprecationWarning")', ) result = testdir.runpytest_subprocess() result.stdout.fnmatch_lines( @@ -536,7 +549,12 @@ class TestDeprecationWarningsByDefault: def test_hidden_by_cmdline(self, testdir): self.create_file(testdir) - result = testdir.runpytest_subprocess("-W", "once::UserWarning") + result = testdir.runpytest_subprocess( + "-W", + "ignore::DeprecationWarning", + "-W", + "ignore::PendingDeprecationWarning", + ) assert WARNINGS_SUMMARY_HEADER not in result.stdout.str() def test_hidden_by_system(self, testdir, monkeypatch):