def check_common_patterns(file_path): """Checks for unwanted patterns in source files.""" rel_path_from_peloton_dir = os.path.relpath(file_path, PELOTON_DIR) # Skip some files if rel_path_from_peloton_dir in SKIP_FILES_LIST: return True with open(file_path, 'r') as opened_file: file_status = True line_ctr = 1 for line in opened_file: for validator_pattern in VALIDATOR_PATTERNS: # Check for patterns one at a time if validator_pattern.search(line): if file_status: LOG.info("Invalid pattern -- " + validator_pattern.pattern + " -- found in : " + file_path ) LOG.info("Line %d: %s", line_ctr, line.strip()) file_status = False line_ctr += 1 return file_status
def check_includes(file_path): """Checks whether local includes are done via #include<...>""" with open(file_path, "r") as file: path_pattern = re.compile(r'^#include <(include/)?(.*?)>') linenum = 0 file_status = True for line in file: linenum += 1 res = path_pattern.match(line) if res: path = res.groups()[1] if path in PATHS: if file_status: LOG.info("Invalid include in %s", file_path) file_status = False LOG.info("Line %s: %s", linenum, line.strip()) if not file_status: LOG.info('includes for peloton header files have must not have ' 'brackets') return file_status
def check_includes(file_path): """Checks whether local includes are done via #include<...>""" with open(file_path, "r") as file: path_pattern = re.compile(r'^#include <(include/)?(.*?)>') linenum = 0 file_status = True for line in file: linenum += 1 res = path_pattern.match(line) if res: path = res.groups()[1] if path in PATHS: if file_status: LOG.info("Invalid include in %s", file_path) file_status = False LOG.info("Line %s: %s", linenum, line.strip()) if not file_status: LOG.info('includes for peloton header files have must not have ' 'brackets' ) return file_status
def format_file(file_path, update_header, clang_format_code): """Formats the file passed as argument.""" file_name = os.path.basename(file_path) abs_path = os.path.abspath(file_path) rel_path_from_peloton_dir = os.path.relpath(abs_path, PELOTON_DIR) with open(file_path, "r+") as file: file_data = file.read() if update_header: # strip old header if it exists header_match = HEADER_REGEX.match(file_data) if not header_match is None: LOG.info("Strip header from %s", file_name) header_comment = header_match.group() LOG.debug("Header comment : %s", header_comment) file_data = file_data.replace(header_comment, "") # add new header LOG.info("Add header to %s", file_name) header_comment_2 = header_comment_line_3 + file_name + "\n" header_comment_4 = header_comment_line_5\ + rel_path_from_peloton_dir + "\n" header_comment = header_comment_1 + header_comment_2 \ + header_comment_3 + header_comment_4 \ + header_comment_5 #print header_comment file_data = header_comment + file_data file.seek(0, 0) file.truncate() file.write(file_data) elif clang_format_code: clang_format(file_path)
def format_file(file_path, update_header, clang_format_code): """Formats the file passed as argument.""" file_name = os.path.basename(file_path) abs_path = os.path.abspath(file_path) rel_path_from_peloton_dir = os.path.relpath(abs_path, PELOTON_DIR) with open(file_path, "r+") as file: file_data = file.read() if update_header: # strip old header if it exists header_match = HEADER_REGEX.match(file_data) if not header_match is None: LOG.info("Strip header from %s", file_name) header_comment = header_match.group() LOG.debug("Header comment : %s", header_comment) file_data = file_data.replace(header_comment,"") # add new header LOG.info("Add header to %s", file_name) header_comment_2 = header_comment_line_3 + file_name + "\n" header_comment_4 = header_comment_line_5\ + rel_path_from_peloton_dir + "\n" header_comment = header_comment_1 + header_comment_2 \ + header_comment_3 + header_comment_4 \ + header_comment_5 #print header_comment file_data = header_comment + file_data file.seek(0, 0) file.truncate() file.write(file_data) elif clang_format_code: clang_format(file_path)
def check_namespaces(file_path): """Scans namespace openings and closings.""" # only check for src files if not file_path.startswith(DEFAULT_DIRS[0]): return True # get required namespaces from path required_namespaces = ['peloton'] + file_path.replace(DEFAULT_DIRS[0] + "/", "").split("/") # for the include files, remove the include item in the list if 'include' in required_namespaces: required_namespaces.remove('include') # cut off the file name at the end of the list required_namespaces = required_namespaces[:-1] with open(file_path, 'r') as file: data = mmap.mmap(file.fileno(), 0, prot=mmap.PROT_READ) # scan for all namespace openings and closings matches = re.findall( r'^ *namespace ([a-z_-]+) {$|^ *} +\/\/ namespace ([a-z_-]+)$', data, flags=re.MULTILINE ) open_namespaces = list() namespace_errors = list() for match in matches: # assert the match is either an opening or a closing assert match[0] or match[1] # 1. namespace opening if match[0]: # add to list of open namespaces open_namespaces.append(match[0]) # remove from list of required namespaces if required_namespaces and required_namespaces[0] == match[0]: required_namespaces.pop(0) # 2. namespace closing else: # check if correct order if open_namespaces and open_namespaces[-1] != match[1]: namespace_errors.append( "This namespace was closed in wrong order: '" + match[1] + "' -- in " + file_path ) # check if present at all if not match[1] in open_namespaces: namespace_errors.append( "This namespace was closed, but is missing a correct " "opening: '" + match[1] + "' -- in " + file_path ) else: # remove from open list open_namespaces.remove(match[1]) if required_namespaces: namespace_errors.append( "Required namespaces are missing or in wrong order: " + str(required_namespaces) + " -- in " + file_path ) if open_namespaces: namespace_errors.append( "These namespaces were not closed properly: " + str(open_namespaces) + " -- in " + file_path ) if namespace_errors: LOG.info("Invalid namespace style -- in " + file_path) for error in namespace_errors: LOG.info(" " + error) return False return True
## ============================================== ## Main Function ## ============================================== if __name__ == '__main__': PARSER = argparse.ArgumentParser( description='Perform source code validation on Peloton source' ) PARSER.add_argument("-f", "--files", nargs='*', help="A list of files to validate" ) ARGS = PARSER.parse_args() LOG.info("Running source validator ...") LOG.info("Peloton root : " + PELOTON_DIR) if ARGS.files: # Validate just the provided files. # In this mode, we perform explicit clang-format checks VALIDATORS.append(clang_check) for each_file in ARGS.files: each_file = os.path.abspath(each_file.lower()) # Fail if the file isn't really a file if not os.path.isfile(each_file): LOG.info("ERROR: " + each_file + " isn't a file") sys.exit(EXIT_FAILURE)
help='Files or directories to (recursively) apply the actions to') ARGS = PARSER.parse_args() if ARGS.staged_files: PELOTON_DIR_bytes = bytes(PELOTON_DIR, 'utf-8') TARGETS = [ str(os.path.abspath(os.path.join(PELOTON_DIR_bytes, f)), 'utf-8') \ for f in subprocess.check_output( ["git", "diff", "--name-only", "HEAD", "--cached", "--diff-filter=d" ] ).split()] if not TARGETS: LOG.error( "no staged files or not calling from a repository -- exiting") sys.exit("no staged files or not calling from a repository") elif not ARGS.paths: LOG.error("no files or directories given -- exiting") sys.exit("no files or directories given") else: TARGETS = ARGS.paths for x in TARGETS: if os.path.isfile(x): LOG.info("Scanning file: %s", x) format_file(x, ARGS.update_header, ARGS.clang_format_code) elif os.path.isdir(x): LOG.info("Scanning directory %s", x) format_dir(x, ARGS.update_header, ARGS.clang_format_code) ## FOR
metavar='PATH', type=str, nargs='*', help='Files or directories to (recursively) apply the actions to') ARGS = PARSER.parse_args() # TARGETS is a list of files with an optional list of hunks, represented as # pair (start, end) of line numbers, 1 based. # element of TARGETS: (filename, None) or (filename, [(start,end)]) if ARGS.staged_files: TARGETS = hunks_from_staged_files() if not TARGETS: LOG.error( "no staged files or not calling from a repository -- exiting") sys.exit("no staged files or not calling from a repository") elif ARGS.number_commits > 0: TARGETS = hunks_from_last_commits(ARGS.number_commits) if not TARGETS: LOG.error( "no changes could be extracted for formatting -- exiting") sys.exit("no changes could be extracted for formatting") elif not ARGS.paths: LOG.error("no files or directories given -- exiting") sys.exit("no files or directories given") else:
ARGS = PARSER.parse_args() if ARGS.staged_files: PELOTON_DIR_bytes = bytes(PELOTON_DIR, 'utf-8') TARGETS = [ str(os.path.abspath(os.path.join(PELOTON_DIR_bytes, f)), 'utf-8') \ for f in subprocess.check_output( ["git", "diff", "--name-only", "HEAD", "--cached", "--diff-filter=d" ] ).split()] if not TARGETS: LOG.error( "no staged files or not calling from a repository -- exiting" ) sys.exit("no staged files or not calling from a repository") elif not ARGS.paths: LOG.error("no files or directories given -- exiting") sys.exit("no files or directories given") else: TARGETS = ARGS.paths for x in TARGETS: if os.path.isfile(x): LOG.info("Scanning file: %s", x) format_file(x, ARGS.update_header, ARGS.clang_format_code) elif os.path.isdir(x): LOG.info("Scanning directory %s", x) format_dir(x, ARGS.update_header, ARGS.clang_format_code)