import logging import re import time import click import restructuredtext_lint from docutils.parsers.rst.directives import register_directive from git import Repo formatter = logging.Formatter("%(name)s :: %(levelname)s :: %(message)s") steam_handler = logging.StreamHandler() # steam_handler = logging.FileHandler('logging.conf') steam_handler.setLevel(logging.DEBUG) steam_handler.setFormatter(formatter) # création de l'objet logger qui va nous servir à écrire dans les logs logger = logging.getLogger("precommit") # on met le niveau du logger à DEBUG, comme ça il écrit tout logger.setLevel(logging.WARNING) logger.addHandler(steam_handler) # Files selection def get_commited_files(repo): hdiff = repo.head.commit.diff() diff = {"A": [], "M": []} for f in hdiff.iter_change_type("A"): diff["A"].append(f.b_path) for f in hdiff.iter_change_type("M"): diff["M"].append(f.b_path) return diff def select_by_extension(files, ext="rst"): return [i for i in files if i.split(".")[-1] == ext and "skeleton" not in i] # Rst linter def rst_lint(filename, ignore_directives=["big_button"]): with open(filename, "r") as f: errors = restructuredtext_lint.lint(f.read()) filtered_errors = [] for e in errors: if "directive" in e.message and any( [i in e.message for i in ignore_directives] ): pass else: logger.warning(f"{filename} \n{e.full_message}\n") filtered_errors.append(e) return filtered_errors # Rst parameters normalize def normalize_file(filename, normalizers={}): logger.debug(f"Normalizing {filename}") logger.debug(f"With {normalizers}") new_file = "" modified_lines = [] with open(filename, "r") as f: for l in f.readlines(): new_line = run_normalizers(l, normalizers) if new_line != l: modified_lines.append(f"{l}") logger.warning(f"{filename}\n\t{l}\t{new_line}") new_file += new_line with open(filename, "w") as f: f.write(new_file) logger.debug(f"{filename} written") return modified_lines def run_normalizers(line, normalizers): for c in normalizers: obs = re.search(c, line) if obs: logger.debug(f"Find for {c}") return normalizers[c](line) return line # Rst function tools def update_date(line): date = time.strftime("%Y-%m-%d") logger.debug(f"Update Date to: {date}") return f":date: {date}\n" def update_modified(line): modified = time.strftime("%Y-%m-%d") logger.debug(f"Update modified to: {modified}") return f":modified: {modified}\n" def normalize_tags(line): logger.debug(f"Normaizing tags") tags = line.split(":")[-1] tags = [i.strip().capitalize() for i in tags.split(",")] tags_str = ", ".join(tags) logger.debug(f"Update tags to: {tags_str}") return f":tags: {tags_str}\n" NORMALIZERS_MODIFIED = { ":modified:.*": update_modified, ":tags:.*": normalize_tags, } NORMALIZERS_NEW = { ":date:.*": update_date, ":modified:.*": update_modified, ":tags:.*": normalize_tags, } @click.command() @click.argument("commited_files", nargs=-1) def main(commited_files: list) -> int: r = Repo() diff = get_commited_files(r) errors = [] modified = [] # New files for f in select_by_extension(diff["A"], "rst"): modified += normalize_file(f, NORMALIZERS_NEW) # Modified files for f in select_by_extension(diff["M"], "rst"): modified += normalize_file(f, NORMALIZERS_MODIFIED) return int(len(errors) > 0) if __name__ == "__main__": main()