summaryrefslogtreecommitdiffstats
path: root/pre_commit/commands
diff options
context:
space:
mode:
Diffstat (limited to 'pre_commit/commands')
-rw-r--r--pre_commit/commands/autoupdate.py25
-rw-r--r--pre_commit/commands/clean.py2
-rw-r--r--pre_commit/commands/gc.py11
-rw-r--r--pre_commit/commands/hook_impl.py30
-rw-r--r--pre_commit/commands/init_templatedir.py5
-rw-r--r--pre_commit/commands/install_uninstall.py36
-rw-r--r--pre_commit/commands/migrate_config.py2
-rw-r--r--pre_commit/commands/run.py26
-rw-r--r--pre_commit/commands/sample_config.py1
-rw-r--r--pre_commit/commands/try_repo.py6
10 files changed, 80 insertions, 64 deletions
diff --git a/pre_commit/commands/autoupdate.py b/pre_commit/commands/autoupdate.py
index 5cb978e..d5352e5 100644
--- a/pre_commit/commands/autoupdate.py
+++ b/pre_commit/commands/autoupdate.py
@@ -1,12 +1,10 @@
+from __future__ import annotations
+
import os.path
import re
from typing import Any
-from typing import Dict
-from typing import List
from typing import NamedTuple
-from typing import Optional
from typing import Sequence
-from typing import Tuple
import pre_commit.constants as C
from pre_commit import git
@@ -29,13 +27,13 @@ from pre_commit.util import yaml_load
class RevInfo(NamedTuple):
repo: str
rev: str
- frozen: Optional[str]
+ frozen: str | None
@classmethod
- def from_config(cls, config: Dict[str, Any]) -> 'RevInfo':
+ def from_config(cls, config: dict[str, Any]) -> RevInfo:
return cls(config['repo'], config['rev'], None)
- def update(self, tags_only: bool, freeze: bool) -> 'RevInfo':
+ def update(self, tags_only: bool, freeze: bool) -> RevInfo:
git_cmd = ('git', *git.NO_FS_MONITOR)
if tags_only:
@@ -61,6 +59,9 @@ class RevInfo(NamedTuple):
except CalledProcessError:
cmd = (*git_cmd, 'rev-parse', 'FETCH_HEAD')
rev = cmd_output(*cmd, cwd=tmp)[1].strip()
+ else:
+ if tags_only:
+ rev = git.get_best_candidate_tag(rev, tmp)
frozen = None
if freeze:
@@ -76,7 +77,7 @@ class RepositoryCannotBeUpdatedError(RuntimeError):
def _check_hooks_still_exist_at_rev(
- repo_config: Dict[str, Any],
+ repo_config: dict[str, Any],
info: RevInfo,
store: Store,
) -> None:
@@ -101,9 +102,9 @@ REV_LINE_RE = re.compile(r'^(\s+)rev:(\s*)([\'"]?)([^\s#]+)(.*)(\r?\n)$')
def _original_lines(
path: str,
- rev_infos: List[Optional[RevInfo]],
+ rev_infos: list[RevInfo | None],
retry: bool = False,
-) -> Tuple[List[str], List[int]]:
+) -> tuple[list[str], list[int]]:
"""detect `rev:` lines or reformat the file"""
with open(path, newline='') as f:
original = f.read()
@@ -120,7 +121,7 @@ def _original_lines(
return _original_lines(path, rev_infos, retry=True)
-def _write_new_config(path: str, rev_infos: List[Optional[RevInfo]]) -> None:
+def _write_new_config(path: str, rev_infos: list[RevInfo | None]) -> None:
lines, idxs = _original_lines(path, rev_infos)
for idx, rev_info in zip(idxs, rev_infos):
@@ -152,7 +153,7 @@ def autoupdate(
"""Auto-update the pre-commit config to the latest versions of repos."""
migrate_config(config_file, quiet=True)
retv = 0
- rev_infos: List[Optional[RevInfo]] = []
+ rev_infos: list[RevInfo | None] = []
changed = False
config = load_config(config_file)
diff --git a/pre_commit/commands/clean.py b/pre_commit/commands/clean.py
index 2be6c16..5119f64 100644
--- a/pre_commit/commands/clean.py
+++ b/pre_commit/commands/clean.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import os.path
from pre_commit import output
diff --git a/pre_commit/commands/gc.py b/pre_commit/commands/gc.py
index 7f6d311..6892e09 100644
--- a/pre_commit/commands/gc.py
+++ b/pre_commit/commands/gc.py
@@ -1,8 +1,7 @@
+from __future__ import annotations
+
import os.path
from typing import Any
-from typing import Dict
-from typing import Set
-from typing import Tuple
import pre_commit.constants as C
from pre_commit import output
@@ -17,9 +16,9 @@ from pre_commit.store import Store
def _mark_used_repos(
store: Store,
- all_repos: Dict[Tuple[str, str], str],
- unused_repos: Set[Tuple[str, str]],
- repo: Dict[str, Any],
+ all_repos: dict[tuple[str, str], str],
+ unused_repos: set[tuple[str, str]],
+ repo: dict[str, Any],
) -> None:
if repo['repo'] == META:
return
diff --git a/pre_commit/commands/hook_impl.py b/pre_commit/commands/hook_impl.py
index 90bb33b..18e5e9f 100644
--- a/pre_commit/commands/hook_impl.py
+++ b/pre_commit/commands/hook_impl.py
@@ -1,10 +1,10 @@
+from __future__ import annotations
+
import argparse
import os.path
import subprocess
import sys
-from typing import Optional
from typing import Sequence
-from typing import Tuple
from pre_commit.commands.run import run
from pre_commit.envcontext import envcontext
@@ -18,7 +18,7 @@ def _run_legacy(
hook_type: str,
hook_dir: str,
args: Sequence[str],
-) -> Tuple[int, bytes]:
+) -> tuple[int, bytes]:
if os.environ.get('PRE_COMMIT_RUNNING_LEGACY'):
raise SystemExit(
f"bug: pre-commit's script is installed in migration mode\n"
@@ -69,16 +69,16 @@ def _ns(
color: bool,
*,
all_files: bool = False,
- remote_branch: Optional[str] = None,
- local_branch: Optional[str] = None,
- from_ref: Optional[str] = None,
- to_ref: Optional[str] = None,
- remote_name: Optional[str] = None,
- remote_url: Optional[str] = None,
- commit_msg_filename: Optional[str] = None,
- checkout_type: Optional[str] = None,
- is_squash_merge: Optional[str] = None,
- rewrite_command: Optional[str] = None,
+ remote_branch: str | None = None,
+ local_branch: str | None = None,
+ from_ref: str | None = None,
+ to_ref: str | None = None,
+ remote_name: str | None = None,
+ remote_url: str | None = None,
+ commit_msg_filename: str | None = None,
+ checkout_type: str | None = None,
+ is_squash_merge: str | None = None,
+ rewrite_command: str | None = None,
) -> argparse.Namespace:
return argparse.Namespace(
color=color,
@@ -109,7 +109,7 @@ def _pre_push_ns(
color: bool,
args: Sequence[str],
stdin: bytes,
-) -> Optional[argparse.Namespace]:
+) -> argparse.Namespace | None:
remote_name = args[0]
remote_url = args[1]
@@ -197,7 +197,7 @@ def _run_ns(
color: bool,
args: Sequence[str],
stdin: bytes,
-) -> Optional[argparse.Namespace]:
+) -> argparse.Namespace | None:
_check_args_length(hook_type, args)
if hook_type == 'pre-push':
return _pre_push_ns(color, args, stdin)
diff --git a/pre_commit/commands/init_templatedir.py b/pre_commit/commands/init_templatedir.py
index 5f17d9c..08af656 100644
--- a/pre_commit/commands/init_templatedir.py
+++ b/pre_commit/commands/init_templatedir.py
@@ -1,6 +1,7 @@
+from __future__ import annotations
+
import logging
import os.path
-from typing import Sequence
from pre_commit.commands.install_uninstall import install
from pre_commit.store import Store
@@ -14,7 +15,7 @@ def init_templatedir(
config_file: str,
store: Store,
directory: str,
- hook_types: Sequence[str],
+ hook_types: list[str] | None,
skip_on_missing_config: bool = True,
) -> int:
install(
diff --git a/pre_commit/commands/install_uninstall.py b/pre_commit/commands/install_uninstall.py
index 50c6443..5ff6cba 100644
--- a/pre_commit/commands/install_uninstall.py
+++ b/pre_commit/commands/install_uninstall.py
@@ -1,14 +1,14 @@
+from __future__ import annotations
+
import logging
import os.path
import shlex
import shutil
import sys
-from typing import Optional
-from typing import Sequence
-from typing import Tuple
from pre_commit import git
from pre_commit import output
+from pre_commit.clientlib import InvalidConfigError
from pre_commit.clientlib import load_config
from pre_commit.repository import all_hooks
from pre_commit.repository import install_hook_envs
@@ -32,11 +32,23 @@ TEMPLATE_START = '# start templated\n'
TEMPLATE_END = '# end templated\n'
+def _hook_types(cfg_filename: str, hook_types: list[str] | None) -> list[str]:
+ if hook_types is not None:
+ return hook_types
+ else:
+ try:
+ cfg = load_config(cfg_filename)
+ except InvalidConfigError:
+ return ['pre-commit']
+ else:
+ return cfg['default_install_hook_types']
+
+
def _hook_paths(
hook_type: str,
- git_dir: Optional[str] = None,
-) -> Tuple[str, str]:
- git_dir = git_dir if git_dir is not None else git.get_git_dir()
+ git_dir: str | None = None,
+) -> tuple[str, str]:
+ git_dir = git_dir if git_dir is not None else git.get_git_common_dir()
pth = os.path.join(git_dir, 'hooks', hook_type)
return pth, f'{pth}.legacy'
@@ -54,7 +66,7 @@ def _install_hook_script(
hook_type: str,
overwrite: bool = False,
skip_on_missing_config: bool = False,
- git_dir: Optional[str] = None,
+ git_dir: str | None = None,
) -> None:
hook_path, legacy_path = _hook_paths(hook_type, git_dir=git_dir)
@@ -103,11 +115,11 @@ def _install_hook_script(
def install(
config_file: str,
store: Store,
- hook_types: Sequence[str],
+ hook_types: list[str] | None,
overwrite: bool = False,
hooks: bool = False,
skip_on_missing_config: bool = False,
- git_dir: Optional[str] = None,
+ git_dir: str | None = None,
) -> int:
if git_dir is None and git.has_core_hookpaths_set():
logger.error(
@@ -116,7 +128,7 @@ def install(
)
return 1
- for hook_type in hook_types:
+ for hook_type in _hook_types(config_file, hook_types):
_install_hook_script(
config_file, hook_type,
overwrite=overwrite,
@@ -150,7 +162,7 @@ def _uninstall_hook_script(hook_type: str) -> None:
output.write_line(f'Restored previous hooks to {hook_path}')
-def uninstall(hook_types: Sequence[str]) -> int:
- for hook_type in hook_types:
+def uninstall(config_file: str, hook_types: list[str] | None) -> int:
+ for hook_type in _hook_types(config_file, hook_types):
_uninstall_hook_script(hook_type)
return 0
diff --git a/pre_commit/commands/migrate_config.py b/pre_commit/commands/migrate_config.py
index fef14cd..c3d0a50 100644
--- a/pre_commit/commands/migrate_config.py
+++ b/pre_commit/commands/migrate_config.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import re
import textwrap
diff --git a/pre_commit/commands/run.py b/pre_commit/commands/run.py
index f8ced0f..37f989b 100644
--- a/pre_commit/commands/run.py
+++ b/pre_commit/commands/run.py
@@ -1,3 +1,5 @@
+from __future__ import annotations
+
import argparse
import contextlib
import functools
@@ -9,12 +11,8 @@ import time
import unicodedata
from typing import Any
from typing import Collection
-from typing import Dict
-from typing import List
from typing import MutableMapping
from typing import Sequence
-from typing import Set
-from typing import Tuple
from identify.identify import tags_from_path
@@ -62,7 +60,7 @@ def filter_by_include_exclude(
names: Collection[str],
include: str,
exclude: str,
-) -> List[str]:
+) -> list[str]:
include_re, exclude_re = re.compile(include), re.compile(exclude)
return [
filename for filename in names
@@ -76,7 +74,7 @@ class Classifier:
self.filenames = [f for f in filenames if os.path.lexists(f)]
@functools.lru_cache(maxsize=None)
- def _types_for_file(self, filename: str) -> Set[str]:
+ def _types_for_file(self, filename: str) -> set[str]:
return tags_from_path(filename)
def by_types(
@@ -85,7 +83,7 @@ class Classifier:
types: Collection[str],
types_or: Collection[str],
exclude_types: Collection[str],
- ) -> List[str]:
+ ) -> list[str]:
types = frozenset(types)
types_or = frozenset(types_or)
exclude_types = frozenset(exclude_types)
@@ -100,7 +98,7 @@ class Classifier:
ret.append(filename)
return ret
- def filenames_for_hook(self, hook: Hook) -> Tuple[str, ...]:
+ def filenames_for_hook(self, hook: Hook) -> tuple[str, ...]:
names = self.filenames
names = filter_by_include_exclude(names, hook.files, hook.exclude)
names = self.by_types(
@@ -117,7 +115,7 @@ class Classifier:
filenames: Collection[str],
include: str,
exclude: str,
- ) -> 'Classifier':
+ ) -> Classifier:
# on windows we normalize all filenames to use forward slashes
# this makes it easier to filter using the `files:` regex
# this also makes improperly quoted shell-based hooks work better
@@ -128,7 +126,7 @@ class Classifier:
return Classifier(filenames)
-def _get_skips(environ: MutableMapping[str, str]) -> Set[str]:
+def _get_skips(environ: MutableMapping[str, str]) -> set[str]:
skips = environ.get('SKIP', '')
return {skip.strip() for skip in skips.split(',') if skip.strip()}
@@ -144,12 +142,12 @@ def _subtle_line(s: str, use_color: bool) -> None:
def _run_single_hook(
classifier: Classifier,
hook: Hook,
- skips: Set[str],
+ skips: set[str],
cols: int,
diff_before: bytes,
verbose: bool,
use_color: bool,
-) -> Tuple[bool, bytes]:
+) -> tuple[bool, bytes]:
filenames = classifier.filenames_for_hook(hook)
if hook.id in skips or hook.alias in skips:
@@ -271,9 +269,9 @@ def _get_diff() -> bytes:
def _run_hooks(
- config: Dict[str, Any],
+ config: dict[str, Any],
hooks: Sequence[Hook],
- skips: Set[str],
+ skips: set[str],
args: argparse.Namespace,
) -> int:
"""Actually run the hooks."""
diff --git a/pre_commit/commands/sample_config.py b/pre_commit/commands/sample_config.py
index 64617c3..82a1617 100644
--- a/pre_commit/commands/sample_config.py
+++ b/pre_commit/commands/sample_config.py
@@ -2,6 +2,7 @@
# determine the latest revision? This adds ~200ms from my tests (and is
# significantly faster than https:// or http://). For now, periodically
# manually updating the revision is fine.
+from __future__ import annotations
SAMPLE_CONFIG = '''\
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
diff --git a/pre_commit/commands/try_repo.py b/pre_commit/commands/try_repo.py
index 4aee209..ef099f5 100644
--- a/pre_commit/commands/try_repo.py
+++ b/pre_commit/commands/try_repo.py
@@ -1,8 +1,8 @@
+from __future__ import annotations
+
import argparse
import logging
import os.path
-from typing import Optional
-from typing import Tuple
import pre_commit.constants as C
from pre_commit import git
@@ -18,7 +18,7 @@ from pre_commit.xargs import xargs
logger = logging.getLogger(__name__)
-def _repo_ref(tmpdir: str, repo: str, ref: Optional[str]) -> Tuple[str, str]:
+def _repo_ref(tmpdir: str, repo: str, ref: str | None) -> tuple[str, str]:
# if `ref` is explicitly passed, use it
if ref is not None:
return repo, ref