diff --git a/__init__.py b/__init__.py index 0613020..90fc302 100644 --- a/__init__.py +++ b/__init__.py @@ -20,7 +20,7 @@ import nodes import torch -version = [1, 16] +version = [1, 17] version_str = f"V{version[0]}.{version[1]}" + (f'.{version[2]}' if len(version) > 2 else '') print(f"### Loading: ComfyUI-Manager ({version_str})") @@ -1198,6 +1198,7 @@ class GitProgress(RemoteProgress): self.pbar.pos = 0 self.pbar.refresh() + def is_valid_url(url): try: result = urlparse(url) @@ -1205,6 +1206,7 @@ def is_valid_url(url): except ValueError: return False + def gitclone_install(files): print(f"install: {files}") for url in files: @@ -1240,6 +1242,11 @@ def gitclone_install(files): return True +def pip_install(packages): + install_cmd = ['#FORCE', sys.executable, "-m", "pip", "install", '-U'] + packages + try_install_script('pip install via manager', '.', install_cmd) + + import platform import subprocess import time @@ -1430,6 +1437,16 @@ async def install_custom_node_git_url(request): return web.Response(status=400) +@server.PromptServer.instance.routes.get("/customnode/install/pip") +async def install_custom_node_git_url(request): + res = False + if "packages" in request.rel_url.query: + packages = request.rel_url.query['packages'] + pip_install(packages.split(' ')) + + return web.Response(status=200) + + @server.PromptServer.instance.routes.post("/customnode/uninstall") async def uninstall_custom_node(request): json_data = await request.json() diff --git a/js/comfyui-manager.js b/js/comfyui-manager.js index 282b260..063851e 100644 --- a/js/comfyui-manager.js +++ b/js/comfyui-manager.js @@ -7,13 +7,13 @@ import { CustomNodesInstaller } from "./custom-nodes-downloader.js"; import { AlternativesInstaller } from "./a1111-alter-downloader.js"; import { SnapshotManager } from "./snapshot.js"; import { ModelInstaller } from "./model-downloader.js"; -import { manager_instance, setManagerInstance, install_via_git_url, rebootAPI } from "./common.js"; +import { manager_instance, setManagerInstance, install_via_git_url, install_pip, rebootAPI } from "./common.js"; var docStyle = document.createElement('style'); docStyle.innerHTML = ` #cm-manager-dialog { width: 1000px; - height: 420px; + height: 450px; box-sizing: content-box; z-index: 10000; } @@ -782,6 +782,18 @@ class ManagerMenuDialog extends ComfyDialog { SnapshotManager.instance = new SnapshotManager(app, self); SnapshotManager.instance.show(); } + }), + $el("button.cm-experimental-button", { + type: "button", + textContent: "Install PIP packages", + onclick: + () => { + var url = prompt("Please enumerate the pip packages to be installed.\n\nExample: insightface opencv-python-headless>=4.1.1\n", ""); + + if (url !== null) { + install_pip(url, self); + } + } }) ]), ]; diff --git a/js/common.js b/js/common.js index c507ddd..4719517 100644 --- a/js/common.js +++ b/js/common.js @@ -80,10 +80,35 @@ export function setManagerInstance(obj) { } function isValidURL(url) { + if(url.includes('&')) + return false; + const pattern = /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/; return pattern.test(url); } +export async function install_pip(packages) { + if(packages.includes('&')) + app.ui.dialog.show(`Invalid PIP package enumeration: '${packages}'`); + + const res = await api.fetchApi(`/customnode/install/pip?packages=${packages}`); + + if(res.status == 200) { + app.ui.dialog.show(`PIP package installation is processed.
To apply the pip packages, please click the button in ComfyUI.`); + + const rebootButton = document.getElementById('cm-reboot-button'); + const self = this; + + rebootButton.addEventListener("click", rebootAPI); + + app.ui.dialog.element.style.zIndex = 10010; + } + else { + app.ui.dialog.show(`Failed to install '${packages}'
See terminal log.`); + app.ui.dialog.element.style.zIndex = 10010; + } +} + export async function install_via_git_url(url, manager_dialog) { if(!url) { return; diff --git a/prestartup_script.py b/prestartup_script.py index 8d472cb..474744f 100644 --- a/prestartup_script.py +++ b/prestartup_script.py @@ -410,13 +410,16 @@ if os.path.exists(script_list_path): try: script = eval(line) - if script[1].startswith('#'): + if script[1].startswith('#') and script[1] != '#FORCE': if script[1] == "#LAZY-INSTALL-SCRIPT": execute_lazy_install_script(script[0], script[2]) elif os.path.exists(script[0]): - if 'pip' in script[1:] and 'install' in script[1:] and is_installed(script[-1]): - continue + if script[1] == "#FORCE": + del script[1] + else: + if 'pip' in script[1:] and 'install' in script[1:] and is_installed(script[-1]): + continue print(f"\n## ComfyUI-Manager: EXECUTE => {script[1:]}") print(f"\n## Execute install/(de)activation script for '{script[0]}'")