Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add no deps param for install for manager-core #2

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import os
import sys

cli_mode_flag = os.path.join(os.path.dirname(__file__), '.enable-cli-only-mode')
is_pytest_running = 'pytest' in sys.modules

if not os.path.exists(cli_mode_flag):
if os.path.exists(cli_mode_flag):
print("\n[ComfyUI-Manager] !! cli-only-mode is enabled !!\n")
elif is_pytest_running:
print("\n[ComfyUI-Manager] !! Running in pytest environment !!\n")
else:
from .glob import manager_server
WEB_DIRECTORY = "js"
else:
print(f"\n[ComfyUI-Manager] !! cli-only-mode is enabled !!\n")

NODE_CLASS_MAPPINGS = {}
__all__ = ['NODE_CLASS_MAPPINGS']
Expand Down
13 changes: 11 additions & 2 deletions glob/manager_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,13 @@ def get_installed_packages():

return pip_map

def call_cli_dependencies():
try:
result = subprocess.check_output([sys.executable, '-m', 'comfy_cli', 'dependency'], universal_newlines=True)
return result, False
except subprocess.CalledProcessError as e:
print("[ComfyUI-Manager] Failed to execute the command 'python -m comfy_cli dependency'.")
return None, True

def clear_pip_cache():
global pip_map
Expand Down Expand Up @@ -1466,6 +1473,7 @@ def write_config():
'downgrade_blacklist': get_config()['downgrade_blacklist'],
'security_level': get_config()['security_level'],
'skip_migration_check': get_config()['skip_migration_check'],
'use_uv_install': get_config()['use_uv_install'],
}
with open(config_path, 'w') as configfile:
config.write(configfile)
Expand Down Expand Up @@ -1500,7 +1508,8 @@ def read_config():
'model_download_by_agent': default_conf['model_download_by_agent'].lower() == 'true' if 'model_download_by_agent' in default_conf else False,
'downgrade_blacklist': default_conf['downgrade_blacklist'] if 'downgrade_blacklist' in default_conf else '',
'skip_migration_check': default_conf['skip_migration_check'].lower() == 'true' if 'skip_migration_check' in default_conf else False,
'security_level': security_level
'security_level': security_level,
'use_uv_install': default_conf['use_uv_install'].lower() == 'true' if 'use_uv_install' in default_conf else False,
}

except Exception:
Expand All @@ -1519,6 +1528,7 @@ def read_config():
'downgrade_blacklist': '',
'skip_migration_check': False,
'security_level': 'normal',
'use_uv_install': False,
}


Expand Down Expand Up @@ -1645,7 +1655,6 @@ def __win_check_git_pull(path):


def execute_install_script(url, repo_path, lazy_mode=False, instant_execution=False, no_deps=False):
# import ipdb; ipdb.set_trace()
install_script_path = os.path.join(repo_path, "install.py")
requirements_path = os.path.join(repo_path, "requirements.txt")

Expand Down
50 changes: 37 additions & 13 deletions glob/manager_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,20 +716,45 @@ async def install_custom_node(request):
print(SECURITY_MESSAGE_GENERAL)
return web.Response(status=404)

no_deps = json_data.get('noDeps', False)

node_spec = core.unified_manager.resolve_node_spec(node_spec_str)

if node_spec is None:
return

node_name, version_spec, is_specified = node_spec
res = await core.unified_manager.install_by_id(node_name, version_spec, json_data['channel'], json_data['mode'], return_postinstall=skip_post_install)
res = await core.unified_manager.install_by_id(node_name, version_spec, json_data['channel'], json_data['mode'], return_postinstall=skip_post_install, no_deps=no_deps)
# discard post install if skip_post_install mode

if res not in ['skip', 'enable', 'install-git', 'install-cnr', 'switch-cnr']:
return web.Response(status=400)

return web.Response(status=200)

@routes.post("/customnode/uv-install-deps")
async def uv_install_deps(request):
if not is_allowed_security_level('middle'):
print(SECURITY_MESSAGE_MIDDLE_OR_BELOW)
return web.Response(status=403)

json_data = await request.json()
node_id = json_data.get('id')
pip_dependencies = json_data.get('pip', [])

if not pip_dependencies:
return web.Response(status=400, text="No dependencies provided")

try:
result = core.call_cli_dependencies()
if result:
return web.Response(status=200, text="Dependencies installed successfully")
else:
return web.Response(status=500, text="Failed to install dependencies")
except Exception as e:
return web.Response(status=500, text=f"Error installing dependencies: {str(e)}")



@routes.post("/customnode/fix")
async def fix_custom_node(request):
Expand Down Expand Up @@ -856,17 +881,6 @@ async def need_to_migrate(request):
return web.Response(text=str(core.need_to_migrate), status=200)


@routes.get("/manager/badge_mode")
async def badge_mode(request):
if "value" in request.rel_url.query:
set_badge_mode(request.rel_url.query['value'])
core.write_config()
else:
return web.Response(text=core.get_config()['badge_mode'], status=200)

