Merge pull request #379 from aadamson/warning-details-dumps-check
Check that we can serialize the warning detail attr
This commit is contained in:
2
changelog/379.bugfix.rst
Normal file
2
changelog/379.bugfix.rst
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Warning attributes are checked to make sure they can be dumped prior to
|
||||||
|
serializing the warning for submission to the master node.
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
|
|
||||||
import py
|
import py
|
||||||
@@ -803,6 +804,39 @@ class TestWarnings:
|
|||||||
result = testdir.runpytest(n)
|
result = testdir.runpytest(n)
|
||||||
result.stdout.fnmatch_lines(["*UserWarning*foo.txt*", "*1 passed, 1 warnings*"])
|
result.stdout.fnmatch_lines(["*UserWarning*foo.txt*", "*1 passed, 1 warnings*"])
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("n", ["-n0", "-n1"])
|
||||||
|
def test_unserializable_warning_details(self, testdir, n):
|
||||||
|
"""Check that warnings with unserializable _WARNING_DETAILS are
|
||||||
|
handled correctly (#379).
|
||||||
|
"""
|
||||||
|
if sys.version_info[0] < 3:
|
||||||
|
# The issue is only present in Python 3 warnings
|
||||||
|
return
|
||||||
|
testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
import warnings, pytest
|
||||||
|
import socket
|
||||||
|
import gc
|
||||||
|
def abuse_socket():
|
||||||
|
s = socket.socket()
|
||||||
|
del s
|
||||||
|
|
||||||
|
# Deliberately provoke a ResourceWarning for an unclosed socket.
|
||||||
|
# The socket itself will end up attached as a value in
|
||||||
|
# _WARNING_DETAIL. We need to test that it is not serialized
|
||||||
|
# (it can't be, so the test will fail if we try to).
|
||||||
|
@pytest.mark.filterwarnings('always')
|
||||||
|
def test_func(tmpdir):
|
||||||
|
abuse_socket()
|
||||||
|
gc.collect()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
testdir.syspathinsert()
|
||||||
|
result = testdir.runpytest(n)
|
||||||
|
result.stdout.fnmatch_lines(
|
||||||
|
["*ResourceWarning*unclosed*", "*1 passed, 1 warnings*"]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class TestNodeFailure:
|
class TestNodeFailure:
|
||||||
def test_load_single(self, testdir):
|
def test_load_single(self, testdir):
|
||||||
|
|||||||
@@ -218,7 +218,15 @@ def serialize_warning_message(warning_message):
|
|||||||
for attr_name in warning_message._WARNING_DETAILS:
|
for attr_name in warning_message._WARNING_DETAILS:
|
||||||
if attr_name in ("message", "category"):
|
if attr_name in ("message", "category"):
|
||||||
continue
|
continue
|
||||||
result[attr_name] = getattr(warning_message, attr_name)
|
attr = getattr(warning_message, attr_name)
|
||||||
|
# Check if we can serialize the warning detail, marking `None` otherwise
|
||||||
|
# Note that we need to define the attr (even as `None`) to allow deserializing
|
||||||
|
try:
|
||||||
|
dumps(attr)
|
||||||
|
except DumpError:
|
||||||
|
result[attr_name] = repr(attr)
|
||||||
|
else:
|
||||||
|
result[attr_name] = attr
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user