Skip to content

fix: handle inline comments in requirements.txt parsing#433

Merged
bigcat88 merged 3 commits intomainfrom
fix/requirements-txt-inline-comments
Apr 20, 2026
Merged

fix: handle inline comments in requirements.txt parsing#433
bigcat88 merged 3 commits intomainfrom
fix/requirements-txt-inline-comments

Conversation

@bigcat88
Copy link
Copy Markdown
Contributor

Summary

Fixes #431comfy node install on a custom node whose requirements.txt contains an inline comment (e.g. matplotlib>=3.3.0 # For visualization) fails with ERROR: Invalid requirement: pip receives the whole line verbatim because comfy-cli parses the file itself and passes each line as a single argv element.

Three locations in comfy-cli parse requirements.txt by hand, all with the same bug class:

# Location Role
1 execute_install_script (custom_nodes/command.py) Install deps of a registry-installed node via pip install <spec> per line
2 parse_req_file (uv.py) Collect specs for uv's download/wheel argv
3 initialize_project_config (registry/config_parser.py) Migrate requirements.txtpyproject.toml [project.dependencies]

Fix

  • (1) Delegate to pip install -r <path> — matches the four other pip install -r call sites already in the repo (install.py:110,128, cmdline.py:415, command.py:397). Fixes inline comments plus line continuations, -e, -r, --index-url, --hash, and environment markers for free.
  • (2), (3) Strip inline comments using pip's exact regex (^|\s+)#.*$. Critically, # is only a comment marker when preceded by whitespace, so VCS URL fragments like git+https://host/r.git#subdirectory=pkg and direct-URL #sha256= hashes survive.
  • (3) additionally filters pip-requirements-file options (-r, -e, --index-url, --find-links) that are not valid PEP 508 specifiers and would have corrupted [project.dependencies] in the generated pyproject.toml.

Why not line.split("#")[0]?

A naive split("#")[0] silently breaks VCS URL fragments, turning git+https://host/mono.git#subdirectory=pkg into git+https://host/mono.git — pip would then fail to find setup.py at the monorepo root. Regression tests guard against this.

Scope note

The reporter's traceback actually originates from ComfyUI-Manager's own execute_install_script (manager_core.py), not comfy-cli — for git-clone nodes ComfyUI-Manager doesn't call back into comfy-cli. comfy-cli has the same class of bug in its own registry-install path, which this PR fixes. ComfyUI-Manager needs a separate patch upstream.

Test plan

  • 13 regression tests added across the three locations, including VCS-fragment preservation guards
  • All new tests fail on unpatched main (verified before implementing)
  • All new tests pass after fix
  • Full unit suite: 688 passed, 0 regressions
  • ruff check + ruff format --check clean
  • Regex verified byte-for-byte identical to pip's pip._internal.req.req_file.COMMENT_RE across 23 tricky inputs (tabs, multiple spaces, VCS fragments, direct-URL hashes, decorative ######, mid-string # without whitespace, env markers, line continuations)
  • pip install --dry-run -r <file> verified to handle empty files, comment-only files, and the reporter's actual input shape
  • Windows manual test (not available in CI) — the startup-scripts file format remains [repo_path, *cmd] as a Python list literal; cm-cli consumers using subprocess.call(cmd[1:]) verbatim are unaffected

Replace the per-line pip install loop in execute_install_script with
`pip install -r <path>`, delegating requirements parsing to pip. This
fixes inline comments being passed verbatim to pip (Invalid requirement
errors) and incidentally handles line continuations, -e, --index-url,
env markers, and hash specs.

