From 321f419329f1a0d9364603ff520e7ccc49e06898 Mon Sep 17 00:00:00 2001 From: Remco de Boer <29308176+redeboer@users.noreply.github.com> Date: Sat, 20 Jan 2024 12:42:57 +0100 Subject: [PATCH] DX: run `nbstripout` before other non-meta hooks (#281) * DOC: relink ` typing_extensions.NotRequired` * MAINT: improve type hints `precommit` sub-hook * MAINT: improve variable naming `__repo_sort_key()` * MAINT: rename repo sort key function * MAINT: simplify update ci.skip function * MAINT: sort repos if mismatch only --- docs/conf.py | 1 + .../check_dev_files/precommit.py | 86 ++++++++----------- 2 files changed, 36 insertions(+), 51 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 6e6221fc..ecd7418e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,6 +22,7 @@ "TOMLDocument": "tomlkit.TOMLDocument", "Table": "tomlkit.items.Table", "V": "typing.TypeVar", + "typing_extensions.NotRequired": ("obj", "typing.NotRequired"), } author = "Common Partial Wave Analysis" autodoc_member_order = "bysource" diff --git a/src/compwa_policy/check_dev_files/precommit.py b/src/compwa_policy/check_dev_files/precommit.py index 622f96c7..17ef09b9 100644 --- a/src/compwa_policy/check_dev_files/precommit.py +++ b/src/compwa_policy/check_dev_files/precommit.py @@ -4,9 +4,9 @@ import re from pathlib import Path -from typing import Iterable +from typing import cast -from ruamel.yaml.comments import CommentedMap, CommentedSeq +from ruamel.yaml.comments import CommentedMap from ruamel.yaml.scalarstring import DoubleQuotedScalarString from compwa_policy.errors import PrecommitError @@ -14,6 +14,7 @@ from compwa_policy.utilities.executor import Executor from compwa_policy.utilities.precommit import ( PrecommitConfig, + Repo, find_repo, load_precommit_config, load_roundtrip_precommit_config, @@ -22,6 +23,8 @@ def main() -> None: + if not CONFIG_PATH.precommit.exists(): + return executor = Executor() executor(_sort_hooks) executor(_update_conda_environment) @@ -32,26 +35,28 @@ def main() -> None: def _sort_hooks() -> None: - yaml = create_prettier_round_trip_yaml() - contents: CommentedMap = yaml.load(CONFIG_PATH.precommit) - repos: CommentedSeq | None = contents.get("repos") + config, yaml = load_roundtrip_precommit_config() + repos = config.get("repos") if repos is None: return - sorted_repos: list[CommentedMap] = sorted(repos, key=__repo_def_sorting) - contents["repos"] = sorted_repos + sorted_repos = sorted(repos, key=__repo_sort_key) if sorted_repos != repos: - yaml.dump(contents, CONFIG_PATH.precommit) + config["repos"] = sorted_repos + yaml.dump(config, CONFIG_PATH.precommit) msg = f"Sorted pre-commit hooks in {CONFIG_PATH.precommit}" raise PrecommitError(msg) -def __repo_def_sorting(repo_def: CommentedMap) -> tuple[int, str]: - if repo_def["repo"] == "meta": - return (0, "meta") - hooks: CommentedSeq = repo_def["hooks"] +def __repo_sort_key(repo: Repo) -> tuple[int, str]: + repo_url = repo["repo"] + if repo_url == "meta": + return 0, "meta" + hooks = repo["hooks"] + if any(hook["id"] == "nbstripout" for hook in hooks): + return 1, repo_url if len(hooks) > 1: - return 1, repo_def["repo"] - return (2, hooks[0]["id"]) + return 2, repo_url + return 3, hooks[0]["id"] def _update_precommit_ci_commit_msg() -> None: @@ -75,47 +80,26 @@ def _update_precommit_ci_commit_msg() -> None: def _update_precommit_ci_skip() -> None: - config = load_precommit_config() - if config.get("ci") is None: + config, yaml = load_roundtrip_precommit_config() + precommit_ci = config.get("ci") + if precommit_ci is None: return local_hooks = get_local_hooks(config) non_functional_hooks = get_non_functional_hooks(config) - expected_skips = set(non_functional_hooks) | set(local_hooks) - if not expected_skips: - if config.get("ci", {}).get("skip") is not None: - yaml = create_prettier_round_trip_yaml() - contents: CommentedMap = yaml.load(CONFIG_PATH.precommit) - del contents.get("ci")["skip"] - contents.yaml_set_comment_before_after_key("repos", before="\n") - yaml.dump(contents, CONFIG_PATH.precommit) - msg = f"No need for a ci.skip in {CONFIG_PATH.precommit}" - raise PrecommitError(msg) - return - existing_skips = __get_precommit_ci_skips(config) + expected_skips = sorted(set(non_functional_hooks) | set(local_hooks)) + existing_skips = precommit_ci.get("skip") + if not expected_skips and existing_skips is not None: + del precommit_ci["skip"] + yaml.dump(config, CONFIG_PATH.precommit) + msg = f"Removed redundant ci.skip section from {CONFIG_PATH.precommit}" + raise PrecommitError(msg) if existing_skips != expected_skips: - __update_precommit_ci_skip(expected_skips) - - -def __update_precommit_ci_skip(expected_skips: Iterable[str]) -> None: - yaml = create_prettier_round_trip_yaml() - contents = yaml.load(CONFIG_PATH.precommit) - ci_section: CommentedMap = contents.get("ci") - if "skip" in ci_section.ca.items: - del ci_section.ca.items["skip"] - skips = CommentedSeq(sorted(expected_skips)) - ci_section["skip"] = skips - contents.yaml_set_comment_before_after_key("repos", before="\n") - yaml.dump(contents, CONFIG_PATH.precommit) - msg = f"Updated ci.skip section in {CONFIG_PATH.precommit}" - raise PrecommitError(msg) - - -def __get_precommit_ci_skips(config: PrecommitConfig) -> set[str]: - precommit_ci = config.get("ci") - if precommit_ci is None: - msg = "Pre-commit config does not contain a ci section" - raise ValueError(msg) - return set(precommit_ci.get("skip", [])) + precommit_ci["skip"] = sorted(expected_skips) + yaml_config = cast(CommentedMap, config) + yaml_config.yaml_set_comment_before_after_key("repos", before="\n") + yaml.dump(yaml_config, CONFIG_PATH.precommit) + msg = f"Updated ci.skip section in {CONFIG_PATH.precommit}" + raise PrecommitError(msg) def get_local_hooks(config: PrecommitConfig) -> list[str]: