feat: support ruff 0.16+, refresh all predefined configs, and handle codeless rules - #209
Conversation
Reviewer's GuideThis PR upgrades Ruff support to 0.16.5, refreshes and validates all predefined configurations, and propagates optional rule metadata through rule evaluation and the TUI so codeless/category rules can be selected, grouped, inspected, searched, and rendered safely. Flow diagram for codeless Ruff rule handlingflowchart TD
A[Ruff rule metadata] --> B[compute_effective_rules]
B --> C{Match code, name, or category}
C --> D[Rule status]
D --> E[Search and inspection]
D --> F[Group by linter or category]
F --> G[Render rule with fallback identifier]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src/ruff_sync/tui/types_.py" line_range="237-238" />
<code_context>
prefix = linter.get("prefix")
if prefix and any(
- r["code"].startswith(prefix) and r["status"] != "Disabled" for r in effective_rules
+ (r.get("code") or "").startswith(prefix) and r.get("status") != "Disabled"
+ for r in effective_rules
):
return True
</code_context>
<issue_to_address>
**issue (broader_impact):** Codeless rules are never considered when activating or populating a linter group: `_is_linter_active` only matches non-empty rule codes, and the linter table still filters on `r["linter"] == linter_name`. A Ruff 0.16.5 rule such as `pytest-fixture-autouse` therefore disappears from its linter view, even when its name or category is selected and its status is Enabled.
**Triggers:** When a codeless Ruff rule has no code and no matching linter string, as represented by the new compatibility test data.
**Suggested fix:** Match linter groups using the rule name/category when the code or linter field is absent, and use the same fallback in the table filter.
</issue_to_address>
### Comment 2
<location path="src/ruff_sync/tui/app.py" line_range="221" />
<code_context>
"""
# Fetch metadata for enrichment
- rule_data = next((r for r in self.effective_rules if r["code"] == rule_code), None)
+ rule_data = next(
+ (
+ r
+ for r in self.effective_rules
+ if r.get("code") == rule_code or r.get("name") == rule_code
+ ),
+ None,
</code_context>
<issue_to_address>
**nitpick:** The `_inspect_rule` implementation now accepts either a rule code or a rule name, but its docstring still says that `rule_code` is the Ruff rule code and gives only a code-based contract. The documented callable contract is therefore false for the newly supported codeless-rule path.
**Triggers:** When the omnibox or a table row selects a codeless rule by name.
**Suggested fix:** Update the parameter documentation to state that the argument may be either a Ruff rule code or a rule name.
```suggestion
rule_code: A Ruff rule code or rule name to inspect.
```
</issue_to_address>Sourcery assessment
Approval pending. 1 finding to address first.
Blocking findings: src/ruff_sync/tui/types_.py:238
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #209 +/- ##
==========================================
+ Coverage 94.21% 94.28% +0.07%
==========================================
Files 10 11 +1
Lines 1590 1610 +20
==========================================
+ Hits 1498 1518 +20
Misses 92 92 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@sourcery-ai review |
|
@sourcery-ai review |
There was a problem hiding this comment.
Hey - I've found 1 issue
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src/ruff_sync/tui/app.py" line_range="224-229" />
<code_context>
"""
# Fetch metadata for enrichment
- rule_data = next((r for r in self.effective_rules if r["code"] == rule_code), None)
+ rule_data = next(
+ (
+ r
+ for r in self.effective_rules
+ if r.get("code") == rule_code or r.get("name") == rule_code
+ ),
+ None,
+ )
</code_context>
<issue_to_address>
**nitpick:** Codeless rules are now passed to `get_ruff_rule_markdown` by name, but its docstring still documents the parameter as a Ruff rule code and gives only a code-based example. This misstates the supported input contract for callers and maintainers.
**Triggers:** When inspecting a codeless rule from the TUI.
**Suggested fix:** Update the `get_ruff_rule_markdown` docstring to state that the argument accepts either a Ruff rule code or rule name, and update the example.
</issue_to_address>Sourcery assessment
Approved.
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
Summary
Adds support for Ruff 0.16+: refreshes all predefined configurations for
v0.16.5, updates the engine and TUI to handle rules that have no short code (codeless/category rules introduced in 0.16.x), and strictly enforces the ban onunittest.mockacross the codebase.Key Changes
Ruff 0.16+ Dev Tooling Update
ruffdev dependency andastral-sh/ruff-pre-commitrev tov0.16.5.uv.lockandAGENTS.md.Predefined Config Audits
configs/kitchen-sink/ruff.toml):Ruff v0.15.5→Ruff v0.16.5.FAST(FastAPI) rule category with doc link.INT(flake8-gettext) entry and corrected theARGdoc link."CPY"(flake8-copyright) now thatCPY001is stable.[lint.pep8-naming]to include Pydantic v2 decorators.[lint.flake8-copyright],[lint.flake8-gettext], and[format].nested-string-quote-style.configs/fastapi/ruff.toml): Added"FAST"to[lint].select.configs/data-science-engineering/ruff.toml): Refreshed for current Ruff conventions.docs/pre-defined-configs.md): Updated rule count to "over 900 rules".Codeless/Category Rule Compatibility (
src/ruff_sync/)Rules introduced in Ruff 0.16.x (e.g.
pytest-fixture-autouse) can lack a short code and match only by category or name. Updatedsystem.py,validation.py, and the TUI layer (tui/types_.py,tui/screens.py,tui/widgets.py,tui/app.py) to handle these rules safely throughout rule evaluation, search, inspection, and rendering.get_ruff_rule_markdown()to reflect support for rule names as well as rule codes.Import Ban Enforcement (
unittest.mock)unittest.mockviaflake8-tidy-imports.banned-api(TID251) andflake8-import-conventions.banned-from(ICN003) inpyproject.tomlandtests/ruff.toml.TID251exclusion fromtests/*per-file-ignoresso that banned mock imports are actively blocked across all tests.unittest.mock/patchusage intests/test_system.pyandtests/tui/test_tui.pywithpytest.MonkeyPatchand lightweight test stubs/spies (FakeProcess,SubprocessSpy).Tests
tests/test_predefined_configs.py(new): Validates all predefined configs parse correctly and asserts expected preset settings.tests/test_rule_logic.py: Expanded with codeless rule behavior coverage.tests/tui/test_tui.py,tests/tui/test_tui_types.py: Extended TUI coverage for codeless rules.tests/test_system.py: Rebuilt withoutunittest.mock, adding full test coverage for rule markdown by name/code, linters, and config fetching.Verification
uv run invoke lint— 0 errorsuv run invoke fmt— cleanuv run invoke type-check— 55 files, mypy strictuv run pytest -vv— 435 passed, 1 xfailedSummary by Sourcery
Upgrade Ruff support to 0.16.5, make codeless rules work throughout the application, refresh predefined configurations, and enforce mock-import restrictions.
New Features:
Bug Fixes:
Enhancements:
Build:
Documentation:
Tests: