From 82785fcd4025c6827f504ce082d99116bff54e11 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Sat, 18 Feb 2017 12:57:26 -0200 Subject: [PATCH] Use warnings.catch_warnings instead of WarningsRecorder This has the benefical side-effect of not calling the original warnings.showwarnings function, which in its original form only writes the formatted warning to sys.stdout. Calling the original warnings.showwarnings has the effect that nested WarningsRecorder all catch the warnings: with WarningsRecorder() as rec1: with WarningsRecorder() as rec2: warnings.warn(UserWarning, 'some warning') (both rec1 and rec2 sees the warning) When running tests with `testdir`, the main pytest session would then see the warnings created by the internal code being tested (if any), and the main pytest session would end up with warnings as well. --- _pytest/warnings.py | 28 +++++----------------------- testing/test_warnings.py | 6 +++--- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/_pytest/warnings.py b/_pytest/warnings.py index 84f64ea92..d654901d0 100644 --- a/_pytest/warnings.py +++ b/_pytest/warnings.py @@ -1,5 +1,3 @@ -from _pytest.recwarn import RecordedWarning, WarningsRecorder -import inspect import os import pytest import warnings @@ -42,35 +40,19 @@ def pytest_addoption(parser): @pytest.hookimpl(hookwrapper=True) def pytest_runtest_call(item): - wrec = WarningsRecorder() - - def showwarning(message, category, filename, lineno, file=None, line=None): - frame = inspect.currentframe() - if '/_pytest/recwarn' in frame.f_back.f_code.co_filename: - # we are in test recorder, so this warning is already handled - return - wrec._list.append(RecordedWarning( - message, category, filename, lineno, file, line)) - # still perform old showwarning functionality - wrec._showwarning( - message, category, filename, lineno, file=file, line=line) - args = item.config.getoption('pythonwarnings') or [] inifilters = item.config.getini("filterwarnings") - with wrec: - _showwarning = wrec._showwarning - warnings.showwarning = showwarning - wrec._module.simplefilter('once') + with warnings.catch_warnings(record=True) as log: + warnings.simplefilter('once') for arg in args: - wrec._module._setoption(arg) + warnings._setoption(arg) for arg in inifilters: - _setoption(wrec._module, arg) + _setoption(warnings, arg) yield - wrec._showwarning = _showwarning - for warning in wrec.list: + for warning in log: msg = warnings.formatwarning( warning.message, warning.category, os.path.relpath(warning.filename), warning.lineno, warning.line) diff --git a/testing/test_warnings.py b/testing/test_warnings.py index 34badaee8..738ef347b 100644 --- a/testing/test_warnings.py +++ b/testing/test_warnings.py @@ -12,7 +12,7 @@ def pyfile_with_warnings(testdir): def test_normal_flow(testdir, pyfile_with_warnings): - result = testdir.runpytest_subprocess() + result = testdir.runpytest() result.stdout.fnmatch_lines([ '*== pytest-warning summary ==*', @@ -35,7 +35,7 @@ def test_as_errors(testdir, pyfile_with_warnings, method): [pytest] filterwarnings= error ''') - result = testdir.runpytest_subprocess(*args) + result = testdir.runpytest(*args) result.stdout.fnmatch_lines([ 'E PendingDeprecationWarning: functionality is pending deprecation', 'test_as_errors.py:3: PendingDeprecationWarning', @@ -52,7 +52,7 @@ def test_ignore(testdir, pyfile_with_warnings, method): filterwarnings= ignore ''') - result = testdir.runpytest_subprocess(*args) + result = testdir.runpytest(*args) result.stdout.fnmatch_lines([ '* 1 passed in *', ])