1
changelog/349.bugfix.rst
Normal file
1
changelog/349.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Correctly handle warnings created with arguments that can't be serialized during the transfer from workers to master node.
|
||||||
@@ -766,6 +766,23 @@ class TestWarnings:
|
|||||||
result = testdir.runpytest(n)
|
result = testdir.runpytest(n)
|
||||||
result.stdout.fnmatch_lines(["*MyWarning*", "*1 passed, 1 warnings*"])
|
result.stdout.fnmatch_lines(["*MyWarning*", "*1 passed, 1 warnings*"])
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("n", ["-n0", "-n1"])
|
||||||
|
def test_unserializable_arguments(self, testdir, n):
|
||||||
|
"""Check that warnings with unserializable arguments are handled correctly (#349)."""
|
||||||
|
testdir.makepyfile(
|
||||||
|
"""
|
||||||
|
import warnings, pytest
|
||||||
|
|
||||||
|
def test_func(tmpdir):
|
||||||
|
fn = (tmpdir / 'foo.txt').ensure(file=1)
|
||||||
|
with fn.open('r') as f:
|
||||||
|
warnings.warn(UserWarning("foo", f))
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
testdir.syspathinsert()
|
||||||
|
result = testdir.runpytest(n)
|
||||||
|
result.stdout.fnmatch_lines(["*UserWarning*foo.txt*", "*1 passed, 1 warnings*"])
|
||||||
|
|
||||||
|
|
||||||
class TestNodeFailure:
|
class TestNodeFailure:
|
||||||
def test_load_single(self, testdir):
|
def test_load_single(self, testdir):
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import time
|
|||||||
|
|
||||||
import _pytest.hookspec
|
import _pytest.hookspec
|
||||||
import pytest
|
import pytest
|
||||||
|
from execnet.gateway_base import dumps, DumpError
|
||||||
|
|
||||||
|
|
||||||
class WorkerInteractor(object):
|
class WorkerInteractor(object):
|
||||||
@@ -181,8 +182,15 @@ def serialize_warning_message(warning_message):
|
|||||||
if isinstance(warning_message.message, Warning):
|
if isinstance(warning_message.message, Warning):
|
||||||
message_module = type(warning_message.message).__module__
|
message_module = type(warning_message.message).__module__
|
||||||
message_class_name = type(warning_message.message).__name__
|
message_class_name = type(warning_message.message).__name__
|
||||||
message_args = warning_message.message.args
|
|
||||||
message_str = str(warning_message.message)
|
message_str = str(warning_message.message)
|
||||||
|
# check now if we can serialize the warning arguments (#349)
|
||||||
|
# if not, we will just use the exception message on the master node
|
||||||
|
try:
|
||||||
|
dumps(warning_message.message.args)
|
||||||
|
except DumpError:
|
||||||
|
message_args = None
|
||||||
|
else:
|
||||||
|
message_args = warning_message.message.args
|
||||||
else:
|
else:
|
||||||
message_str = warning_message.message
|
message_str = warning_message.message
|
||||||
message_module = None
|
message_module = None
|
||||||
|
|||||||
@@ -426,9 +426,16 @@ def unserialize_warning_message(data):
|
|||||||
if data["message_module"]:
|
if data["message_module"]:
|
||||||
mod = importlib.import_module(data["message_module"])
|
mod = importlib.import_module(data["message_module"])
|
||||||
cls = getattr(mod, data["message_class_name"])
|
cls = getattr(mod, data["message_class_name"])
|
||||||
try:
|
message = None
|
||||||
message = cls(*data["message_args"])
|
if data["message_args"] is not None:
|
||||||
except TypeError:
|
try:
|
||||||
|
message = cls(*data["message_args"])
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
if message is None:
|
||||||
|
# could not recreate the original warning instance;
|
||||||
|
# create a generic Warning instance with the original
|
||||||
|
# message at least
|
||||||
message_text = "{mod}.{cls}: {msg}".format(
|
message_text = "{mod}.{cls}: {msg}".format(
|
||||||
mod=data["message_module"],
|
mod=data["message_module"],
|
||||||
cls=data["message_class_name"],
|
cls=data["message_class_name"],
|
||||||
|
|||||||
Reference in New Issue
Block a user