From 185749cf63d01833cdd139a448bb8adbe076411b Mon Sep 17 00:00:00 2001 From: CyberShadowX Date: Thu, 28 May 2026 11:11:31 +0800 Subject: [PATCH] Fix ComfyUI custom node package imports --- nodes.py | 8 +++- smart_metadata_reader/adapters/base.py | 6 +-- smart_metadata_reader/adapters/clip_text.py | 4 +- .../adapters/conditioning.py | 2 +- smart_metadata_reader/adapters/loaders.py | 2 +- smart_metadata_reader/adapters/pysssss.py | 4 +- smart_metadata_reader/adapters/samplers.py | 2 +- .../adapters/text_sources.py | 4 +- tests/test_node_contract.py | 45 +++++++++++++++++++ 9 files changed, 63 insertions(+), 14 deletions(-) diff --git a/nodes.py b/nodes.py index 20915a6..b257485 100644 --- a/nodes.py +++ b/nodes.py @@ -5,8 +5,12 @@ import os from pathlib import Path from typing import Any -from smart_metadata_reader.image_io import load_image_and_mask -from smart_metadata_reader.metadata_reader import parse_metadata_bundle, read_metadata +try: + from .smart_metadata_reader.image_io import load_image_and_mask + from .smart_metadata_reader.metadata_reader import parse_metadata_bundle, read_metadata +except ImportError: + from smart_metadata_reader.image_io import load_image_and_mask + from smart_metadata_reader.metadata_reader import parse_metadata_bundle, read_metadata try: import folder_paths # type: ignore diff --git a/smart_metadata_reader/adapters/base.py b/smart_metadata_reader/adapters/base.py index bbd725f..766f6c2 100644 --- a/smart_metadata_reader/adapters/base.py +++ b/smart_metadata_reader/adapters/base.py @@ -2,9 +2,9 @@ from __future__ import annotations from typing import Protocol -from smart_metadata_reader.graph import GraphIndex -from smart_metadata_reader.models import NodeRecord, PromptSegment -from smart_metadata_reader.trace import TraceCollector +from ..graph import GraphIndex +from ..models import NodeRecord, PromptSegment +from ..trace import TraceCollector class NodeAdapter(Protocol): diff --git a/smart_metadata_reader/adapters/clip_text.py b/smart_metadata_reader/adapters/clip_text.py index 30d74c8..90172cf 100644 --- a/smart_metadata_reader/adapters/clip_text.py +++ b/smart_metadata_reader/adapters/clip_text.py @@ -1,7 +1,7 @@ from __future__ import annotations -from smart_metadata_reader.adapters.base import TextResolutionContext -from smart_metadata_reader.models import NodeRecord, PromptSegment +from .base import TextResolutionContext +from ..models import NodeRecord, PromptSegment class CLIPTextEncodeAdapter: diff --git a/smart_metadata_reader/adapters/conditioning.py b/smart_metadata_reader/adapters/conditioning.py index 94ed59d..2c6cf3d 100644 --- a/smart_metadata_reader/adapters/conditioning.py +++ b/smart_metadata_reader/adapters/conditioning.py @@ -1,6 +1,6 @@ from __future__ import annotations -from smart_metadata_reader.models import NodeRecord +from ..models import NodeRecord ROLE_FIELD_ORDER = { diff --git a/smart_metadata_reader/adapters/loaders.py b/smart_metadata_reader/adapters/loaders.py index 00c467d..33e358a 100644 --- a/smart_metadata_reader/adapters/loaders.py +++ b/smart_metadata_reader/adapters/loaders.py @@ -2,7 +2,7 @@ from __future__ import annotations from typing import Any -from smart_metadata_reader.models import NodeRecord +from ..models import NodeRecord CHECKPOINT_NAME_FIELDS = ("ckpt_name", "checkpoint", "model_name", "name") diff --git a/smart_metadata_reader/adapters/pysssss.py b/smart_metadata_reader/adapters/pysssss.py index 5a5ae93..f54257a 100644 --- a/smart_metadata_reader/adapters/pysssss.py +++ b/smart_metadata_reader/adapters/pysssss.py @@ -1,7 +1,7 @@ from __future__ import annotations -from smart_metadata_reader.adapters.base import TextResolutionContext -from smart_metadata_reader.models import NodeRecord, PromptSegment +from .base import TextResolutionContext +from ..models import NodeRecord, PromptSegment class StringFunctionAdapter: diff --git a/smart_metadata_reader/adapters/samplers.py b/smart_metadata_reader/adapters/samplers.py index 1f9d56d..4f97b3b 100644 --- a/smart_metadata_reader/adapters/samplers.py +++ b/smart_metadata_reader/adapters/samplers.py @@ -2,7 +2,7 @@ from __future__ import annotations from typing import Any -from smart_metadata_reader.models import NodeRecord +from ..models import NodeRecord SAMPLER_CLASS_TYPES = { diff --git a/smart_metadata_reader/adapters/text_sources.py b/smart_metadata_reader/adapters/text_sources.py index 165e4f5..4dd894b 100644 --- a/smart_metadata_reader/adapters/text_sources.py +++ b/smart_metadata_reader/adapters/text_sources.py @@ -1,7 +1,7 @@ from __future__ import annotations -from smart_metadata_reader.adapters.base import TextResolutionContext -from smart_metadata_reader.models import NodeRecord, PromptSegment +from .base import TextResolutionContext +from ..models import NodeRecord, PromptSegment COMMON_TEXT_FIELDS = ( diff --git a/tests/test_node_contract.py b/tests/test_node_contract.py index 18ba02e..aadc3ff 100644 --- a/tests/test_node_contract.py +++ b/tests/test_node_contract.py @@ -1,6 +1,8 @@ import json import importlib.util +import subprocess import sys +import textwrap from types import SimpleNamespace import pytest @@ -184,6 +186,49 @@ def test_plugin_root_init_exports_comfyui_mappings(): assert module.NODE_DISPLAY_NAME_MAPPINGS["SmartMetadataReader"] == "Smart Metadata Reader" +def test_plugin_package_import_works_without_repo_root_on_sys_path(tmp_path): + root_dir = pytest.importorskip("pathlib").Path(__file__).resolve().parents[1] + script = textwrap.dedent( + f""" + import importlib.util + import pathlib + import sys + + root = pathlib.Path({str(root_dir)!r}) + sys.path = [ + path for path in sys.path + if pathlib.Path(path or ".").resolve() != root + ] + for name in list(sys.modules): + if name == "smart_metadata_reader" or name.startswith("smart_metadata_reader."): + sys.modules.pop(name, None) + + spec = importlib.util.spec_from_file_location( + "comfyui_custom_node_under_test", + root / "__init__.py", + submodule_search_locations=[str(root)], + ) + module = importlib.util.module_from_spec(spec) + sys.modules[spec.name] = module + spec.loader.exec_module(module) + assert "SmartMetadataReader" in module.NODE_CLASS_MAPPINGS + assert module.NODE_DISPLAY_NAME_MAPPINGS["SmartMetadataReader"] == "Smart Metadata Reader" + print("package import ok") + """ + ) + + completed = subprocess.run( + [sys.executable, "-c", script], + cwd=tmp_path, + text=True, + capture_output=True, + check=False, + ) + + assert completed.returncode == 0, completed.stderr + assert "package import ok" in completed.stdout + + def test_input_types_prefers_comfyui_filename_list(monkeypatch): import nodes