()
| 62 | |
| 63 | |
| 64 | def main() -> int: |
| 65 | parser = argparse.ArgumentParser() |
| 66 | parser.add_argument("paths", nargs="*", default=["."], help="Files/directories to scan") |
| 67 | parser.add_argument("--output", default="tmp/ruff-report.md", help="Markdown output path") |
| 68 | args = parser.parse_args() |
| 69 | |
| 70 | issues = run_ruff(args.paths) |
| 71 | |
| 72 | by_rule: dict[str, list[dict]] = collections.defaultdict(list) |
| 73 | for item in issues: |
| 74 | by_rule[item.get("code", "UNKNOWN")].append(item) |
| 75 | |
| 76 | out = Path(args.output) |
| 77 | out.parent.mkdir(parents=True, exist_ok=True) |
| 78 | |
| 79 | lines: list[str] = [] |
| 80 | lines.append("# Ruff manual-fix report\n") |
| 81 | lines.append(f"Generated from: `{', '.join(args.paths)}`\n") |
| 82 | lines.append(f"Total remaining issues: **{len(issues)}**\n") |
| 83 | |
| 84 | lines.append("## Summary\n") |
| 85 | lines.append("| Rule | Count | Note |") |
| 86 | lines.append("|---|---:|---|") |
| 87 | for rule, items in sorted(by_rule.items(), key=lambda kv: (-len(kv[1]), kv[0])): |
| 88 | note = RULE_NOTES.get(rule, "") |
| 89 | lines.append(f"| `{rule}` | {len(items)} | {note} |") |
| 90 | lines.append("") |
| 91 | |
| 92 | lines.append("## Suggested triage order\n") |
| 93 | preferred = ["F403", "F405", "F821", "E722", "B904", "E402", "F401", "E501"] |
| 94 | present = [r for r in preferred if r in by_rule] |
| 95 | if present: |
| 96 | for idx, rule in enumerate(present, 1): |
| 97 | lines.append(f"{idx}. `{rule}` — {RULE_NOTES.get(rule, '')}") |
| 98 | lines.append("") |
| 99 | |
| 100 | lines.append("## Table of contents by rule\n") |
| 101 | for rule, items in sorted(by_rule.items(), key=lambda kv: (-len(kv[1]), kv[0])): |
| 102 | anchor = rule.lower() |
| 103 | lines.append(f"- [{rule} ({len(items)})](#{anchor})") |
| 104 | lines.append("") |
| 105 | |
| 106 | for rule, items in sorted(by_rule.items(), key=lambda kv: (-len(kv[1]), kv[0])): |
| 107 | lines.append(f"## {rule}\n") |
| 108 | lines.append(f"Count: **{len(items)}** ") |
| 109 | if rule in RULE_NOTES: |
| 110 | lines.append(f"Hint: {RULE_NOTES[rule]} ") |
| 111 | lines.append("") |
| 112 | |
| 113 | file_groups: dict[str, list[dict]] = collections.defaultdict(list) |
| 114 | for item in items: |
| 115 | file_groups[relpath(item["filename"])].append(item) |
| 116 | |
| 117 | lines.append("### Files affected\n") |
| 118 | lines.append("| File | Count |") |
| 119 | lines.append("|---|---:|") |
| 120 | for filename, entries in sorted(file_groups.items(), key=lambda kv: (-len(kv[1]), kv[0])): |
| 121 | lines.append(f"| `{filename}` | {len(entries)} |") |
no test coverage detected