diff --git a/comfy_cli/command/custom_nodes/command.py b/comfy_cli/command/custom_nodes/command.py index 73ccd536d..48cb401ff 100644 --- a/comfy_cli/command/custom_nodes/command.py +++ b/comfy_cli/command/custom_nodes/command.py @@ -122,14 +122,12 @@ def get_installed_packages(): def try_install_script(repo_path, install_cmd, instant_execution=False): startup_script_path = os.path.join(workspace_manager.workspace_path, "startup-scripts") + # Windows always defers to the startup script. ComfyUI-Manager additionally + # gated this on the ComfyUI checkout being newer than a required commit; + # that comparison was deliberately dropped (Yoland) because comfy-cli tracks + # no required-commit datetime to compare against. if not instant_execution and ( - (len(install_cmd) > 0 and install_cmd[0].startswith("#")) - or ( - platform.system() == "Windows" - # From Yoland: disable commit compare - # and comfy_ui_commit_datetime.date() - # >= comfy_ui_required_commit_datetime.date() - ) + (len(install_cmd) > 0 and install_cmd[0].startswith("#")) or platform.system() == "Windows" ): if not os.path.exists(startup_script_path): os.makedirs(startup_script_path) @@ -141,26 +139,15 @@ def try_install_script(repo_path, install_cmd, instant_execution=False): return True else: - # From Yoland: Disable blacklisting - # if len(install_cmd) == 5 and install_cmd[2:4] == ['pip', 'install']: - # if is_blacklisted(install_cmd[4]): - # print(f"[ComfyUI-Manager] skip black listed pip installation: '{install_cmd[4]}'") - # return True - + # ComfyUI-Manager screened pip installs against a package blacklist here. + # Deliberately not carried over (Yoland): comfy-cli ships no blacklist, + # so every install command runs as given. print(f"\n## ComfyUI-Manager: EXECUTE => {install_cmd}") code = run_script(install_cmd, cwd=repo_path) - # From Yoland: Disable warning - # if platform.system() != "Windows": - # try: - # if comfy_ui_commit_datetime.date() < comfy_ui_required_commit_datetime.date(): - # print("\n\n###################################################################") - # print(f"[WARN] ComfyUI-Manager: Your ComfyUI version ({comfy_ui_revision})[{comfy_ui_commit_datetime.date()}] is too old. Please update to the latest version.") - # print(f"[WARN] The extension installation feature may not work properly in the current installed ComfyUI version on Windows environment.") - # print("###################################################################\n\n") - # except: - # pass - + # ComfyUI-Manager also warned on non-Windows when the ComfyUI checkout + # was older than the required commit. Dropped for the same reason as + # above — there is no required-commit datetime here. if code != 0: print("install script failed") return False @@ -170,12 +157,10 @@ def execute_install_script(repo_path): install_script_path = os.path.join(repo_path, "install.py") requirements_path = os.path.join(repo_path, "requirements.txt") - # From Yoland: disable lazy mode - # if lazy_mode: - # install_cmd = ["#LAZY-INSTALL-SCRIPT", sys.executable] - # try_install_script(repo_path, install_cmd) - # else: - + # ComfyUI-Manager's "lazy mode" — queueing a #LAZY-INSTALL-SCRIPT marker for + # the next startup instead of installing now — was deliberately not carried + # over (Yoland). comfy-cli installs eagerly so failures surface in the + # command that caused them rather than on some later launch. if os.path.exists(requirements_path): print("Install: pip packages") python = resolve_workspace_python(workspace_manager.workspace_path) @@ -1166,7 +1151,6 @@ def validate(): Run validation checks that would be performed during publishing. """ validate_node_for_publishing() - # print("[green]✓ All validation checks passed successfully[/green]") def resolve_publish_changelog(changelog: str | None, changelog_file: str | None) -> str: diff --git a/comfy_cli/command/generate/spec.py b/comfy_cli/command/generate/spec.py index c416140dc..53ef15a99 100644 --- a/comfy_cli/command/generate/spec.py +++ b/comfy_cli/command/generate/spec.py @@ -234,7 +234,7 @@ def resolve_alias(target: str) -> str: # Reve ("reve/v1/image/create", "text-to-image", None), ("reve/v1/image/edit", "image-edit", None), - # Runway (image) + # Runway - image ("runway/text_to_image", "text-to-image", None), # Video — Kling ("kling/v1/videos/text2video", "text-to-video", "kling"), diff --git a/comfy_cli/command/jobs.py b/comfy_cli/command/jobs.py index 7081b980f..ea08d2194 100644 --- a/comfy_cli/command/jobs.py +++ b/comfy_cli/command/jobs.py @@ -1887,7 +1887,7 @@ def _resolve_watch_client_id(host: str, port: int, prompt_id: str) -> str | None if isinstance(q, dict): for key in ("queue_running", "queue_pending"): for entry in q.get(key) or []: - # (number, prompt_id, prompt, extra_data, outputs_to_execute) + # entry layout: number, prompt_id, prompt, extra_data, outputs_to_execute if isinstance(entry, list) and len(entry) > 3 and entry[1] == prompt_id: cid = _client_id_from_extra_data(entry[3]) if cid: diff --git a/comfy_cli/command/nodes.py b/comfy_cli/command/nodes.py index 602671869..d3be6a025 100644 --- a/comfy_cli/command/nodes.py +++ b/comfy_cli/command/nodes.py @@ -897,7 +897,7 @@ def path_cmd( # --------------------------------------------------------------------------- -# browse: types / categories +# browse commands - types and categories # --------------------------------------------------------------------------- diff --git a/comfy_cli/command/run/__init__.py b/comfy_cli/command/run/__init__.py index 8c0768a26..70a342a9e 100644 --- a/comfy_cli/command/run/__init__.py +++ b/comfy_cli/command/run/__init__.py @@ -232,8 +232,8 @@ def execute( renderer = get_renderer() # `preloaded` short-circuits file loading: an in-memory API-format graph - # (e.g. the `comfy run --prompt` injected default) is handed straight in as - # (workflow_dict, display_name, is_ui, checkpoint_user_set). Everything + # (e.g. the `comfy run --prompt` injected default) is handed straight in as a + # workflow_dict / display_name / is_ui / checkpoint_user_set tuple. Everything # downstream is unchanged; `checkpoint_user_set` gates runtime checkpoint # resolution for the bundled default (skip it when the user pinned one). if preloaded is not None: diff --git a/comfy_cli/registry/config_parser.py b/comfy_cli/registry/config_parser.py index 1aa4fcb0b..9c98eae79 100644 --- a/comfy_cli/registry/config_parser.py +++ b/comfy_cli/registry/config_parser.py @@ -113,13 +113,9 @@ def create_comfynode_config(): tool.add("comfy", comfy) document.add("tool", tool) - # Add the default model - # models = tomlkit.array() - # model = tomlkit.inline_table() - # model["location"] = "/checkpoints/model.safetensor" - # model["model_url"] = "https://example.com/model.zip" - # models.append(model) - # comfy["Models"] = models + # No default [tool.comfy].Models entry is scaffolded: a placeholder model + # location/URL pair is not valid for any real node, and publishing rejects + # it, so an empty section is a better starting point than a broken example. # Write the TOML document to a file try: diff --git a/pyproject.toml b/pyproject.toml index 0f56190e6..014407c3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -87,7 +87,9 @@ target-version = "py310" line-length = 120 lint.select = [ + "C901", # mccabe - complexity ratchet, see [tool.ruff.lint.mccabe] below "E", # pycodestyle - Error + "ERA001", # eradicate - commented-out code "F", # default "I", # isort-like behavior (import statement sorting) "Q", # flake8-quotes @@ -98,3 +100,17 @@ lint.select = [ lint.extend-ignore = [ "E501", # Line too long ] + +[tool.ruff.lint.mccabe] +# Ratchet, not a target. 48 is the complexity of the single worst function in +# the tree today (`execute` in comfy_cli/command/run/__init__.py), so this +# enabling adds no new failures. Lower it whenever the worst offender drops; +# never raise it. At the eventual default of 10 there are 92 hits, so getting +# there is a long refactor, not a lint flip. +max-complexity = 48 + +[tool.ruff.lint.per-file-ignores] +# TODO: drop once fix/tarfile-extraction-filter (#734) lands - it rewrites the +# extraction helper that holds this file's single commented-out-code hit, and +# touching the file here would conflict with that branch. +"comfy_cli/utils.py" = ["ERA001"] diff --git a/tests/comfy_cli/command/nodes/test_publish.py b/tests/comfy_cli/command/nodes/test_publish.py index d5df75594..cb4b92d04 100644 --- a/tests/comfy_cli/command/nodes/test_publish.py +++ b/tests/comfy_cli/command/nodes/test_publish.py @@ -46,9 +46,9 @@ def test_publish_fails_on_security_violations(): ): result = runner.invoke(app, ["publish"]) - # TODO: re-enable exit when we disable exec and eval - # assert result.exit_code == 1 - # assert "Security issues found" in result.stdout + # Security findings are reported as warnings and publishing continues: + # exec/eval are still allowed. When they become a hard failure this + # should assert exit_code == 1 and the "Security issues found" wording. assert "Security warnings found" in result.stdout diff --git a/tests/comfy_cli/cql/test_engine.py b/tests/comfy_cli/cql/test_engine.py index 11681520a..2935d2eff 100644 --- a/tests/comfy_cli/cql/test_engine.py +++ b/tests/comfy_cli/cql/test_engine.py @@ -2056,10 +2056,9 @@ class TestDirectModeSlots: def test_extract_finds_all_widget_inputs(self, graph: Graph): wf = _direct_workflow() slots = _extract_frontend_slots(wf, graph) - # KSampler: seed, steps, cfg, sampler_name, scheduler, denoise (6) - # CLIPTextEncode: text (1) - # EmptyLatentImage: width, height, batch_size (3) - # Total: 10 + # 10 widget slots expected - 6 from KSampler (seed, steps, cfg, + # sampler_name, scheduler, denoise), 1 from CLIPTextEncode (text) and + # 3 from EmptyLatentImage (width, height, batch_size). assert len(slots) == 10 names = {s["name"] for s in slots} # No link inputs should appear diff --git a/tests/comfy_cli/output/test_error_envelope_where.py b/tests/comfy_cli/output/test_error_envelope_where.py index 22cb363c9..66b7f2dfb 100644 --- a/tests/comfy_cli/output/test_error_envelope_where.py +++ b/tests/comfy_cli/output/test_error_envelope_where.py @@ -170,7 +170,7 @@ def test_decompose_stamps_the_object_info_route(self, tmp_path, monkeypatch: pyt # --------------------------------------------------------------------------- -# transfer (upload / download) +# transfer - upload / download # --------------------------------------------------------------------------- @@ -196,7 +196,7 @@ def test_download_cloud(self): # --------------------------------------------------------------------------- -# system (system-stats / free) +# system - system-stats / free # --------------------------------------------------------------------------- diff --git a/tests/comfy_cli/test_credentials.py b/tests/comfy_cli/test_credentials.py index 5b37935e3..7110639a5 100644 --- a/tests/comfy_cli/test_credentials.py +++ b/tests/comfy_cli/test_credentials.py @@ -417,7 +417,7 @@ def _violations_in(path: Path) -> list[str]: tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) found: list[str] = [] for node in ast.walk(tree): - # os.environ.get("COMFY_..."), os.getenv("COMFY_...") + # attribute reads - os.environ.get or os.getenv of a COMFY_* name if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute): func = node.func if func.attr == "get" and _is_environ_node(func.value) and node.args: @@ -430,7 +430,7 @@ def _violations_in(path: Path) -> list[str]: # bare get_cloud_session(...) / ensure_fresh_session(...) if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id in SESSION_FUNCS: found.append(f"{path}:{node.lineno}: call to {node.func.id}()") - # os.environ["COMFY_..."] + # subscript reads - os.environ indexed by a COMFY_* name if isinstance(node, ast.Subscript) and _is_environ_node(node.value): if _literal(node.slice) in ENV_VARS: found.append(f"{path}:{node.lineno}: os.environ[{_literal(node.slice)!r}]") diff --git a/tests/comfy_cli/test_host_port.py b/tests/comfy_cli/test_host_port.py index 5e62bf6f8..9aafc5b8c 100644 --- a/tests/comfy_cli/test_host_port.py +++ b/tests/comfy_cli/test_host_port.py @@ -196,7 +196,7 @@ def test_run_ipv6_host_port_reaches_execute(tmp_path): ) assert result.exit_code == 0, result.output args, _ = mock_execute.call_args - # execute(workflow, host, port, ...) + # positional args of execute - workflow, host, port, ... assert args[1] == "[::1]" assert args[2] == 8188 @@ -256,7 +256,7 @@ def test_run_explicit_port_wins_over_embedded_host_port(tmp_path, monkeypatch): ) assert result.exit_code == 0, result.output args, _ = mock_execute.call_args - # execute(workflow, host, port, ...) + # positional args of execute - workflow, host, port, ... assert args[1] == "127.0.0.1" assert args[2] == 9200 diff --git a/tests/comfy_cli/test_tracking.py b/tests/comfy_cli/test_tracking.py index f455c1b77..31716625b 100644 --- a/tests/comfy_cli/test_tracking.py +++ b/tests/comfy_cli/test_tracking.py @@ -49,7 +49,7 @@ def tracking_module(tmp_path): def _last_track_call(provider): args, kwargs = provider.track.call_args - # Provider.track(event_name, distinct_id=..., properties=...) + # Provider.track signature - event_name, distinct_id=..., properties=... event_name = args[0] if args else kwargs.get("event_name") distinct_id = kwargs.get("distinct_id", args[1] if len(args) > 1 else None) properties = kwargs.get("properties", args[2] if len(args) > 2 else {}) diff --git a/tests/e2e/test_e2e.py b/tests/e2e/test_e2e.py index ed2bf23a8..c9c76ef6a 100644 --- a/tests/e2e/test_e2e.py +++ b/tests/e2e/test_e2e.py @@ -313,8 +313,8 @@ def test_install_version_latest_no_github_api(tmp_path): # The actual property under test: we did NOT fall back to the GitHub API. # Both fallback messages from checkout_stable_comfyui mention "GitHub API" - # ("querying GitHub API" and "trying GitHub API as a last resort"); catch - # either via the shared substring so the assertion stays tight even if the + # - "querying GitHub API" and "trying GitHub API as a last resort" - so + # catch either via the shared substring, keeping the assertion tight even if # exact wording changes. combined = proc.stdout + proc.stderr assert "GitHub API" not in combined, (