Adding upstream version 4.2.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
a38bf5d420
commit
2ddebfdc93
9 changed files with 121 additions and 18 deletions
2
.github/workflows/languages.yaml
vendored
2
.github/workflows/languages.yaml
vendored
|
@ -36,7 +36,7 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
include: ${{ fromJSON(needs.vars.outputs.languages) }}
|
include: ${{ fromJSON(needs.vars.outputs.languages) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: asottile/workflows/.github/actions/fast-checkout@v1.4.0
|
- uses: asottile/workflows/.github/actions/fast-checkout@v1.8.1
|
||||||
- uses: actions/setup-python@v4
|
- uses: actions/setup-python@v4
|
||||||
with:
|
with:
|
||||||
python-version: 3.9
|
python-version: 3.9
|
||||||
|
|
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
|
@ -12,12 +12,12 @@ concurrency:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
main-windows:
|
main-windows:
|
||||||
uses: asottile/workflows/.github/workflows/tox.yml@v1.6.0
|
uses: asottile/workflows/.github/workflows/tox.yml@v1.8.1
|
||||||
with:
|
with:
|
||||||
env: '["py39"]'
|
env: '["py39"]'
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
main-linux:
|
main-linux:
|
||||||
uses: asottile/workflows/.github/workflows/tox.yml@v1.6.0
|
uses: asottile/workflows/.github/workflows/tox.yml@v1.8.1
|
||||||
with:
|
with:
|
||||||
env: '["py39", "py310", "py311", "py312"]'
|
env: '["py39", "py310", "py311", "py312"]'
|
||||||
os: ubuntu-latest
|
os: ubuntu-latest
|
||||||
|
|
|
@ -29,15 +29,15 @@ repos:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py39-plus]
|
args: [--py39-plus]
|
||||||
- repo: https://github.com/hhatto/autopep8
|
- repo: https://github.com/hhatto/autopep8
|
||||||
rev: v2.3.1
|
rev: v2.3.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: autopep8
|
- id: autopep8
|
||||||
- repo: https://github.com/PyCQA/flake8
|
- repo: https://github.com/PyCQA/flake8
|
||||||
rev: 7.1.1
|
rev: 7.1.2
|
||||||
hooks:
|
hooks:
|
||||||
- id: flake8
|
- id: flake8
|
||||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||||
rev: v1.14.1
|
rev: v1.15.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: mypy
|
- id: mypy
|
||||||
additional_dependencies: [types-pyyaml]
|
additional_dependencies: [types-pyyaml]
|
||||||
|
|
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -1,3 +1,16 @@
|
||||||
|
4.2.0 - 2025-03-18
|
||||||
|
==================
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- For `language: python` first attempt a versioned python executable for
|
||||||
|
the default language version before consulting a potentially unversioned
|
||||||
|
`sys.executable`.
|
||||||
|
- #3430 PR by @asottile.
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Handle error during conflict detection when a file is named "HEAD"
|
||||||
|
- #3425 PR by @tusharsadhwani.
|
||||||
|
|
||||||
4.1.0 - 2025-01-20
|
4.1.0 - 2025-01-20
|
||||||
==================
|
==================
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,7 @@ def get_conflicted_files() -> set[str]:
|
||||||
merge_diff_filenames = zsplit(
|
merge_diff_filenames = zsplit(
|
||||||
cmd_output(
|
cmd_output(
|
||||||
'git', 'diff', '--name-only', '--no-ext-diff', '-z',
|
'git', 'diff', '--name-only', '--no-ext-diff', '-z',
|
||||||
'-m', tree_hash, 'HEAD', 'MERGE_HEAD',
|
'-m', tree_hash, 'HEAD', 'MERGE_HEAD', '--',
|
||||||
)[1],
|
)[1],
|
||||||
)
|
)
|
||||||
return set(merge_conflict_filenames) | set(merge_diff_filenames)
|
return set(merge_conflict_filenames) | set(merge_diff_filenames)
|
||||||
|
|
|
@ -75,6 +75,13 @@ def _find_by_py_launcher(
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _impl_exe_name() -> str:
|
||||||
|
if sys.implementation.name == 'cpython': # pragma: cpython cover
|
||||||
|
return 'python'
|
||||||
|
else: # pragma: cpython no cover
|
||||||
|
return sys.implementation.name # pypy mostly
|
||||||
|
|
||||||
|
|
||||||
def _find_by_sys_executable() -> str | None:
|
def _find_by_sys_executable() -> str | None:
|
||||||
def _norm(path: str) -> str | None:
|
def _norm(path: str) -> str | None:
|
||||||
_, exe = os.path.split(path.lower())
|
_, exe = os.path.split(path.lower())
|
||||||
|
@ -100,16 +107,23 @@ def _find_by_sys_executable() -> str | None:
|
||||||
|
|
||||||
@functools.lru_cache(maxsize=1)
|
@functools.lru_cache(maxsize=1)
|
||||||
def get_default_version() -> str: # pragma: no cover (platform dependent)
|
def get_default_version() -> str: # pragma: no cover (platform dependent)
|
||||||
# First attempt from `sys.executable` (or the realpath)
|
v_major = f'{sys.version_info[0]}'
|
||||||
exe = _find_by_sys_executable()
|
v_minor = f'{sys.version_info[0]}.{sys.version_info[1]}'
|
||||||
if exe:
|
|
||||||
return exe
|
|
||||||
|
|
||||||
# Next try the `pythonX.X` executable
|
# attempt the likely implementation exe
|
||||||
exe = f'python{sys.version_info[0]}.{sys.version_info[1]}'
|
for potential in (v_minor, v_major):
|
||||||
|
exe = f'{_impl_exe_name()}{potential}'
|
||||||
if find_executable(exe):
|
if find_executable(exe):
|
||||||
return exe
|
return exe
|
||||||
|
|
||||||
|
# next try `sys.executable` (or the realpath)
|
||||||
|
maybe_exe = _find_by_sys_executable()
|
||||||
|
if maybe_exe:
|
||||||
|
return maybe_exe
|
||||||
|
|
||||||
|
# maybe on windows we can find it via py launcher?
|
||||||
|
if sys.platform == 'win32': # pragma: win32 cover
|
||||||
|
exe = f'python{v_minor}'
|
||||||
if _find_by_py_launcher(exe):
|
if _find_by_py_launcher(exe):
|
||||||
return exe
|
return exe
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[metadata]
|
[metadata]
|
||||||
name = pre_commit
|
name = pre_commit
|
||||||
version = 4.1.0
|
version = 4.2.0
|
||||||
description = A framework for managing and maintaining multi-language pre-commit hooks.
|
description = A framework for managing and maintaining multi-language pre-commit hooks.
|
||||||
long_description = file: README.md
|
long_description = file: README.md
|
||||||
long_description_content_type = text/markdown
|
long_description_content_type = text/markdown
|
||||||
|
|
|
@ -141,6 +141,15 @@ def test_get_conflicted_files_unstaged_files(in_merge_conflict):
|
||||||
assert ret == {'conflict_file'}
|
assert ret == {'conflict_file'}
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_conflicted_files_with_file_named_head(in_merge_conflict):
|
||||||
|
resolve_conflict()
|
||||||
|
open('HEAD', 'w').close()
|
||||||
|
cmd_output('git', 'add', 'HEAD')
|
||||||
|
|
||||||
|
ret = set(git.get_conflicted_files())
|
||||||
|
assert ret == {'conflict_file', 'HEAD'}
|
||||||
|
|
||||||
|
|
||||||
MERGE_MSG = b"Merge branch 'foo' into bar\n\nConflicts:\n\tconflict_file\n"
|
MERGE_MSG = b"Merge branch 'foo' into bar\n\nConflicts:\n\tconflict_file\n"
|
||||||
OTHER_MERGE_MSG = MERGE_MSG + b'\tother_conflict_file\n'
|
OTHER_MERGE_MSG = MERGE_MSG + b'\tother_conflict_file\n'
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ from pre_commit.languages import python
|
||||||
from pre_commit.prefix import Prefix
|
from pre_commit.prefix import Prefix
|
||||||
from pre_commit.util import make_executable
|
from pre_commit.util import make_executable
|
||||||
from pre_commit.util import win_exe
|
from pre_commit.util import win_exe
|
||||||
|
from testing.auto_namedtuple import auto_namedtuple
|
||||||
from testing.language_helpers import run_language
|
from testing.language_helpers import run_language
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +35,72 @@ def test_read_pyvenv_cfg_non_utf8(tmpdir):
|
||||||
assert python._read_pyvenv_cfg(pyvenv_cfg) == expected
|
assert python._read_pyvenv_cfg(pyvenv_cfg) == expected
|
||||||
|
|
||||||
|
|
||||||
|
def _get_default_version(
|
||||||
|
*,
|
||||||
|
impl: str,
|
||||||
|
exe: str,
|
||||||
|
found: set[str],
|
||||||
|
version: tuple[int, int],
|
||||||
|
) -> str:
|
||||||
|
sys_exe = f'/fake/path/{exe}'
|
||||||
|
sys_impl = auto_namedtuple(name=impl)
|
||||||
|
sys_ver = auto_namedtuple(major=version[0], minor=version[1])
|
||||||
|
|
||||||
|
def find_exe(s):
|
||||||
|
if s in found:
|
||||||
|
return f'/fake/path/found/{exe}'
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
with (
|
||||||
|
mock.patch.object(sys, 'implementation', sys_impl),
|
||||||
|
mock.patch.object(sys, 'executable', sys_exe),
|
||||||
|
mock.patch.object(sys, 'version_info', sys_ver),
|
||||||
|
mock.patch.object(python, 'find_executable', find_exe),
|
||||||
|
):
|
||||||
|
return python.get_default_version.__wrapped__()
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_version_sys_executable_found():
|
||||||
|
ret = _get_default_version(
|
||||||
|
impl='cpython',
|
||||||
|
exe='python3.12',
|
||||||
|
found={'python3.12'},
|
||||||
|
version=(3, 12),
|
||||||
|
)
|
||||||
|
assert ret == 'python3.12'
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_version_picks_specific_when_found():
|
||||||
|
ret = _get_default_version(
|
||||||
|
impl='cpython',
|
||||||
|
exe='python3',
|
||||||
|
found={'python3', 'python3.12'},
|
||||||
|
version=(3, 12),
|
||||||
|
)
|
||||||
|
assert ret == 'python3.12'
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_version_picks_pypy_versioned_exe():
|
||||||
|
ret = _get_default_version(
|
||||||
|
impl='pypy',
|
||||||
|
exe='python',
|
||||||
|
found={'pypy3.12', 'python3'},
|
||||||
|
version=(3, 12),
|
||||||
|
)
|
||||||
|
assert ret == 'pypy3.12'
|
||||||
|
|
||||||
|
|
||||||
|
def test_default_version_picks_pypy_unversioned_exe():
|
||||||
|
ret = _get_default_version(
|
||||||
|
impl='pypy',
|
||||||
|
exe='python',
|
||||||
|
found={'pypy3', 'python3'},
|
||||||
|
version=(3, 12),
|
||||||
|
)
|
||||||
|
assert ret == 'pypy3'
|
||||||
|
|
||||||
|
|
||||||
def test_norm_version_expanduser():
|
def test_norm_version_expanduser():
|
||||||
home = os.path.expanduser('~')
|
home = os.path.expanduser('~')
|
||||||
if sys.platform == 'win32': # pragma: win32 cover
|
if sys.platform == 'win32': # pragma: win32 cover
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue