Skip to content

Commit 5482dfe

Browse files
authored
Merge pull request #2303 from nicoddemus/recwarn-refactor
Refactor recwarn to use warnings.catch_warnings instead of custom code
2 parents 55b891d + 3c07072 commit 5482dfe

File tree

2 files changed

+11
-47
lines changed

2 files changed

+11
-47
lines changed

_pytest/recwarn.py

Lines changed: 9 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
import sys
77
import warnings
88
import pytest
9-
from collections import namedtuple
109

1110

1211
@pytest.yield_fixture
13-
def recwarn(request):
12+
def recwarn():
1413
"""Return a WarningsRecorder instance that provides these methods:
1514
1615
* ``pop(category=None)``: return last warning matching the category.
@@ -115,19 +114,14 @@ def warns(expected_warning, *args, **kwargs):
115114
return func(*args[1:], **kwargs)
116115

117116

118-
RecordedWarning = namedtuple('RecordedWarning', (
119-
'message', 'category', 'filename', 'lineno', 'file', 'line',
120-
))
121-
122-
123-
class WarningsRecorder(object):
117+
class WarningsRecorder(warnings.catch_warnings):
124118
"""A context manager to record raised warnings.
125119
126120
Adapted from `warnings.catch_warnings`.
127121
"""
128122

129-
def __init__(self, module=None):
130-
self._module = sys.modules['warnings'] if module is None else module
123+
def __init__(self):
124+
super(WarningsRecorder, self).__init__(record=True)
131125
self._entered = False
132126
self._list = []
133127

@@ -164,38 +158,20 @@ def __enter__(self):
164158
if self._entered:
165159
__tracebackhide__ = True
166160
raise RuntimeError("Cannot enter %r twice" % self)
167-
self._entered = True
168-
self._filters = self._module.filters
169-
self._module.filters = self._filters[:]
170-
self._showwarning = self._module.showwarning
171-
172-
def showwarning(message, category, filename, lineno,
173-
file=None, line=None):
174-
self._list.append(RecordedWarning(
175-
message, category, filename, lineno, file, line))
176-
177-
# still perform old showwarning functionality
178-
self._showwarning(
179-
message, category, filename, lineno, file=file, line=line)
180-
181-
self._module.showwarning = showwarning
182-
183-
# allow the same warning to be raised more than once
184-
185-
self._module.simplefilter('always')
161+
self._list = super(WarningsRecorder, self).__enter__()
162+
warnings.simplefilter('always')
186163
return self
187164

188165
def __exit__(self, *exc_info):
189166
if not self._entered:
190167
__tracebackhide__ = True
191168
raise RuntimeError("Cannot exit %r without entering first" % self)
192-
self._module.filters = self._filters
193-
self._module.showwarning = self._showwarning
169+
super(WarningsRecorder, self).__exit__(*exc_info)
194170

195171

196172
class WarningsChecker(WarningsRecorder):
197-
def __init__(self, expected_warning=None, module=None):
198-
super(WarningsChecker, self).__init__(module=module)
173+
def __init__(self, expected_warning=None):
174+
super(WarningsChecker, self).__init__()
199175

200176
msg = ("exceptions must be old-style classes or "
201177
"derived from Warning, not %s")

testing/test_recwarn.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,19 @@
88
def test_recwarn_functional(testdir):
99
reprec = testdir.inline_runsource("""
1010
import warnings
11-
oldwarn = warnings.showwarning
1211
def test_method(recwarn):
13-
assert warnings.showwarning != oldwarn
1412
warnings.warn("hello")
1513
warn = recwarn.pop()
1614
assert isinstance(warn.message, UserWarning)
17-
def test_finalized():
18-
assert warnings.showwarning == oldwarn
1915
""")
2016
res = reprec.countoutcomes()
21-
assert tuple(res) == (2, 0, 0), res
17+
assert tuple(res) == (1, 0, 0), res
2218

2319

2420
class TestWarningsRecorderChecker(object):
25-
def test_recording(self, recwarn):
26-
showwarning = py.std.warnings.showwarning
21+
def test_recording(self):
2722
rec = WarningsRecorder()
2823
with rec:
29-
assert py.std.warnings.showwarning != showwarning
3024
assert not rec.list
3125
py.std.warnings.warn_explicit("hello", UserWarning, "xyz", 13)
3226
assert len(rec.list) == 1
@@ -40,8 +34,6 @@ def test_recording(self, recwarn):
4034
assert l is rec.list
4135
pytest.raises(AssertionError, "rec.pop()")
4236

43-
assert showwarning == py.std.warnings.showwarning
44-
4537
def test_typechecking(self):
4638
from _pytest.recwarn import WarningsChecker
4739
with pytest.raises(TypeError):
@@ -217,17 +209,13 @@ def test_as_contextmanager(self):
217209
excinfo.match(re.escape(message_template.format(warning_classes,
218210
[each.message for each in warninfo])))
219211

220-
221212
def test_record(self):
222213
with pytest.warns(UserWarning) as record:
223214
warnings.warn("user", UserWarning)
224215

225216
assert len(record) == 1
226217
assert str(record[0].message) == "user"
227218

228-
print(repr(record[0]))
229-
assert str(record[0].message) in repr(record[0])
230-
231219
def test_record_only(self):
232220
with pytest.warns(None) as record:
233221
warnings.warn("user", UserWarning)

0 commit comments

Comments
 (0)