Bug: sympy_json.from_jsonable() cannot decode non-compact nodes produced by to_jsonable(..., compact=False)
Severity
Medium
Summary
to_jsonable(expr, compact=False) returns dict-based nodes via _Encoder, but from_jsonable() only accepts list/int/float and always uses _DecoderCompact.
Impact
- Public API is asymmetric: one supported encoding mode cannot be decoded.
- Callers using non-compact mode get
SympyJsonError despite valid payloads.
Affected Code
Root Cause
from_jsonable() hardcodes compact decoder path.
Proposed Fix
Dispatch decoder by node type (dict -> _Decoder, list/int/float -> _DecoderCompact).
Full Patch
diff --git a/src/jaff/sympy_json.py b/src/jaff/sympy_json.py
index a16f786..81fcbb2 100644
--- a/src/jaff/sympy_json.py
+++ b/src/jaff/sympy_json.py
@@ -64,9 +64,13 @@ def to_jsonable(expr: sympy.Basic, *, compact: bool = True, include_assumptions
def from_jsonable(obj: Any) -> sympy.Basic:
- if not isinstance(obj, (list, int, float)):
- raise SympyJsonError(f"Expected list/number node, got {type(obj)!r}")
- return _DecoderCompact().decode(obj)
+ if isinstance(obj, dict):
+ return _Decoder().decode(obj)
+ if isinstance(obj, (list, int, float)):
+ return _DecoderCompact().decode(obj)
+ raise SympyJsonError(
+ f"Expected compact(list/number) or verbose(dict) node, got {type(obj)!r}"
+ )
Bug:
sympy_json.from_jsonable()cannot decode non-compact nodes produced byto_jsonable(..., compact=False)Severity
Medium
Summary
to_jsonable(expr, compact=False)returns dict-based nodes via_Encoder, butfrom_jsonable()only acceptslist/int/floatand always uses_DecoderCompact.Impact
SympyJsonErrordespite valid payloads.Affected Code
src/jaff/sympy_json.pyRoot Cause
from_jsonable()hardcodes compact decoder path.Proposed Fix
Dispatch decoder by node type (
dict->_Decoder,list/int/float->_DecoderCompact).Full Patch