''' Script will test the RDkit python code for conformance with the agreed format using yapf. For each Python file that is found in $RDBASE (excluding the build and External directories), yapf is used with the style configuration in $RDBASE/setup.cfg. If a change is required, the difference is printed. At the end of the process, all non-conformant files are listed and the required yapf command(s) printed. If changes are found, the script will exit with error code 1, otherwise 0. ''' import os import sys from yapf.yapflib.yapf_api import FormatCode rdbase = os.environ.get('RDBASE', '') styleConfig = os.path.join(rdbase, 'setup.cfg') excludeDirs = [ os.path.join(rdbase, 'build'), os.path.join(rdbase, 'External'), ] def pythonFiles(dirname=rdbase): """ Find all python files below directory dirname """ for root, _, files in os.walk(dirname): if any(root.startswith(d) for d in excludeDirs): continue for file in files: if file.endswith(".py"): yield os.path.join(root, file) def yapfChanges(filename): """ Use yapf with the default settings to format file filename """ try: with open(filename) as f: codeBefore = f.read() except UnicodeError: with open(filename, encoding='latin-1') as f: codeBefore = f.read() try: changes, changed = FormatCode(codeBefore, style_config=styleConfig, print_diff=True, filename=filename) except Exception: print(filename) raise if changed: print(changes) return changed if __name__ == "__main__": changedFiles = [] for s in pythonFiles(): if yapfChanges(s): changedFiles.append(s) print() if changedFiles: print('yapf will make changes to the following files:') print('\n'.join(sorted(changedFiles))) print('To apply the required changes to your code use the following command(s)') for s in sorted(set(s.replace(rdbase, '').split(os.sep)[1] for s in changedFiles)): print('yapf --style $RDBASE/setup.cfg --in-place --recursive $RDBASE/{0}'.format(s)) sys.exit(1) print('Code complies with the agreed formatting rules.') sys.exit(0)