Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(812)

Unified Diff: lint_shell_commands.py

Issue 2693893009: [NOT FOR COMMINT] Linter for RunShellCommand calls (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chromium_issues.txt ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lint_shell_commands.py
diff --git a/lint_shell_commands.py b/lint_shell_commands.py
new file mode 100755
index 0000000000000000000000000000000000000000..87bc81b764541852dc4b7fb621e972cc090d8f58
--- /dev/null
+++ b/lint_shell_commands.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+import argparse
+import ast
+import logging
+import os
+import sys
+
+logging.basicConfig(format='%(levelname)s:%(message)s', stream=sys.stdout)
+
+
+def is_true(node):
+ return isinstance(node, ast.Name) and node.id == 'True'
+
+
+def node_repr(node):
+ if isinstance(node, ast.Name):
+ return node.id
+ else:
+ raise NotImplementedError(ast.dump(node))
+
+
+def lint_shell_command_calls(basename, filename):
+ with open(os.path.join(basename, filename)) as f:
+ try:
+ tree = ast.parse(f.read(), filename)
+ except Exception:
+ logging.warning('%s: Parse error, skipping.', filename)
+ return
+
+ for node in ast.walk(tree):
+ if (isinstance(node, ast.Call) and
+ isinstance(node.func, ast.Attribute) and
+ node.func.attr == 'RunShellCommand'):
+
+ if node.args and isinstance(node.args[0], ast.Str):
+ logging.warning(
+ '%s:%s: Avoid passing command as a string.', filename, node.lineno)
+
+ kwargs = {kw.arg: kw.value for kw in node.keywords}
+ check_return = kwargs.get('check_return')
+ if check_return is None:
+ logging.warning(
+ '%s:%s: Missing check_return=True.', filename, node.lineno)
+ elif not is_true(check_return):
+ logging.warning(
+ '%s:%s: Consider switching check_return=%s to True.',
+ filename, node.lineno, node_repr(check_return))
+
+
+def ignore_dir(dirname):
+ return dirname.startswith('.') or dirname == 'third_party'
+
+
+def iter_python_files(root):
+ for abs_dirpath, dirnames, filenames in os.walk(root):
+ dirpath = os.path.relpath(abs_dirpath, root)
+ for filename in filenames:
+ if filename.endswith('.py'):
+ yield os.path.join(dirpath, filename)
+ dirnames[:] = [d for d in dirnames if not ignore_dir(d)]
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('root')
+ args = parser.parse_args()
+
+ args.root = os.path.realpath(args.root)
+ for filename in iter_python_files(args.root):
+ lint_shell_command_calls(args.root, filename)
+
+
+if __name__ == '__main__':
+ sys.exit(main())
« no previous file with comments | « chromium_issues.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698