Skip to content

Commit e55f3c6

Browse files
author
Hamish Downer
committed
(de)serialize - handle args being complex
As this can happen when the RunReport has been through (de)serialization a few times.
1 parent b32b0b1 commit e55f3c6

File tree

2 files changed

+12
-6
lines changed

2 files changed

+12
-6
lines changed

src/sortition_algorithms/utils.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,15 @@ def _unstructure_exception(exc: Exception) -> dict[str, Any]:
117117
"""Unstructure hook for exceptions - store type and args"""
118118
result: dict[str, Any] = {
119119
"type": f"{exc.__class__.__module__}.{exc.__class__.__name__}",
120-
"args": exc.args,
120+
"args": _converter.unstructure(exc.args),
121121
}
122122
# Special handling for SelectionMultilineError which has custom attributes
123123
if hasattr(exc, "all_lines"):
124124
result["all_lines"] = exc.all_lines
125125
if hasattr(exc, "all_errors"):
126126
result["all_errors"] = _converter.unstructure(exc.all_errors)
127+
# this is for InfeasibleQuotasError
127128
if hasattr(exc, "features"):
128-
# Don't serialize features as it's complex and circular
129129
result["features"] = _converter.unstructure(exc.features)
130130
return result
131131

@@ -153,8 +153,6 @@ def _structure_exception(obj: dict[str, Any], _: Any) -> Exception:
153153

154154
features = _converter.structure(obj.get("features", {}), FeatureCollection) # type: ignore[type-abstract]
155155
output = _converter.structure(obj.get("all_lines", ["dummy"]), list[str])[1:]
156-
# We can't fully reconstruct this as it needs a FeatureCollection
157-
# Just create a basic SelectionMultilineError with the lines if available
158156
return errors.InfeasibleQuotasError(features=features, output=output)
159157
elif exc_type_name.startswith("sortition_algorithms.errors."):
160158
# For other custom errors, try to find the class

tests/test_utils.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,11 @@ def test_run_report_with_infeasible_quotas_error_serialisation(self):
520520
features = CaseInsensitiveDict()
521521
features["feat1"] = CaseInsensitiveDict()
522522
features["feat1"]["value1"] = FeatureValueMinMax(min=2, max=4)
523-
report.add_error(InfeasibleQuotasError(features=features, output=["line1", "line2"]))
523+
msgs = ["line1", "line2"]
524+
iq_error = InfeasibleQuotasError(features=features, output=msgs)
525+
# with round trips we can end up with the args being set to include features
526+
iq_error.args = (features, ["intro", *msgs])
527+
report.add_error(iq_error)
524528
serialised_form = report.serialize()
525529
assert "_data" in serialised_form
526530
assert len(serialised_form["_data"]) == 1
@@ -532,7 +536,11 @@ def test_run_report_with_infeasible_quotas_error_deserialisation(self):
532536
features = CaseInsensitiveDict()
533537
features["feat1"] = CaseInsensitiveDict()
534538
features["feat1"]["value1"] = FeatureValueMinMax(min=2, max=4)
535-
report.add_error(InfeasibleQuotasError(features=features, output=["line1", "line2"]))
539+
msgs = ["line1", "line2"]
540+
iq_error = InfeasibleQuotasError(features=features, output=msgs)
541+
# with round trips we can end up with the args being set to include features
542+
iq_error.args = (features, ["intro", *msgs])
543+
report.add_error(iq_error)
536544
serialised_form = report.serialize()
537545
json_report = json.dumps(serialised_form)
538546
from_json = json.loads(json_report)

0 commit comments

Comments
 (0)