Skip to content

Commit

Permalink
fix pytest-dev#12: use a marker object for non-serializable objects
Browse files Browse the repository at this point in the history
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
  • Loading branch information
RonnyPfannschmidt committed May 2, 2023
1 parent e771184 commit c1b926c
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 22 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ next (tbd)

* `#16 <https://github.com/pytest-dev/pytest-reportlog/issues/16>`_: switch recommended file extension to jsonl
* `#17 <https://github.com/pytest-dev/pytest-reportlog/issues/17>`_: add compression support for .bz2/.gz/.xz log file extensions

* `#12 <https://github.com/pytest-dev/pytest-reportlog/issues/12>`_: handle unserializable objects with a pinpointed marker

0.3.0 (2023-04-26)
------------------
Expand Down
21 changes: 5 additions & 16 deletions src/pytest_reportlog/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,7 @@ def close(self):
self._file = None

def _write_json_data(self, data):
try:
json_data = json.dumps(data)
except TypeError:
data = cleanup_unserializable(data)
json_data = json.dumps(data)
json_data = json.dumps(data, default=unserializable_to_marked_str)
self._file.write(json_data + "\n")
self._file.flush()

Expand All @@ -92,7 +88,7 @@ def pytest_warning_recorded(self, warning_message, when, nodeid, location):
),
"filename": warning_message.filename,
"lineno": warning_message.lineno,
"message": warning_message.message,
"message": str(warning_message.message),
}
extra_data = {
"$report_type": "WarningMessage",
Expand All @@ -112,13 +108,6 @@ def pytest_terminal_summary(self, terminalreporter):
terminalreporter.write_sep("-", f"generated report log file: {self._log_path}")


def cleanup_unserializable(d: Dict[str, Any]) -> Dict[str, Any]:
"""Return new dict with entries that are not json serializable by their str()."""
result = {}
for k, v in d.items():
try:
json.dumps({k: v})
except TypeError:
v = str(v)
result[k] = v
return result
def unserializable_to_marked_str(obj: object) -> Dict[str, str]:
"""for a object that json can not serialize. return {"$no-json": str(obj)}"""
return { "$no-json": str(obj)}
12 changes: 7 additions & 5 deletions tests/test_reportlog.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from pathlib import Path
from _pytest.reports import BaseReport

from pytest_reportlog.plugin import cleanup_unserializable, _open_filtered_writer
from pytest_reportlog.plugin import _open_filtered_writer, unserializable_to_marked_str

from typing_extensions import Protocol, Literal

Expand Down Expand Up @@ -132,16 +132,18 @@ def test_warning():
}


def test_cleanup_unserializable():
def test_unserializable_to_marked():
"""Unittest for the cleanup_unserializable function"""


good = {"x": 1, "y": ["a", "b"]}
new = cleanup_unserializable(good)
new = json.loads(json.dumps(good, default=unserializable_to_marked_str))
assert new == good

class C:
def __str__(self):
return "C instance"

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

0 comments on commit c1b926c

Please sign in to comment.