mirror of
https://github.com/Comfy-Org/ComfyUI-Manager.git
synced 2025-12-16 18:02:58 +08:00
improve: black list feature
- check version - support `downgrade_blacklist` in `config.ini` https://github.com/ltdrdata/ComfyUI-Manager/issues/515
This commit is contained in:
parent
f393afc772
commit
d907c45cb0
@ -272,6 +272,13 @@ NODE_CLASS_MAPPINGS.update({
|
|||||||
|
|
||||||
* `Possible(left) + Copy(right)`: When you Double-Click on the left half of the title, it operates as `Possible Input Connections`, and when you Double-Click on the right half, it operates as `Copy All Connections`.
|
* `Possible(left) + Copy(right)`: When you Double-Click on the left half of the title, it operates as `Possible Input Connections`, and when you Double-Click on the right half, it operates as `Copy All Connections`.
|
||||||
|
|
||||||
|
* Prevent downgrade of specific packages
|
||||||
|
* List the package names in the `downgrade_blacklist` section of the `config.ini` file, separating them with commas.
|
||||||
|
* e.g
|
||||||
|
```
|
||||||
|
downgrade_blacklist = diffusers, kornia
|
||||||
|
```
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
* If your `git.exe` is installed in a specific location other than system git, please install ComfyUI-Manager and run ComfyUI. Then, specify the path including the file name in `git_exe = ` in the ComfyUI-Manager/config.ini file that is generated.
|
* If your `git.exe` is installed in a specific location other than system git, please install ComfyUI-Manager and run ComfyUI. Then, specify the path including the file name in `git_exe = ` in the ComfyUI-Manager/config.ini file that is generated.
|
||||||
* If updating ComfyUI-Manager itself fails, please go to the **ComfyUI-Manager** directory and execute the command `git update-ref refs/remotes/origin/main a361cc1 && git fetch --all && git pull`.
|
* If updating ComfyUI-Manager itself fails, please go to the **ComfyUI-Manager** directory and execute the command `git update-ref refs/remotes/origin/main a361cc1 && git fetch --all && git pull`.
|
||||||
|
|||||||
65
__init__.py
65
__init__.py
@ -17,6 +17,7 @@ import re
|
|||||||
import nodes
|
import nodes
|
||||||
import hashlib
|
import hashlib
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from distutils.version import StrictVersion
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -29,7 +30,7 @@ except:
|
|||||||
print(f"[WARN] ComfyUI-Manager: Your ComfyUI version is outdated. Please update to the latest version.")
|
print(f"[WARN] ComfyUI-Manager: Your ComfyUI version is outdated. Please update to the latest version.")
|
||||||
|
|
||||||
|
|
||||||
version = [2, 11]
|
version = [2, 12]
|
||||||
version_str = f"V{version[0]}.{version[1]}" + (f'.{version[2]}' if len(version) > 2 else '')
|
version_str = f"V{version[0]}.{version[1]}" + (f'.{version[2]}' if len(version) > 2 else '')
|
||||||
print(f"### Loading: ComfyUI-Manager ({version_str})")
|
print(f"### Loading: ComfyUI-Manager ({version_str})")
|
||||||
|
|
||||||
@ -38,19 +39,56 @@ comfy_ui_hash = "-"
|
|||||||
|
|
||||||
cache_lock = threading.Lock()
|
cache_lock = threading.Lock()
|
||||||
|
|
||||||
|
pip_map = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_installed_packages():
|
||||||
|
global pip_map
|
||||||
|
|
||||||
|
if pip_map is None:
|
||||||
|
try:
|
||||||
|
result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True)
|
||||||
|
|
||||||
|
pip_map = {}
|
||||||
|
for line in result.split('\n'):
|
||||||
|
x = line.strip()
|
||||||
|
if x:
|
||||||
|
y = line.split()
|
||||||
|
if y[0] == 'Package' or y[0].startswith('-'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
pip_map[y[0]] = y[1]
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.")
|
||||||
|
return set()
|
||||||
|
|
||||||
|
return pip_map
|
||||||
|
|
||||||
|
|
||||||
|
def clear_pip_cache():
|
||||||
|
global pip_map
|
||||||
|
pip_map = None
|
||||||
|
|
||||||
|
|
||||||
def is_blacklisted(name):
|
def is_blacklisted(name):
|
||||||
name = name.strip()
|
name = name.strip()
|
||||||
|
|
||||||
pattern = r'([^<>!=]+)([<>!=]=?)'
|
pattern = r'([^<>!=]+)([<>!=]=?)(.*)'
|
||||||
match = re.search(pattern, name)
|
match = re.search(pattern, name)
|
||||||
|
|
||||||
if match:
|
if match:
|
||||||
name = match.group(1)
|
name = match.group(1)
|
||||||
|
|
||||||
if name in cm_global.pip_downgrade_blacklist:
|
if name in cm_global.pip_downgrade_blacklist:
|
||||||
if match is None or match.group(2) in ['<=', '==', '<']:
|
pips = get_installed_packages()
|
||||||
return True
|
|
||||||
|
if match is None:
|
||||||
|
if name in pips:
|
||||||
|
return True
|
||||||
|
elif match.group(2) in ['<=', '==', '<']:
|
||||||
|
if name in pips:
|
||||||
|
if StrictVersion(pips[name]) >= StrictVersion(match.group(3)):
|
||||||
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -194,7 +232,8 @@ def write_config():
|
|||||||
'component_policy': get_config()['component_policy'],
|
'component_policy': get_config()['component_policy'],
|
||||||
'double_click_policy': get_config()['double_click_policy'],
|
'double_click_policy': get_config()['double_click_policy'],
|
||||||
'windows_selector_event_loop_policy': get_config()['windows_selector_event_loop_policy'],
|
'windows_selector_event_loop_policy': get_config()['windows_selector_event_loop_policy'],
|
||||||
'model_download_by_agent': get_config()['model_download_by_agent']
|
'model_download_by_agent': get_config()['model_download_by_agent'],
|
||||||
|
'downgrade_blacklist': get_config()['downgrade_blacklist']
|
||||||
}
|
}
|
||||||
with open(config_path, 'w') as configfile:
|
with open(config_path, 'w') as configfile:
|
||||||
config.write(configfile)
|
config.write(configfile)
|
||||||
@ -219,6 +258,7 @@ def read_config():
|
|||||||
'double_click_policy': default_conf['double_click_policy'] if 'double_click_policy' in default_conf else 'copy-all',
|
'double_click_policy': default_conf['double_click_policy'] if 'double_click_policy' in default_conf else 'copy-all',
|
||||||
'windows_selector_event_loop_policy': default_conf['windows_selector_event_loop_policy'] if 'windows_selector_event_loop_policy' in default_conf else False,
|
'windows_selector_event_loop_policy': default_conf['windows_selector_event_loop_policy'] if 'windows_selector_event_loop_policy' in default_conf else False,
|
||||||
'model_download_by_agent': default_conf['model_download_by_agent'] if 'model_download_by_agent' in default_conf else False,
|
'model_download_by_agent': default_conf['model_download_by_agent'] if 'model_download_by_agent' in default_conf else False,
|
||||||
|
'downgrade_blacklist': default_conf['downgrade_blacklist'] if 'downgrade_blacklist' in default_conf else '',
|
||||||
}
|
}
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
@ -235,6 +275,7 @@ def read_config():
|
|||||||
'double_click_policy': 'copy-all',
|
'double_click_policy': 'copy-all',
|
||||||
'windows_selector_event_loop_policy': False,
|
'windows_selector_event_loop_policy': False,
|
||||||
'model_download_by_agent': False,
|
'model_download_by_agent': False,
|
||||||
|
'downgrade_blacklist': ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -307,7 +348,6 @@ def try_install_script(url, repo_path, install_cmd):
|
|||||||
print(f"[ComfyUI-Manager] skip black listed pip installation: '{install_cmd[4]}'")
|
print(f"[ComfyUI-Manager] skip black listed pip installation: '{install_cmd[4]}'")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
print(f"\n## ComfyUI-Manager: EXECUTE => {install_cmd}")
|
print(f"\n## ComfyUI-Manager: EXECUTE => {install_cmd}")
|
||||||
code = run_script(install_cmd, cwd=repo_path)
|
code = run_script(install_cmd, cwd=repo_path)
|
||||||
|
|
||||||
@ -831,6 +871,7 @@ def nickname_filter(json_obj):
|
|||||||
|
|
||||||
return json_obj
|
return json_obj
|
||||||
|
|
||||||
|
|
||||||
@server.PromptServer.instance.routes.get("/customnode/getmappings")
|
@server.PromptServer.instance.routes.get("/customnode/getmappings")
|
||||||
async def fetch_customnode_mappings(request):
|
async def fetch_customnode_mappings(request):
|
||||||
mode = request.rel_url.query["mode"]
|
mode = request.rel_url.query["mode"]
|
||||||
@ -903,6 +944,8 @@ async def update_all(request):
|
|||||||
return web.json_response(res, status=status, content_type='application/json')
|
return web.json_response(res, status=status, content_type='application/json')
|
||||||
except:
|
except:
|
||||||
return web.Response(status=400)
|
return web.Response(status=400)
|
||||||
|
finally:
|
||||||
|
clear_pip_cache()
|
||||||
|
|
||||||
|
|
||||||
def convert_markdown_to_html(input_text):
|
def convert_markdown_to_html(input_text):
|
||||||
@ -1586,6 +1629,8 @@ async def install_custom_node(request):
|
|||||||
install_cmd = [sys.executable, "-m", "pip", "install", pname]
|
install_cmd = [sys.executable, "-m", "pip", "install", pname]
|
||||||
try_install_script(json_data['files'][0], ".", install_cmd)
|
try_install_script(json_data['files'][0], ".", install_cmd)
|
||||||
|
|
||||||
|
clear_pip_cache()
|
||||||
|
|
||||||
if res:
|
if res:
|
||||||
print(f"After restarting ComfyUI, please refresh the browser.")
|
print(f"After restarting ComfyUI, please refresh the browser.")
|
||||||
return web.json_response({}, content_type='application/json')
|
return web.json_response({}, content_type='application/json')
|
||||||
@ -1684,6 +1729,8 @@ async def update_custom_node(request):
|
|||||||
if install_type == "git-clone":
|
if install_type == "git-clone":
|
||||||
res = gitclone_update(json_data['files'])
|
res = gitclone_update(json_data['files'])
|
||||||
|
|
||||||
|
clear_pip_cache()
|
||||||
|
|
||||||
if res:
|
if res:
|
||||||
print(f"After restarting ComfyUI, please refresh the browser.")
|
print(f"After restarting ComfyUI, please refresh the browser.")
|
||||||
return web.json_response({}, content_type='application/json')
|
return web.json_response({}, content_type='application/json')
|
||||||
@ -2132,6 +2179,7 @@ if hasattr(server.PromptServer.instance, "app"):
|
|||||||
cors_middleware = server.create_cors_middleware(args.enable_cors_header)
|
cors_middleware = server.create_cors_middleware(args.enable_cors_header)
|
||||||
app.middlewares.append(cors_middleware)
|
app.middlewares.append(cors_middleware)
|
||||||
|
|
||||||
|
|
||||||
@server.PromptServer.instance.routes.post("/manager/set_esheep_workflow_and_images")
|
@server.PromptServer.instance.routes.post("/manager/set_esheep_workflow_and_images")
|
||||||
async def set_esheep_workflow_and_images(request):
|
async def set_esheep_workflow_and_images(request):
|
||||||
json_data = await request.json()
|
json_data = await request.json()
|
||||||
@ -2141,12 +2189,14 @@ async def set_esheep_workflow_and_images(request):
|
|||||||
json.dump(json_data, file, indent=4)
|
json.dump(json_data, file, indent=4)
|
||||||
return web.Response(status=200)
|
return web.Response(status=200)
|
||||||
|
|
||||||
|
|
||||||
@server.PromptServer.instance.routes.get("/manager/get_esheep_workflow_and_images")
|
@server.PromptServer.instance.routes.get("/manager/get_esheep_workflow_and_images")
|
||||||
async def get_esheep_workflow_and_images(request):
|
async def get_esheep_workflow_and_images(request):
|
||||||
with open(os.path.join(comfyui_manager_path, "esheep_share_message.json"), 'r', encoding='utf-8') as file:
|
with open(os.path.join(comfyui_manager_path, "esheep_share_message.json"), 'r', encoding='utf-8') as file:
|
||||||
data = json.load(file)
|
data = json.load(file)
|
||||||
return web.Response(status=200, text=json.dumps(data))
|
return web.Response(status=200, text=json.dumps(data))
|
||||||
|
|
||||||
|
|
||||||
def set_matrix_auth(json_data):
|
def set_matrix_auth(json_data):
|
||||||
homeserver = json_data['homeserver']
|
homeserver = json_data['homeserver']
|
||||||
username = json_data['username']
|
username = json_data['username']
|
||||||
@ -2188,6 +2238,7 @@ def extract_model_file_names(json_data):
|
|||||||
recursive_search(json_data)
|
recursive_search(json_data)
|
||||||
return [f for f in list(file_names) if os.path.splitext(f)[1] in model_filename_extensions]
|
return [f for f in list(file_names) if os.path.splitext(f)[1] in model_filename_extensions]
|
||||||
|
|
||||||
|
|
||||||
def find_file_paths(base_dir, file_names):
|
def find_file_paths(base_dir, file_names):
|
||||||
"""Find the paths of the files in the base directory."""
|
"""Find the paths of the files in the base directory."""
|
||||||
file_paths = {}
|
file_paths = {}
|
||||||
@ -2201,6 +2252,7 @@ def find_file_paths(base_dir, file_names):
|
|||||||
file_paths[file] = os.path.join(root, file)
|
file_paths[file] = os.path.join(root, file)
|
||||||
return file_paths
|
return file_paths
|
||||||
|
|
||||||
|
|
||||||
def compute_sha256_checksum(filepath):
|
def compute_sha256_checksum(filepath):
|
||||||
"""Compute the SHA256 checksum of a file, in chunks"""
|
"""Compute the SHA256 checksum of a file, in chunks"""
|
||||||
sha256 = hashlib.sha256()
|
sha256 = hashlib.sha256()
|
||||||
@ -2209,6 +2261,7 @@ def compute_sha256_checksum(filepath):
|
|||||||
sha256.update(chunk)
|
sha256.update(chunk)
|
||||||
return sha256.hexdigest()
|
return sha256.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
@server.PromptServer.instance.routes.post("/manager/share")
|
@server.PromptServer.instance.routes.post("/manager/share")
|
||||||
async def share_art(request):
|
async def share_art(request):
|
||||||
# get json data
|
# get json data
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import threading
|
|||||||
import re
|
import re
|
||||||
import locale
|
import locale
|
||||||
import platform
|
import platform
|
||||||
|
from distutils.version import StrictVersion
|
||||||
|
|
||||||
|
|
||||||
glob_path = os.path.join(os.path.dirname(__file__), "glob")
|
glob_path = os.path.join(os.path.dirname(__file__), "glob")
|
||||||
@ -292,6 +293,26 @@ else:
|
|||||||
print("** Log path: file logging is disabled")
|
print("** Log path: file logging is disabled")
|
||||||
|
|
||||||
|
|
||||||
|
def read_downgrade_blacklist():
|
||||||
|
try:
|
||||||
|
import configparser
|
||||||
|
config_path = os.path.join(os.path.dirname(__file__), "config.ini")
|
||||||
|
config = configparser.ConfigParser()
|
||||||
|
config.read(config_path)
|
||||||
|
default_conf = config['default']
|
||||||
|
|
||||||
|
if 'downgrade_blacklist' in default_conf:
|
||||||
|
items = default_conf['downgrade_blacklist'].split(',')
|
||||||
|
items = [x.strip() for x in items if x != '']
|
||||||
|
cm_global.pip_downgrade_blacklist += items
|
||||||
|
cm_global.pip_downgrade_blacklist = list(set(cm_global.pip_downgrade_blacklist))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
read_downgrade_blacklist()
|
||||||
|
|
||||||
|
|
||||||
def check_bypass_ssl():
|
def check_bypass_ssl():
|
||||||
try:
|
try:
|
||||||
import configparser
|
import configparser
|
||||||
@ -314,21 +335,30 @@ check_bypass_ssl()
|
|||||||
# Perform install
|
# Perform install
|
||||||
processed_install = set()
|
processed_install = set()
|
||||||
script_list_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "startup-scripts", "install-scripts.txt")
|
script_list_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "startup-scripts", "install-scripts.txt")
|
||||||
pip_list = None
|
pip_map = None
|
||||||
|
|
||||||
|
|
||||||
def get_installed_packages():
|
def get_installed_packages():
|
||||||
global pip_list
|
global pip_map
|
||||||
|
|
||||||
if pip_list is None:
|
if pip_map is None:
|
||||||
try:
|
try:
|
||||||
result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True)
|
result = subprocess.check_output([sys.executable, '-m', 'pip', 'list'], universal_newlines=True)
|
||||||
pip_list = set([line.split()[0].lower() for line in result.split('\n') if line.strip()])
|
|
||||||
|
pip_map = {}
|
||||||
|
for line in result.split('\n'):
|
||||||
|
x = line.strip()
|
||||||
|
if x:
|
||||||
|
y = line.split()
|
||||||
|
if y[0] == 'Package' or y[0].startswith('-'):
|
||||||
|
continue
|
||||||
|
|
||||||
|
pip_map[y[0]] = y[1]
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print(f"[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.")
|
print(f"[ComfyUI-Manager] Failed to retrieve the information of installed pip packages.")
|
||||||
return set()
|
return set()
|
||||||
|
|
||||||
return pip_list
|
return pip_map
|
||||||
|
|
||||||
|
|
||||||
def is_installed(name):
|
def is_installed(name):
|
||||||
@ -337,16 +367,23 @@ def is_installed(name):
|
|||||||
if name.startswith('#'):
|
if name.startswith('#'):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
pattern = r'([^<>!=]+)([<>!=]=?)'
|
pattern = r'([^<>!=]+)([<>!=]=?)(.*)'
|
||||||
match = re.search(pattern, name)
|
match = re.search(pattern, name)
|
||||||
|
|
||||||
if match:
|
if match:
|
||||||
name = match.group(1)
|
name = match.group(1)
|
||||||
|
|
||||||
if name in cm_global.pip_downgrade_blacklist:
|
if name in cm_global.pip_downgrade_blacklist:
|
||||||
if match is None or match.group(2) in ['<=', '==', '<']:
|
pips = get_installed_packages()
|
||||||
print(f"[ComfyUI-Manager] skip black listed pip installation: '{name}'")
|
|
||||||
return True
|
if match is None:
|
||||||
|
if name in pips:
|
||||||
|
return True
|
||||||
|
elif match.group(2) in ['<=', '==', '<']:
|
||||||
|
if name in pips:
|
||||||
|
if StrictVersion(pips[name]) >= StrictVersion(match.group(3)):
|
||||||
|
print(f"[ComfyUI-Manager] skip black listed pip installation: '{name}'")
|
||||||
|
return True
|
||||||
|
|
||||||
return name.lower() in get_installed_packages()
|
return name.lower() in get_installed_packages()
|
||||||
|
|
||||||
@ -499,7 +536,7 @@ if os.path.exists(script_list_path):
|
|||||||
print("#######################################################################\n")
|
print("#######################################################################\n")
|
||||||
|
|
||||||
del processed_install
|
del processed_install
|
||||||
del pip_list
|
del pip_map
|
||||||
|
|
||||||
|
|
||||||
def check_windows_event_loop_policy():
|
def check_windows_event_loop_policy():
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user