1
0
Fork 0

Adding upstream version 2.18.1.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-09 21:32:53 +01:00
parent 9c7f59905e
commit 75996f15a7
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
116 changed files with 718 additions and 410 deletions

View file

@ -1,8 +1,8 @@
from __future__ import annotations
from typing import Callable
from typing import NamedTuple
from typing import Optional
from typing import Sequence
from typing import Tuple
from pre_commit.hook import Hook
from pre_commit.languages import conda
@ -30,7 +30,7 @@ from pre_commit.prefix import Prefix
class Language(NamedTuple):
name: str
# Use `None` for no installation / environment
ENVIRONMENT_DIR: Optional[str]
ENVIRONMENT_DIR: str | None
# return a value to replace `'default` for `language_version`
get_default_version: Callable[[], str]
# return whether the environment is healthy (or should be rebuilt)
@ -38,7 +38,7 @@ class Language(NamedTuple):
# install a repository for the given language and language_version
install_environment: Callable[[Prefix, str, Sequence[str]], None]
# execute a hook and return the exit code and output
run_hook: 'Callable[[Hook, Sequence[str], bool], Tuple[int, bytes]]'
run_hook: Callable[[Hook, Sequence[str], bool], tuple[int, bytes]]
# TODO: back to modules + Protocol: https://github.com/python/mypy/issues/5018

View file

@ -1,8 +1,9 @@
from __future__ import annotations
import contextlib
import os
from typing import Generator
from typing import Sequence
from typing import Tuple
from pre_commit.envcontext import envcontext
from pre_commit.envcontext import PatchesT
@ -86,7 +87,7 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
# TODO: Some rare commands need to be run using `conda run` but mostly we
# can run them without which is much quicker and produces a better
# output.

View file

