Compare commits

..

5 Commits

Author SHA1 Message Date
Dr.Lt.Data
8b8be0af05
Merge 2866193baf into 2779c66b39 2025-12-15 04:02:01 +00:00
Dr.Lt.Data
2779c66b39 feat(version): apply semver-based version sorting to glob and add master fallback
Some checks failed
Publish to PyPI / build-and-publish (push) Has been cancelled
Python Linting / Run Ruff (push) Has been cancelled
- Apply PR #2334 changes to glob/manager_core.py (was only in legacy)
- Add master branch fallback when remote/HEAD reference is unavailable
2025-12-15 03:39:13 +09:00
Dr.Lt.Data
952613c07b fix(api): improve import_fail_info_bulk lookup for cnr_id and aux_id
- Add aux_id format (author/repo) support in normalize_to_github_id()
- Fix get_module_name() to use URL normalization for unknown_active_nodes
- Use NormalizedKeyDict in reload() to maintain normalized key lookup
2025-12-15 02:54:30 +09:00
Benjamin Lu
75f27d99e2 ComfyUI version listing + nightly current fix (#2334)
* Improve comfyui version listing

* Fix ComfyUI semver selection and stable update

* Fix nightly current detection on default branch

* Fix: use tag_ref.name explicitly and cache get_remote_name result

- Use tag_ref.name instead of tag_ref object for checkout
- Cache get_remote_name() result to avoid duplicate calls

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Dr.Lt.Data <dr.lt.data@gmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 23:12:01 +09:00
Dr.Lt.Data
8e8b6ca724 fix(git): handle divergent branches safely + datetime fallback
- Use --ff-only flag to detect non-fast-forward situations
- Create backup branch before resetting divergent local branch
- Reset to remote branch when fast-forward is not possible
- Add timestamp_utils.py for Mac datetime module compatibility
- Migrate all datetime usages to centralized utilities
- Bump version to 4.0.3b5

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-12 22:45:05 +09:00
10 changed files with 388 additions and 105 deletions

View File

@ -0,0 +1,17 @@
from .timestamp_utils import (
current_timestamp,
get_timestamp_for_filename,
get_timestamp_for_path,
get_backup_branch_name,
get_now,
get_unix_timestamp,
)
__all__ = [
'current_timestamp',
'get_timestamp_for_filename',
'get_timestamp_for_path',
'get_backup_branch_name',
'get_now',
'get_unix_timestamp',
]

View File

@ -9,6 +9,7 @@ import yaml
import requests
from tqdm.auto import tqdm
from git.remote import RemoteProgress
from comfyui_manager.common.timestamp_utils import get_backup_branch_name
comfy_path = os.environ.get('COMFYUI_PATH')
@ -222,7 +223,14 @@ def gitpull(path):
repo.close()
return
remote.pull()
try:
repo.git.pull('--ff-only')
except git.GitCommandError:
backup_name = get_backup_branch_name(repo)
repo.create_head(backup_name)
print(f"[ComfyUI-Manager] Cannot fast-forward. Backup created: {backup_name}")
repo.git.reset('--hard', f'{remote_name}/{branch_name}')
print(f"[ComfyUI-Manager] Reset to {remote_name}/{branch_name}")
repo.git.submodule('update', '--init', '--recursive')
new_commit_hash = repo.head.commit.hexsha

View File

@ -74,6 +74,12 @@ def normalize_to_github_id(url) -> str:
return f"{author}/{repo_name}"
# Handle short format like "author/repo" (aux_id format)
if '/' in url and not url.startswith('http'):
parts = url.split('/')
if len(parts) == 2 and parts[0] and parts[1]:
return url
return None

View File

@ -8,13 +8,13 @@ import aiohttp
import json
import threading
import os
from datetime import datetime
import subprocess
import sys
import re
import logging
import platform
import shlex
import time
from functools import lru_cache
@ -176,7 +176,7 @@ def is_file_created_within_one_day(file_path):
return False
file_creation_time = os.path.getctime(file_path)
current_time = datetime.now().timestamp()
current_time = time.time()
time_difference = current_time - file_creation_time
return time_difference <= 86400

View File

@ -0,0 +1,136 @@
"""
Robust timestamp utilities with datetime fallback.
Some environments (especially Mac) have issues with the datetime module
due to local file name conflicts or Homebrew Python module path issues.
"""
import logging
import time as time_module
import uuid
_datetime_available = None
_dt_datetime = None
def _init_datetime():
"""Initialize datetime availability check (lazy, once)."""
global _datetime_available, _dt_datetime
if _datetime_available is not None:
return
try:
import datetime as dt
if hasattr(dt, 'datetime'):
from datetime import datetime as dt_datetime
_dt_datetime = dt_datetime
_datetime_available = True
return
except Exception as e:
logging.debug(f"[ComfyUI-Manager] datetime import failed: {e}")
_datetime_available = False
logging.warning("[ComfyUI-Manager] datetime unavailable, using time module fallback")
def current_timestamp() -> str:
"""
Get current timestamp for logging.
Format: YYYY-MM-DD HH:MM:SS.mmm (or Unix timestamp if fallback)
"""
_init_datetime()
if _datetime_available:
return _dt_datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
return str(time_module.time()).split('.')[0]
def get_timestamp_for_filename() -> str:
"""
Get timestamp suitable for filenames.
Format: YYYYMMDD_HHMMSS
"""
_init_datetime()
if _datetime_available:
return _dt_datetime.now().strftime('%Y%m%d_%H%M%S')
return time_module.strftime('%Y%m%d_%H%M%S')
def get_timestamp_for_path() -> str:
"""
Get timestamp for path/directory names.
Format: YYYY-MM-DD_HH-MM-SS
"""
_init_datetime()
if _datetime_available:
return _dt_datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
return time_module.strftime('%Y-%m-%d_%H-%M-%S')
def get_backup_branch_name(repo=None) -> str:
"""
Get backup branch name with current timestamp.
Format: backup_YYYYMMDD_HHMMSS (or backup_YYYYMMDD_HHMMSS_N if exists)
Args:
repo: Optional git.Repo object. If provided, checks for name collisions
and adds sequential suffix if needed.
Returns:
Unique backup branch name.
"""
base_name = f'backup_{get_timestamp_for_filename()}'
if repo is None:
return base_name
# Check if branch exists
try:
existing_branches = {b.name for b in repo.heads}
except Exception:
return base_name
if base_name not in existing_branches:
return base_name
# Add sequential suffix
for i in range(1, 100):
new_name = f'{base_name}_{i}'
if new_name not in existing_branches:
return new_name
# Ultimate fallback: use UUID (very unlikely to reach here)
return f'{base_name}_{uuid.uuid4().hex[:6]}'
def get_now():
"""
Get current datetime object.
Returns datetime.now() if available, otherwise a FakeDatetime object
that supports basic operations (timestamp(), strftime()).
"""
_init_datetime()
if _datetime_available:
return _dt_datetime.now()
# Fallback: return object with basic datetime-like interface
t = time_module.localtime()
class FakeDatetime:
def timestamp(self):
return time_module.time()
def strftime(self, fmt):
return time_module.strftime(fmt, t)
def isoformat(self):
return time_module.strftime('%Y-%m-%dT%H:%M:%S', t)
return FakeDatetime()
def get_unix_timestamp() -> float:
"""Get current Unix timestamp."""
_init_datetime()
if _datetime_available:
return _dt_datetime.now().timestamp()
return time_module.time()

View File

@ -12,9 +12,9 @@ import re
import shutil
import configparser
import platform
from datetime import datetime
import git
from comfyui_manager.common.timestamp_utils import get_timestamp_for_path, get_backup_branch_name
from git.remote import RemoteProgress
from urllib.parse import urlparse
from tqdm.auto import tqdm
@ -384,8 +384,10 @@ class UnifiedManager:
def get_module_name(self, x):
info = self.active_nodes.get(x)
if info is None:
# Try to find in unknown_active_nodes by comparing normalized URLs
normalized_x = git_utils.normalize_url(x)
for url, fullpath in self.unknown_active_nodes.values():
if url == x:
if url is not None and git_utils.normalize_url(url) == normalized_x:
return os.path.basename(fullpath)
else:
return os.path.basename(info[1])
@ -700,11 +702,11 @@ class UnifiedManager:
import folder_paths
self.custom_node_map_cache = {}
self.cnr_inactive_nodes = {} # node_id -> node_version -> fullpath
self.nightly_inactive_nodes = {} # node_id -> fullpath
self.cnr_inactive_nodes = NormalizedKeyDict() # node_id -> node_version -> fullpath
self.nightly_inactive_nodes = NormalizedKeyDict() # node_id -> fullpath
self.unknown_inactive_nodes = {} # node_id -> repo url * fullpath
self.unknown_active_nodes = {} # node_id -> repo url * fullpath
self.active_nodes = {} # node_id -> node_version * fullpath
self.active_nodes = NormalizedKeyDict() # node_id -> node_version * fullpath
if get_config()['network_mode'] != 'public' or manager_util.is_manager_pip_package():
dont_wait = True
@ -2000,7 +2002,15 @@ def git_repo_update_check_with(path, do_fetch=False, do_update=False, no_deps=Fa
return False, True
try:
remote.pull()
try:
repo.git.pull('--ff-only')
except git.GitCommandError:
backup_name = get_backup_branch_name(repo)
repo.create_head(backup_name)
logging.info(f"[ComfyUI-Manager] Cannot fast-forward. Backup created: {backup_name}")
repo.git.reset('--hard', f'{remote_name}/{branch_name}')
logging.info(f"[ComfyUI-Manager] Reset to {remote_name}/{branch_name}")
repo.git.submodule('update', '--init', '--recursive')
new_commit_hash = repo.head.commit.hexsha
@ -2169,9 +2179,17 @@ def git_pull(path):
current_branch = repo.active_branch
remote_name = current_branch.tracking_branch().remote_name
remote = repo.remote(name=remote_name)
branch_name = current_branch.name
try:
repo.git.pull('--ff-only')
except git.GitCommandError:
backup_name = get_backup_branch_name(repo)
repo.create_head(backup_name)
logging.info(f"[ComfyUI-Manager] Cannot fast-forward. Backup created: {backup_name}")
repo.git.reset('--hard', f'{remote_name}/{branch_name}')
logging.info(f"[ComfyUI-Manager] Reset to {remote_name}/{branch_name}")
remote.pull()
repo.git.submodule('update', '--init', '--recursive')
repo.close()
@ -2439,22 +2457,22 @@ def update_to_stable_comfyui(repo_path):
logging.error('\t'+branch.name)
return "fail", None
versions, current_tag, _ = get_comfyui_versions(repo)
if len(versions) == 0 or (len(versions) == 1 and versions[0] == 'nightly'):
versions, current_tag, latest_tag = get_comfyui_versions(repo)
if latest_tag is None:
logging.info("[ComfyUI-Manager] Unable to update to the stable ComfyUI version.")
return "fail", None
if versions[0] == 'nightly':
latest_tag = versions[1]
else:
latest_tag = versions[0]
if current_tag == latest_tag:
tag_ref = next((t for t in repo.tags if t.name == latest_tag), None)
if tag_ref is None:
logging.info(f"[ComfyUI-Manager] Unable to locate tag '{latest_tag}' in repository.")
return "fail", None
if repo.head.commit == tag_ref.commit:
return "skip", None
else:
logging.info(f"[ComfyUI-Manager] Updating ComfyUI: {current_tag} -> {latest_tag}")
repo.git.checkout(latest_tag)
repo.git.checkout(tag_ref.name)
execute_install_script("ComfyUI", repo_path, instant_execution=False, no_deps=False)
return 'updated', latest_tag
except Exception:
@ -2681,9 +2699,7 @@ async def get_current_snapshot(custom_nodes_only = False):
async def save_snapshot_with_postfix(postfix, path=None, custom_nodes_only = False):
if path is None:
now = datetime.now()
date_time_format = now.strftime("%Y-%m-%d_%H-%M-%S")
date_time_format = get_timestamp_for_path()
file_name = f"{date_time_format}_{postfix}"
path = os.path.join(context.manager_snapshot_path, f"{file_name}.json")
@ -3274,36 +3290,85 @@ async def restore_snapshot(snapshot_path, git_helper_extras=None):
def get_comfyui_versions(repo=None):
if repo is None:
repo = git.Repo(context.comfy_path)
repo = repo or git.Repo(context.comfy_path)
remote_name = None
try:
remote = get_remote_name(repo)
repo.remotes[remote].fetch()
remote_name = get_remote_name(repo)
repo.remotes[remote_name].fetch()
except Exception:
logging.error("[ComfyUI-Manager] Failed to fetch ComfyUI")
versions = [x.name for x in repo.tags if x.name.startswith('v')]
def parse_semver(tag_name):
match = re.match(r'^v(\d+)\.(\d+)\.(\d+)$', tag_name)
return tuple(int(x) for x in match.groups()) if match else None
# nearest tag
versions = sorted(versions, key=lambda v: repo.git.log('-1', '--format=%ct', v), reverse=True)
versions = versions[:4]
def normalize_describe(tag_name):
if not tag_name:
return None
base = tag_name.split('-', 1)[0]
return base if parse_semver(base) else None
current_tag = repo.git.describe('--tags')
# Collect semver tags and sort descending (highest first)
semver_tags = []
for tag in repo.tags:
semver = parse_semver(tag.name)
if semver:
semver_tags.append((semver, tag.name))
semver_tags.sort(key=lambda x: x[0], reverse=True)
semver_tags = [name for _, name in semver_tags]
if current_tag not in versions:
versions = sorted(versions + [current_tag], key=lambda v: repo.git.log('-1', '--format=%ct', v), reverse=True)
versions = versions[:4]
latest_tag = semver_tags[0] if semver_tags else None
main_branch = repo.heads.master
latest_commit = main_branch.commit
latest_tag = repo.git.describe('--tags', latest_commit.hexsha)
try:
described = repo.git.describe('--tags')
except Exception:
described = ''
if latest_tag != versions[0]:
versions.insert(0, 'nightly')
else:
versions[0] = 'nightly'
try:
exact_tag = repo.git.describe('--tags', '--exact-match')
except Exception:
exact_tag = ''
head_is_default = False
if remote_name:
try:
default_head_ref = repo.refs[f'{remote_name}/HEAD']
default_commit = default_head_ref.reference.commit
head_is_default = repo.head.commit == default_commit
except Exception:
# Fallback: compare directly with master branch
try:
if 'master' in [h.name for h in repo.heads]:
head_is_default = repo.head.commit == repo.heads.master.commit
except Exception:
head_is_default = False
nearest_semver = normalize_describe(described)
exact_semver = exact_tag if parse_semver(exact_tag) else None
if head_is_default and not exact_tag:
current_tag = 'nightly'
else:
current_tag = exact_tag or described or 'nightly'
# Prepare semver list for display: top 4 plus the current/nearest semver if missing
display_semver_tags = semver_tags[:4]
if exact_semver and exact_semver not in display_semver_tags:
display_semver_tags.append(exact_semver)
elif nearest_semver and nearest_semver not in display_semver_tags:
display_semver_tags.append(nearest_semver)
versions = ['nightly']
if current_tag and not exact_semver and current_tag not in versions and current_tag not in display_semver_tags:
versions.append(current_tag)
for tag in display_semver_tags:
if tag not in versions:
versions.append(tag)
versions = versions[:6]
return versions, current_tag, latest_tag

View File

@ -20,10 +20,12 @@ import threading
import traceback
import urllib.request
import uuid
import time
import zipfile
from datetime import datetime, timedelta
from typing import Any, Optional
from comfyui_manager.common.timestamp_utils import get_timestamp_for_filename, get_now
import folder_paths
import latent_preview
import nodes
@ -267,9 +269,9 @@ class TaskQueue:
def _start_new_batch(self) -> None:
"""Start a new batch session for tracking operations."""
self.batch_id = (
f"batch_{datetime.now().strftime('%Y%m%d_%H%M%S')}_{uuid.uuid4().hex[:8]}"
f"batch_{get_timestamp_for_filename()}_{uuid.uuid4().hex[:8]}"
)
self.batch_start_time = datetime.now().isoformat()
self.batch_start_time = get_now().isoformat()
self.batch_state_before = self._capture_system_state()
logging.debug("[ComfyUI-Manager] Started new batch: %s", self.batch_id)
@ -300,7 +302,7 @@ class TaskQueue:
MessageTaskStarted(
ui_id=item.ui_id,
kind=item.kind,
timestamp=datetime.now(),
timestamp=get_now(),
state=self.get_current_state(),
),
client_id=item.client_id, # Send task started only to the client that requested it
@ -317,8 +319,7 @@ class TaskQueue:
"""Mark task as completed and add to history"""
with self.mutex:
now = datetime.now()
timestamp = now.isoformat()
now = get_now()
# Remove task from running_tasks using the task_index
self.running_tasks.pop(task_index, None)
@ -383,7 +384,7 @@ class TaskQueue:
result=result_msg,
kind=item.kind,
status=status,
timestamp=datetime.fromisoformat(timestamp),
timestamp=now,
state=self.get_current_state(),
),
client_id=item.client_id, # Send completion only to the client that requested it
@ -494,7 +495,7 @@ class TaskQueue:
)
try:
end_time = datetime.now().isoformat()
end_time = get_now().isoformat()
state_after = self._capture_system_state()
operations = self._extract_batch_operations()
@ -562,7 +563,7 @@ class TaskQueue:
"""Capture current ComfyUI system state for batch record."""
logging.debug("[ComfyUI-Manager] Capturing system state for batch record")
return ComfyUISystemState(
snapshot_time=datetime.now().isoformat(),
snapshot_time=get_now().isoformat(),
comfyui_version=self._get_comfyui_version_info(),
frontend_version=self._get_frontend_version(),
python_version=platform.python_version(),
@ -789,8 +790,8 @@ class TaskQueue:
to avoid disrupting normal operations.
"""
try:
cutoff = datetime.now() - timedelta(days=16)
cutoff_timestamp = cutoff.timestamp()
# 16 days in seconds
cutoff_timestamp = time.time() - (16 * 24 * 60 * 60)
pattern = os.path.join(context.manager_batch_history_path, "batch_*.json")
removed_count = 0

View File

@ -15,6 +15,7 @@ import platform
from datetime import datetime
import git
from comfyui_manager.common.timestamp_utils import get_timestamp_for_path, get_backup_branch_name
from git.remote import RemoteProgress
from urllib.parse import urlparse
from tqdm.auto import tqdm
@ -2012,7 +2013,15 @@ def git_repo_update_check_with(path, do_fetch=False, do_update=False, no_deps=Fa
return False, True
try:
remote.pull()
try:
repo.git.pull('--ff-only')
except git.GitCommandError:
backup_name = get_backup_branch_name(repo)
repo.create_head(backup_name)
logging.info(f"[ComfyUI-Manager] Cannot fast-forward. Backup created: {backup_name}")
repo.git.reset('--hard', f'{remote_name}/{branch_name}')
logging.info(f"[ComfyUI-Manager] Reset to {remote_name}/{branch_name}")
repo.git.submodule('update', '--init', '--recursive')
new_commit_hash = repo.head.commit.hexsha
@ -2167,9 +2176,17 @@ def git_pull(path):
current_branch = repo.active_branch
remote_name = current_branch.tracking_branch().remote_name
remote = repo.remote(name=remote_name)
branch_name = current_branch.name
try:
repo.git.pull('--ff-only')
except git.GitCommandError:
backup_name = get_backup_branch_name(repo)
repo.create_head(backup_name)
logging.info(f"[ComfyUI-Manager] Cannot fast-forward. Backup created: {backup_name}")
repo.git.reset('--hard', f'{remote_name}/{branch_name}')
logging.info(f"[ComfyUI-Manager] Reset to {remote_name}/{branch_name}")
remote.pull()
repo.git.submodule('update', '--init', '--recursive')
repo.close()
@ -2437,22 +2454,22 @@ def update_to_stable_comfyui(repo_path):
logging.error('\t'+branch.name)
return "fail", None
versions, current_tag, _ = get_comfyui_versions(repo)
if len(versions) == 0 or (len(versions) == 1 and versions[0] == 'nightly'):
versions, current_tag, latest_tag = get_comfyui_versions(repo)
if latest_tag is None:
logging.info("[ComfyUI-Manager] Unable to update to the stable ComfyUI version.")
return "fail", None
if versions[0] == 'nightly':
latest_tag = versions[1]
else:
latest_tag = versions[0]
if current_tag == latest_tag:
tag_ref = next((t for t in repo.tags if t.name == latest_tag), None)
if tag_ref is None:
logging.info(f"[ComfyUI-Manager] Unable to locate tag '{latest_tag}' in repository.")
return "fail", None
if repo.head.commit == tag_ref.commit:
return "skip", None
else:
logging.info(f"[ComfyUI-Manager] Updating ComfyUI: {current_tag} -> {latest_tag}")
repo.git.checkout(latest_tag)
repo.git.checkout(tag_ref.name)
execute_install_script("ComfyUI", repo_path, instant_execution=False, no_deps=False)
return 'updated', latest_tag
except Exception:
@ -2683,9 +2700,7 @@ async def get_current_snapshot(custom_nodes_only = False):
async def save_snapshot_with_postfix(postfix, path=None, custom_nodes_only = False):
if path is None:
now = datetime.now()
date_time_format = now.strftime("%Y-%m-%d_%H-%M-%S")
date_time_format = get_timestamp_for_path()
file_name = f"{date_time_format}_{postfix}"
path = os.path.join(context.manager_snapshot_path, f"{file_name}.json")
@ -3276,36 +3291,85 @@ async def restore_snapshot(snapshot_path, git_helper_extras=None):
def get_comfyui_versions(repo=None):
if repo is None:
repo = git.Repo(context.comfy_path)
repo = repo or git.Repo(context.comfy_path)
remote_name = None
try:
remote = get_remote_name(repo)
repo.remotes[remote].fetch()
remote_name = get_remote_name(repo)
repo.remotes[remote_name].fetch()
except Exception:
logging.error("[ComfyUI-Manager] Failed to fetch ComfyUI")
versions = [x.name for x in repo.tags if x.name.startswith('v')]
def parse_semver(tag_name):
match = re.match(r'^v(\d+)\.(\d+)\.(\d+)$', tag_name)
return tuple(int(x) for x in match.groups()) if match else None
# nearest tag
versions = sorted(versions, key=lambda v: repo.git.log('-1', '--format=%ct', v), reverse=True)
versions = versions[:4]
def normalize_describe(tag_name):
if not tag_name:
return None
base = tag_name.split('-', 1)[0]
return base if parse_semver(base) else None
current_tag = repo.git.describe('--tags')
# Collect semver tags and sort descending (highest first)
semver_tags = []
for tag in repo.tags:
semver = parse_semver(tag.name)
if semver:
semver_tags.append((semver, tag.name))
semver_tags.sort(key=lambda x: x[0], reverse=True)
semver_tags = [name for _, name in semver_tags]
if current_tag not in versions:
versions = sorted(versions + [current_tag], key=lambda v: repo.git.log('-1', '--format=%ct', v), reverse=True)
versions = versions[:4]
latest_tag = semver_tags[0] if semver_tags else None
main_branch = repo.heads.master
latest_commit = main_branch.commit
latest_tag = repo.git.describe('--tags', latest_commit.hexsha)
try:
described = repo.git.describe('--tags')
except Exception:
described = ''
if latest_tag != versions[0]:
versions.insert(0, 'nightly')
else:
versions[0] = 'nightly'
try:
exact_tag = repo.git.describe('--tags', '--exact-match')
except Exception:
exact_tag = ''
head_is_default = False
if remote_name:
try:
default_head_ref = repo.refs[f'{remote_name}/HEAD']
default_commit = default_head_ref.reference.commit
head_is_default = repo.head.commit == default_commit
except Exception:
# Fallback: compare directly with master branch
try:
if 'master' in [h.name for h in repo.heads]:
head_is_default = repo.head.commit == repo.heads.master.commit
except Exception:
head_is_default = False
nearest_semver = normalize_describe(described)
exact_semver = exact_tag if parse_semver(exact_tag) else None
if head_is_default and not exact_tag:
current_tag = 'nightly'
else:
current_tag = exact_tag or described or 'nightly'
# Prepare semver list for display: top 4 plus the current/nearest semver if missing
display_semver_tags = semver_tags[:4]
if exact_semver and exact_semver not in display_semver_tags:
display_semver_tags.append(exact_semver)
elif nearest_semver and nearest_semver not in display_semver_tags:
display_semver_tags.append(nearest_semver)
versions = ['nightly']
if current_tag and not exact_semver and current_tag not in versions and current_tag not in display_semver_tags:
versions.append(current_tag)
for tag in display_semver_tags:
if tag not in versions:
versions.append(tag)
versions = versions[:6]
return versions, current_tag, latest_tag

View File

@ -16,25 +16,11 @@ from .common import security_check
from .common import manager_util
from .common import cm_global
from .common import manager_downloader
from .common.timestamp_utils import current_timestamp
import folder_paths
manager_util.add_python_path_to_env()
import datetime as dt
if hasattr(dt, 'datetime'):
from datetime import datetime as dt_datetime
def current_timestamp():
return dt_datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
else:
# NOTE: Occurs in some Mac environments.
import time
logging.error(f"[ComfyUI-Manager] fallback timestamp mode\n datetime module is invalid: '{dt.__file__}'")
def current_timestamp():
return str(time.time()).split('.')[0]
cm_global.pip_blacklist = {'torch', 'torchaudio', 'torchsde', 'torchvision'}
cm_global.pip_downgrade_blacklist = ['torch', 'torchaudio', 'torchsde', 'torchvision', 'transformers', 'safetensors', 'kornia']

View File

@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "comfyui-manager"
license = { text = "GPL-3.0-only" }
version = "4.0.3b4"
version = "4.0.3b5"
requires-python = ">= 3.9"
description = "ComfyUI-Manager provides features to install and manage custom nodes for ComfyUI, as well as various functionalities to assist with ComfyUI."
readme = "README.md"