GH-109408: Move the C file whitespace check from patchcheck to pre-commit (#109890)

Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
This commit is contained in:
Adam Turner 2023-10-10 14:40:08 +01:00 committed by GitHub
parent e24f9ae703
commit f5edb56328
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 90 deletions

View File

@ -32,6 +32,21 @@ repos:
types: [python]
exclude: '^(Lib/test/tokenizedata/|Tools/c-analyzer/cpython/_parser).*$'
- repo: local
hooks:
- id: c-file-whitespace
name: "Check C file whitespace"
entry: "python Tools/patchcheck/untabify.py"
language: "system"
types_or: ['c', 'c++']
# Don't check the style of vendored libraries
exclude: |
(?x)^(
Modules/_decimal/.*
| Modules/libmpdec/.*
| Modules/expat/.*
)$
- repo: https://github.com/sphinx-contrib/sphinx-lint
rev: v0.6.8
hooks:

View File

@ -1,29 +1,15 @@
#!/usr/bin/env python3
"""Check proposed changes for common issues."""
import re
import sys
import shutil
import os.path
import subprocess
import sysconfig
import untabify
def get_python_source_dir():
src_dir = sysconfig.get_config_var('abs_srcdir')
if not src_dir:
src_dir = sysconfig.get_config_var('srcdir')
return os.path.abspath(src_dir)
# Excluded directories which are copies of external libraries:
# don't check their coding style
EXCLUDE_DIRS = [
os.path.join('Modules', '_decimal', 'libmpdec'),
os.path.join('Modules', 'expat'),
os.path.join('Modules', 'zlib'),
]
SRCDIR = get_python_source_dir()
@ -154,47 +140,8 @@ def changed_files(base_branch=None):
else:
sys.exit('need a git checkout to get modified files')
filenames2 = []
for filename in filenames:
# Normalize the path to be able to match using .startswith()
filename = os.path.normpath(filename)
if any(filename.startswith(path) for path in EXCLUDE_DIRS):
# Exclude the file
continue
filenames2.append(filename)
return filenames2
def report_modified_files(file_paths):
count = len(file_paths)
if count == 0:
return n_files_str(count)
else:
lines = [f"{n_files_str(count)}:"]
for path in file_paths:
lines.append(f" {path}")
return "\n".join(lines)
#: Python files that have tabs by design:
_PYTHON_FILES_WITH_TABS = frozenset({
'Tools/c-analyzer/cpython/_parser.py',
})
@status("Fixing C file whitespace", info=report_modified_files)
def normalize_c_whitespace(file_paths):
"""Report if any C files """
fixed = []
for path in file_paths:
abspath = os.path.join(SRCDIR, path)
with open(abspath, 'r') as f:
if '\t' not in f.read():
continue
untabify.process(abspath, 8, verbose=False)
fixed.append(path)
return fixed
# Normalize the path to be able to match using str.startswith()
return list(map(os.path.normpath, filenames))
@status("Docs modified", modal=True)
@ -234,33 +181,12 @@ def regenerated_pyconfig_h_in(file_paths):
return "not needed"
def ci(pull_request):
if pull_request == 'false':
print('Not a pull request; skipping')
return
base_branch = get_base_branch()
file_paths = changed_files(base_branch)
c_files = [fn for fn in file_paths if fn.endswith(('.c', '.h'))]
fixed = []
fixed.extend(normalize_c_whitespace(c_files))
if not fixed:
print('No whitespace issues found')
else:
count = len(fixed)
print(f'Please fix the {n_files_str(count)} with whitespace issues')
print('(on Unix you can run `make patchcheck` to make the fixes)')
sys.exit(1)
def main():
base_branch = get_base_branch()
file_paths = changed_files(base_branch)
c_files = [fn for fn in file_paths if fn.endswith(('.c', '.h'))]
doc_files = [fn for fn in file_paths if fn.startswith('Doc') and
fn.endswith(('.rst', '.inc'))]
misc_files = {p for p in file_paths if p.startswith('Misc')}
# C rules enforcement.
normalize_c_whitespace(c_files)
# Docs updated.
docs_modified(doc_files)
# Misc/ACKS changed.
@ -283,12 +209,4 @@ def main():
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--ci',
help='Perform pass/fail checks')
args = parser.parse_args()
if args.ci:
ci(args.ci)
else:
main()
main()

View File

@ -21,8 +21,7 @@ def main():
if optname == '-t':
tabsize = int(optvalue)
for filename in args:
process(filename, tabsize)
return max(process(filename, tabsize) for filename in args)
def process(filename, tabsize, verbose=True):
@ -32,10 +31,10 @@ def process(filename, tabsize, verbose=True):
encoding = f.encoding
except IOError as msg:
print("%r: I/O error: %s" % (filename, msg))
return
return 2
newtext = text.expandtabs(tabsize)
if newtext == text:
return
return 0
backup = filename + "~"
try:
os.unlink(backup)
@ -49,7 +48,8 @@ def process(filename, tabsize, verbose=True):
f.write(newtext)
if verbose:
print(filename)
return 1
if __name__ == '__main__':
main()
raise SystemExit(main())