@ -1,14 +1,16 @@
from __future__ import annotations
import contextlib
import os
from typing import Generator
from typing import Sequence
from typing import Tuple
from pre_commit.envcontext import envcontext
from pre_commit.envcontext import PatchesT
from pre_commit.envcontext import Var
from pre_commit.hook import Hook
from pre_commit.languages import helpers
from pre_commit.parse_shebang import find_executable
from pre_commit.prefix import Prefix
from pre_commit.util import clean_path_on_failure
@ -26,6 +28,14 @@ def install_environment(
helpers.assert_version_default('coursier', version)
helpers.assert_no_additional_deps('coursier', additional_dependencies)
# Support both possible executable names (either "cs" or "coursier")
executable = find_executable('cs') or find_executable('coursier')
if executable is None:
raise AssertionError(
'pre-commit requires system-installed "cs" or "coursier" '
'executables in the application search path',
)
envdir = prefix.path(helpers.environment_dir(ENVIRONMENT_DIR, version))
channel = prefix.path('.pre-commit-channel')
with clean_path_on_failure(envdir):
@ -35,7 +45,7 @@ def install_environment(
helpers.run_setup_cmd(
prefix,
(
'cs',
executable,
'install',
'--default-channels=false',
f'--channel={channel}',
@ -66,6 +76,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]: # pragma: win32 no cover
) -> tuple[int, bytes]: # pragma: win32 no cover
with in_env(hook.prefix):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,10 +1,11 @@
from __future__ import annotations
import contextlib
import os.path
import shutil
import tempfile
from typing import Generator
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit.envcontext import envcontext
@ -76,7 +77,7 @@ def install_environment(
with tempfile.TemporaryDirectory() as dep_tmp:
dep, _, version = dep_s.partition(':')
if version:
dep_cmd: Tuple[str, ...] = (dep, '--version', version)
dep_cmd: tuple[str, ...] = (dep, '--version', version)
else:
dep_cmd = (dep,)
@ -104,6 +105,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,8 +1,9 @@
from __future__ import annotations
import hashlib
import json
import os
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit.hook import Hook
@ -76,7 +77,7 @@ def build_docker_image(
*,
pull: bool,
) -> None: # pragma: win32 no cover
cmd: Tuple[str, ...] = (
cmd: tuple[str, ...] = (
'docker', 'build',
'--tag', docker_tag(prefix),
'--label', PRE_COMMIT_LABEL,
@ -105,14 +106,14 @@ def install_environment(
os.mkdir(directory)
def get_docker_user() -> Tuple[str, ...]: # pragma: win32 no cover
def get_docker_user() -> tuple[str, ...]: # pragma: win32 no cover
try:
return ('-u', f'{os.getuid()}:{os.getgid()}')
except AttributeError:
return ()
def docker_cmd() -> Tuple[str, ...]: # pragma: win32 no cover
def docker_cmd() -> tuple[str, ...]: # pragma: win32 no cover
return (
'docker', 'run',
'--rm',
@ -129,7 +130,7 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]: # pragma: win32 no cover
) -> tuple[int, bytes]: # pragma: win32 no cover
# Rebuild the docker image in case it has gone missing, as many people do
# automated cleanup of docker images.
build_docker_image(hook.prefix, pull=False)

View file

@ -1,5 +1,6 @@
from __future__ import annotations
from typing import Sequence
from typing import Tuple
from pre_commit.hook import Hook
from pre_commit.languages import helpers
@ -15,6 +16,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]: # pragma: win32 no cover
) -> tuple[int, bytes]: # pragma: win32 no cover
cmd = docker_cmd() + hook.cmd
return helpers.run_xargs(hook, cmd, file_args, color=color)

View file

@ -1,8 +1,9 @@
from __future__ import annotations
import contextlib
import os.path
from typing import Generator
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit.envcontext import envcontext
@ -84,6 +85,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,5 +1,6 @@
from __future__ import annotations
from typing import Sequence
from typing import Tuple
from pre_commit.hook import Hook
from pre_commit.languages import helpers
@ -14,7 +15,7 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
out = f'{hook.entry}\n\n'.encode()
out += b'\n'.join(f.encode() for f in file_args) + b'\n'
return 1, out

View file

@ -1,9 +1,10 @@
from __future__ import annotations
import contextlib
import os.path
import sys
from typing import Generator
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit import git
@ -95,6 +96,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,13 +1,12 @@
from __future__ import annotations
import multiprocessing
import os
import random
import re
from typing import Any
from typing import List
from typing import Optional
from typing import overload
from typing import Sequence
from typing import Tuple
from typing import TYPE_CHECKING
import pre_commit.constants as C
@ -32,7 +31,7 @@ def exe_exists(exe: str) -> bool:
homedir = os.path.expanduser('~')
try:
common: Optional[str] = os.path.commonpath((found, homedir))
common: str | None = os.path.commonpath((found, homedir))
except ValueError: # on windows, different drives raises ValueError
common = None
@ -48,7 +47,7 @@ def exe_exists(exe: str) -> bool:
)
def run_setup_cmd(prefix: Prefix, cmd: Tuple[str, ...], **kwargs: Any) -> None:
def run_setup_cmd(prefix: Prefix, cmd: tuple[str, ...], **kwargs: Any) -> None:
cmd_output_b(*cmd, cwd=prefix.prefix_dir, **kwargs)
@ -58,7 +57,7 @@ def environment_dir(d: None, language_version: str) -> None: ...
def environment_dir(d: str, language_version: str) -> str: ...
def environment_dir(d: Optional[str], language_version: str) -> Optional[str]:
def environment_dir(d: str | None, language_version: str) -> str | None:
if d is None:
return None
else:
@ -68,7 +67,8 @@ def environment_dir(d: Optional[str], language_version: str) -> Optional[str]:
def assert_version_default(binary: str, version: str) -> None:
if version != C.DEFAULT:
raise AssertionError(
f'For now, pre-commit requires system-installed {binary}',
f'for now, pre-commit requires system-installed {binary} -- '
f'you selected `language_version: {version}`',
)
@ -78,8 +78,9 @@ def assert_no_additional_deps(
) -> None:
if additional_deps:
raise AssertionError(
f'For now, pre-commit does not support '
f'additional_dependencies for {lang}',
f'for now, pre-commit does not support '
f'additional_dependencies for {lang} -- '
f'you selected `additional_dependencies: {additional_deps}`',
)
@ -95,7 +96,7 @@ def no_install(
prefix: Prefix,
version: str,
additional_dependencies: Sequence[str],
) -> 'NoReturn':
) -> NoReturn:
raise AssertionError('This type is not installable')
@ -113,7 +114,7 @@ def target_concurrency(hook: Hook) -> int:
return 1
def _shuffled(seq: Sequence[str]) -> List[str]:
def _shuffled(seq: Sequence[str]) -> list[str]:
"""Deterministically shuffle"""
fixed_random = random.Random()
fixed_random.seed(FIXED_RANDOM_SEED, version=1)
@ -125,10 +126,10 @@ def _shuffled(seq: Sequence[str]) -> List[str]:
def run_xargs(
hook: Hook,
cmd: Tuple[str, ...],
cmd: tuple[str, ...],
file_args: Sequence[str],
**kwargs: Any,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
# Shuffle the files so that they more evenly fill out the xargs partitions,
# but do it deterministically in case a hook cares about ordering.
file_args = _shuffled(file_args)

View file

@ -1,9 +1,10 @@
from __future__ import annotations
import contextlib
import os
import sys
from typing import Generator
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit.envcontext import envcontext
@ -85,6 +86,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]: # pragma: win32 no cover
) -> tuple[int, bytes]: # pragma: win32 no cover
with in_env(hook.prefix):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,10 +1,11 @@
from __future__ import annotations
import contextlib
import functools
import os
import sys
from typing import Generator
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit.envcontext import envcontext
@ -122,6 +123,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix, hook.language_version):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,9 +1,10 @@
from __future__ import annotations
import contextlib
import os
import shlex
from typing import Generator
from typing import Sequence
from typing import Tuple
from pre_commit.envcontext import envcontext
from pre_commit.envcontext import PatchesT
@ -62,6 +63,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix, hook.language_version):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,11 +1,11 @@
from __future__ import annotations
import argparse
import re
import sys
from typing import NamedTuple
from typing import Optional
from typing import Pattern
from typing import Sequence
from typing import Tuple
from pre_commit import output
from pre_commit.hook import Hook
@ -90,12 +90,12 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
exe = (sys.executable, '-m', __name__) + tuple(hook.args) + (hook.entry,)
return xargs(exe, file_args, color=color)
def main(argv: Optional[Sequence[str]] = None) -> int:
def main(argv: Sequence[str] | None = None) -> int:
parser = argparse.ArgumentParser(
description=(
'grep-like finder using python regexes. Unlike grep, this tool '

View file

@ -1,12 +1,11 @@
from __future__ import annotations
import contextlib
import functools
import os
import sys
from typing import Dict
from typing import Generator
from typing import Optional
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit.envcontext import envcontext
@ -35,7 +34,7 @@ def _version_info(exe: str) -> str:
return f'<<error retrieving version from {exe}>>'
def _read_pyvenv_cfg(filename: str) -> Dict[str, str]:
def _read_pyvenv_cfg(filename: str) -> dict[str, str]:
ret = {}
with open(filename, encoding='UTF-8') as f:
for line in f:
@ -65,7 +64,7 @@ def get_env_patch(venv: str) -> PatchesT:
def _find_by_py_launcher(
version: str,
) -> Optional[str]: # pragma: no cover (windows only)
) -> str | None: # pragma: no cover (windows only)
if version.startswith('python'):
num = version[len('python'):]
cmd = ('py', f'-{num}', '-c', 'import sys; print(sys.executable)')
@ -77,8 +76,8 @@ def _find_by_py_launcher(
return None
def _find_by_sys_executable() -> Optional[str]:
def _norm(path: str) -> Optional[str]:
def _find_by_sys_executable() -> str | None:
def _norm(path: str) -> str | None:
_, exe = os.path.split(path.lower())
exe, _, _ = exe.partition('.exe')
if exe not in {'python', 'pythonw'} and find_executable(exe):
@ -133,7 +132,7 @@ def _sys_executable_matches(version: str) -> bool:
return sys.version_info[:len(info)] == info
def norm_version(version: str) -> Optional[str]:
def norm_version(version: str) -> str | None:
if version == C.DEFAULT: # use virtualenv's default
return None
elif _sys_executable_matches(version): # virtualenv defaults to our exe
@ -209,6 +208,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix, hook.language_version):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,10 +1,11 @@
from __future__ import annotations
import contextlib
import os
import shlex
import shutil
from typing import Generator
from typing import Sequence
from typing import Tuple
from pre_commit.envcontext import envcontext
from pre_commit.envcontext import PatchesT
@ -58,7 +59,11 @@ def _prefix_if_non_local_file_entry(
def _rscript_exec() -> str:
return os.path.join(os.getenv('R_HOME', ''), 'Rscript')
r_home = os.environ.get('R_HOME')
if r_home is None:
return 'Rscript'
else:
return os.path.join(r_home, 'bin', 'Rscript')
def _entry_validate(entry: Sequence[str]) -> None:
@ -80,7 +85,7 @@ def _entry_validate(entry: Sequence[str]) -> None:
)
def _cmd_from_hook(hook: Hook) -> Tuple[str, ...]:
def _cmd_from_hook(hook: Hook) -> tuple[str, ...]:
entry = shlex.split(hook.entry)
_entry_validate(entry)
@ -102,9 +107,7 @@ def install_environment(
shutil.copy(prefix.path('renv.lock'), env_dir)
shutil.copytree(prefix.path('renv'), os.path.join(env_dir, 'renv'))
cmd_output_b(
_rscript_exec(), '--vanilla', '-e',
f"""\
r_code_inst_environment = f"""\
prefix_dir <- {prefix.prefix_dir!r}
options(
repos = c(CRAN = "https://cran.rstudio.com"),
@ -131,24 +134,41 @@ def install_environment(
if (is_package) {{
renv::install(prefix_dir)
}}
""",
"""
cmd_output_b(
_rscript_exec(), '--vanilla', '-e',
_inline_r_setup(r_code_inst_environment),
cwd=env_dir,
)
if additional_dependencies:
r_code_inst_add = 'renv::install(commandArgs(trailingOnly = TRUE))'
with in_env(prefix, version):
cmd_output_b(
_rscript_exec(), *RSCRIPT_OPTS, '-e',
'renv::install(commandArgs(trailingOnly = TRUE))',
_inline_r_setup(r_code_inst_add),
*additional_dependencies,
cwd=env_dir,
)
def _inline_r_setup(code: str) -> str:
"""
Some behaviour of R cannot be configured via env variables, but can
only be configured via R options once R has started. These are set here.
"""
with_option = f"""\
options(install.packages.compile.from.source = "never")
{code}
"""
return with_option
def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix, hook.language_version):
return helpers.run_xargs(
hook, _cmd_from_hook(hook), file_args, color=color,

View file

@ -1,3 +1,5 @@
from __future__ import annotations
import contextlib
import functools
import os.path
@ -5,7 +7,6 @@ import shutil
import tarfile
from typing import Generator
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit.envcontext import envcontext
@ -146,6 +147,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix, hook.language_version):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,9 +1,9 @@
from __future__ import annotations
import contextlib
import os.path
from typing import Generator
from typing import Sequence
from typing import Set
from typing import Tuple
import toml
@ -39,7 +39,7 @@ def in_env(prefix: Prefix) -> Generator[None, None, None]:
def _add_dependencies(
cargo_toml_path: str,
additional_dependencies: Set[str],
additional_dependencies: set[str],
) -> None:
with open(cargo_toml_path, 'r+') as f:
cargo_toml = toml.load(f)
@ -81,7 +81,7 @@ def install_environment(
_add_dependencies(prefix.path('Cargo.toml'), lib_deps)
with clean_path_on_failure(directory):
packages_to_install: Set[Tuple[str, ...]] = {('--path', '.')}
packages_to_install: set[tuple[str, ...]] = {('--path', '.')}
for cli_dep in cli_deps:
cli_dep = cli_dep[len('cli:'):]
package, _, version = cli_dep.partition(':')
@ -101,6 +101,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
with in_env(hook.prefix):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,5 +1,6 @@
from __future__ import annotations
from typing import Sequence
from typing import Tuple
from pre_commit.hook import Hook
from pre_commit.languages import helpers
@ -14,6 +15,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
cmd = (hook.prefix.path(hook.cmd[0]), *hook.cmd[1:])
return helpers.run_xargs(hook, cmd, file_args, color=color)

View file

@ -1,8 +1,9 @@
from __future__ import annotations
import contextlib
import os
from typing import Generator
from typing import Sequence
from typing import Tuple
import pre_commit.constants as C
from pre_commit.envcontext import envcontext
@ -59,6 +60,6 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]: # pragma: win32 no cover
) -> tuple[int, bytes]: # pragma: win32 no cover
with in_env(hook.prefix):
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)

View file

@ -1,5 +1,6 @@
from __future__ import annotations
from typing import Sequence
from typing import Tuple
from pre_commit.hook import Hook
from pre_commit.languages import helpers
@ -15,5 +16,5 @@ def run_hook(
hook: Hook,
file_args: Sequence[str],
color: bool,
) -> Tuple[int, bytes]:
) -> tuple[int, bytes]:
return helpers.run_xargs(hook, hook.cmd, file_args, color=color)