return web.Response(status=200)


@routes.get("/manager/channel_url_list")
async def channel_url_list(request):
channels = core.get_channel_dict()
Expand All @@ -890,6 +904,16 @@ async def channel_url_list(request):

return web.Response(status=200)

@routes.get("/manager/uv-install")
async def uv_install(request):
if "value" in request.rel_url.query:
value = request.rel_url.query['value'].lower() == 'true'
core.get_config()['use_uv_install'] = value
core.write_config()
return web.Response(status=200)
else:
return web.json_response({"use_uv_install": core.get_config().get('use_uv_install', False)}, status=200)


def add_target_blank(html_text):
pattern = r'(<a\s+href="[^"]*"\s*[^>]*)(>)'
Expand Down
29 changes: 29 additions & 0 deletions js/comfyui-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -775,6 +775,12 @@ class ManagerMenuDialog extends ComfyDialog {
uc_checkbox_text.style.cursor = "pointer";
this.update_check_checkbox.checked = true;

this.use_uv_install_checkbox = $el("input", { type: 'checkbox', id: "use_uv_install" }, [])
const use_uv_checkbox_text = $el("label", { for: "use_uv_install" }, [" Use UV Install"])
use_uv_checkbox_text.style.color = "var(--fg-color)";
use_uv_checkbox_text.style.cursor = "pointer";
this.use_uv_install_checkbox.checked = false;

// db mode
this.datasrc_combo = document.createElement("select");
this.datasrc_combo.setAttribute("title", "Configure where to retrieve node/model information. If set to 'local,' the channel is ignored, and if set to 'channel (remote),' it fetches the latest information each time the list is opened.");
Expand Down Expand Up @@ -809,10 +815,33 @@ class ManagerMenuDialog extends ComfyDialog {

}
});
api.fetchApi('/manager/uv-install')
.then(response => response.json())
.then(data => {
this.use_uv_install_checkbox.checked = data.use_uv_install;

this.use_uv_install_checkbox.addEventListener('change', function (event) {
api.fetchApi(`/manager/uv-install?value=${event.target.checked}`)
.then(response => {
if (response.status !== 200) {
console.error("Failed to update UV Install setting");
}
})
.catch(error => {
console.error("Error updating UV Install setting:", error);
});
});


})
.catch(error => {
console.error("Error fetching initial UV Install setting:", error);
});


return [
$el("div", {}, [this.update_check_checkbox, uc_checkbox_text]),
$el("div", {}, [this.use_uv_install_checkbox, use_uv_checkbox_text]),
$el("br", {}, []),
this.datasrc_combo,
channel_combo,
Expand Down
8 changes: 7 additions & 1 deletion js/custom-nodes-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@ export class CustomNodesManager {

const res = await api.fetchApi(`/customnode/${api_mode}`, {
method: 'POST',
body: JSON.stringify(data)
body: JSON.stringify(manager_instance.use_uv_install_checkbox.checked ? { ...data, noDeps: true } : data)
});

if (res.error) {
Expand Down Expand Up @@ -1257,6 +1257,12 @@ export class CustomNodesManager {

}

if (manager_instance.use_uv_install_checkbox.checked) {
const res = await api.fetchApi(`/customnode/uv-install-deps`, {
method: 'POST',
});
}

target.classList.remove("cn-btn-loading");

if (errorMsg) {
Expand Down
8 changes: 8 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Pytest Unit Tests

## Install test dependencies

`pip install -r tests/requirements.txt`

## Run tests
`pytest tests/`
Empty file added tests/glob_test/__init__.py
Empty file.
37 changes: 37 additions & 0 deletions tests/glob_test/manager_core_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import pytest
import subprocess
import sys
import os

sys.path.append(os.path.join(os.getcwd(), "glob"))
import manager_core

def test_call_cli_dependencies_success(mocker):
"""Test successful execution of call_cli_dependencies()."""
mock_check_output = mocker.patch('subprocess.check_output')
mock_check_output.return_value = "Mocked dependencies output"

result, error_occurred = manager_core.call_cli_dependencies()

assert result == "Mocked dependencies output"
assert error_occurred is False
mock_check_output.assert_called_once_with([sys.executable, '-m', 'comfy_cli', 'dependency'], universal_newlines=True)


def test_call_cli_dependencies_failure(mocker):
"""Test failure case of call_cli_dependencies()."""
mock_check_output = mocker.patch('subprocess.check_output')
mock_check_output.side_effect = subprocess.CalledProcessError(1, 'cmd')

from io import StringIO
import sys
captured_output = StringIO()
sys.stdout = captured_output

result, error_occurred = manager_core.call_cli_dependencies()

sys.stdout = sys.__stdout__

assert result is None
assert error_occurred is True
assert "[ComfyUI-Manager] Failed to execute the command 'python -m comfy_cli dependency'." in captured_output.getvalue()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nl@eof in these files

1 change: 1 addition & 0 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest>=7.8.0