1+ import re
2+ import sys
3+ import shutil
14import os .path
25import subprocess
3- import sys
46
57import reindent
8+ import untabify
69
710
811def n_files_str (count ):
@@ -29,17 +32,26 @@ def call_fxn(*args, **kwargs):
2932
3033
3134@status ("Getting the list of files that have been added/changed" ,
32- info = lambda x : n_files_str (len (x )))
35+ info = lambda x : n_files_str (len (x )))
3336def changed_files ():
34- """Run ``svn status`` and return a set of files that have been
35- changed/added.
36- """
37- cmd = 'svn status --quiet --non-interactive --ignore-externals'
38- svn_st = subprocess .Popen (cmd , shell = True , stdout = subprocess .PIPE )
39- svn_st .wait ()
40- output = (x .decode ().rstrip ().rsplit (None , 1 )[- 1 ]
41- for x in svn_st .stdout if x [0 ] in b'AM' )
42- return set (path for path in output if os .path .isfile (path ))
37+ """Get the list of changed or added files from the VCS."""
38+ if os .path .isdir ('.hg' ):
39+ vcs = 'hg'
40+ cmd = 'hg status --added --modified --no-status'
41+ elif os .path .isdir ('.svn' ):
42+ vcs = 'svn'
43+ cmd = 'svn status --quiet --non-interactive --ignore-externals'
44+ else :
45+ sys .exit ('need a checkout to get modified files' )
46+
47+ st = subprocess .Popen (cmd .split (), stdout = subprocess .PIPE )
48+ st .wait ()
49+ if vcs == 'hg' :
50+ return [x .decode ().rstrip () for x in st .stdout ]
51+ else :
52+ output = (x .decode ().rstrip ().rsplit (None , 1 )[- 1 ]
53+ for x in st .stdout if x [0 ] in b'AM' )
54+ return set (path for path in output if os .path .isfile (path ))
4355
4456
4557def report_modified_files (file_paths ):
@@ -64,6 +76,39 @@ def normalize_whitespace(file_paths):
6476 return fixed
6577
6678
79+ @status ("Fixing C file whitespace" , info = report_modified_files )
80+ def normalize_c_whitespace (file_paths ):
81+ """Report if any C files """
82+ fixed = []
83+ for path in file_paths :
84+ with open (path , 'r' ) as f :
85+ if '\t ' not in f .read ():
86+ continue
87+ untabify .process (path , 8 , verbose = False )
88+ fixed .append (path )
89+ return fixed
90+
91+
92+ ws_re = re .compile (br'\s+(\r?\n)$' )
93+
94+ @status ("Fixing docs whitespace" , info = report_modified_files )
95+ def normalize_docs_whitespace (file_paths ):
96+ fixed = []
97+ for path in file_paths :
98+ try :
99+ with open (path , 'rb' ) as f :
100+ lines = f .readlines ()
101+ new_lines = [ws_re .sub (br'\1' , line ) for line in lines ]
102+ if new_lines != lines :
103+ shutil .copyfile (path , path + '.bak' )
104+ with open (path , 'wb' ) as f :
105+ f .writelines (new_lines )
106+ fixed .append (path )
107+ except Exception as err :
108+ print ('Cannot fix %s: %s' % (path , err ))
109+ return fixed
110+
111+
67112@status ("Docs modified" , modal = True )
68113def docs_modified (file_paths ):
69114 """Report if any file in the Doc directory has been changed."""
@@ -86,12 +131,16 @@ def main():
86131 file_paths = changed_files ()
87132 python_files = [fn for fn in file_paths if fn .endswith ('.py' )]
88133 c_files = [fn for fn in file_paths if fn .endswith (('.c' , '.h' ))]
89- docs = [fn for fn in file_paths if fn .startswith ('Doc' )]
134+ doc_files = [fn for fn in file_paths if fn .startswith ('Doc' )]
90135 special_files = {'Misc/ACKS' , 'Misc/NEWS' } & set (file_paths )
91136 # PEP 8 whitespace rules enforcement.
92137 normalize_whitespace (python_files )
138+ # C rules enforcement.
139+ normalize_c_whitespace (c_files )
140+ # Doc whitespace enforcement.
141+ normalize_docs_whitespace (doc_files )
93142 # Docs updated.
94- docs_modified (docs )
143+ docs_modified (doc_files )
95144 # Misc/ACKS changed.
96145 credit_given (special_files )
97146 # Misc/NEWS changed.
0 commit comments