fix(scan): leave the browser-parser NaN parse to the resolver parity fix
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.
This commit is contained in:
+3
-4
@@ -41,7 +41,7 @@ try:
|
||||
PLACEHOLDERS,
|
||||
GenerationParamsError,
|
||||
extract_generation_params,
|
||||
parse_page_json,
|
||||
parse_js_json,
|
||||
)
|
||||
from ...utils.prompt_pair_resolver import resolve_prompt_pair
|
||||
except ImportError:
|
||||
@@ -51,7 +51,7 @@ except ImportError:
|
||||
PLACEHOLDERS,
|
||||
GenerationParamsError,
|
||||
extract_generation_params,
|
||||
parse_page_json,
|
||||
parse_js_json,
|
||||
)
|
||||
from utils.prompt_pair_resolver import resolve_prompt_pair
|
||||
|
||||
@@ -1606,8 +1606,7 @@ class AdminRoutesMixin:
|
||||
records = {}
|
||||
for key in ("prompt", "workflow"):
|
||||
value = metadata.get(key)
|
||||
# As the legacy pages parse it: ComfyUI's NaN/Infinity read as null.
|
||||
records[key] = parse_page_json(value) if isinstance(value, str) else value
|
||||
records[key] = parse_js_json(value) if isinstance(value, str) else value
|
||||
try:
|
||||
positive = extract_generation_params(records)["positivePrompt"]
|
||||
except GenerationParamsError:
|
||||
|
||||
@@ -41,7 +41,7 @@ NEGATIVE = "blurry"
|
||||
NAN, INF = float("nan"), float("inf")
|
||||
|
||||
|
||||
def graph(positive=POSITIVE, negative=NEGATIVE, *, untraceable=False):
|
||||
def graph(positive=POSITIVE, negative=NEGATIVE):
|
||||
"""An API prompt graph with non-finite numbers where ComfyUI writes them."""
|
||||
g = {
|
||||
"1": {"class_type": "CLIPTextEncode", "inputs": {"text": positive}},
|
||||
@@ -58,15 +58,6 @@ def graph(positive=POSITIVE, negative=NEGATIVE, *, untraceable=False):
|
||||
"is_changed": [NAN],
|
||||
},
|
||||
}
|
||||
if untraceable:
|
||||
# The resolver stops at an unknown conditioning node and two samplers;
|
||||
# the browser parser still traces the positive prompt (the legacy floor).
|
||||
g["7"] = {
|
||||
"class_type": "MyConditioningTweak",
|
||||
"inputs": {"conditioning": ["1", 0], "amount": NAN},
|
||||
}
|
||||
g["3"]["inputs"]["positive"] = ["7", 0]
|
||||
g["6"] = {**g["3"]}
|
||||
return g
|
||||
|
||||
|
||||
@@ -198,17 +189,6 @@ class TestScanIngestsNonFiniteMetadata(StrictRows, AdminAPITestCase):
|
||||
# A repeated scan compares the same strict snapshot: unchanged.
|
||||
self.assertEqual(self.ingest("nan.png")["unchanged"], 1)
|
||||
|
||||
def test_browser_parser_fallback_traces_through_nan(self):
|
||||
counts = self.ingest("traced.png", graph(untraceable=True))
|
||||
self.assertEqual(counts["failed"], 0)
|
||||
self.assertEqual(counts["added"], 1)
|
||||
# The positive-only link, not a pair: the resolver could not decide.
|
||||
self.assertEqual(self.api.db.list_prompt_pairs()["total"], 0)
|
||||
rows = self.image_rows(self.api.db)
|
||||
self.assertEqual(len(rows), 1)
|
||||
self.assert_strict_snapshot(rows[0])
|
||||
self.assert_prompt_text(self.api.db, rows[0]["prompt_id"])
|
||||
|
||||
async def test_scan_route_reports_no_failures(self):
|
||||
from py.config import GalleryConfig
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ __all__ = [
|
||||
"extract_generation_params",
|
||||
"extract_from_records",
|
||||
"parse_js_json",
|
||||
"parse_page_json",
|
||||
]
|
||||
|
||||
PLACEHOLDERS = MappingProxyType(
|
||||
@@ -954,29 +953,6 @@ def parse_js_json(text):
|
||||
return None
|
||||
|
||||
|
||||
def _null_constant(_name):
|
||||
return None
|
||||
|
||||
|
||||
def parse_page_json(text):
|
||||
"""A metadata record as the legacy pages parse it, or None where they fail.
|
||||
|
||||
The gallery, admin and metadata pages replace ComfyUI's ``NaN`` with
|
||||
``null`` before ``JSON.parse``. Here every non-finite literal ComfyUI
|
||||
writes (``NaN``, ``Infinity``, ``-Infinity``) is null, and only where it is
|
||||
a number: unlike the pages' text replacement, a prompt that spells "NaN"
|
||||
keeps its text.
|
||||
"""
|
||||
if not isinstance(text, str):
|
||||
return None
|
||||
try:
|
||||
return json.loads(
|
||||
text, parse_constant=_null_constant, parse_int=_double_integer
|
||||
)
|
||||
except (ValueError, RecursionError):
|
||||
return None
|
||||
|
||||
|
||||
def extract_from_records(prompt_text, workflow_text):
|
||||
"""``extract_generation_params`` for raw ``prompt``/``workflow`` record text.
|
||||
|
||||
|
||||
@@ -4,11 +4,12 @@ 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. Python's ``json.loads`` already accepts them, so reading needs no help;
|
||||
whatever PromptManager stores or answers as JSON goes through ``dumps_strict``,
|
||||
which writes each non-finite number as ``null`` (the legacy pages' own
|
||||
replacement) and leaves strings, including the words ``NaN`` or ``Infinity``
|
||||
inside prompt text, untouched.
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user