summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-02-18 18:44:43 +0100
committerGitHub <noreply@github.com>2020-02-18 18:44:43 +0100
commit5e47e0bcba7585909a11e9c7424e864fc26a7fd2 (patch)
treefd808e05f549866b81fbaed527c0226355c02af3 /scripts
parent41fcba5dd7ecbbc788814c722f31e630422ba28e (diff)
downloadpsutil-5e47e0bcba7585909a11e9c7424e864fc26a7fd2.tar.gz
Add C linter script (#1698)
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/internal/.git-pre-commit16
-rwxr-xr-xscripts/internal/clinter.py76
-rwxr-xr-xscripts/internal/winmake.py4
3 files changed, 92 insertions, 4 deletions
diff --git a/scripts/internal/.git-pre-commit b/scripts/internal/.git-pre-commit
index 621879df..e6009253 100755
--- a/scripts/internal/.git-pre-commit
+++ b/scripts/internal/.git-pre-commit
@@ -77,6 +77,8 @@ def main():
out = sh("git diff --cached --name-only")
py_files = [x for x in out.split('\n') if x.endswith('.py') and
os.path.exists(x)]
+ c_files = [x for x in out.split('\n') if x.endswith(('.c', '.h')) and
+ os.path.exists(x)]
lineno = 0
kw = {'encoding': 'utf8'} if sys.version_info[0] == 3 else {}
@@ -100,7 +102,7 @@ def main():
print("%s:%s %s" % (path, lineno, line))
return exit("commit aborted: bare except clause")
- # flake8
+ # Python linter
if py_files:
try:
import flake8 # NOQA
@@ -108,12 +110,22 @@ def main():
return exit("commit aborted: flake8 is not installed; "
"run 'make setup-dev-env'")
- # XXX: we should scape spaces and possibly other amenities here
+ # XXX: we should escape spaces and possibly other amenities here
ret = subprocess.call(
"%s -m flake8 %s" % (sys.executable, " ".join(py_files)),
shell=True)
if ret != 0:
return exit("commit aborted: python code is not flake8 compliant")
+ # C linter
+ if c_files:
+ # XXX: we should escape spaces and possibly other amenities here
+ cmd = "%s scripts/internal/clinter.py %s" % (
+ sys.executable, " ".join(c_files))
+ print(cmd)
+ ret = subprocess.call(cmd, shell=True)
+ if ret != 0:
+ return exit("commit aborted: C code didn't pass style check")
+
main()
diff --git a/scripts/internal/clinter.py b/scripts/internal/clinter.py
new file mode 100755
index 00000000..1d4ba9b1
--- /dev/null
+++ b/scripts/internal/clinter.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python3
+
+# Copyright (c) 2009 Giampaolo Rodola'. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""A super simple linter to check C syntax."""
+
+from __future__ import print_function
+import argparse
+import sys
+
+
+warned = False
+
+
+def warn(path, line, lineno, msg):
+ global warned
+ warned = True
+ print("%s:%s: %s" % (path, lineno, msg), file=sys.stderr)
+
+
+def check_line(path, line, idx, lines):
+ s = line
+ lineno = idx + 1
+ eof = lineno == len(lines)
+ if s.endswith(' \n'):
+ warn(path, line, lineno, "extra space at EOL")
+ elif '\t' in line:
+ warn(path, line, lineno, "line has a tab")
+ elif s.endswith('\r\n'):
+ warn(path, line, lineno, "Windows line ending")
+ # end of global block, e.g. "}newfunction...":
+ elif s == "}\n":
+ if not eof:
+ nextline = lines[idx + 1]
+ # "#" is a pre-processor line
+ if nextline != '\n' and \
+ nextline.strip()[0] != '#' and \
+ nextline.strip()[:2] != '*/':
+ warn(path, line, lineno, "expected 1 blank line")
+
+ sls = s.lstrip()
+ if sls.startswith('//') and sls[2] != ' ' and line.strip() != '//':
+ warn(path, line, lineno, "no space after // comment")
+
+ # e.g. "if(..." after keywords
+ keywords = ("if", "else", "while", "do", "enum", "for")
+ for kw in keywords:
+ if sls.startswith(kw + '('):
+ warn(path, line, lineno, "missing space between %r and '('" % kw)
+ # eof
+ if eof:
+ if not line.endswith('\n'):
+ warn(path, line, lineno, "no blank line at EOF")
+
+
+def process(path):
+ with open(path, 'rt') as f:
+ lines = f.readlines()
+ for idx, line in enumerate(lines):
+ check_line(path, line, idx, lines)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('paths', nargs='+', help='path(s) to a file(s)')
+ args = parser.parse_args()
+ for path in args.paths:
+ process(path)
+ if warned:
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/internal/winmake.py b/scripts/internal/winmake.py
index f54211d9..4d3fa318 100755
--- a/scripts/internal/winmake.py
+++ b/scripts/internal/winmake.py
@@ -386,7 +386,7 @@ def setup_dev_env():
sh("%s -m pip install -U %s" % (PYTHON, " ".join(DEPS)))
-def flake8():
+def lint():
"""Run flake8 against all py files"""
py_files = subprocess.check_output("git ls-files")
if PY3:
@@ -551,11 +551,11 @@ def main():
sp.add_parser('build', help="build")
sp.add_parser('clean', help="deletes dev files")
sp.add_parser('coverage', help="run coverage tests.")
- sp.add_parser('flake8', help="run flake8 against all py files")
sp.add_parser('help', help="print this help")
sp.add_parser('install', help="build + install in develop/edit mode")
sp.add_parser('install-git-hooks', help="install GIT pre-commit hook")
sp.add_parser('install-pip', help="install pip")
+ sp.add_parser('lint', help="run flake8 against all py files")
sp.add_parser('print-access-denied', help="print AD exceptions")
sp.add_parser('print-api-speed', help="benchmark all API calls")
sp.add_parser('setup-dev-env', help="install deps")