Merging upstream version 4.2.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f3d71e86d5
commit
4f187f2e34
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:
|
||||
include: ${{ fromJSON(needs.vars.outputs.languages) }}
|
||||
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
|
||||
with:
|
||||
python-version: 3.9
|
||||
|
|
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
|
@ -12,12 +12,12 @@ concurrency:
|
|||
|
||||
jobs:
|
||||
main-windows:
|
||||
uses: asottile/workflows/.github/workflows/tox.yml@v1.6.0
|
||||
uses: asottile/workflows/.github/workflows/tox.yml@v1.8.1
|
||||
with:
|
||||
env: '["py39"]'
|
||||
os: windows-latest
|
||||
main-linux:
|
||||
uses: asottile/workflows/.github/workflows/tox.yml@v1.6.0
|
||||
uses: asottile/workflows/.github/workflows/tox.yml@v1.8.1
|
||||
with:
|
||||
env: '["py39", "py310", "py311", "py312"]'
|
||||
os: ubuntu-latest
|
||||
|
|
|
@ -29,15 +29,15 @@ repos:
|
|||
- id: pyupgrade
|
||||
args: [--py39-plus]
|
||||
- repo: https://github.com/hhatto/autopep8
|
||||
rev: v2.3.1
|
||||
rev: v2.3.2
|
||||
hooks:
|
||||
- id: autopep8
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 7.1.1
|
||||
rev: 7.1.2
|
||||
hooks:
|
||||
- id: flake8
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v1.14.1
|
||||
rev: v1.15.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
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
|
||||
==================
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ def get_conflicted_files() -> set[str]:
|
|||
merge_diff_filenames = zsplit(
|
||||
cmd_output(
|
||||
'git', 'diff', '--name-only', '--no-ext-diff', '-z',
|
||||
'-m', tree_hash, 'HEAD', 'MERGE_HEAD',
|
||||
'-m', tree_hash, 'HEAD', 'MERGE_HEAD', '--',
|
||||
)[1],
|
||||
)
|
||||
return set(merge_conflict_filenames) | set(merge_diff_filenames)
|
||||
|
|
|
@ -75,6 +75,13 @@ def _find_by_py_launcher(
|
|||
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 _norm(path: str) -> str | None:
|
||||
_, exe = os.path.split(path.lower())
|
||||
|
@ -100,16 +107,23 @@ def _find_by_sys_executable() -> str | None:
|
|||
|
||||
@functools.lru_cache(maxsize=1)
|
||||
def get_default_version() -> str: # pragma: no cover (platform dependent)
|
||||
# First attempt from `sys.executable` (or the realpath)
|
||||
exe = _find_by_sys_executable()
|
||||
if exe:
|
||||
return exe
|
||||
v_major = f'{sys.version_info[0]}'
|
||||
v_minor = f'{sys.version_info[0]}.{sys.version_info[1]}'
|
||||
|
||||
# Next try the `pythonX.X` executable
|
||||
exe = f'python{sys.version_info[0]}.{sys.version_info[1]}'
|
||||
# attempt the likely implementation exe
|
||||
for potential in (v_minor, v_major):
|
||||
exe = f'{_impl_exe_name()}{potential}'
|
||||
if find_executable(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):
|
||||
return exe
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[metadata]
|
||||
name = pre_commit
|
||||
version = 4.1.0
|
||||
version = 4.2.0
|
||||
description = A framework for managing and maintaining multi-language pre-commit hooks.
|
||||
long_description = file: README.md
|
||||
long_description_content_type = text/markdown
|
||||
|
|
|
@ -141,6 +141,15 @@ def test_get_conflicted_files_unstaged_files(in_merge_conflict):
|
|||
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"
|
||||
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.util import make_executable
|
||||
from pre_commit.util import win_exe
|
||||
from testing.auto_namedtuple import auto_namedtuple
|
||||
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
|
||||
|
||||
|
||||
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():
|
||||
home = os.path.expanduser('~')
|
||||
if sys.platform == 'win32': # pragma: win32 cover
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue