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

Side by Side 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 unified diff | Download patch
« no previous file with comments | « chromium_issues.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 import argparse
3 import ast
4 import logging
5 import os
6 import sys
7
8 logging.basicConfig(format='%(levelname)s:%(message)s', stream=sys.stdout)
9
10
11 def is_true(node):
12 return isinstance(node, ast.Name) and node.id == 'True'
13
14
15 def node_repr(node):
16 if isinstance(node, ast.Name):
17 return node.id
18 else:
19 raise NotImplementedError(ast.dump(node))
20
21
22 def lint_shell_command_calls(basename, filename):
23 with open(os.path.join(basename, filename)) as f:
24 try:
25 tree = ast.parse(f.read(), filename)
26 except Exception:
27 logging.warning('%s: Parse error, skipping.', filename)
28 return
29
30 for node in ast.walk(tree):
31 if (isinstance(node, ast.Call) and
32 isinstance(node.func, ast.Attribute) and
33 node.func.attr == 'RunShellCommand'):
34
35 if node.args and isinstance(node.args[0], ast.Str):
36 logging.warning(
37 '%s:%s: Avoid passing command as a string.', filename, node.lineno)
38
39 kwargs = {kw.arg: kw.value for kw in node.keywords}
40 check_return = kwargs.get('check_return')
41 if check_return is None:
42 logging.warning(
43 '%s:%s: Missing check_return=True.', filename, node.lineno)
44 elif not is_true(check_return):
45 logging.warning(
46 '%s:%s: Consider switching check_return=%s to True.',
47 filename, node.lineno, node_repr(check_return))
48
49
50 def ignore_dir(dirname):
51 return dirname.startswith('.') or dirname == 'third_party'
52
53
54 def iter_python_files(root):
55 for abs_dirpath, dirnames, filenames in os.walk(root):
56 dirpath = os.path.relpath(abs_dirpath, root)
57 for filename in filenames:
58 if filename.endswith('.py'):
59 yield os.path.join(dirpath, filename)
60 dirnames[:] = [d for d in dirnames if not ignore_dir(d)]
61
62
63 def main():
64 parser = argparse.ArgumentParser()
65 parser.add_argument('root')
66 args = parser.parse_args()
67
68 args.root = os.path.realpath(args.root)
69 for filename in iter_python_files(args.root):
70 lint_shell_command_calls(args.root, filename)
71
72
73 if __name__ == '__main__':
74 sys.exit(main())
OLDNEW
« 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