Skip to content

fix: strip trailing slashes from model paths at entrypoint#41

Closed
pipe1os wants to merge 19 commits into
mainfrom
advisor/008-fix-comparison-trailing-slash
Closed

fix: strip trailing slashes from model paths at entrypoint#41
pipe1os wants to merge 19 commits into
mainfrom
advisor/008-fix-comparison-trailing-slash

Conversation

@pipe1os

@pipe1os pipe1os commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

This fixes a bug where model paths with trailing slashes caused empty basenames in the comparison table. The change strips trailing slashes from the inputs in args.file at the entry point of the CLI.

Motivation & Context

When running comparisons, trailing slashes on paths (for example, meta-llama/Llama-2-7b-hf/) resulted in split("/")[-1] returning an empty string. Stripping trailing slashes in main prevents empty name columns and potential Hugging Face routing errors.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactoring (no functional changes, no api changes)
  • Documentation update

How Has This Been Tested?

  • Unit tests

I added a unit test test_cli_strips_trailing_slashes_from_model_paths in tests/test_cli.py to verify that the CLI strips trailing slashes from model paths for both single and multiple model runs.

Screenshots (if appropriate)

Checklist

  • My code follows the code style of this project.
  • My commit messages follow the Conventional Commits format, are lowercase, imperative, and specific.
  • I have updated the documentation accordingly (if applicable).
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@pipe1os, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 51 minutes and 21 seconds. Learn how PR review limits work.

To continue reviewing without waiting, enable usage-based billing in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: febe4afe-6d64-4c00-911e-24a2cf1e0890

📥 Commits

Reviewing files that changed from the base of the PR and between 0e82634 and 7634916.

📒 Files selected for processing (2)
  • src/modelinfo/cli.py
  • tests/test_cli.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch advisor/008-fix-comparison-trailing-slash

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.

@codacy-production

codacy-production Bot commented Jun 27, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@codacy-production codacy-production Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

While this PR is titled as a fix for trailing slashes, it introduces significant scope creep by adding remote GGUF support and refactoring UI logic. These additions have caused a substantial increase in complexity, particularly in src/modelinfo/parsers/huggingface.py (+41) and src/modelinfo/cli.py (+3), without corresponding documentation in the PR description.

A critical logic gap exists in the path-stripping implementation which fails to account for Windows backslashes, potentially leaving the original bug unresolved for local Windows users. Additionally, while the UI now correctly respects the --gpu-util parameter, this functional change is undocumented and lacks automated test verification.

About this PR

  • This PR contains significant scope creep. It adds support for remote GGUF repositories and alters UI hardware-fit logic, which are not mentioned in the PR title or description. Large, undocumented feature additions increase the risk of regressions and should ideally be separated into distinct pull requests.
  • The change in UI hardware-fit logic (switching from a hardcoded 90% utilization threshold to the dynamic --gpu-util parameter) is undocumented in the PR description. Please update the documentation to reflect how this parameter now influences UI warnings.
2 comments outside of the diff
src/modelinfo/cli.py

line 276 🟡 MEDIUM RISK
Suggestion: Use os.path.basename to correctly extract the model name regardless of the operating system's path separator. Relying on split('/')[-1] will fail to provide a clean display name on Windows systems using backslashes.

line 133 🟡 MEDIUM RISK
The analyze_model function is performing too many distinct tasks: determining if a path is remote, fetching from the network, and dispatching to format-specific parsers. Consider refactoring the resource resolution and loading logic into a dedicated helper function (e.g., load_model_resources).

Test suggestions

  • CLI strips trailing slashes from both single and multiple input paths
  • Identify and fetch metadata for a remote GGUF repository
  • Inspect a specific GGUF file within a remote repository using path-style notation
  • Render a comparison table for GGUF repositories with multiple variants
  • Hardware fit logic correctly utilizes the 'gpu_util' parameter for VRAM calculations
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Hardware fit logic correctly utilizes the 'gpu_util' parameter for VRAM calculations

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

Comment thread src/modelinfo/cli.py Outdated

# Strip trailing slashes from paths/repos to prevent empty basenames and routing issues
if args.file:
args.file = [path.rstrip("/") for path in args.file if path]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 MEDIUM RISK

Suggestion: The current implementation only strips forward slashes. On Windows, users often use backslashes in local paths, which will still cause issues with basename extraction and directory checks if left unstripped. Consider using .rstrip("/\\") to handle both forward and backward trailing slashes.

Comment thread tests/test_cli.py Outdated
Comment on lines +189 to +202
def fake_fetch(repo_id, *, fetch_tensors, timeout):
tensors = {
"__metadata__": {
"general.architecture": "llama",
"llama.block_count": 32,
"llama.attention.head_count_kv": 8,
"llama.attention.key_length": 128,
"gguf_variants": [
{"filename": "model-q4.gguf", "size": 1000000000},
{"filename": "model-q8.gguf", "size": 2000000000}
],
"repo_id": "org/model-gguf"
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ LOW RISK

Suggestion: The tensors metadata dictionary defined here is redundant with the data returned by the _get_mock_gguf_group_data helper. Simplify the test by calling the helper directly.

Comment thread tests/test_parsers.py
Comment on lines +96 to +109
{"rfilename": "model-q4.gguf", "size": 1000000000}
]
}).encode("utf-8")
elif "model-q4.gguf" in url:
import struct
header = b"GGUF" + struct.pack("<IQQ", 2, 0, 0)
return header
raise ValueError(f"Unexpected url: {url}")

monkeypatch.setattr(huggingface, "_make_request", fake_make_request)

tensors, config, format_name, disk_size = huggingface.fetch_huggingface_repo("org/model-gguf")

assert format_name == "GGUF"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ LOW RISK

Suggestion: The mock implementation for Hugging Face API requests is duplicated across multiple GGUF parsing tests. Extracting this logic into a shared helper or a pytest fixture would improve maintainability.

Comment thread src/modelinfo/ui.py
if gpu_name:
utilization = vram_bytes / (max_vram_gb * 1024**3) if max_vram_gb > 0 else 2.0
if utilization <= 0.90:
if utilization <= gpu_util:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚪ LOW RISK

Suggestion: This correctly replaces the hardcoded 0.90 threshold with the user-configurable 'gpu_util' parameter as specified in the CLI arguments. Note that this change currently lacks an automated test scenario.

@pipe1os pipe1os closed this Jun 27, 2026
@pipe1os pipe1os deleted the advisor/008-fix-comparison-trailing-slash branch June 27, 2026 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant