Skip to content

Commit c12ea57

Browse files
fix pytest-dev#12: use a marker object for non-serializable objects
instead of str this creates a difference in logged data warning messages needed a change instead of toplevel values, only the sub-object is affected
1 parent d47e1ae commit c12ea57

File tree

3 files changed

+13
-21
lines changed

3 files changed

+13
-21
lines changed

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Next (tbd)
33

44
* `#16 <https://github.com/pytest-dev/pytest-reportlog/issues/15>`_: switch recommended file extension to `jsonl <https://jsonlines.org/>`__.
55
* `#17 <https://github.com/pytest-dev/pytest-reportlog/issues/17>`_: add compression support for ``.bz2``/``.gz``/``.xz`` log file extensions.
6+
* `#12 <https://github.com/pytest-dev/pytest-reportlog/issues/12>`_: handle unserializable objects with a pinpointed marker
67

78

89
0.3.0 (2023-04-26)

src/pytest_reportlog/plugin.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -63,11 +63,7 @@ def close(self):
6363
self._file = None
6464

6565
def _write_json_data(self, data):
66-
try:
67-
json_data = json.dumps(data)
68-
except TypeError:
69-
data = cleanup_unserializable(data)
70-
json_data = json.dumps(data)
66+
json_data = json.dumps(data, default=unserializable_to_marked_str)
7167
self._file.write(json_data + "\n")
7268
self._file.flush()
7369

@@ -92,7 +88,7 @@ def pytest_warning_recorded(self, warning_message, when, nodeid, location):
9288
),
9389
"filename": warning_message.filename,
9490
"lineno": warning_message.lineno,
95-
"message": warning_message.message,
91+
"message": str(warning_message.message),
9692
}
9793
extra_data = {
9894
"$report_type": "WarningMessage",
@@ -112,13 +108,6 @@ def pytest_terminal_summary(self, terminalreporter):
112108
terminalreporter.write_sep("-", f"generated report log file: {self._log_path}")
113109

114110

115-
def cleanup_unserializable(d: Dict[str, Any]) -> Dict[str, Any]:
116-
"""Return new dict with entries that are not json serializable by their str()."""
117-
result = {}
118-
for k, v in d.items():
119-
try:
120-
json.dumps({k: v})
121-
except TypeError:
122-
v = str(v)
123-
result[k] = v
124-
return result
111+
def unserializable_to_marked_str(obj: object) -> Dict[str, str]:
112+
"""for a object that json can not serialize. return {"$no-json": str(obj)}"""
113+
return { "$no-json": str(obj)}

tests/test_reportlog.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from pathlib import Path
77
from _pytest.reports import BaseReport
88

9-
from pytest_reportlog.plugin import cleanup_unserializable, _open_filtered_writer
9+
from pytest_reportlog.plugin import _open_filtered_writer, unserializable_to_marked_str
1010

1111
from typing_extensions import Protocol, Literal
1212

@@ -133,16 +133,18 @@ def test_warning():
133133
}
134134

135135

136-
def test_cleanup_unserializable():
136+
def test_unserializable_to_marked():
137137
"""Unittest for the cleanup_unserializable function"""
138+
139+
138140
good = {"x": 1, "y": ["a", "b"]}
139-
new = cleanup_unserializable(good)
141+
new = json.loads(json.dumps(good, default=unserializable_to_marked_str))
140142
assert new == good
141143

142144
class C:
143145
def __str__(self):
144146
return "C instance"
145147

146148
bad = {"x": 1, "y": ["a", "b"], "c": C()}
147-
new = cleanup_unserializable(bad)
148-
assert new == {"x": 1, "c": "C instance", "y": ["a", "b"]}
149+
new_bad = json.loads(json.dumps(bad, default=unserializable_to_marked_str))
150+
assert new_bad == {**bad, "c": {"$no-json": "C instance"}}

0 commit comments

Comments
 (0)