-
Notifications
You must be signed in to change notification settings - Fork 6.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
serve workflow templates from custom_nodes (#6193)
* add GET /workflow_templates * serve workflow templates from custom_nodes * refactor into custom_node_manager, add test * remove unused import * revert changes in folder_paths * Remove trailing whitespace. * account for multiple custom_nodes paths
- Loading branch information
Showing
4 changed files
with
83 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
from __future__ import annotations | ||
|
||
import os | ||
import folder_paths | ||
import glob | ||
from aiohttp import web | ||
|
||
class CustomNodeManager: | ||
""" | ||
Placeholder to refactor the custom node management features from ComfyUI-Manager. | ||
Currently it only contains the custom workflow templates feature. | ||
""" | ||
def add_routes(self, routes, webapp, loadedModules): | ||
|
||
@routes.get("/workflow_templates") | ||
async def get_workflow_templates(request): | ||
"""Returns a web response that contains the map of custom_nodes names and their associated workflow templates. The ones without templates are omitted.""" | ||
files = [ | ||
file | ||
for folder in folder_paths.get_folder_paths("custom_nodes") | ||
for file in glob.glob(os.path.join(folder, '*/example_workflows/*.json')) | ||
] | ||
workflow_templates_dict = {} # custom_nodes folder name -> example workflow names | ||
for file in files: | ||
custom_nodes_name = os.path.basename(os.path.dirname(os.path.dirname(file))) | ||
workflow_name = os.path.splitext(os.path.basename(file))[0] | ||
workflow_templates_dict.setdefault(custom_nodes_name, []).append(workflow_name) | ||
return web.json_response(workflow_templates_dict) | ||
|
||
# Serve workflow templates from custom nodes. | ||
for module_name, module_dir in loadedModules: | ||
workflows_dir = os.path.join(module_dir, 'example_workflows') | ||
if os.path.exists(workflows_dir): | ||
webapp.add_routes([web.static('/api/workflow_templates/' + module_name, workflows_dir)]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import pytest | ||
from aiohttp import web | ||
from unittest.mock import patch | ||
from app.custom_node_manager import CustomNodeManager | ||
|
||
pytestmark = ( | ||
pytest.mark.asyncio | ||
) # This applies the asyncio mark to all test functions in the module | ||
|
||
@pytest.fixture | ||
def custom_node_manager(): | ||
return CustomNodeManager() | ||
|
||
@pytest.fixture | ||
def app(custom_node_manager): | ||
app = web.Application() | ||
routes = web.RouteTableDef() | ||
custom_node_manager.add_routes(routes, app, [("ComfyUI-TestExtension1", "ComfyUI-TestExtension1")]) | ||
app.add_routes(routes) | ||
return app | ||
|
||
async def test_get_workflow_templates(aiohttp_client, app, tmp_path): | ||
client = await aiohttp_client(app) | ||
# Setup temporary custom nodes file structure with 1 workflow file | ||
custom_nodes_dir = tmp_path / "custom_nodes" | ||
example_workflows_dir = custom_nodes_dir / "ComfyUI-TestExtension1" / "example_workflows" | ||
example_workflows_dir.mkdir(parents=True) | ||
template_file = example_workflows_dir / "workflow1.json" | ||
template_file.write_text('') | ||
|
||
with patch('folder_paths.folder_names_and_paths', { | ||
'custom_nodes': ([str(custom_nodes_dir)], None) | ||
}): | ||
response = await client.get('/workflow_templates') | ||
assert response.status == 200 | ||
workflows_dict = await response.json() | ||
assert isinstance(workflows_dict, dict) | ||
assert "ComfyUI-TestExtension1" in workflows_dict | ||
assert isinstance(workflows_dict["ComfyUI-TestExtension1"], list) | ||
assert workflows_dict["ComfyUI-TestExtension1"][0] == "workflow1" |