A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 8, 12:30 UTC
[Misc] Add pre-commit hook to catch boolean ops in with-statements (#34271)
Signed-off-by: Tyler Michael Smith <tlrmchlsmth@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Tyler Michael Smith committed
Feb 10, 2026 at 18:13 UTC
c4b9e6778f9d8054c1665b2d1c2cb0ee36e9e2f5
2 files changed
+75
.pre-commit-config.yaml
+5
@@ -143,6 +143,11 @@ repos:
143
name: Check attention backend documentation is up to date
144
entry: python tools/pre_commit/generate_attention_backend_docs.py --check
145
language: python
146
+ - id: check-boolean-context-manager
147
+ name: Check for boolean ops in with-statements
148
+ entry: python tools/pre_commit/check_boolean_context_manager.py
149
+ language: python
150
+ types: [python]
151
# Keep `suggestion` last
152
- id: suggestion
153
name: Suggestion
tools/pre_commit/check_boolean_context_manager.py
new
+70
@@ -0,0 +1,70 @@
1
+# SPDX-License-Identifier: Apache-2.0
2
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
+"""Lint: detect `with a() and b():` (boolean op in with-statement context).
4
+
5
+Using `and`/`or` to combine context managers is almost always a bug:
6
+
7
+ with ctx_a() and ctx_b(): # BUG: only ctx_b is entered
8
+ with ctx_a() or ctx_b(): # BUG: only ctx_a is entered
9
+
10
+The correct way to combine context managers is:
11
+
12
+ with ctx_a(), ctx_b(): # comma-separated
13
+ with (ctx_a(), ctx_b()): # parenthesized (Python 3.10+)
14
+ with contextlib.ExitStack() ... # ExitStack
15
+"""
16
+
17
+import ast
18
+import sys
19
+
20
+
21
+def check_file(filepath: str) -> list[str]:
22
+ try:
23
+ with open(filepath, encoding="utf-8") as f:
24
+ source = f.read()
25
+ except (OSError, UnicodeDecodeError):
26
+ return []
27
+
28
+ try:
29
+ tree = ast.parse(source, filename=filepath)
30
+ except SyntaxError:
31
+ return []
32
+
33
+ violations = []
34
+ for node in ast.walk(tree):
35
+ if isinstance(node, (ast.With, ast.AsyncWith)):
36
+ for item in node.items:
37
+ if isinstance(item.context_expr, ast.BoolOp):
38
+ op = "and" if isinstance(item.context_expr.op, ast.And) else "or"
39
+ violations.append(
40
+ f"{filepath}:{item.context_expr.lineno}: "
41
+ f"boolean `{op}` used to combine context managers "
42
+ f"in `with` statement — use a comma instead"
43
+ )
44
+ return violations
45
+
46
+
47
+def main() -> int:
48
+ if len(sys.argv) < 2:
49
+ print("Usage: check_boolean_context_manager.py <file> ...", file=sys.stderr)
50
+ return 1
51
+
52
+ all_violations = []
53
+ for filepath in sys.argv[1:]:
54
+ all_violations.extend(check_file(filepath))
55
+
56
+ if all_violations:
57
+ print(
58
+ "❌ Boolean operator used to combine context managers in `with` "
59
+ "statement.\n"
60
+ " `with a() and b():` only enters `b()` as a context manager.\n"
61
+ " Use `with a(), b():` or `with (a(), b()):` instead.\n"
62
+ )
63
+ for v in all_violations:
64
+ print(f" {v}")
65
+ return 1
66
+ return 0
67
+
68
+
69
+if __name__ == "__main__":
70
+ sys.exit(main())