#!/usr/bin/env python3 # # Copyright (C) 2020 Apple Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. import argparse, os, re # For now: Searches all files in current directory tree. # Reads every file so it does take a while. # On my fast computer takes about 15 seconds for WebCore. # Things to do next: # # Clever default for use on WebKit source tree instead of current directory by default. # Report third party sources separately from WebKit project files. # Hard-coded for now, could read these out of a file instead. # Term, then the regular expression for that term. nonInclusiveTerms = [ [ "blacklist", rb"black ?list" ], [ "whitelist", rb"white ?list" ], [ "slave", rb"slave" ] ] IGNORE_DIRECTORIES = ['.svn', '.git', 'autoinstalled', 'buildstream', 'node_modules'] IGNORE_FILES_STARTING_WITH = ('ChangeLog') IGNORE_FILES_ENDING_WITH = ('.log', '.order', '.pyc', '.swp', '.xcuserstate', '.db', '.db-shm', '.db-wal') IGNORE_FILE_NAMES = ['report-non-inclusive-language', 'inclusive_language.py'] parser = argparse.ArgumentParser(description='Report counts and locations of non-inclusive terms.') parser.add_argument('--verbose', '-v', action='store_true'); args = parser.parse_args() for term in nonInclusiveTerms: term[1] = re.compile(term[1], re.IGNORECASE) term.append(0) term.append(0) root = os.getcwd() for subroot, directories, files in os.walk(root): prefix = subroot[len(root) + 1:] if any(directory in prefix.split('/') for directory in IGNORE_DIRECTORIES): continue for file in files: if file.startswith(IGNORE_FILES_STARTING_WITH): continue if file.endswith(IGNORE_FILES_ENDING_WITH): continue if file in IGNORE_FILE_NAMES: continue if os.path.islink(os.path.join(subroot, file)): continue handle = open(os.path.join(subroot, file), "rb") for line in handle.readlines(): for term in nonInclusiveTerms: if re.search(term[1], line): term[2] += 1 if args.verbose: for term in nonInclusiveTerms: if term[2] != 0: print(os.path.join(prefix, file) + ": " + term[0] + ": " + str(term[2])) for term in nonInclusiveTerms: term[3] += term[2] term[2] = 0 details = ['{}: {}'.format(term[0], term[3]) for term in nonInclusiveTerms] total = sum([term[3] for term in nonInclusiveTerms]) print('Total: {} ({})'.format(total, ', '.join(details)))