refactor(entrypoint): extract node definitions

This commit is contained in:
Dariusz L
2026-08-02 03:19:32 +02:00
parent a6e8fe1c55
commit e09d3c2bf8
3 changed files with 121 additions and 65 deletions
+18 -65
View File
@@ -21,6 +21,7 @@ if not __package__ or __package__ == "":
sys.modules[package_name] = current_module
if not hasattr(current_module, "__path__"):
current_module.__path__ = [this_dir]
from .core import node_definitions as _node_definitions
from .core.extension import ModelResolverExtension
from .core.file_manager import (
FileManagerError,
@@ -54,77 +55,29 @@ from .core.version import (
# Web directory for JavaScript interface
WEB_DIRECTORY = "./web"
MODEL_RESOLVER_DEPENDENCY_NODE_TYPE = "ModelResolverDependency"
MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME = "Model Resolver Opener"
MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY = "Model Resolver/Workflow"
ComfyExtension = _node_definitions.ComfyExtension
io = _node_definitions.io
ModelResolverDependencyNode = _node_definitions.ModelResolverDependencyNode
MODEL_RESOLVER_DEPENDENCY_NODE_TYPE = (
_node_definitions.MODEL_RESOLVER_DEPENDENCY_NODE_TYPE
)
MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME = (
_node_definitions.MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME
)
MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY = (
_node_definitions.MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY
)
MODEL_RESOLVER_DEPENDENCY_NODE_DESCRIPTION = (
"This passive node declares Model Resolver as a workflow dependency and opens "
"its tools. It does not process images, models, or prompts. To stop adding it "
"automatically, open Model Resolver, go to Options -> Defaults -> and disable "
"'Embed opener node'. We recommend keeping it in an unobtrusive part of the "
"canvas: it helps ComfyUI-Manager identify and offer Model Resolver on other "
"ComfyUI installations, making the workflow easier to use in the future."
_node_definitions.MODEL_RESOLVER_DEPENDENCY_NODE_DESCRIPTION
)
try:
from comfy_api.latest import ComfyExtension, io
except Exception:
ComfyExtension = None
io = None
if ComfyExtension is not None and io is not None:
class ModelResolverDependencyNode(io.ComfyNode):
"""Canvas node that declares Model Resolver and opens its workflow tools."""
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id=MODEL_RESOLVER_DEPENDENCY_NODE_TYPE,
display_name=MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME,
category=MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY,
description=MODEL_RESOLVER_DEPENDENCY_NODE_DESCRIPTION,
inputs=[],
outputs=[],
)
@classmethod
def execute(cls) -> io.NodeOutput:
return io.NodeOutput()
class ModelResolverNodeExtension(ComfyExtension):
async def get_node_list(self) -> list[type[io.ComfyNode]]:
return [ModelResolverDependencyNode]
async def comfy_entrypoint() -> ComfyExtension:
return ModelResolverNodeExtension()
ModelResolverNodeExtension = _node_definitions.ModelResolverNodeExtension
comfy_entrypoint = _node_definitions.comfy_entrypoint
__all__ = ["WEB_DIRECTORY", "comfy_entrypoint"]
else:
class ModelResolverDependencyNode:
"""Legacy fallback for ComfyUI builds without the v3 custom-node API."""
DESCRIPTION = MODEL_RESOLVER_DEPENDENCY_NODE_DESCRIPTION
RETURN_TYPES = ()
FUNCTION = "noop"
CATEGORY = MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY
@classmethod
def INPUT_TYPES(cls):
return {"required": {}}
def noop(self):
return ()
NODE_CLASS_MAPPINGS = {
MODEL_RESOLVER_DEPENDENCY_NODE_TYPE: ModelResolverDependencyNode,
}
NODE_DISPLAY_NAME_MAPPINGS = {
MODEL_RESOLVER_DEPENDENCY_NODE_TYPE: MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME,
}
NODE_CLASS_MAPPINGS = _node_definitions.NODE_CLASS_MAPPINGS
NODE_DISPLAY_NAME_MAPPINGS = _node_definitions.NODE_DISPLAY_NAME_MAPPINGS
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", "WEB_DIRECTORY"]
+74
View File
@@ -0,0 +1,74 @@
"""ComfyUI node definitions and runtime compatibility exports."""
try:
from comfy_api.latest import ComfyExtension, io
except Exception:
ComfyExtension = None
io = None
MODEL_RESOLVER_DEPENDENCY_NODE_TYPE = "ModelResolverDependency"
MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME = "Model Resolver Opener"
MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY = "Model Resolver/Workflow"
MODEL_RESOLVER_DEPENDENCY_NODE_DESCRIPTION = (
"This passive node declares Model Resolver as a workflow dependency and opens "
"its tools. It does not process images, models, or prompts. To stop adding it "
"automatically, open Model Resolver, go to Options -> Defaults -> and disable "
"'Embed opener node'. We recommend keeping it in an unobtrusive part of the "
"canvas: it helps ComfyUI-Manager identify and offer Model Resolver on other "
"ComfyUI installations, making the workflow easier to use in the future."
)
if ComfyExtension is not None and io is not None:
class ModelResolverDependencyNode(io.ComfyNode):
"""Canvas node that declares Model Resolver and opens its workflow tools."""
@classmethod
def define_schema(cls) -> io.Schema:
return io.Schema(
node_id=MODEL_RESOLVER_DEPENDENCY_NODE_TYPE,
display_name=MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME,
category=MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY,
description=MODEL_RESOLVER_DEPENDENCY_NODE_DESCRIPTION,
inputs=[],
outputs=[],
)
@classmethod
def execute(cls) -> io.NodeOutput:
return io.NodeOutput()
class ModelResolverNodeExtension(ComfyExtension):
async def get_node_list(self) -> list[type[io.ComfyNode]]:
return [ModelResolverDependencyNode]
async def comfy_entrypoint() -> ComfyExtension:
return ModelResolverNodeExtension()
__all__ = ["comfy_entrypoint"]
else:
class ModelResolverDependencyNode:
"""Legacy fallback for ComfyUI builds without the v3 custom-node API."""
DESCRIPTION = MODEL_RESOLVER_DEPENDENCY_NODE_DESCRIPTION
RETURN_TYPES = ()
FUNCTION = "noop"
CATEGORY = MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY
@classmethod
def INPUT_TYPES(cls):
return {"required": {}}
def noop(self):
return ()
NODE_CLASS_MAPPINGS = {
MODEL_RESOLVER_DEPENDENCY_NODE_TYPE: ModelResolverDependencyNode,
}
NODE_DISPLAY_NAME_MAPPINGS = {
MODEL_RESOLVER_DEPENDENCY_NODE_TYPE: MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME,
}
__all__ = ["NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS"]
+29
View File
@@ -0,0 +1,29 @@
import importlib
def test_node_definitions_expose_stable_model_resolver_metadata():
module = importlib.import_module("core.node_definitions")
assert module.MODEL_RESOLVER_DEPENDENCY_NODE_TYPE == (
"ModelResolverDependency"
)
assert module.MODEL_RESOLVER_DEPENDENCY_NODE_CATEGORY == (
"Model Resolver/Workflow"
)
assert module.MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME == (
"Model Resolver Opener"
)
assert "ModelResolverDependencyNode" in dir(module)
def test_node_definitions_preserve_runtime_specific_exports():
module = importlib.import_module("core.node_definitions")
if module.ComfyExtension is not None and module.io is not None:
assert callable(module.comfy_entrypoint)
assert "comfy_entrypoint" in module.__all__
else:
assert module.NODE_CLASS_MAPPINGS[module.MODEL_RESOLVER_DEPENDENCY_NODE_TYPE]
assert module.NODE_DISPLAY_NAME_MAPPINGS[
module.MODEL_RESOLVER_DEPENDENCY_NODE_TYPE
] == module.MODEL_RESOLVER_DEPENDENCY_NODE_DISPLAY_NAME