Fix deprecated flag not propagating to schema in dataset nodes

ImageProcessingNode and TextProcessingNode set is_deprecated as a class
attribute but never forwarded it into the io.Schema built by their shared
define_schema(), so /object_info reported deprecated: false for nodes like
ResizeImagesByShorterEdgeNode, TextToLowercaseNode, and ReplaceTextNode
despite is_deprecated = True on the class. The frontend's hide-deprecated
filter reads the schema, not the class attribute, so these nodes kept
showing up in search.

Forward cls.is_deprecated into io.Schema(...) in both base classes, same as
SaveImageDataSetToFolderNode already does directly. Adds a regression test
asserting schema.is_deprecated matches the class flag for every dataset node.
This commit is contained in:
Claude
2026-08-09 06:54:25 +00:00
parent cbbc9dab1f
commit aee16f4a08
3 changed files with 54 additions and 0 deletions

View File

@@ -342,6 +342,11 @@
comments, but do not disrespect her.
- Warning and info messages should be short and actionable. Remove noisy or
misleading messages rather than adding more logging.
- Setting `is_deprecated` (or similar flags like `is_experimental`) as a class
attribute on a V3 (`io.ComfyNode`) node is not enough by itself: it must also
be passed into the `io.Schema(...)` returned by `define_schema()` (e.g.
`is_deprecated=cls.is_deprecated`). `/object_info` and the frontend's
deprecated-node filtering read the schema, not the class attribute.
- Documentation and README edits should be concise, factual, and tied to the
changed behavior.

View File

@@ -701,6 +701,7 @@ class ImageProcessingNode(io.ComfyNode):
tooltip="Processed images",
)
],
is_deprecated=cls.is_deprecated,
)
@classmethod
@@ -873,6 +874,7 @@ class TextProcessingNode(io.ComfyNode):
tooltip="Processed texts",
)
],
is_deprecated=cls.is_deprecated,
)
@classmethod

View File

@@ -0,0 +1,47 @@
from comfy_extras import nodes_dataset
def _all_node_classes():
"""Every node class registered by the dataset extension."""
return [
cls for cls in vars(nodes_dataset).values()
if isinstance(cls, type) and issubclass(cls, nodes_dataset.io.ComfyNode)
]
def test_is_deprecated_propagates_to_schema():
"""A node's class-level is_deprecated flag must reach define_schema()'s
io.Schema, since /object_info (and the frontend's deprecated-node filter)
reads the schema, not the class attribute. See PR that fixed nodes like
ReplaceTextNode reporting deprecated: false despite is_deprecated = True."""
for node_cls in _all_node_classes():
if getattr(node_cls, "node_id", "") is None:
continue # abstract base class (ImageProcessingNode/TextProcessingNode), not a real node
if not hasattr(node_cls, "is_deprecated"):
continue # node builds its Schema with is_deprecated inline, nothing to compare
class_flag = bool(node_cls.is_deprecated)
schema_flag = bool(node_cls.define_schema().is_deprecated)
assert schema_flag == class_flag, (
f"{node_cls.__name__}: class is_deprecated={class_flag} but "
f"define_schema().is_deprecated={schema_flag}"
)
def test_known_deprecated_nodes_report_deprecated_in_schema():
deprecated_nodes = [
nodes_dataset.ResizeImagesByShorterEdgeNode,
nodes_dataset.ResizeImagesByLongerEdgeNode,
nodes_dataset.MergeImageListsNode,
nodes_dataset.TextToLowercaseNode,
nodes_dataset.TextToUppercaseNode,
nodes_dataset.AddTextPrefixNode,
nodes_dataset.AddTextSuffixNode,
nodes_dataset.ReplaceTextNode,
nodes_dataset.StripWhitespaceNode,
nodes_dataset.MergeTextListsNode,
nodes_dataset.SaveImageDataSetToFolderNode,
]
for node_cls in deprecated_nodes:
assert node_cls.define_schema().is_deprecated is True, (
f"{node_cls.__name__} should report deprecated: true in its schema"
)