Also strip inline comments (matching pip's COMMENT_RE regex) in:
- parse_req_file in uv.py, which feeds pip download/wheel argv.
- initialize_project_config in registry/config_parser.py, which produces
  pyproject.toml [project.dependencies]; additionally skip pip-only
  options (-r, -e, --index-url, --find-links) that are not valid PEP 508
  specifiers and would corrupt the generated TOML.

The regex (^|\s+)#.*$ matches pip's exact rule: `#` only starts a
comment when preceded by whitespace, so VCS URL fragments like

Signed-off-by: Alexander Piskun <bigcat88@icloud.com>
#subdirectory=pkg and direct-URL #sha256= hashes survive.
@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. bug Something isn't working labels Apr 20, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 20, 2026

📝 Walkthrough

Walkthrough

Replaces per-line pip installs with a single pip install -r <requirements.txt> using an absolute path, adds an _inline_comment_re regex and updates requirements parsing to strip inline comments only when # is preceded by whitespace, and expands tests for parsing and install behavior — no more "#" slip.

Changes

Cohort / File(s) Summary
Requirements installation flow
comfy_cli/command/custom_nodes/command.py
Replace iterating over requirement lines and multiple pip calls with one pip install -r <absolute_requirements_path> invocation; ensure the requirements.txt path is absolute when running with cwd=repo_path.
Requirements parsing logic
comfy_cli/registry/config_parser.py, comfy_cli/uv.py
Introduce _inline_comment_re and update parsing to remove inline comments only when # is preceded by whitespace or start-of-line; trim results, skip empty lines, and exclude pip-only option lines (emit warnings for dropped options in config parser).
Config parser tests
tests/comfy_cli/registry/test_config_parser.py
Add helper to init a git repo with requirements.txt and tests verifying inline comment stripping, ignoring full/indented comments, filtering out pip directives/options (with warnings), and preserving VCS fragment identifiers.
Install script tests
tests/comfy_cli/test_custom_nodes_python_resolution.py
Add tests asserting a single subprocess call: [python, -m, pip, install, -r, <abs_path>], that inline # ... comments are not forwarded to pip argv, and that -r argument is absolute even for relative repo paths.
UV parser tests
tests/uv/test_uv.py
Add parse_req_file() unit tests covering inline comment stripping (only when # preceded by whitespace), skipping full-line/indented comments, preserving VCS/hash fragments, handling fragments plus trailing comments, splitting -- options, and CRLF line endings.
🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed All code changes directly address issue #431: execute_install_script delegates to pip's -r flag, parse_req_file and initialize_project_config strip inline comments using pip-compatible regex, and pip-only options are filtered from PEP 508 parsing.
Out of Scope Changes check ✅ Passed All changes focus on inline comment handling in requirements.txt parsing across three locations; no unrelated refactoring or scope creep detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/requirements-txt-inline-comments
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch fix/requirements-txt-inline-comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 20, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

@@            Coverage Diff             @@
##             main     #433      +/-   ##
==========================================
+ Coverage   77.15%   77.47%   +0.32%     
==========================================
  Files          35       35              
  Lines        4311     4316       +5     
==========================================
+ Hits         3326     3344      +18     
+ Misses        985      972      -13     
Files with missing lines Coverage Δ
comfy_cli/command/custom_nodes/command.py 83.94% <100.00%> (-0.16%) ⬇️
comfy_cli/registry/config_parser.py 93.78% <100.00%> (+0.36%) ⬆️
comfy_cli/uv.py 70.03% <100.00%> (+4.65%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@comfy_cli/command/custom_nodes/command.py`:
- Around line 171-175: The pip install call builds install_cmd with the
possibly-relative requirements_path which, when combined with subprocess
cwd=repo_path in try_install_script, can produce a duplicated path; change the
code that constructs install_cmd (where install_cmd = [python, "-m", "pip",
"install", "-r", requirements_path]) to pass an absolute path for
requirements_path (e.g., compute abs_requirements =
os.path.abspath(requirements_path) or os.path.join(os.path.abspath(repo_path),
...) before creating install_cmd) so pip receives "-r" followed by an absolute
file path; update the creation of install_cmd in the block that uses
resolve_workspace_python, requirements_path and repo_path.

In `@comfy_cli/uv.py`:
- Around line 40-43: The duplicate pip-style comment regex (_inline_comment_re =
re.compile(r"(^|\s+)#.*$")) appears in this module and in the config parser;
extract it into a single shared helper (e.g., a small requirements-parsing
helper exposing INLINE_COMMENT_RE or get_inline_comment_re) and replace the
local _inline_comment_re definitions with an import of that symbol in both
places (the current uv module and the config parser module), add a short
docstring explaining the pip behavior, and run/update any tests that reference
the regex to ensure no behavioral change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e0303f7e-ca8c-4162-8f9e-5238c36a663f

📥 Commits

Reviewing files that changed from the base of the PR and between 5f8937f and a399d41.

📒 Files selected for processing (6)
  • comfy_cli/command/custom_nodes/command.py
  • comfy_cli/registry/config_parser.py
  • comfy_cli/uv.py
  • tests/comfy_cli/registry/test_config_parser.py
  • tests/comfy_cli/test_custom_nodes_python_resolution.py
  • tests/uv/test_uv.py

Comment thread comfy_cli/command/custom_nodes/command.py
Comment thread comfy_cli/uv.py
try_install_script runs pip with cwd=repo_path, so if requirements_path
were relative it would get re-resolved against that cwd, producing a
doubled path like <rel>/<rel>/requirements.txt.

Wrap the requirements_path with os.path.abspath before handing it to
pip to make the -r target unambiguous regardless of whether the caller
passes an absolute or relative repo_path. Add a regression test that
invokes execute_install_script with a relative repo_path.

Signed-off-by: Alexander Piskun <bigcat88@icloud.com>
Address review feedback:

- initialize_project_config now prints a warning for each requirements.txt
  line it skips when generating [project.dependencies] (-r, -e, -c,
  --index-url, etc.). Previously these were silently dropped, leaving
  node authors to debug a missing dep in pyproject.toml with no signal.

- Tighten test_inline_comment_not_passed_to_pip to assert the exact
  comment-laden raw line does not leak into pip argv, instead of a
  loose "no # in argv" check (which could false-fail if a path in argv
  ever happened to contain a #).

- Add regression test for CRLF line endings in parse_req_file so
  Windows-authored requirements.txt files are covered.

Signed-off-by: Alexander Piskun <bigcat88@icloud.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@comfy_cli/registry/config_parser.py`:
- Around line 266-268: Replace the lone print call that emits the pip-only
requirements warning with typer.echo to match the rest of this module's logging
style: change the print(...) that outputs f"Warning: skipping pip-only option
from requirements.txt (not valid as PEP 508 dep): {line!r}" to typer.echo(...)
and ensure typer is imported in config_parser.py (the surrounding helpers like
validate_and_extract_os_classifiers and validate_version use typer.echo, so
mirror that pattern).

In `@tests/uv/test_uv.py`:
- Around line 417-420: Add a short docstring to the test function
test_parse_req_file_preserves_double_dash_options explaining that parse_req_file
intentionally preserves double-dash CLI-style options (e.g.,
"--extra-index-url") for downstream pip consumption, and clarifying this is
distinct from the compile stage where DependencyCompiler (see
test_compiled_output_has_no_extra_index_url) strips such options from compiled
output; place the docstring at the top of
test_parse_req_file_preserves_double_dash_options so future readers understand
the different responsibilities of parse_req_file vs. DependencyCompiler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: c787457b-d88b-4975-8ec2-a2de60271e3c

📥 Commits

Reviewing files that changed from the base of the PR and between 5cc0d14 and be32c01.

📒 Files selected for processing (4)
  • comfy_cli/registry/config_parser.py
  • tests/comfy_cli/registry/test_config_parser.py
  • tests/comfy_cli/test_custom_nodes_python_resolution.py
  • tests/uv/test_uv.py

Comment thread comfy_cli/registry/config_parser.py
Comment thread tests/uv/test_uv.py
@bigcat88 bigcat88 merged commit 3beb2e5 into main Apr 20, 2026
15 checks passed
@bigcat88 bigcat88 deleted the fix/requirements-txt-inline-comments branch April 20, 2026 13:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

requirements.txt parsing breaks on inline comments

1 participant