Skip to content

Commit 2b4b044

Browse files
authored
Merge pull request #795 from NHSDigital/improve-linter
Improve linter by switching from deny listing to allow listing
2 parents 517b4c2 + 73e8c38 commit 2b4b044

File tree

1 file changed

+35
-33
lines changed

1 file changed

+35
-33
lines changed

scripts/lint_model_usage_in_views.py

Lines changed: 35 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,38 @@
11
#!/usr/bin/env python3
2-
"""Simple linter to spot denylisted model usage within Django view modules."""
2+
"""Check for model usage without provider scoping within Django view modules."""
33

44
import argparse
5+
import re
56
import sys
7+
from dataclasses import dataclass
68
from pathlib import Path
79

8-
# Expected to be run from repository root
9-
REPO_ROOT = Path.cwd()
10-
11-
DENYLISTED_MODELS = (
12-
"Appointment",
13-
"Clinic",
14-
"Participant",
15-
"Symptom",
16-
"BreastCancerHistoryItem",
10+
REPO_ROOT = Path(__file__).parent.parent
11+
12+
ALLOWLISTED_MODELS = (
13+
"User",
14+
"Provider",
15+
"BenignLumpHistoryItem", # Temporarily allowed
16+
"BreastAugmentationHistoryItem", # Temporarily allowed
17+
"CystHistoryItem", # Temporarily allowed
18+
"ImplantedMedicalDeviceHistoryItem", # Temporarily allowed
19+
"MastectomyOrLumpectomyHistoryItem", # Temporarily allowed
20+
"OtherProcedureHistoryItem", # Temporarily allowed
21+
"ParticipantReportedMammogram", # Temporarily allowed
1722
)
18-
DENYLISTED_HELPERS = ("get_object_or_404(",)
1923

24+
TARGETS = {
25+
"model.objects": re.compile(r"(?P<model_name>\w+)\.objects"),
26+
"model.get_object_or_404": re.compile(r"(?P<model_name>\w+)\.get_object_or_404"),
27+
}
2028

21-
class Match:
22-
__slots__ = ("path", "line_number", "target", "line")
2329

24-
def __init__(self, path, line_number, target, line):
25-
self.path = path
26-
self.line_number = line_number
27-
self.target = target
28-
self.line = line
30+
@dataclass
31+
class Match:
32+
path: Path
33+
line_number: int
34+
target: str
35+
line: str
2936

3037

3138
def parse_args():
@@ -63,28 +70,23 @@ def find_view_modules(base_dir):
6370

6471

6572
def find_matches(paths):
66-
targets = {
67-
f"{model_name}.objects": f"{model_name}.objects"
68-
for model_name in DENYLISTED_MODELS
69-
}
70-
for helper in DENYLISTED_HELPERS:
71-
targets[helper] = helper
72-
7373
for path in paths:
7474
try:
7575
text = path.read_text(encoding="utf-8")
7676
except UnicodeDecodeError:
7777
continue
7878

7979
for line_number, line in enumerate(text.splitlines(), start=1):
80-
for needle, label in targets.items():
81-
if needle in line:
82-
yield Match(
83-
path=path,
84-
line_number=line_number,
85-
target=label,
86-
line=line.strip(),
87-
)
80+
for label, regex in TARGETS.items():
81+
if match := regex.search(line):
82+
model_name = match.group("model_name")
83+
if model_name not in ALLOWLISTED_MODELS:
84+
yield Match(
85+
path=path,
86+
line_number=line_number,
87+
target=label,
88+
line=line.strip(),
89+
)
8890

8991

9092
def main():

0 commit comments

Comments
 (0)