Files
computer-playbook/tests/lint/filesystem/python/test_no_redundant_bool_patterns.py
T
kevinveenbirkenbachandClaude Opus 5 5137465c6f style: delete every comment the comments-valid policy rejects
3529 invalid comments in 528 files, grandfathered in while the linter
only saw the working-tree diff. Removal ran through the linter's own
collectors, so detection and deletion cannot drift: a comment whose
opener line is blank before it and whose closer line is blank after it
loses all its lines, anything else loses only the comment region, and a
line left holding a bare delimiter goes with it.

Five files keep their comments behind a nocheck marker instead. Four are
upstream configs whose inline docs are upstream's own (mautrix, systemd
journald, nextcloud-oidc-login, MediaWiki). In littlejs the
commented-out entries ARE the deactivation mechanism for an example
tile, so deleting them would delete configuration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 03:22:02 +02:00

177 lines
6.5 KiB
Python

"""Lint guard: redundant boolean expressions in Jinja2 / Ansible YAML.
Two related anti-patterns are flagged here. Each is independently
suppressible via its own marker so a legitimate exception can opt out
of one without disabling the other.
1. ``redundant-bool-ternary`` — ``<bool-expr> | ternary('true','false')``
for any boolean-producing left side: the ``bool`` filter, an ``in``
/ ``not in`` / ``is`` / ``is not`` / comparison operator, a Jinja
``is defined`` / ``is none`` test, etc. The ``ternary`` is a no-op
on a value that is already a boolean — its only effect is to swap
``True`` / ``False`` for the lowercase string tokens
``'true'`` / ``'false'``, and every consumer the project actually
feeds these to (PHP ``filter_var(..., FILTER_VALIDATE_BOOLEAN)``,
JS ``String(x).toLowerCase() === "true"``, dotenv-style flags,
Ansible ``bool``-comparing conditionals) accepts ``True`` / ``False``
just as well. Convention::
{{ FOO | bool }}
{{ 'web-app-lam' in group_names }}
{{ (A == B) }}
The detector keys on the literal ``'true'`` / ``'false'`` payload
inside ``ternary(…)``. Real string conversions that happen to use
``ternary`` use other labels (``'yes'`` / ``'no'``, ``'1'`` / ``'0'``,
…) and are NOT matched. ``... | bool | string | lower`` is also NOT
matched — it lower-cases the output to the literal token
``true`` / ``false``, which IS sometimes required by Rails / Elixir
consumers.
2. ``redundant-bool-comparison`` — ``... | bool == True/False`` and the
lower-case / quoted variants (``== true``, ``== "false"``, …).
Comparing a boolean against a boolean literal is a tautology that
hides intent. Convention::
when: FOO | bool # truthy branch
when: not (FOO | bool) # falsy branch
Per-line opt-out::
# nocheck: redundant-bool-ternary
{# nocheck: redundant-bool-comparison #}
The marker grammar is documented at
``docs/contributing/actions/testing/suppression.md``.
"""
from __future__ import annotations
import re
import unittest
from pathlib import Path
from utils.annotations.suppress import suppressed_line_numbers
from utils.cache.files import PROJECT_ROOT, iter_project_files, read_text
_PATTERN_TERNARY: re.Pattern[str] = re.compile(
r"""\|\s*ternary\(\s*['"]true['"]\s*,\s*['"]false['"]\s*\)""",
)
_PATTERN_COMPARISON: re.Pattern[str] = re.compile(
r"""\|\s*bool\s*==\s*(?:['"]?(?:true|false)['"]?)""",
re.IGNORECASE,
)
_SCAN_EXTENSIONS: tuple[str, ...] = (".j2", ".yml", ".yaml")
def _scan_paths() -> list[Path]:
"""Iterate every production template / YAML file via the shared
file-walk cache (tests dir excluded)."""
out: list[Path] = []
for s in iter_project_files(extensions=_SCAN_EXTENSIONS, exclude_tests=True):
p = Path(s)
try:
p.relative_to(PROJECT_ROOT)
except ValueError:
continue
out.append(p)
return sorted(out)
def _file_offenders(path: Path, pattern: re.Pattern[str], rule: str) -> list[str]:
"""Return ``[]`` if the file is clean, or a list of human-readable
``line N: <snippet>`` strings for each match of ``pattern`` on a
line not annotated with ``noqa: <rule>``.
"""
try:
src = read_text(str(path))
except (OSError, UnicodeDecodeError):
return []
lines = src.splitlines()
noqa_lines = suppressed_line_numbers(lines, rule)
offenders: list[str] = []
for idx, line in enumerate(lines, start=1):
if idx in noqa_lines:
continue
if pattern.search(line) is None:
continue
offenders.append(f"line {idx}: {line.strip()}")
return offenders
def _collect(pattern: re.Pattern[str], rule: str) -> dict[Path, list[str]]:
out: dict[Path, list[str]] = {}
for path in _scan_paths():
issues = _file_offenders(path, pattern, rule)
if issues:
out[path] = issues
return out
def _format_failure(
headline: str,
offenders: dict[Path, list[str]],
fix: str,
) -> str:
rel = lambda p: p.relative_to(PROJECT_ROOT) # noqa: E731
lines = [headline]
for path, issues in sorted(offenders.items()):
lines.append(f" - {rel(path)}:")
lines.extend(f" * {issue}" for issue in issues)
lines.append("")
lines.append(fix)
return "\n".join(lines)
class TestNoRedundantBoolPatterns(unittest.TestCase):
"""Reject ``| bool | ternary(…)`` and ``| bool == <bool-literal>``."""
def test_no_redundant_bool_ternary(self) -> None:
offenders = _collect(_PATTERN_TERNARY, "redundant-bool-ternary")
if not offenders:
return
self.fail(
_format_failure(
f"{len(offenders)} file(s) end a boolean expression with "
f"`| ternary('true','false')`. That ternary is a no-op on "
f"a value that is already a boolean — its only effect is "
f"to swap `True`/`False` for the lowercase string tokens "
f"`'true'`/`'false'`, which every consumer the project "
f"actually feeds them to accepts unchanged:",
offenders,
"Fix: drop the `| ternary('true','false')` segment. The "
"preceding expression already evaluates to the truth value "
"you want — `FOO | bool`, `'web-app-X' in group_names`, "
"`(A == B)`, `FOO is defined`, etc. If the consumer "
"truly requires the literal lowercase tokens 'true'/'false', "
"use `... | bool | string | lower` and annotate the line "
"with `noqa: redundant-bool-ternary` (with a one-line "
"comment explaining why).",
)
)
def test_no_redundant_bool_comparison(self) -> None:
offenders = _collect(_PATTERN_COMPARISON, "redundant-bool-comparison")
if not offenders:
return
self.fail(
_format_failure(
f"{len(offenders)} file(s) compare `... | bool` against a "
f"bool literal. The comparison is a no-op — `... | bool` "
f"already produces the boolean you are testing for:",
offenders,
"Fix: replace `FOO | bool == True` with `FOO | bool` and "
"`FOO | bool == False` with `not (FOO | bool)`. If a real "
"tri-state guard is intended, annotate the line with "
"`noqa: redundant-bool-comparison` and document why.",
)
)
if __name__ == "__main__": # pragma: no cover
unittest.main()