fix(feature-flags): bare flags default to true, robust coercion, drop wrapper

Address code review feedback:
- _coerce_flag_value: wrap coercion in try/except (ValueError, TypeError)
  and log a warning instead of crashing startup on malformed values.
- _parse_cli_feature_flags: bare --feature-flag KEY (no '=') now defaults
  to 'true' so registered bool flags work as toggles.
- Remove the get_cli_feature_flag_registry() wrapper; export and use
  CLI_FEATURE_FLAG_REGISTRY directly in main.py and tests.

Add tests for coercion-failure fallback and bare-flag default behavior.

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019deba2-bfe2-7118-913c-562beee48972
This commit is contained in:
Jedrzej Kosinski
2026-05-03 04:49:22 -07:00
parent 393248c8fa
commit d187c3510e
3 changed files with 45 additions and 19 deletions

View File

@@ -5,6 +5,7 @@ This module handles capability negotiation between frontend and backend,
allowing graceful protocol evolution while maintaining backward compatibility.
"""
import logging
from typing import Any, TypedDict
from comfy.cli_args import args
@@ -27,11 +28,6 @@ CLI_FEATURE_FLAG_REGISTRY: dict[str, FeatureFlagInfo] = {
}
def get_cli_feature_flag_registry() -> dict[str, FeatureFlagInfo]:
"""Return the registry of known CLI-settable feature flags."""
return {k: dict(v) for k, v in CLI_FEATURE_FLAG_REGISTRY.items()}
_COERCE_FNS: dict[str, Any] = {
"bool": lambda v: v.lower() == "true",
"int": lambda v: int(v),
@@ -40,26 +36,41 @@ _COERCE_FNS: dict[str, Any] = {
def _coerce_flag_value(key: str, raw_value: str) -> Any:
"""Coerce a raw string value using the registry type, or keep as string."""
"""Coerce a raw string value using the registry type, or keep as string.
Returns the raw string if the key is unregistered, the type is unknown,
or coercion fails (with a warning logged in the failure case).
"""
info = CLI_FEATURE_FLAG_REGISTRY.get(key)
if info is None:
return raw_value
coerce = _COERCE_FNS.get(info["type"])
if coerce is None:
return raw_value
return coerce(raw_value)
try:
return coerce(raw_value)
except (ValueError, TypeError):
logging.warning(
"Could not coerce --feature-flag %s=%r to %s; using raw string.",
key, raw_value, info["type"],
)
return raw_value
def _parse_cli_feature_flags() -> dict[str, Any]:
"""Parse --feature-flag key=value pairs from CLI args into a dict."""
"""Parse --feature-flag key=value pairs from CLI args into a dict.
Items without '=' default to the value 'true' (bare flag form).
"""
result: dict[str, Any] = {}
for item in getattr(args, "feature_flag", []):
if "=" not in item:
continue
key, _, raw_value = item.partition("=")
key, sep, raw_value = item.partition("=")
key = key.strip()
if key:
result[key] = _coerce_flag_value(key, raw_value.strip())
if not key:
continue
if not sep:
raw_value = "true"
result[key] = _coerce_flag_value(key, raw_value.strip())
return result