11from __future__ import annotations
22
33import typing
4- from typing import Any
4+ from typing import TYPE_CHECKING , Any
5+
6+ if TYPE_CHECKING :
7+ from collections .abc import Generator
8+
59
610__all__ = ["Family" , "get_families" ]
711
@@ -16,23 +20,74 @@ class Family(typing.TypedDict, total=False):
1620 description : str # Defaults to empty
1721
1822
19- def get_families (pyproject : dict [str , Any ]) -> dict [str , Family ]:
20- pyproject_description = f"- Detected build backend: `{ pyproject .get ('build-system' , {}).get ('build-backend' , 'MISSING' )} `"
21- if isinstance (license := pyproject .get ("project" , {}).get ("license" , {}), str ):
22- pyproject_description += f"\n - SPDX license expression: `{ license } `"
23- elif classifiers := pyproject .get ("project" , {}).get ("classifiers" , []):
24- licenses = [
25- c .removeprefix ("License :: " ).removeprefix ("OSI Approved :: " )
26- for c in classifiers
27- if c .startswith ("License :: " )
28- ]
29- if licenses :
30- pyproject_description += f"\n - Detected license(s): { ', ' .join (licenses )} "
23+ def general_description (pyproject : dict [str , Any ]) -> Generator [str , None , None ]:
24+ yield f"- Detected build backend: `{ pyproject .get ('build-system' , {}).get ('build-backend' , 'MISSING' )} `"
25+ match pyproject :
26+ case {"project" : {"license" : str () as license }}:
27+ yield f"- SPDX license expression: `{ license } `"
28+ case {"project" : {"classifiers" : classifiers }}:
29+ licenses = [
30+ c .removeprefix ("License :: " ).removeprefix ("OSI Approved :: " )
31+ for c in classifiers
32+ if c .startswith ("License :: " )
33+ ]
34+ if licenses :
35+ yield f"- Detected license(s): { ', ' .join (licenses )} "
36+
37+
38+ def ruff_description (ruff : dict [str , Any ]) -> str :
39+ common = {
40+ "ARG" ,
41+ "B" ,
42+ "C4" ,
43+ "DTZ" ,
44+ "EM" ,
45+ "EXE" ,
46+ "FA" ,
47+ "FURB" ,
48+ "G" ,
49+ "I" ,
50+ "ICN" ,
51+ "NPY" ,
52+ "PD" ,
53+ "PERF" ,
54+ "PGH" ,
55+ "PIE" ,
56+ "PL" ,
57+ "PT" ,
58+ "PTH" ,
59+ "PYI" ,
60+ "RET" ,
61+ "RUF" ,
62+ "SIM" ,
63+ "SLOT" ,
64+ "T20" ,
65+ "TC" ,
66+ "UP" ,
67+ "YTT" ,
68+ }
69+
70+ match ruff :
71+ case (
72+ {"lint" : {"select" : x } | {"extend-select" : x }}
73+ | {"select" : x }
74+ | {"extend-select" : x }
75+ ):
76+ selected = set (x )
77+ known = common - selected
78+ if not known or "ALL" in selected :
79+ return "All mentioned rules selected"
80+ rulelist = ", " .join (f'"{ r } "' for r in known )
81+ return f"Rules mentioned in guide but not here: `{ rulelist } `"
82+ return ""
83+
84+
85+ def get_families (pyproject : dict [str , Any ], ruff : dict [str , Any ]) -> dict [str , Family ]:
3186 return {
3287 "general" : Family (
3388 name = "General" ,
3489 order = - 3 ,
35- description = pyproject_description ,
90+ description = " \n " . join ( general_description ( pyproject )) ,
3691 ),
3792 "pyproject" : Family (
3893 name = "PyProject" ,
@@ -49,6 +104,7 @@ def get_families(pyproject: dict[str, Any]) -> dict[str, Family]:
49104 ),
50105 "ruff" : Family (
51106 name = "Ruff" ,
107+ description = ruff_description (ruff ),
52108 ),
53109 "docs" : Family (
54110 name = "Documentation" ,
0 commit comments