1from plain.models import OperationalError, ProgrammingError
2from plain.preflight import PreflightCheck, PreflightResult, register_check
3from plain.runtime import settings
4
5from .bridge import get_flag_class
6from .exceptions import FlagImportError
7
8
9@register_check(name="flags.unused_flags")
10class CheckUnusedFlags(PreflightCheck):
11 """
12 Check for flags that are in the database, but no longer defined in code.
13
14 Only returns Info errors because it is valid to leave them if you're worried about
15 putting the flag back, but they should probably be deleted eventually.
16 """
17
18 def run(self) -> list[PreflightResult]:
19 # Import here to avoid circular import
20 from .models import Flag
21
22 errors = []
23
24 flag_names = Flag.query.all().values_list("name", flat=True)
25
26 try:
27 flag_names = set(flag_names)
28 except (ProgrammingError, OperationalError):
29 # The table doesn't exist yet
30 # (migrations probably haven't run yet),
31 # so we can't check it.
32 return errors
33
34 for flag_name in flag_names:
35 try:
36 get_flag_class(flag_name)
37 except FlagImportError:
38 errors.append(
39 PreflightResult(
40 fix=f"Flag {flag_name} is not used. Remove the flag from the database or define it in the {settings.FLAGS_MODULE} module.",
41 warning=True,
42 id="flags.unused_flags",
43 )
44 )
45
46 return errors