The scan fallback's legacy-page parse (parse_page_json in _graph_prompt_text) is owned by the resolver parity change, which adds the same helper with the legacy pages' exact rule (NaN reads as null, Infinity still rejected). This branch keeps only the strict serialization of stored and answered JSON.
43 lines
1.7 KiB
Python
43 lines
1.7 KiB
Python
"""Strict JSON output for values that may carry ComfyUI's non-finite numbers.
|
|
|
|
ComfyUI writes its metadata with Python's default ``json.dumps``, so a graph can
|
|
hold ``NaN``, ``Infinity`` and ``-Infinity`` (an ``IS_CHANGED`` that returns
|
|
``float("nan")`` puts ``"is_changed": [NaN]`` into every saved prompt). Those
|
|
literals are not JSON: browsers' ``JSON.parse`` and ``allow_nan=False`` reject
|
|
them. Reading follows the legacy pages (``parse_page_json`` where the browser
|
|
parser is mirrored; Python's ``json.loads`` elsewhere). Whatever PromptManager
|
|
stores or answers as JSON goes through ``dumps_strict``, which writes each
|
|
non-finite number as ``null`` (the legacy pages' own replacement for NaN) and
|
|
leaves strings, including the words ``NaN`` or ``Infinity`` inside prompt
|
|
text, untouched.
|
|
"""
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
__all__ = ["dumps_strict"]
|
|
|
|
|
|
def _null(_constant: str) -> None:
|
|
return None
|
|
|
|
|
|
def dumps_strict(value: Any, **kwargs: Any) -> str:
|
|
"""``json.dumps(value, allow_nan=False, **kwargs)`` with non-finite numbers null.
|
|
|
|
A value without non-finite numbers serializes byte for byte as the plain
|
|
call does. Any other error (a cycle, an unserializable object) still raises.
|
|
"""
|
|
kwargs.pop("allow_nan", None)
|
|
try:
|
|
return json.dumps(value, allow_nan=False, **kwargs)
|
|
except ValueError as error:
|
|
if "Out of range float" not in str(error):
|
|
raise
|
|
# The non-strict text spells each non-finite number as a bare literal, never
|
|
# inside a string, so parsing it back maps exactly those numbers to null.
|
|
lenient = json.dumps(value, allow_nan=True, default=kwargs.get("default"))
|
|
return json.dumps(
|
|
json.loads(lenient, parse_constant=_null), allow_nan=False, **kwargs
|
|
)
|