Skip to content

Commit fbaca88

Browse files
authored
feat: add more Ruff checks, and a helper script (#670)
* feat: add more Ruff checks, and a helper script Signed-off-by: Henry Schreiner <[email protected]> * fix: make sure the lists match Signed-off-by: Henry Schreiner <[email protected]> --------- Signed-off-by: Henry Schreiner <[email protected]>
1 parent 141396d commit fbaca88

File tree

8 files changed

+241
-83
lines changed

8 files changed

+241
-83
lines changed

docs/pages/guides/style.md

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -217,34 +217,42 @@ won't tell you what or why it fixed things.
217217
```toml
218218
[tool.ruff.lint]
219219
extend-select = [
220-
"ARG", # flake8-unused-arguments
221-
"B", # flake8-bugbear
222-
"C4", # flake8-comprehensions
223-
"DTZ", # flake8-datetimez
224-
"EM", # flake8-errmsg
225-
"EXE", # flake8-executable
226-
"FA", # flake8-future-annotations
227-
"FURB", # refurb
228-
"G", # flake8-logging-format
229-
"I", # isort
230-
"ICN", # flake8-import-conventions
231-
"NPY", # NumPy specific rules
232-
"PD", # pandas-vet
233-
"PERF", # perflint
234-
"PGH", # pygrep-hooks
235-
"PIE", # flake8-pie
236-
"PL", # pylint
237-
"PT", # flake8-pytest-style
238-
"PTH", # flake8-use-pathlib
239-
"PYI", # flake8-pyi
240-
"RET", # flake8-return
241-
"RUF", # Ruff-specific
242-
"SIM", # flake8-simplify
243-
"SLOT", # flake8-slots
244-
"T20", # flake8-print
245-
"TC", # flake8-type-checking
246-
"UP", # pyupgrade
247-
"YTT", # flake8-2020
220+
"ARG", # flake8-unused-arguments
221+
"B", # flake8-bugbear
222+
"BLE", # flake8-blind-except
223+
"C4", # flake8-comprehensions
224+
"DTZ", # flake8-datetimez
225+
"EM", # flake8-errmsg
226+
"EXE", # flake8-executable
227+
"FA", # flake8-future-annotations
228+
"FLY", # flynt
229+
"FURB", # refurb
230+
"G", # flake8-logging-format
231+
"I", # isort
232+
"ICN", # flake8-import-conventions
233+
"ISC", # flake8-implicit-str-concat
234+
"LOG", # flake8-logging
235+
"NPY", # NumPy specific rules
236+
"PD", # pandas-vet
237+
"PERF", # perflint
238+
"PGH", # pygrep-hooks
239+
"PIE", # flake8-pie
240+
"PL", # pylint
241+
"PT", # flake8-pytest-style
242+
"PTH", # flake8-use-pathlib
243+
"PYI", # flake8-pyi
244+
"Q", # flake8-quotes
245+
"RET", # flake8-return
246+
"RSE", # flake8-raise
247+
"RUF", # Ruff-specific
248+
"SIM", # flake8-simplify
249+
"SLOT", # flake8-slots
250+
"T10", # flake8-debugger
251+
"T20", # flake8-print
252+
"TC", # flake8-type-checking
253+
"TRY", # tryceratops
254+
"UP", # pyupgrade
255+
"YTT", # flake8-2020
248256
]
249257
ignore = [
250258
"PLR09", # Too many <...>

helpers/cog_cc.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ def yaml(self) -> str:
2626
result.append(f" help: {self.prompt}")
2727
if self.choices:
2828
result.append(" choices:")
29-
for choice in self.choices:
30-
result.append(
31-
f' "{choice.description}": {choice.name}'
32-
if choice.description
33-
else f" - {choice.name}"
34-
)
29+
result.extend(
30+
f' "{choice.description}": {choice.name}'
31+
if choice.description
32+
else f" - {choice.name}"
33+
for choice in self.choices
34+
)
3535
return "\n".join(result)
3636

3737

helpers/extensions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class CookiecutterContext(SmartDict):
3939

4040
@CookiecutterContext.register
4141
def __year(_):
42-
return str(datetime.datetime.today().year)
42+
return str(datetime.datetime.now(tz=datetime.timezone.utc).year)
4343

4444

4545
@CookiecutterContext.register

helpers/missing_ruff.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/usr/bin/env -S uv run --script
2+
3+
# /// script
4+
# dependencies = ["ruff", "rich"]
5+
# ///
6+
7+
8+
import argparse
9+
import json
10+
import subprocess
11+
from collections.abc import Iterator
12+
from pathlib import Path
13+
14+
import tomllib
15+
from rich import print
16+
from rich.columns import Columns
17+
from rich.panel import Panel
18+
from ruff.__main__ import find_ruff_bin
19+
20+
libs = {"AIR", "ASYNC", "DJ", "FAST", "INT", "NPY", "PD"}
21+
specialty = {
22+
"CPY", # preview only
23+
"A", # Naming related
24+
"N", # Naming related
25+
"ANN", # Not all rules good
26+
"TID", # Not all rules good
27+
"C90", # Complexity
28+
"COM", # Trailing commas inform the formatter
29+
"D", # Requires everything documented
30+
"DOC", # Style-specific
31+
"ERA", # Check for commented code
32+
"FBT", # Can't be applied to old code very well
33+
"FIX", # TODO's are okay
34+
"TD", # Picky on todo rules
35+
"INP", # Namespace packages are correct sometimes
36+
"S", # Security (can be picky)
37+
"SLF", # Very picky
38+
}
39+
40+
41+
def process_dir(path: Path) -> None:
42+
with path.joinpath("pyproject.toml").open("rb") as f:
43+
pyproject = tomllib.load(f)
44+
45+
match pyproject:
46+
case {"tool": {"ruff": {"lint": {"extend-select": selection}}}}:
47+
selected = frozenset(selection)
48+
case _:
49+
raise SystemExit(1)
50+
51+
linter_txt = subprocess.run(
52+
[find_ruff_bin(), "linter", "--output-format=json"],
53+
check=True,
54+
capture_output=True,
55+
text=True,
56+
cwd=path,
57+
).stdout
58+
linter = json.loads(linter_txt)
59+
60+
lint_info = {r["prefix"]: r["name"] for r in linter if r["prefix"] not in {"", "F"}}
61+
62+
selected_items = {k: v for k, v in lint_info.items() if k in selected}
63+
all_uns_items = {k: v for k, v in lint_info.items() if k not in selected}
64+
unselected_items = {
65+
k: v for k, v in all_uns_items.items() if k not in libs | specialty
66+
}
67+
libs_items = {k: v for k, v in all_uns_items.items() if k in libs}
68+
spec_items = {k: v for k, v in all_uns_items.items() if k in specialty}
69+
70+
def print_each(items: dict[str, str]) -> Iterator[str]:
71+
for k, v in items.items():
72+
kk = f'[green]"{k}"[/green],'
73+
yield f" {kk:23} [dim]# {v}[/dim]"
74+
75+
panel_sel = Panel(
76+
"\n".join(print_each(selected_items)), title="Selected", border_style="green"
77+
)
78+
panel_lib = Panel(
79+
"\n".join(print_each(libs_items)),
80+
title="Library specific",
81+
border_style="yellow",
82+
)
83+
panel_spec = Panel(
84+
"\n".join(print_each(spec_items)), title="Specialized", border_style="yellow"
85+
)
86+
uns = "\n".join(print_each(unselected_items))
87+
88+
if uns:
89+
print(Columns([panel_sel, panel_lib, panel_spec]))
90+
print("[red]Unselected [dim](copy and paste ready)")
91+
print(uns)
92+
93+
94+
def main() -> None:
95+
parser = argparse.ArgumentParser(description="Look up Ruff rules in a directory")
96+
parser.add_argument(
97+
"path",
98+
nargs="?",
99+
type=Path,
100+
default=Path.cwd(),
101+
help="Directory to process (default: current working directory)",
102+
)
103+
args = parser.parse_args()
104+
105+
process_dir(args.path)
106+
107+
108+
if __name__ == "__main__":
109+
main()

pyproject.toml

Lines changed: 37 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -158,26 +158,43 @@ messages_control.disable = [
158158

159159
[tool.ruff.lint]
160160
extend-select = [
161-
"ARG", # flake8-unused-arguments
162-
"B", # flake8-bugbear
163-
"C4", # flake8-comprehensions
164-
"EM", # flake8-errmsg
165-
"FA", # flake8-future-annotations
166-
"I", # isort
167-
"ICN", # flake8-import-conventions
168-
"PGH", # pygrep-hooks
169-
"PIE", # flake8-pie
170-
"PL", # pylint
171-
"PT", # flake8-pytest-style
172-
"PTH", # flake8-use-pathlib
173-
"RET", # flake8-return
174-
"RUF", # Ruff-specific
175-
"SIM", # flake8-simplify
176-
"T20", # flake8-print
177-
"TC", # flake8-type-check
178-
"TID251", # flake8-tidy-imports.banned-api
179-
"UP", # pyupgrade
180-
"YTT", # flake8-2020
161+
"ARG", # flake8-unused-arguments
162+
"B", # flake8-bugbear
163+
"BLE", # flake8-blind-except
164+
"C4", # flake8-comprehensions
165+
"DTZ", # flake8-datetimez
166+
"EM", # flake8-errmsg
167+
"EXE", # flake8-executable
168+
"FA", # flake8-future-annotations
169+
"FLY", # flynt
170+
"FURB", # refurb
171+
"G", # flake8-logging-format
172+
"I", # isort
173+
"ICN", # flake8-import-conventions
174+
"ISC", # flake8-implicit-str-concat
175+
"LOG", # flake8-logging
176+
"NPY", # NumPy specific rules
177+
"PD", # pandas-vet
178+
"PERF", # perflint
179+
"PGH", # pygrep-hooks
180+
"PIE", # flake8-pie
181+
"PL", # pylint
182+
"PT", # flake8-pytest-style
183+
"PTH", # flake8-use-pathlib
184+
"PYI", # flake8-pyi
185+
"Q", # flake8-quotes
186+
"RET", # flake8-return
187+
"RSE", # flake8-raise
188+
"RUF", # Ruff-specific
189+
"SIM", # flake8-simplify
190+
"SLOT", # flake8-slots
191+
"T10", # flake8-debugger
192+
"T20", # flake8-print
193+
"TC", # flake8-type-checking
194+
"TID251", # flake8-tidy-imports.banned-api
195+
"TRY", # tryceratops
196+
"UP", # pyupgrade
197+
"YTT", # flake8-2020
181198
]
182199
ignore = [
183200
"PLR", # Design related pylint codes

src/sp_repo_review/families.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,19 @@ def ruff_description(ruff: dict[str, Any]) -> str:
4848
common = {
4949
"ARG",
5050
"B",
51+
"BLE",
5152
"C4",
5253
"DTZ",
5354
"EM",
5455
"EXE",
5556
"FA",
57+
"FLY",
5658
"FURB",
5759
"G",
5860
"I",
5961
"ICN",
62+
"ISC",
63+
"LOG",
6064
"NPY",
6165
"PD",
6266
"PERF",
@@ -66,12 +70,16 @@ def ruff_description(ruff: dict[str, Any]) -> str:
6670
"PT",
6771
"PTH",
6872
"PYI",
73+
"Q",
6974
"RET",
75+
"RSE",
7076
"RUF",
7177
"SIM",
7278
"SLOT",
79+
"T10",
7380
"T20",
7481
"TC",
82+
"TRY",
7583
"UP",
7684
"YTT",
7785
}

tests/test_families.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,19 @@ def test_python_requires():
6060
ALL_RULES = [
6161
"ARG",
6262
"B",
63+
"BLE",
6364
"C4",
6465
"DTZ",
6566
"EM",
6667
"EXE",
6768
"FA",
69+
"FLY",
6870
"FURB",
6971
"G",
7072
"I",
7173
"ICN",
74+
"ISC",
75+
"LOG",
7276
"NPY",
7377
"PD",
7478
"PERF",
@@ -78,12 +82,16 @@ def test_python_requires():
7882
"PT",
7983
"PTH",
8084
"PYI",
85+
"Q",
8186
"RET",
87+
"RSE",
8288
"RUF",
8389
"SIM",
8490
"SLOT",
91+
"T10",
8592
"T20",
8693
"TC",
94+
"TRY",
8795
"UP",
8896
"YTT",
8997
]

0 commit comments

Comments
 (0)