From dbdb642ed2ab2c2d9cda0761abde51711e5c0802 Mon Sep 17 00:00:00 2001 From: "Dr.Lt.Data" <128333288+ltdrdata@users.noreply.github.com> Date: Thu, 12 Nov 2026 01:37:59 +0900 Subject: [PATCH] v4: Align minimum Python version with ComfyUI (#3490) --- .github/workflows/ci.yml | 10 ++++++---- .github/workflows/e2e.yml | 1 + CHANGELOG.md | 5 +++++ README.md | 2 ++ docs/dev/TEST-environment-setup.md | 8 +++++--- pyproject.toml | 15 +-------------- tests/e2e/scripts/setup_e2e_env.py | 25 ++++++++++++++++++++---- tests/e2e/scripts/setup_e2e_env.sh | 31 +++++++++++++++--------------- 8 files changed, 56 insertions(+), 41 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 47b1d0077..01eae0fed 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: code-quality: name: Code Quality Checks - # Python 3.9 builds are unavailable for Ubuntu 26.04. + # Use a fixed image for syntax checks; E2E separately tests the latest runners. runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v4 @@ -53,11 +53,13 @@ jobs: files_ignore: | comfyui_manager/legacy/** - - name: Setup Python - if: steps.changed-py-files.outputs.any_changed == 'true' + - name: Setup minimum supported Python uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: '3.10' + + - name: Check syntax on minimum supported Python + run: python -m compileall -q comfyui_manager cm_cli - name: Install dependencies if: steps.changed-py-files.outputs.any_changed == 'true' diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index f511984a5..c2385f17c 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -58,6 +58,7 @@ jobs: shell: bash env: MANAGER_ROOT: ${{ github.workspace }} + UV_PYTHON: ${{ matrix.python-version }} run: | python tests/e2e/scripts/setup_e2e_env.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fdfbae22..8f7727207 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning 2.0.0](https://semver.org/spec/ ## [Unreleased] +### Changed + +- Require Python 3.10 or newer to match ComfyUI's minimum supported version. + Python 3.9 is no longer supported. + ### Security - Allow administrators to exempt selected Registry IDs from the flagged CNR diff --git a/README.md b/README.md index 97dac1471..afb6271e9 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,8 @@ ## Installation +Requires Python 3.10 or newer, matching ComfyUI's minimum Python version. + * When installing the latest ComfyUI, it will be automatically installed as a dependency, so manual installation is no longer necessary. * Manual installation of the nightly version: diff --git a/docs/dev/TEST-environment-setup.md b/docs/dev/TEST-environment-setup.md index 56dc364d5..151542b48 100644 --- a/docs/dev/TEST-environment-setup.md +++ b/docs/dev/TEST-environment-setup.md @@ -25,11 +25,13 @@ rm -rf /tmp/e2e_test | Script | Purpose | Input | Output | |--------|---------|-------|--------| -| `setup_e2e_env.sh` | Full environment setup (8 steps) | `E2E_ROOT`, `MANAGER_ROOT`, `COMFYUI_BRANCH` (default: master), `PYTHON` (default: python3) | `E2E_ROOT=` on last line | +| `setup_e2e_env.sh` | Full environment setup (8 steps) | `E2E_ROOT`, `MANAGER_ROOT`, `COMFYUI_BRANCH` (default: master), `UV_PYTHON` (optional uv request) | `E2E_ROOT=` on last line | | `start_comfyui.sh` | Foreground-blocking launcher | `E2E_ROOT`, `PORT` (default: 8199), `TIMEOUT` (default: 120s) | `COMFYUI_PID= PORT=` | | `stop_comfyui.sh` | Graceful shutdown | `E2E_ROOT`, `PORT` (default: 8199) | — | -**Idempotent**: `setup_e2e_env.sh` checks for a `.e2e_setup_complete` marker file and skips setup if the environment already exists. +**Interpreter selection**: both setup scripts use `uv venv --project "$MANAGER_ROOT"`, so uv reads Manager's `pyproject.toml` and honors its `.python-version` file and `UV_PYTHON`. To select a specific interpreter, set `UV_PYTHON` to a request such as `3.10` or an absolute executable path. The scripts do not read the old `PYTHON` variable. Explicit uv selections can override the project requirement, so the resulting venv is still checked for Python 3.10+. Selection applies only to new venvs. + +**Idempotent**: both setup scripts reuse a completed environment only after checking that its venv runs Python 3.10+. If an existing venv is too old or its interpreter cannot run, recreate it with a supported interpreter in a fresh `E2E_ROOT`. **Blocking mechanism**: `start_comfyui.sh` uses `tail -n +1 -f | grep -q -m1 'To see the GUI'` to block until ComfyUI is ready. No polling loop needed. @@ -37,7 +39,7 @@ rm -rf /tmp/e2e_test ## Prerequisites -- Python 3.9+ +- Python 3.10+ in the E2E venv (selected automatically by uv during automated setup) - Git - `uv` (install via `pip install uv` or [standalone](https://docs.astral.sh/uv/getting-started/installation/)) diff --git a/pyproject.toml b/pyproject.toml index 8a011c54d..1362eb00c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta" name = "comfyui-manager" license = { text = "GPL-3.0-only" } version = "4.3" -requires-python = ">= 3.9" +requires-python = ">=3.10" 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" keywords = ["comfyui", "comfyui-manager"] @@ -52,16 +52,3 @@ include = ["comfyui_manager*", "cm_cli*"] [project.scripts] cm-cli = "cm_cli:main" - -[tool.ruff] -line-length = 120 -target-version = "py39" - -[tool.ruff.lint] -select = [ - "E4", # default - "E7", # default - "E9", # default - "F", # default - "I", # isort-like behavior (import statement sorting) -] diff --git a/tests/e2e/scripts/setup_e2e_env.py b/tests/e2e/scripts/setup_e2e_env.py index 02c1c445e..18af406f5 100644 --- a/tests/e2e/scripts/setup_e2e_env.py +++ b/tests/e2e/scripts/setup_e2e_env.py @@ -1,12 +1,14 @@ """Cross-platform E2E environment setup for ComfyUI + Manager. Creates an isolated ComfyUI installation with ComfyUI-Manager for E2E testing. -Idempotent: skips setup if marker file and key artifacts already exist. +Idempotent: skips setup if marker, key artifacts, and a supported venv already exist. +uv reads the Manager project's Python requirement when creating a venv. Input env vars: E2E_ROOT — target directory (required) MANAGER_ROOT — manager repo root (default: auto-detected) COMFYUI_BRANCH — ComfyUI branch to clone (default: master) + UV_PYTHON — optional uv Python request for a new venv Output (last line of stdout): E2E_ROOT=/path/to/environment @@ -46,6 +48,18 @@ def run(cmd: list[str], **kwargs) -> subprocess.CompletedProcess: return subprocess.run(cmd, check=True, **kwargs) +def check_python_version(python: str) -> None: + try: + version = subprocess.check_output( + [python, "-c", "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"], + text=True, + ).strip() + except (OSError, subprocess.CalledProcessError) as exc: + die(f"Cannot run venv Python: {python}: {exc}. Recreate the E2E environment with Python 3.10+.") + if tuple(map(int, version.split("."))) < (3, 10): + die(f"Python 3.10+ required, found {version} ({python}). Recreate the E2E environment.") + + def detect_manager_root() -> Path: """Walk up from this script to find pyproject.toml.""" d = Path(__file__).resolve().parent @@ -69,7 +83,7 @@ def venv_bin(root: Path, name: str) -> str: return str(root / "venv" / "bin" / name) -def is_already_setup(root: Path, manager_root: Path) -> bool: +def is_already_setup(root: Path) -> bool: marker = root / ".e2e_setup_complete" comfyui = root / "comfyui" venv = root / "venv" @@ -119,7 +133,9 @@ def main() -> None: branch = os.environ.get("COMFYUI_BRANCH", "master") # Idempotency - if is_already_setup(root, manager_root): + if (root / "venv").is_dir(): + check_python_version(venv_python(root)) + if is_already_setup(root): log("Environment already set up (marker file exists). Skipping.") print(f"E2E_ROOT={root}") return @@ -138,7 +154,8 @@ def main() -> None: log("Step 2/7: venv already exists, skipping") else: log("Step 2/7: Creating virtual environment...") - run(["uv", "venv", str(venv_dir)]) + run(["uv", "venv", "--project", str(manager_root), str(venv_dir)]) + check_python_version(venv_python(root)) py = venv_python(root) diff --git a/tests/e2e/scripts/setup_e2e_env.sh b/tests/e2e/scripts/setup_e2e_env.sh index fcc4bf44d..73cb223db 100755 --- a/tests/e2e/scripts/setup_e2e_env.sh +++ b/tests/e2e/scripts/setup_e2e_env.sh @@ -2,13 +2,13 @@ # setup_e2e_env.sh — Automated E2E environment setup for ComfyUI + Manager # # Creates an isolated ComfyUI installation with ComfyUI-Manager for E2E testing. -# Idempotent: skips setup if marker file and key artifacts already exist. +# Idempotent: skips setup if marker, key artifacts, and a supported venv already exist. # # Input env vars: # E2E_ROOT — target directory (default: auto-generated via mktemp) # MANAGER_ROOT — manager repo root (default: auto-detected from script location) # COMFYUI_BRANCH — ComfyUI branch to clone (default: master) -# PYTHON — Python executable (default: python3) +# UV_PYTHON — optional uv Python request for a new venv # # Output (last line of stdout): # E2E_ROOT=/path/to/environment @@ -44,29 +44,25 @@ detect_manager_root() { return 1 } +check_python_version() { + "$1" -c 'import sys +if sys.version_info < (3, 10): + sys.exit(f"Python 3.10+ required, found {sys.version_info.major}.{sys.version_info.minor}")' \ + || die "Cannot use venv Python: $1. Recreate the E2E environment with Python 3.10+." +} + # --- Validate prerequisites --- validate_prerequisites() { - local py="${PYTHON:-python3}" local missing=() command -v git >/dev/null 2>&1 || missing+=("git") command -v uv >/dev/null 2>&1 || missing+=("uv") - command -v "$py" >/dev/null 2>&1 || missing+=("$py") if [[ ${#missing[@]} -gt 0 ]]; then die "Missing prerequisites: ${missing[*]}" fi - # Verify Python version >= 3.9 - local py_version - py_version=$("$py" -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')") - local major minor - major="${py_version%%.*}" - minor="${py_version##*.}" - if [[ "$major" -lt 3 ]] || { [[ "$major" -eq 3 ]] && [[ "$minor" -lt 9 ]]; }; then - die "Python 3.9+ required, found $py_version" - fi - log "Prerequisites OK (python=$py_version, git=$(git --version | awk '{print $3}'), uv=$(uv --version 2>&1 | awk '{print $2}'))" + log "Prerequisites OK (git=$(git --version | awk '{print $3}'), uv=$(uv --version 2>&1 | awk '{print $2}'))" } # --- Check idempotency: skip if already set up --- @@ -151,7 +147,6 @@ log "MANAGER_ROOT=$MANAGER_ROOT" # Validate prerequisites validate_prerequisites -PYTHON="${PYTHON:-python3}" COMFYUI_BRANCH="${COMFYUI_BRANCH:-master}" # Create or use E2E_ROOT @@ -166,6 +161,9 @@ else fi # Idempotency check +if [[ -d "$E2E_ROOT/venv" ]]; then + check_python_version "$E2E_ROOT/venv/bin/python" +fi check_already_setup "$E2E_ROOT" # Cleanup trap: remove E2E_ROOT on failure only if we created it @@ -191,7 +189,8 @@ log "Step 2/8: Creating virtual environment..." if [[ -d "$E2E_ROOT/venv" ]]; then log " venv already exists, skipping" else - uv venv "$E2E_ROOT/venv" + uv venv --project "$MANAGER_ROOT" "$E2E_ROOT/venv" + check_python_version "$E2E_ROOT/venv/bin/python" fi VENV_PY="$E2E_ROOT/venv/bin/python"