返回 last30days-skill
test_no_bare_open_read.py
根目录 / tests / test_no_bare_open_read.py
1 """Prevent direct ``open(...).read()`` calls in the CLI entrypoint."""
2
3 from __future__ import annotations
4
5 import ast
6 from pathlib import Path
7
8 ROOT = Path(__file__).resolve().parents[1]
9 LAST30DAYS = ROOT / "skills" / "last30days" / "scripts" / "last30days.py"
10
11
12 class BareOpenReadFinder(ast.NodeVisitor):
13 def __init__(self) -> None:
14 self.violations: list[int] = []
15
16 def visit_Call(self, node: ast.Call) -> None:
17 func = node.func
18 if (
19 isinstance(func, ast.Attribute)
20 and func.attr == "read"
21 and isinstance(func.value, ast.Call)
22 and isinstance(func.value.func, ast.Name)
23 and func.value.func.id == "open"
24 ):
25 self.violations.append(node.lineno)
26 self.generic_visit(node)
27
28
29 def test_last30days_does_not_call_read_directly_on_open():
30 tree = ast.parse(LAST30DAYS.read_text(encoding="utf-8"), filename=str(LAST30DAYS))
31 finder = BareOpenReadFinder()
32 finder.visit(tree)
33
34 assert not finder.violations, (
35 "Use a context manager for file reads instead of direct open(...).read() "
36 f"in {LAST30DAYS.relative_to(ROOT)} at lines: {finder.violations}"
37 )
38
38 lines PYTHON