blob: 1e2002fb4c7ef9f065020280a2ef3aabf063191c [file] [log] [blame]
Christian Heimesada8c3b2008-03-18 18:26:33 +00001import os.path
2import subprocess
3import sys
4
5import reindent
6
7
Brett Cannon058173e2010-07-04 22:05:34 +00008def n_files_str(count):
9 """Return 'N file(s)' with the proper plurality on 'file'."""
10 return "{} file{}".format(count, "s" if count != 1 else "")
11
Florent Xiclunae4a33802010-08-09 12:24:20 +000012
Christian Heimesada8c3b2008-03-18 18:26:33 +000013def status(message, modal=False, info=None):
14 """Decorator to output status info to stdout."""
15 def decorated_fxn(fxn):
16 def call_fxn(*args, **kwargs):
17 sys.stdout.write(message + ' ... ')
18 sys.stdout.flush()
19 result = fxn(*args, **kwargs)
20 if not modal and not info:
21 print("done")
22 elif info:
23 print(info(result))
24 else:
Florent Xiclunae4a33802010-08-09 12:24:20 +000025 print("yes" if result else "NO")
Christian Heimesada8c3b2008-03-18 18:26:33 +000026 return result
27 return call_fxn
28 return decorated_fxn
29
Florent Xiclunae4a33802010-08-09 12:24:20 +000030
Christian Heimesada8c3b2008-03-18 18:26:33 +000031@status("Getting the list of files that have been added/changed",
Brett Cannon058173e2010-07-04 22:05:34 +000032 info=lambda x: n_files_str(len(x)))
Christian Heimesada8c3b2008-03-18 18:26:33 +000033def changed_files():
34 """Run ``svn status`` and return a set of files that have been
Florent Xiclunae4a33802010-08-09 12:24:20 +000035 changed/added.
36 """
Christian Heimesada8c3b2008-03-18 18:26:33 +000037 cmd = 'svn status --quiet --non-interactive --ignore-externals'
38 svn_st = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
39 svn_st.wait()
Florent Xiclunae4a33802010-08-09 12:24:20 +000040 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))
43
Christian Heimesada8c3b2008-03-18 18:26:33 +000044
Brett Cannon058173e2010-07-04 22:05:34 +000045def report_modified_files(file_paths):
46 count = len(file_paths)
47 if count == 0:
48 return n_files_str(count)
49 else:
50 lines = ["{}:".format(n_files_str(count))]
51 for path in file_paths:
52 lines.append(" {}".format(path))
53 return "\n".join(lines)
54
Florent Xiclunae4a33802010-08-09 12:24:20 +000055
Brett Cannon058173e2010-07-04 22:05:34 +000056@status("Fixing whitespace", info=report_modified_files)
Christian Heimesada8c3b2008-03-18 18:26:33 +000057def normalize_whitespace(file_paths):
58 """Make sure that the whitespace for .py files have been normalized."""
59 reindent.makebackup = False # No need to create backups.
Brett Cannon058173e2010-07-04 22:05:34 +000060 fixed = []
61 for path in (x for x in file_paths if x.endswith('.py')):
62 if reindent.check(path):
63 fixed.append(path)
64 return fixed
Christian Heimesada8c3b2008-03-18 18:26:33 +000065
Florent Xiclunae4a33802010-08-09 12:24:20 +000066
Christian Heimesada8c3b2008-03-18 18:26:33 +000067@status("Docs modified", modal=True)
68def docs_modified(file_paths):
Brett Cannon058173e2010-07-04 22:05:34 +000069 """Report if any file in the Doc directory has been changed."""
70 return bool(file_paths)
Christian Heimesada8c3b2008-03-18 18:26:33 +000071
Florent Xiclunae4a33802010-08-09 12:24:20 +000072
Christian Heimesada8c3b2008-03-18 18:26:33 +000073@status("Misc/ACKS updated", modal=True)
74def credit_given(file_paths):
75 """Check if Misc/ACKS has been changed."""
Benjamin Peterson058e31e2009-01-16 03:54:08 +000076 return 'Misc/ACKS' in file_paths
Christian Heimesada8c3b2008-03-18 18:26:33 +000077
Florent Xiclunae4a33802010-08-09 12:24:20 +000078
Christian Heimesada8c3b2008-03-18 18:26:33 +000079@status("Misc/NEWS updated", modal=True)
80def reported_news(file_paths):
81 """Check if Misc/NEWS has been changed."""
Benjamin Peterson058e31e2009-01-16 03:54:08 +000082 return 'Misc/NEWS' in file_paths
Christian Heimesada8c3b2008-03-18 18:26:33 +000083
84
85def main():
86 file_paths = changed_files()
Brett Cannon058173e2010-07-04 22:05:34 +000087 python_files = [fn for fn in file_paths if fn.endswith('.py')]
88 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')]
90 special_files = {'Misc/ACKS', 'Misc/NEWS'} & set(file_paths)
91 # PEP 8 whitespace rules enforcement.
92 normalize_whitespace(python_files)
Christian Heimesada8c3b2008-03-18 18:26:33 +000093 # Docs updated.
Brett Cannon058173e2010-07-04 22:05:34 +000094 docs_modified(docs)
Christian Heimesada8c3b2008-03-18 18:26:33 +000095 # Misc/ACKS changed.
Brett Cannon058173e2010-07-04 22:05:34 +000096 credit_given(special_files)
Christian Heimesada8c3b2008-03-18 18:26:33 +000097 # Misc/NEWS changed.
Brett Cannon058173e2010-07-04 22:05:34 +000098 reported_news(special_files)
Christian Heimesada8c3b2008-03-18 18:26:33 +000099
100 # Test suite run and passed.
101 print()
102 print("Did you run the test suite?")
103
104
105if __name__ == '__main__':
106 main()