From 49666141fa9ed7cecc0b917354c18ad016afbdfc Mon Sep 17 00:00:00 2001 From: Ethanfel Date: Thu, 2 Jul 2026 20:34:35 +0200 Subject: [PATCH] Fail closed on dynamic mapping duplicate safety --- .../test_generate_popular_node_signatures.py | 64 +++++++++++++++++++ tools/generate_popular_node_signatures.py | 6 +- 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/tests/test_generate_popular_node_signatures.py b/tests/test_generate_popular_node_signatures.py index 41c9600..bab788e 100644 --- a/tests/test_generate_popular_node_signatures.py +++ b/tests/test_generate_popular_node_signatures.py @@ -585,6 +585,70 @@ class DynamicDupNode: "namespace-alias-dunder-setitem-replacement-duplicate-node-pack", ) + def test_dynamic_node_class_mapping_assignment_suppresses_static_duplicate_safety(self): + source_a = ''' +class StaticDupNode: + RETURN_TYPES = ("IMAGE",) + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "image": ("IMAGE",), + }, + } + + +NODE_CLASS_MAPPINGS = { + "DupNode": StaticDupNode, +} +''' + source_b = ''' +def build_mappings(): + return {"DupNode": object} + + +NODE_CLASS_MAPPINGS = build_mappings() +''' + result = self._extract_two_sources( + source_a, + source_b, + "dynamic-assignment-duplicate-safety-pack", + ) + + self.assertEqual({}, result["nodes"]) + self.assertEqual("no_static_nodes", result["pack"]["status"]) + + def test_wildcard_import_suppresses_static_duplicate_safety(self): + source_a = ''' +class StaticDupNode: + RETURN_TYPES = ("IMAGE",) + + @classmethod + def INPUT_TYPES(cls): + return { + "required": { + "image": ("IMAGE",), + }, + } + + +NODE_CLASS_MAPPINGS = { + "DupNode": StaticDupNode, +} +''' + source_b = ''' +from dynamic_nodes import * +''' + result = self._extract_two_sources( + source_a, + source_b, + "wildcard-import-duplicate-safety-pack", + ) + + self.assertEqual({}, result["nodes"]) + self.assertEqual("no_static_nodes", result["pack"]["status"]) + def test_unsupported_reassignment_invalidates_static_env_value(self): source = ''' def build_inputs(): diff --git a/tools/generate_popular_node_signatures.py b/tools/generate_popular_node_signatures.py index c7aa565..459780f 100644 --- a/tools/generate_popular_node_signatures.py +++ b/tools/generate_popular_node_signatures.py @@ -2273,7 +2273,7 @@ def _node_class_mapping_mutation_string_keys(stmt, env, aliases=None, namespace_ def _node_class_mapping_keys(tree): if _has_module_wildcard_import(tree): - return set() + return _INVALID keys = set() env = {} class_bindings = {} @@ -2281,6 +2281,8 @@ def _node_class_mapping_keys(tree): namespace_aliases = set() for stmt in tree.body: if isinstance(stmt, ast.Assign) and _name_is_assigned(stmt, "NODE_CLASS_MAPPINGS"): + if not isinstance(stmt.value, ast.Dict): + return _INVALID literal_keys, literal_ambiguous = _literal_module_dict_string_keys_state(stmt.value, env) keys.update(literal_keys) if literal_ambiguous: @@ -2290,6 +2292,8 @@ def _node_class_mapping_keys(tree): and _name_is_assigned(stmt, "NODE_CLASS_MAPPINGS") and stmt.value is not None ): + if not isinstance(stmt.value, ast.Dict): + return _INVALID literal_keys, literal_ambiguous = _literal_module_dict_string_keys_state(stmt.value, env) keys.update(literal_keys) if literal_ambiguous: