Skip to content

Commit c3dbd05

Browse files
authored
Merge pull request #379 from aadamson/warning-details-dumps-check
Check that we can serialize the warning detail attr
2 parents 76075f5 + b9423d8 commit c3dbd05

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

changelog/379.bugfix.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Warning attributes are checked to make sure they can be dumped prior to
2+
serializing the warning for submission to the master node.

testing/acceptance_test.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
22
import re
3+
import sys
34
import textwrap
45

56
import py
@@ -803,6 +804,39 @@ def test_func(tmpdir):
803804
result = testdir.runpytest(n)
804805
result.stdout.fnmatch_lines(["*UserWarning*foo.txt*", "*1 passed, 1 warnings*"])
805806

807+
@pytest.mark.parametrize("n", ["-n0", "-n1"])
808+
def test_unserializable_warning_details(self, testdir, n):
809+
"""Check that warnings with unserializable _WARNING_DETAILS are
810+
handled correctly (#379).
811+
"""
812+
if sys.version_info[0] < 3:
813+
# The issue is only present in Python 3 warnings
814+
return
815+
testdir.makepyfile(
816+
"""
817+
import warnings, pytest
818+
import socket
819+
import gc
820+
def abuse_socket():
821+
s = socket.socket()
822+
del s
823+
824+
# Deliberately provoke a ResourceWarning for an unclosed socket.
825+
# The socket itself will end up attached as a value in
826+
# _WARNING_DETAIL. We need to test that it is not serialized
827+
# (it can't be, so the test will fail if we try to).
828+
@pytest.mark.filterwarnings('always')
829+
def test_func(tmpdir):
830+
abuse_socket()
831+
gc.collect()
832+
"""
833+
)
834+
testdir.syspathinsert()
835+
result = testdir.runpytest(n)
836+
result.stdout.fnmatch_lines(
837+
["*ResourceWarning*unclosed*", "*1 passed, 1 warnings*"]
838+
)
839+
806840

807841
class TestNodeFailure:
808842
def test_load_single(self, testdir):

xdist/remote.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,15 @@ def serialize_warning_message(warning_message):
218218
for attr_name in warning_message._WARNING_DETAILS:
219219
if attr_name in ("message", "category"):
220220
continue
221-
result[attr_name] = getattr(warning_message, attr_name)
221+
attr = getattr(warning_message, attr_name)
222+
# Check if we can serialize the warning detail, marking `None` otherwise
223+
# Note that we need to define the attr (even as `None`) to allow deserializing
224+
try:
225+
dumps(attr)
226+
except DumpError:
227+
result[attr_name] = repr(attr)
228+
else:
229+
result[attr_name] = attr
222230
return result
223231

224232

0 commit comments

Comments
 (0)